1 // Copyright 2009 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/regexp/regexp-stack.h" 6 7 #include "src/execution/isolate.h" 8 #include "src/utils/memcopy.h" 9 10 namespace v8 { 11 namespace internal { 12 RegExpStackScope(Isolate * isolate)13RegExpStackScope::RegExpStackScope(Isolate* isolate) 14 : regexp_stack_(isolate->regexp_stack()), 15 old_sp_top_delta_(regexp_stack_->sp_top_delta()) { 16 DCHECK(regexp_stack_->IsValid()); 17 } 18 ~RegExpStackScope()19RegExpStackScope::~RegExpStackScope() { 20 CHECK_EQ(old_sp_top_delta_, regexp_stack_->sp_top_delta()); 21 regexp_stack_->ResetIfEmpty(); 22 } 23 RegExpStack()24RegExpStack::RegExpStack() : thread_local_(this) {} 25 ~RegExpStack()26RegExpStack::~RegExpStack() { thread_local_.FreeAndInvalidate(); } 27 ArchiveStack(char * to)28char* RegExpStack::ArchiveStack(char* to) { 29 if (!thread_local_.owns_memory_) { 30 // Force dynamic stacks prior to archiving. Any growth will do. A dynamic 31 // stack is needed because stack archival & restoration rely on `memory_` 32 // pointing at a fixed-location backing store, whereas the static stack is 33 // tied to a RegExpStack instance. 34 EnsureCapacity(thread_local_.memory_size_ + 1); 35 DCHECK(thread_local_.owns_memory_); 36 } 37 38 MemCopy(reinterpret_cast<void*>(to), &thread_local_, kThreadLocalSize); 39 thread_local_ = ThreadLocal(this); 40 return to + kThreadLocalSize; 41 } 42 43 RestoreStack(char * from)44char* RegExpStack::RestoreStack(char* from) { 45 MemCopy(&thread_local_, reinterpret_cast<void*>(from), kThreadLocalSize); 46 return from + kThreadLocalSize; 47 } 48 ResetToStaticStack(RegExpStack * regexp_stack)49void RegExpStack::ThreadLocal::ResetToStaticStack(RegExpStack* regexp_stack) { 50 if (owns_memory_) DeleteArray(memory_); 51 52 memory_ = regexp_stack->static_stack_; 53 memory_top_ = regexp_stack->static_stack_ + kStaticStackSize; 54 memory_size_ = kStaticStackSize; 55 stack_pointer_ = memory_top_; 56 limit_ = reinterpret_cast<Address>(regexp_stack->static_stack_) + 57 kStackLimitSlack * kSystemPointerSize; 58 owns_memory_ = false; 59 } 60 FreeAndInvalidate()61void RegExpStack::ThreadLocal::FreeAndInvalidate() { 62 if (owns_memory_) DeleteArray(memory_); 63 64 // This stack may not be used after being freed. Just reset to invalid values 65 // to ensure we don't accidentally use old memory areas. 66 memory_ = nullptr; 67 memory_top_ = nullptr; 68 memory_size_ = 0; 69 stack_pointer_ = nullptr; 70 limit_ = kMemoryTop; 71 } 72 EnsureCapacity(size_t size)73Address RegExpStack::EnsureCapacity(size_t size) { 74 if (size > kMaximumStackSize) return kNullAddress; 75 if (thread_local_.memory_size_ < size) { 76 if (size < kMinimumDynamicStackSize) size = kMinimumDynamicStackSize; 77 byte* new_memory = NewArray<byte>(size); 78 if (thread_local_.memory_size_ > 0) { 79 // Copy original memory into top of new memory. 80 MemCopy(new_memory + size - thread_local_.memory_size_, 81 thread_local_.memory_, thread_local_.memory_size_); 82 if (thread_local_.owns_memory_) DeleteArray(thread_local_.memory_); 83 } 84 ptrdiff_t delta = sp_top_delta(); 85 thread_local_.memory_ = new_memory; 86 thread_local_.memory_top_ = new_memory + size; 87 thread_local_.memory_size_ = size; 88 thread_local_.stack_pointer_ = thread_local_.memory_top_ + delta; 89 thread_local_.limit_ = reinterpret_cast<Address>(new_memory) + 90 kStackLimitSlack * kSystemPointerSize; 91 thread_local_.owns_memory_ = true; 92 } 93 return reinterpret_cast<Address>(thread_local_.memory_top_); 94 } 95 96 97 } // namespace internal 98 } // namespace v8 99