• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)13 RegExpStackScope::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()19 RegExpStackScope::~RegExpStackScope() {
20   CHECK_EQ(old_sp_top_delta_, regexp_stack_->sp_top_delta());
21   regexp_stack_->ResetIfEmpty();
22 }
23 
RegExpStack()24 RegExpStack::RegExpStack() : thread_local_(this) {}
25 
~RegExpStack()26 RegExpStack::~RegExpStack() { thread_local_.FreeAndInvalidate(); }
27 
ArchiveStack(char * to)28 char* 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)44 char* RegExpStack::RestoreStack(char* from) {
45   MemCopy(&thread_local_, reinterpret_cast<void*>(from), kThreadLocalSize);
46   return from + kThreadLocalSize;
47 }
48 
ResetToStaticStack(RegExpStack * regexp_stack)49 void 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()61 void 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)73 Address 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