Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: runtime/vm/zone.cc

Issue 2762323002: Reimplemented zone memory tracking to avoid race conditions that were causing crashes in the previo… (Closed)
Patch Set: Removed zone usage tracking. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/zone.h ('k') | runtime/vm/zone_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/dart_api_state.h" 9 #include "vm/dart_api_state.h"
10 #include "vm/flags.h" 10 #include "vm/flags.h"
(...skipping 12 matching lines...) Expand all
23 intptr_t size() const { return size_; } 23 intptr_t size() const { return size_; }
24 24
25 uword start() { return address(sizeof(Segment)); } 25 uword start() { return address(sizeof(Segment)); }
26 uword end() { return address(size_); } 26 uword end() { return address(size_); }
27 27
28 // Allocate or delete individual segments. 28 // Allocate or delete individual segments.
29 static Segment* New(intptr_t size, Segment* next); 29 static Segment* New(intptr_t size, Segment* next);
30 static void DeleteSegmentList(Segment* segment); 30 static void DeleteSegmentList(Segment* segment);
31 31
32 private: 32 private:
33 static void IncrementMemoryCapacity(uintptr_t size);
34 static void DecrementMemoryCapacity(uintptr_t size);
siva 2017/03/22 23:36:06 The two versions of IncrementMemoryCapacity/Decrem
35
33 Segment* next_; 36 Segment* next_;
34 intptr_t size_; 37 intptr_t size_;
35 38
36 // Computes the address of the nth byte in this segment. 39 // Computes the address of the nth byte in this segment.
37 uword address(int n) { return reinterpret_cast<uword>(this) + n; } 40 uword address(int n) { return reinterpret_cast<uword>(this) + n; }
38 41
39 static void Delete(Segment* segment) { free(segment); } 42 static void Delete(Segment* segment) { free(segment); }
40 43
41 DISALLOW_IMPLICIT_CONSTRUCTORS(Segment); 44 DISALLOW_IMPLICIT_CONSTRUCTORS(Segment);
42 }; 45 };
43 46
44 47
48 Zone::Segment* Zone::Segment::New(intptr_t size, Zone::Segment* next) {
49 ASSERT(size >= 0);
50 Segment* result = reinterpret_cast<Segment*>(malloc(size));
51 if (result == NULL) {
52 OUT_OF_MEMORY();
53 }
54 ASSERT(Utils::IsAligned(result->start(), Zone::kAlignment));
55 #ifdef DEBUG
56 // Zap the entire allocated segment (including the header).
57 memset(result, kZapUninitializedByte, size);
58 #endif
59 result->next_ = next;
60 result->size_ = size;
61 IncrementMemoryCapacity(size);
62 return result;
63 }
64
65
45 void Zone::Segment::DeleteSegmentList(Segment* head) { 66 void Zone::Segment::DeleteSegmentList(Segment* head) {
46 Segment* current = head; 67 Segment* current = head;
47 Thread* current_thread = Thread::Current();
48 while (current != NULL) { 68 while (current != NULL) {
49 if (current_thread != NULL) { 69 DecrementMemoryCapacity(current->size());
50 current_thread->DecrementMemoryUsage(current->size());
51 } else if (ApiNativeScope::Current() != NULL) {
52 // If there is no current thread, we might be inside of a native scope.
53 ApiNativeScope::DecrementNativeScopeMemoryUsage(current->size());
54 }
55 Segment* next = current->next(); 70 Segment* next = current->next();
56 #ifdef DEBUG 71 #ifdef DEBUG
57 // Zap the entire current segment (including the header). 72 // Zap the entire current segment (including the header).
58 memset(current, kZapDeletedByte, current->size()); 73 memset(current, kZapDeletedByte, current->size());
59 #endif 74 #endif
60 Segment::Delete(current); 75 Segment::Delete(current);
61 current = next; 76 current = next;
62 } 77 }
63 } 78 }
64 79
65 80
66 Zone::Segment* Zone::Segment::New(intptr_t size, Zone::Segment* next) { 81 void Zone::Segment::IncrementMemoryCapacity(uintptr_t size) {
67 ASSERT(size >= 0); 82 Thread* current_thread = Thread::Current();
68 Segment* result = reinterpret_cast<Segment*>(malloc(size)); 83 if (current_thread != NULL) {
69 if (result == NULL) { 84 current_thread->IncrementMemoryCapacity(size);
70 OUT_OF_MEMORY();
71 }
72 ASSERT(Utils::IsAligned(result->start(), Zone::kAlignment));
73 #ifdef DEBUG
74 // Zap the entire allocated segment (including the header).
75 memset(result, kZapUninitializedByte, size);
76 #endif
77 result->next_ = next;
78 result->size_ = size;
79 Thread* current = Thread::Current();
80 if (current != NULL) {
81 current->IncrementMemoryUsage(size);
82 } else if (ApiNativeScope::Current() != NULL) { 85 } else if (ApiNativeScope::Current() != NULL) {
83 // If there is no current thread, we might be inside of a native scope. 86 // If there is no current thread, we might be inside of a native scope.
84 ApiNativeScope::IncrementNativeScopeMemoryUsage(size); 87 ApiNativeScope::IncrementNativeScopeMemoryCapacity(size);
85 } 88 }
86 return result;
87 } 89 }
88 90
91
92 void Zone::Segment::DecrementMemoryCapacity(uintptr_t size) {
93 Thread* current_thread = Thread::Current();
94 if (current_thread != NULL) {
95 current_thread->DecrementMemoryCapacity(size);
96 } else if (ApiNativeScope::Current() != NULL) {
97 // If there is no current thread, we might be inside of a native scope.
98 ApiNativeScope::DecrementNativeScopeMemoryCapacity(size);
99 }
100 }
101
102
89 // TODO(bkonyi): We need to account for the initial chunk size when a new zone 103 // TODO(bkonyi): We need to account for the initial chunk size when a new zone
90 // is created within a new thread or ApiNativeScope when calculating high 104 // is created within a new thread or ApiNativeScope when calculating high
91 // watermarks or memory consumption. 105 // watermarks or memory consumption.
92 Zone::Zone() 106 Zone::Zone()
93 : initial_buffer_(buffer_, kInitialChunkSize), 107 : initial_buffer_(buffer_, kInitialChunkSize),
94 position_(initial_buffer_.start()), 108 position_(initial_buffer_.start()),
95 limit_(initial_buffer_.end()), 109 limit_(initial_buffer_.end()),
96 head_(NULL), 110 head_(NULL),
97 large_segments_(NULL), 111 large_segments_(NULL),
98 handles_(), 112 handles_(),
99 previous_(NULL) { 113 previous_(NULL) {
100 ASSERT(Utils::IsAligned(position_, kAlignment)); 114 ASSERT(Utils::IsAligned(position_, kAlignment));
101 Thread* current = Thread::Current(); 115 IncrementMemoryCapacity(kInitialChunkSize);
102 if (current != NULL) {
103 current->IncrementMemoryUsage(kInitialChunkSize);
104 }
105 #ifdef DEBUG 116 #ifdef DEBUG
106 // Zap the entire initial buffer. 117 // Zap the entire initial buffer.
107 memset(initial_buffer_.pointer(), kZapUninitializedByte, 118 memset(initial_buffer_.pointer(), kZapUninitializedByte,
108 initial_buffer_.size()); 119 initial_buffer_.size());
109 #endif 120 #endif
110 } 121 }
111 122
112 123
113 Zone::~Zone() { 124 Zone::~Zone() {
114 if (FLAG_trace_zones) { 125 if (FLAG_trace_zones) {
115 DumpZoneSizes(); 126 DumpZoneSizes();
116 } 127 }
117 Thread* current = Thread::Current();
118 if (current != NULL) {
119 current->DecrementMemoryUsage(kInitialChunkSize);
120 }
121 DeleteAll(); 128 DeleteAll();
129 DecrementMemoryCapacity(kInitialChunkSize);
122 } 130 }
123 131
124 132
125 void Zone::DeleteAll() { 133 void Zone::DeleteAll() {
126 // Traverse the chained list of segments, zapping (in debug mode) 134 // Traverse the chained list of segments, zapping (in debug mode)
127 // and freeing every zone segment. 135 // and freeing every zone segment.
128 if (head_ != NULL) { 136 if (head_ != NULL) {
129 Segment::DeleteSegmentList(head_); 137 Segment::DeleteSegmentList(head_);
130 } 138 }
131 if (large_segments_ != NULL) { 139 if (large_segments_ != NULL) {
132 Segment::DeleteSegmentList(large_segments_); 140 Segment::DeleteSegmentList(large_segments_);
133 } 141 }
134 // Reset zone state. 142 // Reset zone state.
135 #ifdef DEBUG 143 #ifdef DEBUG
136 memset(initial_buffer_.pointer(), kZapDeletedByte, initial_buffer_.size()); 144 memset(initial_buffer_.pointer(), kZapDeletedByte, initial_buffer_.size());
137 #endif 145 #endif
138 position_ = initial_buffer_.start(); 146 position_ = initial_buffer_.start();
139 limit_ = initial_buffer_.end(); 147 limit_ = initial_buffer_.end();
140 head_ = NULL; 148 head_ = NULL;
141 large_segments_ = NULL; 149 large_segments_ = NULL;
142 previous_ = NULL; 150 previous_ = NULL;
143 handles_.Reset(); 151 handles_.Reset();
144 } 152 }
145 153
146 154
147 intptr_t Zone::SizeInBytes() const { 155 uintptr_t Zone::SizeInBytes() const {
148 intptr_t size = 0; 156 uintptr_t size = 0;
149 for (Segment* s = large_segments_; s != NULL; s = s->next()) { 157 for (Segment* s = large_segments_; s != NULL; s = s->next()) {
150 size += s->size(); 158 size += s->size();
151 } 159 }
152 if (head_ == NULL) { 160 if (head_ == NULL) {
153 return size + (position_ - initial_buffer_.start()); 161 return size + (position_ - initial_buffer_.start());
154 } 162 }
155 size += initial_buffer_.size(); 163 size += initial_buffer_.size();
156 for (Segment* s = head_->next(); s != NULL; s = s->next()) { 164 for (Segment* s = head_->next(); s != NULL; s = s->next()) {
157 size += s->size(); 165 size += s->size();
158 } 166 }
159 return size + (position_ - head_->start()); 167 return size + (position_ - head_->start());
160 } 168 }
161 169
162 170
163 intptr_t Zone::CapacityInBytes() const { 171 uintptr_t Zone::CapacityInBytes() const {
164 intptr_t size = 0; 172 uintptr_t size = 0;
165 for (Segment* s = large_segments_; s != NULL; s = s->next()) { 173 for (Segment* s = large_segments_; s != NULL; s = s->next()) {
166 size += s->size(); 174 size += s->size();
167 } 175 }
168 if (head_ == NULL) { 176 if (head_ == NULL) {
169 return size + initial_buffer_.size(); 177 return size + initial_buffer_.size();
170 } 178 }
171 size += initial_buffer_.size(); 179 size += initial_buffer_.size();
172 for (Segment* s = head_; s != NULL; s = s->next()) { 180 for (Segment* s = head_; s != NULL; s = s->next()) {
173 size += s->size(); 181 size += s->size();
174 } 182 }
175 return size; 183 return size;
176 } 184 }
177 185
178 186
187 void Zone::IncrementMemoryCapacity(uintptr_t size) {
188 Thread* current_thread = Thread::Current();
189 if (current_thread != NULL) {
190 current_thread->IncrementMemoryCapacity(size);
191 } else if (ApiNativeScope::Current() != NULL) {
192 // If there is no current thread, we might be inside of a native scope.
193 ApiNativeScope::IncrementNativeScopeMemoryCapacity(size);
194 }
195 }
196
197
198 void Zone::DecrementMemoryCapacity(uintptr_t size) {
199 Thread* current_thread = Thread::Current();
200 if (current_thread != NULL) {
201 current_thread->DecrementMemoryCapacity(size);
202 } else if (ApiNativeScope::Current() != NULL) {
203 // If there is no current thread, we might be inside of a native scope.
204 ApiNativeScope::DecrementNativeScopeMemoryCapacity(size);
205 }
206 }
207
208
179 uword Zone::AllocateExpand(intptr_t size) { 209 uword Zone::AllocateExpand(intptr_t size) {
180 ASSERT(size >= 0); 210 ASSERT(size >= 0);
181 if (FLAG_trace_zones) { 211 if (FLAG_trace_zones) {
182 OS::PrintErr("*** Expanding zone 0x%" Px "\n", 212 OS::PrintErr("*** Expanding zone 0x%" Px "\n",
183 reinterpret_cast<intptr_t>(this)); 213 reinterpret_cast<intptr_t>(this));
184 DumpZoneSizes(); 214 DumpZoneSizes();
185 } 215 }
186 // Make sure the requested size is already properly aligned and that 216 // Make sure the requested size is already properly aligned and that
187 // there isn't enough room in the Zone to satisfy the request. 217 // there isn't enough room in the Zone to satisfy the request.
188 ASSERT(Utils::IsAligned(size, kAlignment)); 218 ASSERT(Utils::IsAligned(size, kAlignment));
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 va_end(args); 323 va_end(args);
294 return buffer; 324 return buffer;
295 } 325 }
296 326
297 327
298 char* Zone::VPrint(const char* format, va_list args) { 328 char* Zone::VPrint(const char* format, va_list args) {
299 return OS::VSCreate(this, format, args); 329 return OS::VSCreate(this, format, args);
300 } 330 }
301 331
302 332
303 #ifndef PRODUCT
304 // TODO(bkonyi): Currently dead code. See issue #28885.
305 void Zone::PrintJSON(JSONStream* stream) const {
306 JSONObject jsobj(stream);
307 intptr_t capacity = CapacityInBytes();
308 intptr_t used_size = SizeInBytes();
309 jsobj.AddProperty("type", "_Zone");
310 jsobj.AddProperty("capacity", capacity);
311 jsobj.AddProperty("used", used_size);
312 }
313 #endif
314
315
316 StackZone::StackZone(Thread* thread) : StackResource(thread), zone_() { 333 StackZone::StackZone(Thread* thread) : StackResource(thread), zone_() {
317 if (FLAG_trace_zones) { 334 if (FLAG_trace_zones) {
318 OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n", 335 OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
319 reinterpret_cast<intptr_t>(this), 336 reinterpret_cast<intptr_t>(this),
320 reinterpret_cast<intptr_t>(&zone_)); 337 reinterpret_cast<intptr_t>(&zone_));
321 } 338 }
322 zone_.Link(thread->zone()); 339 zone_.Link(thread->zone());
323 thread->set_zone(&zone_); 340 thread->set_zone(&zone_);
324 } 341 }
325 342
326 343
327 StackZone::~StackZone() { 344 StackZone::~StackZone() {
328 ASSERT(thread()->zone() == &zone_); 345 ASSERT(thread()->zone() == &zone_);
329 thread()->set_zone(zone_.previous_); 346 thread()->set_zone(zone_.previous_);
330 if (FLAG_trace_zones) { 347 if (FLAG_trace_zones) {
331 OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n", 348 OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
332 reinterpret_cast<intptr_t>(this), 349 reinterpret_cast<intptr_t>(this),
333 reinterpret_cast<intptr_t>(&zone_)); 350 reinterpret_cast<intptr_t>(&zone_));
334 } 351 }
335 } 352 }
336 353
337 } // namespace dart 354 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/zone.h ('k') | runtime/vm/zone_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698