v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
zone.cc
Go to the documentation of this file.
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 #include <string.h>
29 
30 #include "v8.h"
31 #include "zone-inl.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 
37 // Segments represent chunks of memory: They have starting address
38 // (encoded in the this pointer) and a size in bytes. Segments are
39 // chained together forming a LIFO structure with the newest segment
40 // available as segment_head_. Segments are allocated using malloc()
41 // and de-allocated using free().
42 
43 class Segment {
44  public:
45  void Initialize(Segment* next, int size) {
46  next_ = next;
47  size_ = size;
48  }
49 
50  Segment* next() const { return next_; }
51  void clear_next() { next_ = NULL; }
52 
53  int size() const { return size_; }
54  int capacity() const { return size_ - sizeof(Segment); }
55 
56  Address start() const { return address(sizeof(Segment)); }
57  Address end() const { return address(size_); }
58 
59  private:
60  // Computes the address of the nth byte in this segment.
61  Address address(int n) const {
62  return Address(this) + n;
63  }
64 
65  Segment* next_;
66  int size_;
67 };
68 
69 
71  : allocation_size_(0),
72  segment_bytes_allocated_(0),
73  position_(0),
74  limit_(0),
75  segment_head_(NULL),
76  isolate_(isolate) {
77 }
78 
79 
81  DeleteAll();
83 
84  ASSERT(segment_bytes_allocated_ == 0);
85 }
86 
87 
89 #ifdef DEBUG
90  // Constant byte value used for zapping dead memory in debug mode.
91  static const unsigned char kZapDeadByte = 0xcd;
92 #endif
93 
94  // Find a segment with a suitable size to keep around.
95  Segment* keep = NULL;
96  // Traverse the chained list of segments, zapping (in debug mode)
97  // and freeing every segment except the one we wish to keep.
98  for (Segment* current = segment_head_; current != NULL; ) {
99  Segment* next = current->next();
100  if (keep == NULL && current->size() <= kMaximumKeptSegmentSize) {
101  // Unlink the segment we wish to keep from the list.
102  keep = current;
103  keep->clear_next();
104  } else {
105  int size = current->size();
106 #ifdef DEBUG
107  // Un-poison first so the zapping doesn't trigger ASan complaints.
108  ASAN_UNPOISON_MEMORY_REGION(current, size);
109  // Zap the entire current segment (including the header).
110  memset(current, kZapDeadByte, size);
111 #endif
112  DeleteSegment(current, size);
113  }
114  current = next;
115  }
116 
117  // If we have found a segment we want to keep, we must recompute the
118  // variables 'position' and 'limit' to prepare for future allocate
119  // attempts. Otherwise, we must clear the position and limit to
120  // force a new segment to be allocated on demand.
121  if (keep != NULL) {
122  Address start = keep->start();
123  position_ = RoundUp(start, kAlignment);
124  limit_ = keep->end();
125  // Un-poison so we can re-use the segment later.
126  ASAN_UNPOISON_MEMORY_REGION(start, keep->capacity());
127 #ifdef DEBUG
128  // Zap the contents of the kept segment (but not the header).
129  memset(start, kZapDeadByte, keep->capacity());
130 #endif
131  } else {
132  position_ = limit_ = 0;
133  }
134 
135  // Update the head segment to be the kept segment (if any).
136  segment_head_ = keep;
137 }
138 
139 
141 #ifdef DEBUG
142  // Constant byte value used for zapping dead memory in debug mode.
143  static const unsigned char kZapDeadByte = 0xcd;
144 #endif
145 
146  ASSERT(segment_head_ == NULL || segment_head_->next() == NULL);
147  if (segment_head_ != NULL) {
148  int size = segment_head_->size();
149 #ifdef DEBUG
150  // Un-poison first so the zapping doesn't trigger ASan complaints.
151  ASAN_UNPOISON_MEMORY_REGION(segment_head_, size);
152  // Zap the entire kept segment (including the header).
153  memset(segment_head_, kZapDeadByte, size);
154 #endif
155  DeleteSegment(segment_head_, size);
156  segment_head_ = NULL;
157  }
158 
159  ASSERT(segment_bytes_allocated_ == 0);
160 }
161 
162 
163 // Creates a new segment, sets it size, and pushes it to the front
164 // of the segment chain. Returns the new segment.
165 Segment* Zone::NewSegment(int size) {
166  Segment* result = reinterpret_cast<Segment*>(Malloced::New(size));
168  if (result != NULL) {
169  result->Initialize(segment_head_, size);
170  segment_head_ = result;
171  }
172  return result;
173 }
174 
175 
176 // Deletes the given segment. Does not touch the segment chain.
177 void Zone::DeleteSegment(Segment* segment, int size) {
179  Malloced::Delete(segment);
180 }
181 
182 
183 Address Zone::NewExpand(int size) {
184  // Make sure the requested size is already properly aligned and that
185  // there isn't enough room in the Zone to satisfy the request.
186  ASSERT(size == RoundDown(size, kAlignment));
187  ASSERT(size > limit_ - position_);
188 
189  // Compute the new segment size. We use a 'high water mark'
190  // strategy, where we increase the segment size every time we expand
191  // except that we employ a maximum segment size when we delete. This
192  // is to avoid excessive malloc() and free() overhead.
193  Segment* head = segment_head_;
194  const size_t old_size = (head == NULL) ? 0 : head->size();
195  static const size_t kSegmentOverhead = sizeof(Segment) + kAlignment;
196  const size_t new_size_no_overhead = size + (old_size << 1);
197  size_t new_size = kSegmentOverhead + new_size_no_overhead;
198  const size_t min_new_size = kSegmentOverhead + static_cast<size_t>(size);
199  // Guard against integer overflow.
200  if (new_size_no_overhead < static_cast<size_t>(size) ||
201  new_size < static_cast<size_t>(kSegmentOverhead)) {
203  return NULL;
204  }
205  if (new_size < static_cast<size_t>(kMinimumSegmentSize)) {
206  new_size = kMinimumSegmentSize;
207  } else if (new_size > static_cast<size_t>(kMaximumSegmentSize)) {
208  // Limit the size of new segments to avoid growing the segment size
209  // exponentially, thus putting pressure on contiguous virtual address space.
210  // All the while making sure to allocate a segment large enough to hold the
211  // requested size.
212  new_size = Max(min_new_size, static_cast<size_t>(kMaximumSegmentSize));
213  }
214  if (new_size > INT_MAX) {
216  return NULL;
217  }
218  Segment* segment = NewSegment(static_cast<int>(new_size));
219  if (segment == NULL) {
221  return NULL;
222  }
223 
224  // Recompute 'top' and 'limit' based on the new segment.
225  Address result = RoundUp(segment->start(), kAlignment);
226  position_ = result + size;
227  // Check for address overflow.
228  // (Should not happen since the segment is guaranteed to accomodate
229  // size bytes + header and alignment padding)
230  if (reinterpret_cast<uintptr_t>(position_)
231  < reinterpret_cast<uintptr_t>(result)) {
233  return NULL;
234  }
235  limit_ = segment->end();
236  ASSERT(position_ <= limit_);
237  return result;
238 }
239 
240 
241 } } // namespace v8::internal
byte * Address
Definition: globals.h:186
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static void Delete(void *p)
Definition: allocation.cc:51
void Initialize(Segment *next, int size)
Definition: zone.cc:45
static void * New(size_t size)
Definition: allocation.cc:42
T Max(T a, T b)
Definition: utils.h:227
#define ASAN_UNPOISON_MEMORY_REGION(start, size)
Definition: zone-inl.h:36
#define ASSERT(condition)
Definition: checks.h:329
void DeleteAll()
Definition: zone.cc:88
Zone(Isolate *isolate)
Definition: zone.cc:70
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
Address start() const
Definition: zone.cc:56
int capacity() const
Definition: zone.cc:54
Address end() const
Definition: zone.cc:57
T RoundUp(T x, intptr_t m)
Definition: utils.h:144
void adjust_segment_bytes_allocated(int delta)
Definition: zone-inl.h:104
void DeleteKeptSegment()
Definition: zone.cc:140
Segment * next() const
Definition: zone.cc:50
void clear_next()
Definition: zone.cc:51
T RoundDown(T x, intptr_t m)
Definition: utils.h:136
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
int size() const
Definition: zone.cc:53