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