• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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