OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/zone.h" | 5 #include "vm/zone.h" |
6 | 6 |
7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
11 #include "vm/os.h" | 11 #include "vm/os.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 DEFINE_DEBUG_FLAG(bool, trace_zone_sizes, | 15 DEFINE_DEBUG_FLAG(bool, trace_zone_sizes, |
16 false, "Traces allocation sizes in the zone."); | 16 false, "Traces allocation sizes in the zone."); |
17 | 17 |
18 | 18 |
19 // Zone segments represent chunks of memory: They have starting | 19 // Zone segments represent chunks of memory: They have starting |
20 // address encoded in the this pointer and a size in bytes. They are | 20 // address encoded in the this pointer and a size in bytes. They are |
21 // chained together to form the backing storage for an expanding zone. | 21 // chained together to form the backing storage for an expanding zone. |
22 class BaseZone::Segment { | 22 class Zone::Segment { |
23 public: | 23 public: |
24 Segment* next() const { return next_; } | 24 Segment* next() const { return next_; } |
25 intptr_t size() const { return size_; } | 25 intptr_t size() const { return size_; } |
26 | 26 |
27 uword start() { return address(sizeof(Segment)); } | 27 uword start() { return address(sizeof(Segment)); } |
28 uword end() { return address(size_); } | 28 uword end() { return address(size_); } |
29 | 29 |
30 // Allocate or delete individual segments. | 30 // Allocate or delete individual segments. |
31 static Segment* New(intptr_t size, Segment* next); | 31 static Segment* New(intptr_t size, Segment* next); |
32 static void DeleteSegmentList(Segment* segment); | 32 static void DeleteSegmentList(Segment* segment); |
33 | 33 |
34 private: | 34 private: |
35 Segment* next_; | 35 Segment* next_; |
36 intptr_t size_; | 36 intptr_t size_; |
37 | 37 |
38 // Computes the address of the nth byte in this segment. | 38 // Computes the address of the nth byte in this segment. |
39 uword address(int n) { return reinterpret_cast<uword>(this) + n; } | 39 uword address(int n) { return reinterpret_cast<uword>(this) + n; } |
40 | 40 |
41 static void Delete(Segment* segment) { delete[] segment; } | 41 static void Delete(Segment* segment) { delete[] segment; } |
42 | 42 |
43 DISALLOW_IMPLICIT_CONSTRUCTORS(Segment); | 43 DISALLOW_IMPLICIT_CONSTRUCTORS(Segment); |
44 }; | 44 }; |
45 | 45 |
46 | 46 |
47 void BaseZone::Segment::DeleteSegmentList(Segment* head) { | 47 void Zone::Segment::DeleteSegmentList(Segment* head) { |
48 Segment* current = head; | 48 Segment* current = head; |
49 while (current != NULL) { | 49 while (current != NULL) { |
50 Segment* next = current->next(); | 50 Segment* next = current->next(); |
51 #ifdef DEBUG | 51 #ifdef DEBUG |
52 // Zap the entire current segment (including the header). | 52 // Zap the entire current segment (including the header). |
53 memset(current, kZapDeletedByte, current->size()); | 53 memset(current, kZapDeletedByte, current->size()); |
54 #endif | 54 #endif |
55 Segment::Delete(current); | 55 Segment::Delete(current); |
56 current = next; | 56 current = next; |
57 } | 57 } |
58 } | 58 } |
59 | 59 |
60 | 60 |
61 BaseZone::Segment* BaseZone::Segment::New(intptr_t size, | 61 Zone::Segment* Zone::Segment::New(intptr_t size, Zone::Segment* next) { |
62 BaseZone::Segment* next) { | |
63 ASSERT(size >= 0); | 62 ASSERT(size >= 0); |
64 Segment* result = reinterpret_cast<Segment*>(new uint8_t[size]); | 63 Segment* result = reinterpret_cast<Segment*>(new uint8_t[size]); |
65 if (result != NULL) { | 64 if (result != NULL) { |
66 #ifdef DEBUG | 65 #ifdef DEBUG |
67 // Zap the entire allocated segment (including the header). | 66 // Zap the entire allocated segment (including the header). |
68 memset(result, kZapUninitializedByte, size); | 67 memset(result, kZapUninitializedByte, size); |
69 #endif | 68 #endif |
70 result->next_ = next; | 69 result->next_ = next; |
71 result->size_ = size; | 70 result->size_ = size; |
72 } | 71 } |
73 return result; | 72 return result; |
74 } | 73 } |
75 | 74 |
76 | 75 |
77 BaseZone::BaseZone() | 76 Zone::Zone() |
78 : initial_buffer_(buffer_, kInitialChunkSize), | 77 : initial_buffer_(buffer_, kInitialChunkSize), |
79 position_(initial_buffer_.start()), | 78 position_(initial_buffer_.start()), |
80 limit_(initial_buffer_.end()), | 79 limit_(initial_buffer_.end()), |
81 head_(NULL), | 80 head_(NULL), |
82 large_segments_(NULL) { | 81 large_segments_(NULL), |
| 82 handles_() { |
83 #ifdef DEBUG | 83 #ifdef DEBUG |
84 // Zap the entire initial buffer. | 84 // Zap the entire initial buffer. |
85 memset(initial_buffer_.pointer(), kZapUninitializedByte, | 85 memset(initial_buffer_.pointer(), kZapUninitializedByte, |
86 initial_buffer_.size()); | 86 initial_buffer_.size()); |
87 #endif | 87 #endif |
88 } | 88 } |
89 | 89 |
90 | 90 |
91 BaseZone::~BaseZone() { | 91 Zone::~Zone() { |
92 DeleteAll(); | 92 DeleteAll(); |
93 #if defined(DEBUG) | 93 #if defined(DEBUG) |
94 if (FLAG_trace_zone_sizes) { | 94 if (FLAG_trace_zone_sizes) { |
95 DumpZoneSizes(); | 95 DumpZoneSizes(); |
96 } | 96 } |
97 #endif | 97 #endif |
98 } | 98 } |
99 | 99 |
100 | 100 |
101 void BaseZone::DeleteAll() { | 101 void Zone::DeleteAll() { |
102 // Traverse the chained list of segments, zapping (in debug mode) | 102 // Traverse the chained list of segments, zapping (in debug mode) |
103 // and freeing every zone segment. | 103 // and freeing every zone segment. |
104 Segment::DeleteSegmentList(head_); | 104 Segment::DeleteSegmentList(head_); |
105 Segment::DeleteSegmentList(large_segments_); | 105 Segment::DeleteSegmentList(large_segments_); |
106 | 106 |
107 // Reset zone state. | 107 // Reset zone state. |
108 #ifdef DEBUG | 108 #ifdef DEBUG |
109 memset(initial_buffer_.pointer(), kZapDeletedByte, initial_buffer_.size()); | 109 memset(initial_buffer_.pointer(), kZapDeletedByte, initial_buffer_.size()); |
110 #endif | 110 #endif |
111 position_ = initial_buffer_.start(); | 111 position_ = initial_buffer_.start(); |
112 limit_ = initial_buffer_.end(); | 112 limit_ = initial_buffer_.end(); |
113 head_ = NULL; | 113 head_ = NULL; |
114 large_segments_ = NULL; | 114 large_segments_ = NULL; |
115 } | 115 } |
116 | 116 |
117 | 117 |
118 intptr_t BaseZone::SizeInBytes() const { | 118 intptr_t Zone::SizeInBytes() const { |
119 intptr_t size = 0; | 119 intptr_t size = 0; |
120 for (Segment* s = large_segments_; s != NULL; s = s->next()) { | 120 for (Segment* s = large_segments_; s != NULL; s = s->next()) { |
121 size += s->size(); | 121 size += s->size(); |
122 } | 122 } |
123 if (head_ == NULL) { | 123 if (head_ == NULL) { |
124 return size + (position_ - initial_buffer_.start()); | 124 return size + (position_ - initial_buffer_.start()); |
125 } | 125 } |
126 size += initial_buffer_.size(); | 126 size += initial_buffer_.size(); |
127 for (Segment* s = head_->next(); s != NULL; s = s->next()) { | 127 for (Segment* s = head_->next(); s != NULL; s = s->next()) { |
128 size += s->size(); | 128 size += s->size(); |
129 } | 129 } |
130 return size + (position_ - head_->start()); | 130 return size + (position_ - head_->start()); |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 uword BaseZone::AllocateExpand(intptr_t size) { | 134 uword Zone::AllocateExpand(intptr_t size) { |
135 #if defined(DEBUG) | 135 #if defined(DEBUG) |
136 ASSERT(size >= 0); | 136 ASSERT(size >= 0); |
137 if (FLAG_trace_zone_sizes) { | 137 if (FLAG_trace_zone_sizes) { |
138 DumpZoneSizes(); | 138 DumpZoneSizes(); |
139 } | 139 } |
140 // Make sure the requested size is already properly aligned and that | 140 // Make sure the requested size is already properly aligned and that |
141 // there isn't enough room in the Zone to satisfy the request. | 141 // there isn't enough room in the Zone to satisfy the request. |
142 ASSERT(Utils::IsAligned(size, kAlignment)); | 142 ASSERT(Utils::IsAligned(size, kAlignment)); |
143 intptr_t free_size = (limit_ - position_); | 143 intptr_t free_size = (limit_ - position_); |
144 ASSERT(free_size < size); | 144 ASSERT(free_size < size); |
(...skipping 12 matching lines...) Expand all Loading... |
157 | 157 |
158 // Recompute 'position' and 'limit' based on the new head segment. | 158 // Recompute 'position' and 'limit' based on the new head segment. |
159 uword result = Utils::RoundUp(head_->start(), kAlignment); | 159 uword result = Utils::RoundUp(head_->start(), kAlignment); |
160 position_ = result + size; | 160 position_ = result + size; |
161 limit_ = head_->end(); | 161 limit_ = head_->end(); |
162 ASSERT(position_ <= limit_); | 162 ASSERT(position_ <= limit_); |
163 return result; | 163 return result; |
164 } | 164 } |
165 | 165 |
166 | 166 |
167 uword BaseZone::AllocateLargeSegment(intptr_t size) { | 167 uword Zone::AllocateLargeSegment(intptr_t size) { |
168 #if defined(DEBUG) | 168 #if defined(DEBUG) |
169 ASSERT(size >= 0); | 169 ASSERT(size >= 0); |
170 // Make sure the requested size is already properly aligned and that | 170 // Make sure the requested size is already properly aligned and that |
171 // there isn't enough room in the Zone to satisfy the request. | 171 // there isn't enough room in the Zone to satisfy the request. |
172 ASSERT(Utils::IsAligned(size, kAlignment)); | 172 ASSERT(Utils::IsAligned(size, kAlignment)); |
173 intptr_t free_size = (limit_ - position_); | 173 intptr_t free_size = (limit_ - position_); |
174 ASSERT(free_size < size); | 174 ASSERT(free_size < size); |
175 #endif | 175 #endif |
176 | 176 |
177 // Create a new large segment and chain it up. | 177 // Create a new large segment and chain it up. |
178 ASSERT(Utils::IsAligned(sizeof(Segment), kAlignment)); | 178 ASSERT(Utils::IsAligned(sizeof(Segment), kAlignment)); |
179 size += sizeof(Segment); // Account for book keeping fields in size. | 179 size += sizeof(Segment); // Account for book keeping fields in size. |
180 large_segments_ = Segment::New(size, large_segments_); | 180 large_segments_ = Segment::New(size, large_segments_); |
181 | 181 |
182 uword result = Utils::RoundUp(large_segments_->start(), kAlignment); | 182 uword result = Utils::RoundUp(large_segments_->start(), kAlignment); |
183 return result; | 183 return result; |
184 } | 184 } |
185 | 185 |
186 | 186 |
187 char* BaseZone::MakeCopyOfString(const char* str) { | 187 char* Zone::MakeCopyOfString(const char* str) { |
188 intptr_t len = strlen(str) + 1; // '\0'-terminated. | 188 intptr_t len = strlen(str) + 1; // '\0'-terminated. |
189 char* copy = Alloc<char>(len); | 189 char* copy = Alloc<char>(len); |
190 strncpy(copy, str, len); | 190 strncpy(copy, str, len); |
191 return copy; | 191 return copy; |
192 } | 192 } |
193 | 193 |
194 | 194 |
195 #if defined(DEBUG) | 195 #if defined(DEBUG) |
196 void BaseZone::DumpZoneSizes() { | 196 void Zone::DumpZoneSizes() { |
197 intptr_t size = 0; | 197 intptr_t size = 0; |
198 for (Segment* s = large_segments_; s != NULL; s = s->next()) { | 198 for (Segment* s = large_segments_; s != NULL; s = s->next()) { |
199 size += s->size(); | 199 size += s->size(); |
200 } | 200 } |
201 OS::Print("Size in bytes allocated, Total = %"Pd" Large Segments = %"Pd"\n", | 201 OS::Print("Size in bytes allocated, Total = %"Pd" Large Segments = %"Pd"\n", |
202 SizeInBytes(), size); | 202 SizeInBytes(), size); |
203 } | 203 } |
204 #endif | 204 #endif |
205 | 205 |
206 | 206 |
207 Zone::Zone(BaseIsolate* isolate) | 207 StackZone::StackZone(BaseIsolate* isolate) |
208 : StackResource(isolate), | 208 : StackResource(isolate), |
209 zone_(), | 209 zone_(), |
210 handles_(), | |
211 previous_(NULL) { | 210 previous_(NULL) { |
212 // Assert that there is no current zone as we only want to scope | 211 // Assert that there is no current zone as we only want to scope |
213 // zones when transitioning from generated dart code to dart VM | 212 // zones when transitioning from generated dart code to dart VM |
214 // runtime code. | 213 // runtime code. |
215 previous_ = isolate->current_zone(); | 214 previous_ = isolate->current_zone(); |
216 isolate->set_current_zone(this); | 215 isolate->set_current_zone(this); |
217 } | 216 } |
218 | 217 |
219 | 218 |
220 Zone::~Zone() { | 219 StackZone::~StackZone() { |
221 ASSERT(isolate()->current_zone() == this); | 220 ASSERT(isolate()->current_zone() == this); |
222 isolate()->set_current_zone(previous_); | 221 isolate()->set_current_zone(previous_); |
223 } | 222 } |
224 | 223 |
225 | 224 |
226 void Zone::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 225 void StackZone::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
227 Zone* zone = this; | 226 StackZone* zone = this; |
228 while (zone != NULL) { | 227 while (zone != NULL) { |
229 zone->handles()->VisitObjectPointers(visitor); | 228 zone->handles()->VisitObjectPointers(visitor); |
230 zone = zone->previous_; | 229 zone = zone->previous_; |
231 } | 230 } |
232 } | 231 } |
233 | 232 |
234 | 233 |
235 char* Zone::PrintToString(const char* format, ...) { | 234 char* StackZone::PrintToString(const char* format, ...) { |
236 va_list args; | 235 va_list args; |
237 va_start(args, format); | 236 va_start(args, format); |
238 intptr_t len = OS::VSNPrint(NULL, 0, format, args); | 237 intptr_t len = OS::VSNPrint(NULL, 0, format, args); |
239 va_end(args); | 238 va_end(args); |
240 | 239 |
241 char* buffer = Alloc<char>(len + 1); | 240 char* buffer = Alloc<char>(len + 1); |
242 va_list args2; | 241 va_list args2; |
243 va_start(args2, format); | 242 va_start(args2, format); |
244 OS::VSNPrint(buffer, (len + 1), format, args2); | 243 OS::VSNPrint(buffer, (len + 1), format, args2); |
245 va_end(args2); | 244 va_end(args2); |
246 | 245 |
247 return buffer; | 246 return buffer; |
248 } | 247 } |
249 | 248 |
250 | 249 |
251 } // namespace dart | 250 } // namespace dart |
OLD | NEW |