Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_ZONE_H_
     29 #define V8_ZONE_H_
     30 
     31 namespace v8 {
     32 namespace internal {
     33 
     34 
     35 // Zone scopes are in one of two modes.  Either they delete the zone
     36 // on exit or they do not.
     37 enum ZoneScopeMode {
     38   DELETE_ON_EXIT,
     39   DONT_DELETE_ON_EXIT
     40 };
     41 
     42 class Segment;
     43 
     44 // The Zone supports very fast allocation of small chunks of
     45 // memory. The chunks cannot be deallocated individually, but instead
     46 // the Zone supports deallocating all chunks in one fast
     47 // operation. The Zone is used to hold temporary data structures like
     48 // the abstract syntax tree, which is deallocated after compilation.
     49 
     50 // Note: There is no need to initialize the Zone; the first time an
     51 // allocation is attempted, a segment of memory will be requested
     52 // through a call to malloc().
     53 
     54 // Note: The implementation is inherently not thread safe. Do not use
     55 // from multi-threaded code.
     56 
     57 class Zone {
     58  public:
     59   // Allocate 'size' bytes of memory in the Zone; expands the Zone by
     60   // allocating new segments of memory on demand using malloc().
     61   inline void* New(int size);
     62 
     63   template <typename T>
     64   inline T* NewArray(int length);
     65 
     66   // Delete all objects and free all memory allocated in the Zone.
     67   void DeleteAll();
     68 
     69   // Returns true if more memory has been allocated in zones than
     70   // the limit allows.
     71   inline bool excess_allocation();
     72 
     73   inline void adjust_segment_bytes_allocated(int delta);
     74 
     75   static unsigned allocation_size_;
     76 
     77  private:
     78   friend class Isolate;
     79   friend class ZoneScope;
     80 
     81   // All pointers returned from New() have this alignment.
     82   static const int kAlignment = kPointerSize;
     83 
     84   // Never allocate segments smaller than this size in bytes.
     85   static const int kMinimumSegmentSize = 8 * KB;
     86 
     87   // Never allocate segments larger than this size in bytes.
     88   static const int kMaximumSegmentSize = 1 * MB;
     89 
     90   // Never keep segments larger than this size in bytes around.
     91   static const int kMaximumKeptSegmentSize = 64 * KB;
     92 
     93   // Report zone excess when allocation exceeds this limit.
     94   int zone_excess_limit_;
     95 
     96   // The number of bytes allocated in segments.  Note that this number
     97   // includes memory allocated from the OS but not yet allocated from
     98   // the zone.
     99   int segment_bytes_allocated_;
    100 
    101   // Each isolate gets its own zone.
    102   Zone();
    103 
    104   // Expand the Zone to hold at least 'size' more bytes and allocate
    105   // the bytes. Returns the address of the newly allocated chunk of
    106   // memory in the Zone. Should only be called if there isn't enough
    107   // room in the Zone already.
    108   Address NewExpand(int size);
    109 
    110   // Creates a new segment, sets it size, and pushes it to the front
    111   // of the segment chain. Returns the new segment.
    112   Segment* NewSegment(int size);
    113 
    114   // Deletes the given segment. Does not touch the segment chain.
    115   void DeleteSegment(Segment* segment, int size);
    116 
    117   // The free region in the current (front) segment is represented as
    118   // the half-open interval [position, limit). The 'position' variable
    119   // is guaranteed to be aligned as dictated by kAlignment.
    120   Address position_;
    121   Address limit_;
    122 
    123   int scope_nesting_;
    124 
    125   Segment* segment_head_;
    126   Isolate* isolate_;
    127 };
    128 
    129 
    130 // ZoneObject is an abstraction that helps define classes of objects
    131 // allocated in the Zone. Use it as a base class; see ast.h.
    132 class ZoneObject {
    133  public:
    134   // Allocate a new ZoneObject of 'size' bytes in the Zone.
    135   inline void* operator new(size_t size);
    136   inline void* operator new(size_t size, Zone* zone);
    137 
    138   // Ideally, the delete operator should be private instead of
    139   // public, but unfortunately the compiler sometimes synthesizes
    140   // (unused) destructors for classes derived from ZoneObject, which
    141   // require the operator to be visible. MSVC requires the delete
    142   // operator to be public.
    143 
    144   // ZoneObjects should never be deleted individually; use
    145   // Zone::DeleteAll() to delete all zone objects in one go.
    146   void operator delete(void*, size_t) { UNREACHABLE(); }
    147 };
    148 
    149 
    150 class AssertNoZoneAllocation {
    151  public:
    152   inline AssertNoZoneAllocation();
    153   inline ~AssertNoZoneAllocation();
    154  private:
    155   bool prev_;
    156 };
    157 
    158 
    159 // The ZoneListAllocationPolicy is used to specialize the GenericList
    160 // implementation to allocate ZoneLists and their elements in the
    161 // Zone.
    162 class ZoneListAllocationPolicy {
    163  public:
    164   // Allocate 'size' bytes of memory in the zone.
    165   static inline void* New(int size);
    166 
    167   // De-allocation attempts are silently ignored.
    168   static void Delete(void* p) { }
    169 };
    170 
    171 
    172 // ZoneLists are growable lists with constant-time access to the
    173 // elements. The list itself and all its elements are allocated in the
    174 // Zone. ZoneLists cannot be deleted individually; you can delete all
    175 // objects in the Zone by calling Zone::DeleteAll().
    176 template<typename T>
    177 class ZoneList: public List<T, ZoneListAllocationPolicy> {
    178  public:
    179   // Construct a new ZoneList with the given capacity; the length is
    180   // always zero. The capacity must be non-negative.
    181   explicit ZoneList(int capacity)
    182       : List<T, ZoneListAllocationPolicy>(capacity) { }
    183 
    184   // Construct a new ZoneList by copying the elements of the given ZoneList.
    185   explicit ZoneList(const ZoneList<T>& other)
    186       : List<T, ZoneListAllocationPolicy>(other.length()) {
    187     AddAll(other);
    188   }
    189 };
    190 
    191 
    192 // Introduce a convenience type for zone lists of map handles.
    193 typedef ZoneList<Handle<Map> > ZoneMapList;
    194 
    195 
    196 // ZoneScopes keep track of the current parsing and compilation
    197 // nesting and cleans up generated ASTs in the Zone when exiting the
    198 // outer-most scope.
    199 class ZoneScope BASE_EMBEDDED {
    200  public:
    201   // TODO(isolates): pass isolate pointer here.
    202   inline explicit ZoneScope(ZoneScopeMode mode);
    203 
    204   virtual ~ZoneScope();
    205 
    206   inline bool ShouldDeleteOnExit();
    207 
    208   // For ZoneScopes that do not delete on exit by default, call this
    209   // method to request deletion on exit.
    210   void DeleteOnExit() {
    211     mode_ = DELETE_ON_EXIT;
    212   }
    213 
    214   inline static int nesting();
    215 
    216  private:
    217   Isolate* isolate_;
    218   ZoneScopeMode mode_;
    219 };
    220 
    221 
    222 // A zone splay tree.  The config type parameter encapsulates the
    223 // different configurations of a concrete splay tree (see splay-tree.h).
    224 // The tree itself and all its elements are allocated in the Zone.
    225 template <typename Config>
    226 class ZoneSplayTree: public SplayTree<Config, ZoneListAllocationPolicy> {
    227  public:
    228   ZoneSplayTree()
    229       : SplayTree<Config, ZoneListAllocationPolicy>() {}
    230   ~ZoneSplayTree();
    231 };
    232 
    233 
    234 } }  // namespace v8::internal
    235 
    236 #endif  // V8_ZONE_H_
    237