| 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 |