The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / zone.cc @ 40c0f755

History | View | Annotate | Download (6.59 KB)

1
// Copyright 2006-2008 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 "v8.h"
29

    
30
#include "zone-inl.h"
31

    
32
namespace v8 { namespace internal {
33

    
34

    
35
Address Zone::position_ = 0;
36
Address Zone::limit_ = 0;
37
int Zone::zone_excess_limit_ = 256 * MB;
38
int Zone::segment_bytes_allocated_ = 0;
39

    
40
bool AssertNoZoneAllocation::allow_allocation_ = true;
41

    
42
int ZoneScope::nesting_ = 0;
43

    
44
// Segments represent chunks of memory: They have starting address
45
// (encoded in the this pointer) and a size in bytes. Segments are
46
// chained together forming a LIFO structure with the newest segment
47
// available as Segment::head(). Segments are allocated using malloc()
48
// and de-allocated using free().
49

    
50
class Segment {
51
 public:
52
  Segment* next() const { return next_; }
53
  void clear_next() { next_ = NULL; }
54

    
55
  int size() const { return size_; }
56
  int capacity() const { return size_ - sizeof(Segment); }
57

    
58
  Address start() const { return address(sizeof(Segment)); }
59
  Address end() const { return address(size_); }
60

    
61
  static Segment* head() { return head_; }
62
  static void set_head(Segment* head) { head_ = head; }
63

    
64
  // Creates a new segment, sets it size, and pushes it to the front
65
  // of the segment chain. Returns the new segment.
66
  static Segment* New(int size) {
67
    Segment* result = reinterpret_cast<Segment*>(Malloced::New(size));
68
    Zone::adjust_segment_bytes_allocated(size);
69
    if (result != NULL) {
70
      result->next_ = head_;
71
      result->size_ = size;
72
      head_ = result;
73
    }
74
    return result;
75
  }
76

    
77
  // Deletes the given segment. Does not touch the segment chain.
78
  static void Delete(Segment* segment, int size) {
79
    Zone::adjust_segment_bytes_allocated(-size);
80
    Malloced::Delete(segment);
81
  }
82

    
83
  static int bytes_allocated() { return bytes_allocated_; }
84

    
85
 private:
86
  // Computes the address of the nth byte in this segment.
87
  Address address(int n) const {
88
    return Address(this) + n;
89
  }
90

    
91
  static Segment* head_;
92
  static int bytes_allocated_;
93
  Segment* next_;
94
  int size_;
95
};
96

    
97

    
98
Segment* Segment::head_ = NULL;
99
int Segment::bytes_allocated_ = 0;
100

    
101

    
102
void Zone::DeleteAll() {
103
#ifdef DEBUG
104
  // Constant byte value used for zapping dead memory in debug mode.
105
  static const unsigned char kZapDeadByte = 0xcd;
106
#endif
107

    
108
  // Find a segment with a suitable size to keep around.
109
  Segment* keep = Segment::head();
110
  while (keep != NULL && keep->size() > kMaximumKeptSegmentSize) {
111
    keep = keep->next();
112
  }
113

    
114
  // Traverse the chained list of segments, zapping (in debug mode)
115
  // and freeing every segment except the one we wish to keep.
116
  Segment* current = Segment::head();
117
  while (current != NULL) {
118
    Segment* next = current->next();
119
    if (current == keep) {
120
      // Unlink the segment we wish to keep from the list.
121
      current->clear_next();
122
    } else {
123
      int size = current->size();
124
#ifdef DEBUG
125
      // Zap the entire current segment (including the header).
126
      memset(current, kZapDeadByte, size);
127
#endif
128
      Segment::Delete(current, size);
129
    }
130
    current = next;
131
  }
132

    
133
  // If we have found a segment we want to keep, we must recompute the
134
  // variables 'position' and 'limit' to prepare for future allocate
135
  // attempts. Otherwise, we must clear the position and limit to
136
  // force a new segment to be allocated on demand.
137
  if (keep != NULL) {
138
    Address start = keep->start();
139
    position_ = RoundUp(start, kAlignment);
140
    limit_ = keep->end();
141
#ifdef DEBUG
142
    // Zap the contents of the kept segment (but not the header).
143
    memset(start, kZapDeadByte, keep->capacity());
144
#endif
145
  } else {
146
    position_ = limit_ = 0;
147
  }
148

    
149
  // Update the head segment to be the kept segment (if any).
150
  Segment::set_head(keep);
151
}
152

    
153

    
154
Address Zone::NewExpand(int size) {
155
  // Make sure the requested size is already properly aligned and that
156
  // there isn't enough room in the Zone to satisfy the request.
157
  ASSERT(size == RoundDown(size, kAlignment));
158
  ASSERT(position_ + size > limit_);
159

    
160
  // Compute the new segment size. We use a 'high water mark'
161
  // strategy, where we increase the segment size every time we expand
162
  // except that we employ a maximum segment size when we delete. This
163
  // is to avoid excessive malloc() and free() overhead.
164
  Segment* head = Segment::head();
165
  int old_size = (head == NULL) ? 0 : head->size();
166
  static const int kSegmentOverhead = sizeof(Segment) + kAlignment;
167
  int new_size = kSegmentOverhead + size + (old_size << 1);
168
  if (new_size < kMinimumSegmentSize) {
169
    new_size = kMinimumSegmentSize;
170
  } else if (new_size > kMaximumSegmentSize) {
171
    // Limit the size of new segments to avoid growing the segment size
172
    // exponentially, thus putting pressure on contiguous virtual address space.
173
    // All the while making sure to allocate a segment large enough to hold the
174
    // requested size.
175
    new_size = Max(kSegmentOverhead + size, kMaximumSegmentSize);
176
  }
177
  Segment* segment = Segment::New(new_size);
178
  if (segment == NULL) V8::FatalProcessOutOfMemory("Zone");
179

    
180
  // Recompute 'top' and 'limit' based on the new segment.
181
  Address result = RoundUp(segment->start(), kAlignment);
182
  position_ = result + size;
183
  limit_ = segment->end();
184
  ASSERT(position_ <= limit_);
185
  return result;
186
}
187

    
188

    
189
} }  // namespace v8::internal