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 #ifndef V8_REGEXP_STACK_H_ 6 #define V8_REGEXP_STACK_H_ 7 8 namespace v8 { 9 namespace internal { 10 11 class RegExpStack; 12 13 // Maintains a per-v8thread stack area that can be used by irregexp 14 // implementation for its backtracking stack. 15 // Since there is only one stack area, the Irregexp implementation is not 16 // re-entrant. I.e., no regular expressions may be executed in the same thread 17 // during a preempted Irregexp execution. 18 class RegExpStackScope { 19 public: 20 // Create and delete an instance to control the life-time of a growing stack. 21 22 // Initializes the stack memory area if necessary. 23 explicit RegExpStackScope(Isolate* isolate); 24 ~RegExpStackScope(); // Releases the stack if it has grown. 25 stack()26 RegExpStack* stack() const { return regexp_stack_; } 27 28 private: 29 RegExpStack* regexp_stack_; 30 31 DISALLOW_COPY_AND_ASSIGN(RegExpStackScope); 32 }; 33 34 35 class RegExpStack { 36 public: 37 // Number of allocated locations on the stack below the limit. 38 // No sequence of pushes must be longer that this without doing a stack-limit 39 // check. 40 static const int kStackLimitSlack = 32; 41 42 // Gives the top of the memory used as stack. stack_base()43 Address stack_base() { 44 DCHECK(thread_local_.memory_size_ != 0); 45 return thread_local_.memory_ + thread_local_.memory_size_; 46 } 47 48 // The total size of the memory allocated for the stack. stack_capacity()49 size_t stack_capacity() { return thread_local_.memory_size_; } 50 51 // If the stack pointer gets below the limit, we should react and 52 // either grow the stack or report an out-of-stack exception. 53 // There is only a limited number of locations below the stack limit, 54 // so users of the stack should check the stack limit during any 55 // sequence of pushes longer that this. limit_address()56 Address* limit_address() { return &(thread_local_.limit_); } 57 58 // Ensures that there is a memory area with at least the specified size. 59 // If passing zero, the default/minimum size buffer is allocated. 60 Address EnsureCapacity(size_t size); 61 62 // Thread local archiving. ArchiveSpacePerThread()63 static int ArchiveSpacePerThread() { 64 return static_cast<int>(sizeof(ThreadLocal)); 65 } 66 char* ArchiveStack(char* to); 67 char* RestoreStack(char* from); FreeThreadResources()68 void FreeThreadResources() { thread_local_.Free(); } 69 70 private: 71 RegExpStack(); 72 ~RegExpStack(); 73 74 // Artificial limit used when no memory has been allocated. 75 static const uintptr_t kMemoryTop = static_cast<uintptr_t>(-1); 76 77 // Minimal size of allocated stack area. 78 static const size_t kMinimumStackSize = 1 * KB; 79 80 // Maximal size of allocated stack area. 81 static const size_t kMaximumStackSize = 64 * MB; 82 83 // Structure holding the allocated memory, size and limit. 84 struct ThreadLocal { ThreadLocalThreadLocal85 ThreadLocal() { Clear(); } 86 // If memory_size_ > 0 then memory_ must be non-NULL. 87 Address memory_; 88 size_t memory_size_; 89 Address limit_; ClearThreadLocal90 void Clear() { 91 memory_ = NULL; 92 memory_size_ = 0; 93 limit_ = reinterpret_cast<Address>(kMemoryTop); 94 } 95 void Free(); 96 }; 97 98 // Address of allocated memory. memory_address()99 Address memory_address() { 100 return reinterpret_cast<Address>(&thread_local_.memory_); 101 } 102 103 // Address of size of allocated memory. memory_size_address()104 Address memory_size_address() { 105 return reinterpret_cast<Address>(&thread_local_.memory_size_); 106 } 107 108 // Resets the buffer if it has grown beyond the default/minimum size. 109 // After this, the buffer is either the default size, or it is empty, so 110 // you have to call EnsureCapacity before using it again. 111 void Reset(); 112 113 ThreadLocal thread_local_; 114 Isolate* isolate_; 115 116 friend class ExternalReference; 117 friend class Isolate; 118 friend class RegExpStackScope; 119 120 DISALLOW_COPY_AND_ASSIGN(RegExpStack); 121 }; 122 123 }} // namespace v8::internal 124 125 #endif // V8_REGEXP_STACK_H_ 126