1 // Copyright 2012 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 #include "allocation.h" 32 #include "checks.h" 33 #include "hashmap.h" 34 #include "globals.h" 35 #include "list.h" 36 #include "splay-tree.h" 37 38 namespace v8 { 39 namespace internal { 40 41 42 // Zone scopes are in one of two modes. Either they delete the zone 43 // on exit or they do not. 44 enum ZoneScopeMode { 45 DELETE_ON_EXIT, 46 DONT_DELETE_ON_EXIT 47 }; 48 49 class Segment; 50 class Isolate; 51 52 // The Zone supports very fast allocation of small chunks of 53 // memory. The chunks cannot be deallocated individually, but instead 54 // the Zone supports deallocating all chunks in one fast 55 // operation. The Zone is used to hold temporary data structures like 56 // the abstract syntax tree, which is deallocated after compilation. 57 58 // Note: There is no need to initialize the Zone; the first time an 59 // allocation is attempted, a segment of memory will be requested 60 // through a call to malloc(). 61 62 // Note: The implementation is inherently not thread safe. Do not use 63 // from multi-threaded code. 64 65 class Zone { 66 public: 67 // Allocate 'size' bytes of memory in the Zone; expands the Zone by 68 // allocating new segments of memory on demand using malloc(). 69 inline void* New(int size); 70 71 template <typename T> 72 inline T* NewArray(int length); 73 74 // Deletes all objects and free all memory allocated in the Zone. Keeps one 75 // small (size <= kMaximumKeptSegmentSize) segment around if it finds one. 76 void DeleteAll(); 77 78 // Deletes the last small segment kept around by DeleteAll(). 79 void DeleteKeptSegment(); 80 81 // Returns true if more memory has been allocated in zones than 82 // the limit allows. 83 inline bool excess_allocation(); 84 85 inline void adjust_segment_bytes_allocated(int delta); 86 isolate()87 inline Isolate* isolate() { return isolate_; } 88 89 static unsigned allocation_size_; 90 91 private: 92 friend class Isolate; 93 friend class ZoneScope; 94 95 // All pointers returned from New() have this alignment. In addition, if the 96 // object being allocated has a size that is divisible by 8 then its alignment 97 // will be 8. 98 static const int kAlignment = kPointerSize; 99 100 // Never allocate segments smaller than this size in bytes. 101 static const int kMinimumSegmentSize = 8 * KB; 102 103 // Never allocate segments larger than this size in bytes. 104 static const int kMaximumSegmentSize = 1 * MB; 105 106 // Never keep segments larger than this size in bytes around. 107 static const int kMaximumKeptSegmentSize = 64 * KB; 108 109 // Report zone excess when allocation exceeds this limit. 110 int zone_excess_limit_; 111 112 // The number of bytes allocated in segments. Note that this number 113 // includes memory allocated from the OS but not yet allocated from 114 // the zone. 115 int segment_bytes_allocated_; 116 117 // Each isolate gets its own zone. 118 Zone(); 119 120 // Expand the Zone to hold at least 'size' more bytes and allocate 121 // the bytes. Returns the address of the newly allocated chunk of 122 // memory in the Zone. Should only be called if there isn't enough 123 // room in the Zone already. 124 Address NewExpand(int size); 125 126 // Creates a new segment, sets it size, and pushes it to the front 127 // of the segment chain. Returns the new segment. 128 Segment* NewSegment(int size); 129 130 // Deletes the given segment. Does not touch the segment chain. 131 void DeleteSegment(Segment* segment, int size); 132 133 // The free region in the current (front) segment is represented as 134 // the half-open interval [position, limit). The 'position' variable 135 // is guaranteed to be aligned as dictated by kAlignment. 136 Address position_; 137 Address limit_; 138 139 int scope_nesting_; 140 141 Segment* segment_head_; 142 Isolate* isolate_; 143 }; 144 145 146 // ZoneObject is an abstraction that helps define classes of objects 147 // allocated in the Zone. Use it as a base class; see ast.h. 148 class ZoneObject { 149 public: 150 // Allocate a new ZoneObject of 'size' bytes in the Zone. 151 INLINE(void* operator new(size_t size)); 152 INLINE(void* operator new(size_t size, Zone* zone)); 153 154 // Ideally, the delete operator should be private instead of 155 // public, but unfortunately the compiler sometimes synthesizes 156 // (unused) destructors for classes derived from ZoneObject, which 157 // require the operator to be visible. MSVC requires the delete 158 // operator to be public. 159 160 // ZoneObjects should never be deleted individually; use 161 // Zone::DeleteAll() to delete all zone objects in one go. delete(void *,size_t)162 void operator delete(void*, size_t) { UNREACHABLE(); } delete(void * pointer,Zone * zone)163 void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); } 164 }; 165 166 167 // The ZoneListAllocationPolicy is used to specialize the GenericList 168 // implementation to allocate ZoneLists and their elements in the 169 // Zone. 170 class ZoneListAllocationPolicy { 171 public: 172 // Allocate 'size' bytes of memory in the zone. 173 static void* New(int size); 174 175 // De-allocation attempts are silently ignored. Delete(void * p)176 static void Delete(void* p) { } 177 }; 178 179 180 // ZoneLists are growable lists with constant-time access to the 181 // elements. The list itself and all its elements are allocated in the 182 // Zone. ZoneLists cannot be deleted individually; you can delete all 183 // objects in the Zone by calling Zone::DeleteAll(). 184 template<typename T> 185 class ZoneList: public List<T, ZoneListAllocationPolicy> { 186 public: 187 INLINE(void* operator new(size_t size)); 188 INLINE(void* operator new(size_t size, Zone* zone)); 189 190 // Construct a new ZoneList with the given capacity; the length is 191 // always zero. The capacity must be non-negative. ZoneList(int capacity)192 explicit ZoneList(int capacity) 193 : List<T, ZoneListAllocationPolicy>(capacity) { } 194 195 // Construct a new ZoneList by copying the elements of the given ZoneList. ZoneList(const ZoneList<T> & other)196 explicit ZoneList(const ZoneList<T>& other) 197 : List<T, ZoneListAllocationPolicy>(other.length()) { 198 AddAll(other); 199 } 200 delete(void * pointer)201 void operator delete(void* pointer) { UNREACHABLE(); } delete(void * pointer,Zone * zone)202 void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); } 203 }; 204 205 206 // ZoneScopes keep track of the current parsing and compilation 207 // nesting and cleans up generated ASTs in the Zone when exiting the 208 // outer-most scope. 209 class ZoneScope BASE_EMBEDDED { 210 public: 211 INLINE(ZoneScope(Isolate* isolate, ZoneScopeMode mode)); 212 213 virtual ~ZoneScope(); 214 215 inline bool ShouldDeleteOnExit(); 216 217 // For ZoneScopes that do not delete on exit by default, call this 218 // method to request deletion on exit. DeleteOnExit()219 void DeleteOnExit() { 220 mode_ = DELETE_ON_EXIT; 221 } 222 223 inline static int nesting(); 224 225 private: 226 Isolate* isolate_; 227 ZoneScopeMode mode_; 228 }; 229 230 231 // A zone splay tree. The config type parameter encapsulates the 232 // different configurations of a concrete splay tree (see splay-tree.h). 233 // The tree itself and all its elements are allocated in the Zone. 234 template <typename Config> 235 class ZoneSplayTree: public SplayTree<Config, ZoneListAllocationPolicy> { 236 public: ZoneSplayTree()237 ZoneSplayTree() 238 : SplayTree<Config, ZoneListAllocationPolicy>() {} 239 ~ZoneSplayTree(); 240 }; 241 242 243 typedef TemplateHashMapImpl<ZoneListAllocationPolicy> ZoneHashMap; 244 245 } } // namespace v8::internal 246 247 #endif // V8_ZONE_H_ 248