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