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

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

Issue 70183010: Fixes a couple problems with GC of unoptimized code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/parser.h » ('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/pages.h" 5 #include "vm/pages.h"
6 6
7 #include "platform/assert.h" 7 #include "platform/assert.h"
8 #include "vm/compiler_stats.h" 8 #include "vm/compiler_stats.h"
9 #include "vm/gc_marker.h" 9 #include "vm/gc_marker.h"
10 #include "vm/gc_sweeper.h" 10 #include "vm/gc_sweeper.h"
11 #include "vm/object.h" 11 #include "vm/object.h"
12 #include "vm/virtual_memory.h" 12 #include "vm/virtual_memory.h"
13 13
14 namespace dart { 14 namespace dart {
15 15
16 DEFINE_FLAG(int, heap_growth_space_ratio, 10, 16 DEFINE_FLAG(int, heap_growth_space_ratio, 10,
17 "The desired maximum percentage of free space after GC"); 17 "The desired maximum percentage of free space after GC");
18 DEFINE_FLAG(int, heap_growth_time_ratio, 3, 18 DEFINE_FLAG(int, heap_growth_time_ratio, 3,
19 "The desired maximum percentage of time spent in GC"); 19 "The desired maximum percentage of time spent in GC");
20 DEFINE_FLAG(int, heap_growth_rate, 4, 20 DEFINE_FLAG(int, heap_growth_rate, 4,
21 "The size the heap is grown, in heap pages"); 21 "The size the heap is grown, in heap pages");
22 DEFINE_FLAG(bool, print_free_list_before_gc, false, 22 DEFINE_FLAG(bool, print_free_list_before_gc, false,
23 "Print free list statistics before a GC"); 23 "Print free list statistics before a GC");
24 DEFINE_FLAG(bool, print_free_list_after_gc, false, 24 DEFINE_FLAG(bool, print_free_list_after_gc, false,
25 "Print free list statistics after a GC"); 25 "Print free list statistics after a GC");
26 DEFINE_FLAG(bool, collect_code, false, 26 DEFINE_FLAG(bool, collect_code, true,
27 "Attempt to GC infrequently used code."); 27 "Attempt to GC infrequently used code.");
28 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000, 28 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
29 "Time between attempts to collect unused code."); 29 "Time between attempts to collect unused code.");
30 DEFINE_FLAG(bool, log_code_drop, false, 30 DEFINE_FLAG(bool, log_code_drop, false,
31 "Emit a log message when pointers to unused code are dropped."); 31 "Emit a log message when pointers to unused code are dropped.");
32 DEFINE_FLAG(bool, always_drop_code, false,
33 "Always try to drop code if the function's usage counter is >= 0");
32 34
33 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { 35 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) {
34 ASSERT(memory->size() > VirtualMemory::PageSize()); 36 ASSERT(memory->size() > VirtualMemory::PageSize());
35 bool is_executable = (type == kExecutable); 37 bool is_executable = (type == kExecutable);
36 memory->Commit(is_executable); 38 memory->Commit(is_executable);
37 39
38 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address()); 40 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address());
39 result->memory_ = memory; 41 result->memory_ = memory;
40 result->next_ = NULL; 42 result->next_ = NULL;
41 result->executable_ = is_executable; 43 result->executable_ = is_executable;
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 page = page->next(); 380 page = page->next();
379 } 381 }
380 page = large_pages_; 382 page = large_pages_;
381 while (page != NULL) { 383 while (page != NULL) {
382 page->WriteProtect(read_only); 384 page->WriteProtect(read_only);
383 page = page->next(); 385 page = page->next();
384 } 386 }
385 } 387 }
386 388
387 389
388 class CodeDetacherVisitor : public ObjectVisitor { 390 bool PageSpace::ShouldCollectCode() {
389 public:
390 explicit CodeDetacherVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
391
392 virtual void VisitObject(RawObject* obj);
393
394 private:
395 static bool MayDetachCode(const Function& fn);
396 DISALLOW_COPY_AND_ASSIGN(CodeDetacherVisitor);
397 };
398
399
400 bool CodeDetacherVisitor::MayDetachCode(const Function& fn) {
401 return fn.HasCode() && // Not already detached.
402 !fn.HasOptimizedCode() &&
403 !fn.HasBreakpoint() &&
404 (fn.usage_counter() > 0);
405 }
406
407
408 void CodeDetacherVisitor::VisitObject(RawObject* raw_obj) {
409 Isolate* isolate = Isolate::Current();
410 HANDLESCOPE(isolate);
411 const Object& obj = Object::Handle(raw_obj);
412 if (obj.GetClassId() == kFunctionCid) {
413 const Function& fn = Function::Cast(obj);
414 if (CodeDetacherVisitor::MayDetachCode(fn)) {
415 fn.set_usage_counter(fn.usage_counter() / 2);
416 if (fn.usage_counter() == 0) {
417 if (FLAG_log_code_drop) {
418 const String& name = String::Handle(fn.name());
419 OS::Print("Detaching code for function %s\n", name.ToCString());
420 }
421 fn.DetachCode();
422 }
423 }
424 }
425 }
426
427
428 void PageSpace::TryDetachingCode() {
429 // Try to collect code if enough time has passed since the last attempt. 391 // Try to collect code if enough time has passed since the last attempt.
430 const int64_t start = OS::GetCurrentTimeMicros(); 392 const int64_t start = OS::GetCurrentTimeMicros();
431 const int64_t last_code_collection_in_us = 393 const int64_t last_code_collection_in_us =
432 page_space_controller_.last_code_collection_in_us(); 394 page_space_controller_.last_code_collection_in_us();
395
433 if ((start - last_code_collection_in_us) > 396 if ((start - last_code_collection_in_us) >
434 FLAG_code_collection_interval_in_us) { 397 FLAG_code_collection_interval_in_us) {
435 if (FLAG_log_code_drop) { 398 if (FLAG_log_code_drop) {
436 OS::Print("Trying to detach code.\n"); 399 OS::Print("Trying to detach code.\n");
437 } 400 }
438 Isolate* isolate = Isolate::Current();
439 CodeDetacherVisitor code_detacher(isolate);
440 heap_->IterateObjects(&code_detacher);
441 page_space_controller_.set_last_code_collection_in_us(start); 401 page_space_controller_.set_last_code_collection_in_us(start);
402 return true;
442 } 403 }
404 return false;
443 } 405 }
444 406
445 407
446 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 408 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
447 // MarkSweep is not reentrant. Make sure that is the case. 409 // MarkSweep is not reentrant. Make sure that is the case.
448 ASSERT(!sweeping_); 410 ASSERT(!sweeping_);
449 sweeping_ = true; 411 sweeping_ = true;
450 Isolate* isolate = Isolate::Current(); 412 Isolate* isolate = Isolate::Current();
451 if (FLAG_collect_code) {
452 TryDetachingCode();
453 }
454 413
455 NoHandleScope no_handles(isolate); 414 NoHandleScope no_handles(isolate);
456 415
457 if (FLAG_print_free_list_before_gc) { 416 if (FLAG_print_free_list_before_gc) {
458 OS::Print("Data Freelist (before GC):\n"); 417 OS::Print("Data Freelist (before GC):\n");
459 freelist_[HeapPage::kData].Print(); 418 freelist_[HeapPage::kData].Print();
460 OS::Print("Executable Freelist (before GC):\n"); 419 OS::Print("Executable Freelist (before GC):\n");
461 freelist_[HeapPage::kExecutable].Print(); 420 freelist_[HeapPage::kExecutable].Print();
462 } 421 }
463 422
464 if (FLAG_verify_before_gc) { 423 if (FLAG_verify_before_gc) {
465 OS::PrintErr("Verifying before MarkSweep..."); 424 OS::PrintErr("Verifying before MarkSweep...");
466 heap_->Verify(); 425 heap_->Verify();
467 OS::PrintErr(" done.\n"); 426 OS::PrintErr(" done.\n");
468 } 427 }
469 428
470 const int64_t start = OS::GetCurrentTimeMicros(); 429 const int64_t start = OS::GetCurrentTimeMicros();
471 430
472 // Mark all reachable old-gen objects. 431 // Mark all reachable old-gen objects.
432 bool collect_code = FLAG_collect_code && ShouldCollectCode();
473 GCMarker marker(heap_); 433 GCMarker marker(heap_);
474 marker.MarkObjects(isolate, this, invoke_api_callbacks); 434 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
475 435
476 int64_t mid1 = OS::GetCurrentTimeMicros(); 436 int64_t mid1 = OS::GetCurrentTimeMicros();
477 437
478 // Reset the bump allocation page to unused. 438 // Reset the bump allocation page to unused.
479 // Reset the freelists and setup sweeping. 439 // Reset the freelists and setup sweeping.
480 freelist_[HeapPage::kData].Reset(); 440 freelist_[HeapPage::kData].Reset();
481 freelist_[HeapPage::kExecutable].Reset(); 441 freelist_[HeapPage::kExecutable].Reset();
482 442
483 int64_t mid2 = OS::GetCurrentTimeMicros(); 443 int64_t mid2 = OS::GetCurrentTimeMicros();
484 444
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 return 0; 622 return 0;
663 } else { 623 } else {
664 ASSERT(total_time >= gc_time); 624 ASSERT(total_time >= gc_time);
665 int result= static_cast<int>((static_cast<double>(gc_time) / 625 int result= static_cast<int>((static_cast<double>(gc_time) /
666 static_cast<double>(total_time)) * 100); 626 static_cast<double>(total_time)) * 100);
667 return result; 627 return result;
668 } 628 }
669 } 629 }
670 630
671 } // namespace dart 631 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698