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

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

Issue 1541073002: Implement safepointing of threads (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix-typo Created 4 years, 10 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/heap.h ('k') | runtime/vm/heap_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/heap.h" 5 #include "vm/heap.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"
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 return addr; 92 return addr;
93 } 93 }
94 94
95 95
96 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) { 96 uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) {
97 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0); 97 ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
98 uword addr = old_space_.TryAllocate(size, type); 98 uword addr = old_space_.TryAllocate(size, type);
99 if (addr != 0) { 99 if (addr != 0) {
100 return addr; 100 return addr;
101 } 101 }
102 // If we are in the process of running a sweep wait for the sweeper to free 102 // If we are in the process of running a sweep, wait for the sweeper to free
103 // memory. 103 // memory.
104 Thread* thread = Thread::Current();
104 { 105 {
105 MonitorLocker ml(old_space_.tasks_lock()); 106 MonitorLocker ml(old_space_.tasks_lock());
106 addr = old_space_.TryAllocate(size, type); 107 addr = old_space_.TryAllocate(size, type);
107 while ((addr == 0) && (old_space_.tasks() > 0)) { 108 while ((addr == 0) && (old_space_.tasks() > 0)) {
108 ml.Wait(); 109 ml.WaitWithSafepointCheck(thread);
109 addr = old_space_.TryAllocate(size, type); 110 addr = old_space_.TryAllocate(size, type);
110 } 111 }
111 } 112 }
112 if (addr != 0) { 113 if (addr != 0) {
113 return addr; 114 return addr;
114 } 115 }
115 Thread* thread = Thread::Current();
116 if (thread->CanCollectGarbage()) { 116 if (thread->CanCollectGarbage()) {
117 // All GC tasks finished without allocating successfully. Run a full GC. 117 // All GC tasks finished without allocating successfully. Run a full GC.
118 CollectAllGarbage(); 118 CollectAllGarbage();
119 addr = old_space_.TryAllocate(size, type); 119 addr = old_space_.TryAllocate(size, type);
120 if (addr != 0) { 120 if (addr != 0) {
121 return addr; 121 return addr;
122 } 122 }
123 // Wait for all of the concurrent tasks to finish before giving up. 123 // Wait for all of the concurrent tasks to finish before giving up.
124 { 124 {
125 MonitorLocker ml(old_space_.tasks_lock()); 125 MonitorLocker ml(old_space_.tasks_lock());
126 addr = old_space_.TryAllocate(size, type); 126 addr = old_space_.TryAllocate(size, type);
127 while ((addr == 0) && (old_space_.tasks() > 0)) { 127 while ((addr == 0) && (old_space_.tasks() > 0)) {
128 ml.Wait(); 128 ml.WaitWithSafepointCheck(thread);
129 addr = old_space_.TryAllocate(size, type); 129 addr = old_space_.TryAllocate(size, type);
130 } 130 }
131 } 131 }
132 if (addr != 0) { 132 if (addr != 0) {
133 return addr; 133 return addr;
134 } 134 }
135 // Force growth before attempting another synchronous GC. 135 // Force growth before attempting another synchronous GC.
136 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); 136 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth);
137 if (addr != 0) { 137 if (addr != 0) {
138 return addr; 138 return addr;
139 } 139 }
140 // Before throwing an out-of-memory error try a synchronous GC. 140 // Before throwing an out-of-memory error try a synchronous GC.
141 CollectAllGarbage(); 141 CollectAllGarbage();
142 { 142 {
143 MonitorLocker ml(old_space_.tasks_lock()); 143 MonitorLocker ml(old_space_.tasks_lock());
144 while (old_space_.tasks() > 0) { 144 while (old_space_.tasks() > 0) {
145 ml.Wait(); 145 ml.WaitWithSafepointCheck(thread);
146 } 146 }
147 } 147 }
148 } 148 }
149 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth); 149 addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth);
150 if (addr != 0) { 150 if (addr != 0) {
151 return addr; 151 return addr;
152 } 152 }
153 // Give up allocating this object. 153 // Give up allocating this object.
154 OS::PrintErr( 154 OS::PrintErr(
155 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size); 155 "Exhausted heap space, trying to allocate %" Pd " bytes.\n", size);
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 } 307 }
308 raw_obj = FindOldObject(visitor); 308 raw_obj = FindOldObject(visitor);
309 if (raw_obj != Object::null()) { 309 if (raw_obj != Object::null()) {
310 return raw_obj; 310 return raw_obj;
311 } 311 }
312 raw_obj = FindObjectInCodeSpace(visitor); 312 raw_obj = FindObjectInCodeSpace(visitor);
313 return raw_obj; 313 return raw_obj;
314 } 314 }
315 315
316 316
317 bool Heap::BeginNewSpaceGC() { 317 bool Heap::BeginNewSpaceGC(Thread* thread) {
318 MonitorLocker ml(&gc_in_progress_monitor_); 318 MonitorLocker ml(&gc_in_progress_monitor_);
319 bool start_gc_on_thread = true; 319 bool start_gc_on_thread = true;
320 while (gc_new_space_in_progress_ || 320 while (gc_new_space_in_progress_ ||
321 gc_old_space_in_progress_) { 321 gc_old_space_in_progress_) {
322 start_gc_on_thread = !gc_new_space_in_progress_; 322 start_gc_on_thread = !gc_new_space_in_progress_;
323 ml.Wait(); 323 ml.WaitWithSafepointCheck(thread);
324 } 324 }
325 if (start_gc_on_thread) { 325 if (start_gc_on_thread) {
326 gc_new_space_in_progress_ = true; 326 gc_new_space_in_progress_ = true;
327 return true; 327 return true;
328 } 328 }
329 return false; 329 return false;
330 } 330 }
331 331
332 332
333 void Heap::EndNewSpaceGC() { 333 void Heap::EndNewSpaceGC() {
334 MonitorLocker ml(&gc_in_progress_monitor_); 334 MonitorLocker ml(&gc_in_progress_monitor_);
335 ASSERT(gc_new_space_in_progress_); 335 ASSERT(gc_new_space_in_progress_);
336 gc_new_space_in_progress_ = false; 336 gc_new_space_in_progress_ = false;
337 ml.NotifyAll(); 337 ml.NotifyAll();
338 } 338 }
339 339
340 340
341 bool Heap::BeginOldSpaceGC() { 341 bool Heap::BeginOldSpaceGC(Thread* thread) {
342 MonitorLocker ml(&gc_in_progress_monitor_); 342 MonitorLocker ml(&gc_in_progress_monitor_);
343 bool start_gc_on_thread = true; 343 bool start_gc_on_thread = true;
344 while (gc_new_space_in_progress_ || 344 while (gc_new_space_in_progress_ ||
345 gc_old_space_in_progress_) { 345 gc_old_space_in_progress_) {
346 start_gc_on_thread = !gc_old_space_in_progress_; 346 start_gc_on_thread = !gc_old_space_in_progress_;
347 ml.Wait(); 347 ml.WaitWithSafepointCheck(thread);
348 } 348 }
349 if (start_gc_on_thread) { 349 if (start_gc_on_thread) {
350 gc_old_space_in_progress_ = true; 350 gc_old_space_in_progress_ = true;
351 return true; 351 return true;
352 } 352 }
353 return false; 353 return false;
354 } 354 }
355 355
356 356
357 void Heap::EndOldSpaceGC() { 357 void Heap::EndOldSpaceGC() {
(...skipping 10 matching lines...) Expand all
368 class_table->ResetCountersNew(); 368 class_table->ResetCountersNew();
369 } else { 369 } else {
370 class_table->ResetCountersOld(); 370 class_table->ResetCountersOld();
371 } 371 }
372 } 372 }
373 373
374 374
375 void Heap::CollectNewSpaceGarbage(Thread* thread, 375 void Heap::CollectNewSpaceGarbage(Thread* thread,
376 ApiCallbacks api_callbacks, 376 ApiCallbacks api_callbacks,
377 GCReason reason) { 377 GCReason reason) {
378 if (BeginNewSpaceGC()) { 378 if (BeginNewSpaceGC(thread)) {
379 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); 379 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
380 RecordBeforeGC(kNew, reason); 380 RecordBeforeGC(kNew, reason);
381 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId); 381 VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId);
382 TimelineDurationScope tds(thread, 382 TimelineDurationScope tds(thread,
383 isolate()->GetGCStream(), 383 isolate()->GetGCStream(),
384 "CollectNewGeneration"); 384 "CollectNewGeneration");
385 UpdateClassHeapStatsBeforeGC(kNew); 385 UpdateClassHeapStatsBeforeGC(kNew);
386 new_space_.Scavenge(invoke_api_callbacks); 386 new_space_.Scavenge(invoke_api_callbacks);
387 isolate()->class_table()->UpdatePromoted(); 387 isolate()->class_table()->UpdatePromoted();
388 UpdatePretenurePolicy(); 388 UpdatePretenurePolicy();
389 RecordAfterGC(kNew); 389 RecordAfterGC(kNew);
390 PrintStats(); 390 PrintStats();
391 EndNewSpaceGC(); 391 EndNewSpaceGC();
392 if (old_space_.NeedsGarbageCollection()) { 392 if (old_space_.NeedsGarbageCollection()) {
393 // Old collections should call the API callbacks. 393 // Old collections should call the API callbacks.
394 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kPromotion); 394 CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kPromotion);
395 } 395 }
396 } 396 }
397 } 397 }
398 398
399 399
400 void Heap::CollectOldSpaceGarbage(Thread* thread, 400 void Heap::CollectOldSpaceGarbage(Thread* thread,
401 ApiCallbacks api_callbacks, 401 ApiCallbacks api_callbacks,
402 GCReason reason) { 402 GCReason reason) {
403 if (BeginOldSpaceGC()) { 403 if (BeginOldSpaceGC(thread)) {
404 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks); 404 bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
405 RecordBeforeGC(kOld, reason); 405 RecordBeforeGC(kOld, reason);
406 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId); 406 VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId);
407 TimelineDurationScope tds(thread, 407 TimelineDurationScope tds(thread,
408 isolate()->GetGCStream(), 408 isolate()->GetGCStream(),
409 "CollectOldGeneration"); 409 "CollectOldGeneration");
410 UpdateClassHeapStatsBeforeGC(kOld); 410 UpdateClassHeapStatsBeforeGC(kOld);
411 old_space_.MarkSweep(invoke_api_callbacks); 411 old_space_.MarkSweep(invoke_api_callbacks);
412 RecordAfterGC(kOld); 412 RecordAfterGC(kOld);
413 PrintStats(); 413 PrintStats();
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 Dart::vm_isolate()->heap()->WriteProtect(false, include_code_pages_); 844 Dart::vm_isolate()->heap()->WriteProtect(false, include_code_pages_);
845 } 845 }
846 846
847 847
848 WritableVMIsolateScope::~WritableVMIsolateScope() { 848 WritableVMIsolateScope::~WritableVMIsolateScope() {
849 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0); 849 ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0);
850 Dart::vm_isolate()->heap()->WriteProtect(true, include_code_pages_); 850 Dart::vm_isolate()->heap()->WriteProtect(true, include_code_pages_);
851 } 851 }
852 852
853 } // namespace dart 853 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/heap.h ('k') | runtime/vm/heap_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698