11cb0ef41Sopenharmony_ci// Copyright 2009 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/regexp/regexp-stack.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/execution/isolate.h" 81cb0ef41Sopenharmony_ci#include "src/utils/memcopy.h" 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_cinamespace v8 { 111cb0ef41Sopenharmony_cinamespace internal { 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciRegExpStackScope::RegExpStackScope(Isolate* isolate) 141cb0ef41Sopenharmony_ci : regexp_stack_(isolate->regexp_stack()), 151cb0ef41Sopenharmony_ci old_sp_top_delta_(regexp_stack_->sp_top_delta()) { 161cb0ef41Sopenharmony_ci DCHECK(regexp_stack_->IsValid()); 171cb0ef41Sopenharmony_ci} 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciRegExpStackScope::~RegExpStackScope() { 201cb0ef41Sopenharmony_ci CHECK_EQ(old_sp_top_delta_, regexp_stack_->sp_top_delta()); 211cb0ef41Sopenharmony_ci regexp_stack_->ResetIfEmpty(); 221cb0ef41Sopenharmony_ci} 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciRegExpStack::RegExpStack() : thread_local_(this) {} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciRegExpStack::~RegExpStack() { thread_local_.FreeAndInvalidate(); } 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_cichar* RegExpStack::ArchiveStack(char* to) { 291cb0ef41Sopenharmony_ci if (!thread_local_.owns_memory_) { 301cb0ef41Sopenharmony_ci // Force dynamic stacks prior to archiving. Any growth will do. A dynamic 311cb0ef41Sopenharmony_ci // stack is needed because stack archival & restoration rely on `memory_` 321cb0ef41Sopenharmony_ci // pointing at a fixed-location backing store, whereas the static stack is 331cb0ef41Sopenharmony_ci // tied to a RegExpStack instance. 341cb0ef41Sopenharmony_ci EnsureCapacity(thread_local_.memory_size_ + 1); 351cb0ef41Sopenharmony_ci DCHECK(thread_local_.owns_memory_); 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci MemCopy(reinterpret_cast<void*>(to), &thread_local_, kThreadLocalSize); 391cb0ef41Sopenharmony_ci thread_local_ = ThreadLocal(this); 401cb0ef41Sopenharmony_ci return to + kThreadLocalSize; 411cb0ef41Sopenharmony_ci} 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cichar* RegExpStack::RestoreStack(char* from) { 451cb0ef41Sopenharmony_ci MemCopy(&thread_local_, reinterpret_cast<void*>(from), kThreadLocalSize); 461cb0ef41Sopenharmony_ci return from + kThreadLocalSize; 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_civoid RegExpStack::ThreadLocal::ResetToStaticStack(RegExpStack* regexp_stack) { 501cb0ef41Sopenharmony_ci if (owns_memory_) DeleteArray(memory_); 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci memory_ = regexp_stack->static_stack_; 531cb0ef41Sopenharmony_ci memory_top_ = regexp_stack->static_stack_ + kStaticStackSize; 541cb0ef41Sopenharmony_ci memory_size_ = kStaticStackSize; 551cb0ef41Sopenharmony_ci stack_pointer_ = memory_top_; 561cb0ef41Sopenharmony_ci limit_ = reinterpret_cast<Address>(regexp_stack->static_stack_) + 571cb0ef41Sopenharmony_ci kStackLimitSlack * kSystemPointerSize; 581cb0ef41Sopenharmony_ci owns_memory_ = false; 591cb0ef41Sopenharmony_ci} 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_civoid RegExpStack::ThreadLocal::FreeAndInvalidate() { 621cb0ef41Sopenharmony_ci if (owns_memory_) DeleteArray(memory_); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // This stack may not be used after being freed. Just reset to invalid values 651cb0ef41Sopenharmony_ci // to ensure we don't accidentally use old memory areas. 661cb0ef41Sopenharmony_ci memory_ = nullptr; 671cb0ef41Sopenharmony_ci memory_top_ = nullptr; 681cb0ef41Sopenharmony_ci memory_size_ = 0; 691cb0ef41Sopenharmony_ci stack_pointer_ = nullptr; 701cb0ef41Sopenharmony_ci limit_ = kMemoryTop; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ciAddress RegExpStack::EnsureCapacity(size_t size) { 741cb0ef41Sopenharmony_ci if (size > kMaximumStackSize) return kNullAddress; 751cb0ef41Sopenharmony_ci if (thread_local_.memory_size_ < size) { 761cb0ef41Sopenharmony_ci if (size < kMinimumDynamicStackSize) size = kMinimumDynamicStackSize; 771cb0ef41Sopenharmony_ci byte* new_memory = NewArray<byte>(size); 781cb0ef41Sopenharmony_ci if (thread_local_.memory_size_ > 0) { 791cb0ef41Sopenharmony_ci // Copy original memory into top of new memory. 801cb0ef41Sopenharmony_ci MemCopy(new_memory + size - thread_local_.memory_size_, 811cb0ef41Sopenharmony_ci thread_local_.memory_, thread_local_.memory_size_); 821cb0ef41Sopenharmony_ci if (thread_local_.owns_memory_) DeleteArray(thread_local_.memory_); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci ptrdiff_t delta = sp_top_delta(); 851cb0ef41Sopenharmony_ci thread_local_.memory_ = new_memory; 861cb0ef41Sopenharmony_ci thread_local_.memory_top_ = new_memory + size; 871cb0ef41Sopenharmony_ci thread_local_.memory_size_ = size; 881cb0ef41Sopenharmony_ci thread_local_.stack_pointer_ = thread_local_.memory_top_ + delta; 891cb0ef41Sopenharmony_ci thread_local_.limit_ = reinterpret_cast<Address>(new_memory) + 901cb0ef41Sopenharmony_ci kStackLimitSlack * kSystemPointerSize; 911cb0ef41Sopenharmony_ci thread_local_.owns_memory_ = true; 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci return reinterpret_cast<Address>(thread_local_.memory_top_); 941cb0ef41Sopenharmony_ci} 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci} // namespace internal 981cb0ef41Sopenharmony_ci} // namespace v8 99