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