• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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_ZONE_H_
6 #define V8_ZONE_H_
7 
8 #include "src/allocation.h"
9 #include "src/checks.h"
10 #include "src/hashmap.h"
11 #include "src/globals.h"
12 #include "src/list.h"
13 #include "src/splay-tree.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 
19 class Segment;
20 class Isolate;
21 
22 // The Zone supports very fast allocation of small chunks of
23 // memory. The chunks cannot be deallocated individually, but instead
24 // the Zone supports deallocating all chunks in one fast
25 // operation. The Zone is used to hold temporary data structures like
26 // the abstract syntax tree, which is deallocated after compilation.
27 
28 // Note: There is no need to initialize the Zone; the first time an
29 // allocation is attempted, a segment of memory will be requested
30 // through a call to malloc().
31 
32 // Note: The implementation is inherently not thread safe. Do not use
33 // from multi-threaded code.
34 
35 class Zone {
36  public:
37   explicit Zone(Isolate* isolate);
38   ~Zone();
39   // Allocate 'size' bytes of memory in the Zone; expands the Zone by
40   // allocating new segments of memory on demand using malloc().
41   inline void* New(int size);
42 
43   template <typename T>
44   inline T* NewArray(int length);
45 
46   // Deletes all objects and free all memory allocated in the Zone. Keeps one
47   // small (size <= kMaximumKeptSegmentSize) segment around if it finds one.
48   void DeleteAll();
49 
50   // Deletes the last small segment kept around by DeleteAll(). You
51   // may no longer allocate in the Zone after a call to this method.
52   void DeleteKeptSegment();
53 
54   // Returns true if more memory has been allocated in zones than
55   // the limit allows.
56   inline bool excess_allocation();
57 
58   inline void adjust_segment_bytes_allocated(int delta);
59 
allocation_size()60   inline unsigned allocation_size() { return allocation_size_; }
61 
isolate()62   inline Isolate* isolate() { return isolate_; }
63 
64  private:
65   friend class Isolate;
66 
67   // All pointers returned from New() have this alignment.  In addition, if the
68   // object being allocated has a size that is divisible by 8 then its alignment
69   // will be 8. ASan requires 8-byte alignment.
70 #ifdef V8_USE_ADDRESS_SANITIZER
71   static const int kAlignment = 8;
72   STATIC_ASSERT(kPointerSize <= 8);
73 #else
74   static const int kAlignment = kPointerSize;
75 #endif
76 
77   // Never allocate segments smaller than this size in bytes.
78   static const int kMinimumSegmentSize = 8 * KB;
79 
80   // Never allocate segments larger than this size in bytes.
81   static const int kMaximumSegmentSize = 1 * MB;
82 
83   // Never keep segments larger than this size in bytes around.
84   static const int kMaximumKeptSegmentSize = 64 * KB;
85 
86   // Report zone excess when allocation exceeds this limit.
87   static const int kExcessLimit = 256 * MB;
88 
89   // The number of bytes allocated in this zone so far.
90   unsigned allocation_size_;
91 
92   // The number of bytes allocated in segments.  Note that this number
93   // includes memory allocated from the OS but not yet allocated from
94   // the zone.
95   int segment_bytes_allocated_;
96 
97   // Expand the Zone to hold at least 'size' more bytes and allocate
98   // the bytes. Returns the address of the newly allocated chunk of
99   // memory in the Zone. Should only be called if there isn't enough
100   // room in the Zone already.
101   Address NewExpand(int size);
102 
103   // Creates a new segment, sets it size, and pushes it to the front
104   // of the segment chain. Returns the new segment.
105   INLINE(Segment* NewSegment(int size));
106 
107   // Deletes the given segment. Does not touch the segment chain.
108   INLINE(void DeleteSegment(Segment* segment, int size));
109 
110   // The free region in the current (front) segment is represented as
111   // the half-open interval [position, limit). The 'position' variable
112   // is guaranteed to be aligned as dictated by kAlignment.
113   Address position_;
114   Address limit_;
115 
116   Segment* segment_head_;
117   Isolate* isolate_;
118 };
119 
120 
121 // ZoneObject is an abstraction that helps define classes of objects
122 // allocated in the Zone. Use it as a base class; see ast.h.
123 class ZoneObject {
124  public:
125   // Allocate a new ZoneObject of 'size' bytes in the Zone.
126   INLINE(void* operator new(size_t size, Zone* zone));
127 
128   // Ideally, the delete operator should be private instead of
129   // public, but unfortunately the compiler sometimes synthesizes
130   // (unused) destructors for classes derived from ZoneObject, which
131   // require the operator to be visible. MSVC requires the delete
132   // operator to be public.
133 
134   // ZoneObjects should never be deleted individually; use
135   // Zone::DeleteAll() to delete all zone objects in one go.
delete(void *,size_t)136   void operator delete(void*, size_t) { UNREACHABLE(); }
delete(void * pointer,Zone * zone)137   void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
138 };
139 
140 
141 // The ZoneScope is used to automatically call DeleteAll() on a
142 // Zone when the ZoneScope is destroyed (i.e. goes out of scope)
143 struct ZoneScope {
144  public:
ZoneScopeZoneScope145   explicit ZoneScope(Zone* zone) : zone_(zone) { }
~ZoneScopeZoneScope146   ~ZoneScope() { zone_->DeleteAll(); }
147 
zoneZoneScope148   Zone* zone() { return zone_; }
149 
150  private:
151   Zone* zone_;
152 };
153 
154 
155 // The ZoneAllocationPolicy is used to specialize generic data
156 // structures to allocate themselves and their elements in the Zone.
157 struct ZoneAllocationPolicy {
158  public:
ZoneAllocationPolicyZoneAllocationPolicy159   explicit ZoneAllocationPolicy(Zone* zone) : zone_(zone) { }
160   INLINE(void* New(size_t size));
INLINEZoneAllocationPolicy161   INLINE(static void Delete(void *pointer)) { }
zoneZoneAllocationPolicy162   Zone* zone() { return zone_; }
163 
164  private:
165   Zone* zone_;
166 };
167 
168 
169 // ZoneLists are growable lists with constant-time access to the
170 // elements. The list itself and all its elements are allocated in the
171 // Zone. ZoneLists cannot be deleted individually; you can delete all
172 // objects in the Zone by calling Zone::DeleteAll().
173 template<typename T>
174 class ZoneList: public List<T, ZoneAllocationPolicy> {
175  public:
176   // Construct a new ZoneList with the given capacity; the length is
177   // always zero. The capacity must be non-negative.
ZoneList(int capacity,Zone * zone)178   ZoneList(int capacity, Zone* zone)
179       : List<T, ZoneAllocationPolicy>(capacity, ZoneAllocationPolicy(zone)) { }
180 
181   INLINE(void* operator new(size_t size, Zone* zone));
182 
183   // Construct a new ZoneList by copying the elements of the given ZoneList.
ZoneList(const ZoneList<T> & other,Zone * zone)184   ZoneList(const ZoneList<T>& other, Zone* zone)
185       : List<T, ZoneAllocationPolicy>(other.length(),
186                                       ZoneAllocationPolicy(zone)) {
187     AddAll(other, zone);
188   }
189 
190   // We add some convenience wrappers so that we can pass in a Zone
191   // instead of a (less convenient) ZoneAllocationPolicy.
INLINE(void Add (const T & element,Zone * zone))192   INLINE(void Add(const T& element, Zone* zone)) {
193     List<T, ZoneAllocationPolicy>::Add(element, ZoneAllocationPolicy(zone));
194   }
INLINE(void AddAll (const List<T,ZoneAllocationPolicy> & other,Zone * zone))195   INLINE(void AddAll(const List<T, ZoneAllocationPolicy>& other, Zone* zone)) {
196     List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
197   }
INLINE(void AddAll (const Vector<T> & other,Zone * zone))198   INLINE(void AddAll(const Vector<T>& other, Zone* zone)) {
199     List<T, ZoneAllocationPolicy>::AddAll(other, ZoneAllocationPolicy(zone));
200   }
INLINE(void InsertAt (int index,const T & element,Zone * zone))201   INLINE(void InsertAt(int index, const T& element, Zone* zone)) {
202     List<T, ZoneAllocationPolicy>::InsertAt(index, element,
203                                             ZoneAllocationPolicy(zone));
204   }
INLINE(Vector<T> AddBlock (T value,int count,Zone * zone))205   INLINE(Vector<T> AddBlock(T value, int count, Zone* zone)) {
206     return List<T, ZoneAllocationPolicy>::AddBlock(value, count,
207                                                    ZoneAllocationPolicy(zone));
208   }
INLINE(void Allocate (int length,Zone * zone))209   INLINE(void Allocate(int length, Zone* zone)) {
210     List<T, ZoneAllocationPolicy>::Allocate(length, ZoneAllocationPolicy(zone));
211   }
INLINE(void Initialize (int capacity,Zone * zone))212   INLINE(void Initialize(int capacity, Zone* zone)) {
213     List<T, ZoneAllocationPolicy>::Initialize(capacity,
214                                               ZoneAllocationPolicy(zone));
215   }
216 
delete(void * pointer)217   void operator delete(void* pointer) { UNREACHABLE(); }
delete(void * pointer,Zone * zone)218   void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
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, ZoneAllocationPolicy> {
227  public:
ZoneSplayTree(Zone * zone)228   explicit ZoneSplayTree(Zone* zone)
229       : SplayTree<Config, ZoneAllocationPolicy>(ZoneAllocationPolicy(zone)) {}
230   ~ZoneSplayTree();
231 
232   INLINE(void* operator new(size_t size, Zone* zone));
233 
delete(void * pointer)234   void operator delete(void* pointer) { UNREACHABLE(); }
delete(void * pointer,Zone * zone)235   void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
236 };
237 
238 
239 typedef TemplateHashMapImpl<ZoneAllocationPolicy> ZoneHashMap;
240 
241 } }  // namespace v8::internal
242 
243 #endif  // V8_ZONE_H_
244