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

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

Issue 27802002: Disconnects code objects from infrequently used unoptimized functions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/stub_code.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, true,
27 "Attempt to GC infrequently used code.");
28 DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
29 "Time between attempts to collect unused code.");
30 DEFINE_FLAG(bool, log_code_drop, false,
31 "Emit a log message when pointers to unused code are dropped.");
26 32
27 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { 33 HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) {
28 ASSERT(memory->size() > VirtualMemory::PageSize()); 34 ASSERT(memory->size() > VirtualMemory::PageSize());
29 bool is_executable = (type == kExecutable); 35 bool is_executable = (type == kExecutable);
30 memory->Commit(is_executable); 36 memory->Commit(is_executable);
31 37
32 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address()); 38 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address());
33 result->memory_ = memory; 39 result->memory_ = memory;
34 result->next_ = NULL; 40 result->next_ = NULL;
35 result->executable_ = is_executable; 41 result->executable_ = is_executable;
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 page = page->next(); 377 page = page->next();
372 } 378 }
373 page = large_pages_; 379 page = large_pages_;
374 while (page != NULL) { 380 while (page != NULL) {
375 page->WriteProtect(read_only); 381 page->WriteProtect(read_only);
376 page = page->next(); 382 page = page->next();
377 } 383 }
378 } 384 }
379 385
380 386
387
388 class CodeDetacherVisitor : public ObjectVisitor {
389 public:
390 explicit CodeDetacherVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
391
392 virtual void VisitObject(RawObject* obj);
393
394 private:
395 DISALLOW_COPY_AND_ASSIGN(CodeDetacherVisitor);
396 };
397
398
399 void CodeDetacherVisitor::VisitObject(RawObject* raw_obj) {
400 Isolate* isolate = Isolate::Current();
401 HANDLESCOPE(isolate);
402 const Object& obj = Object::Handle(raw_obj);
403 if (obj.GetClassId() == kFunctionCid) {
404 const Function& fn = Function::Cast(obj);
405 if (!fn.HasOptimizedCode() &&
406 !fn.HasBreakpoint() &&
407 fn.HasCode() && // Not already detached.
408 (fn.usage_counter() > 0)) {
409 fn.set_usage_counter(fn.usage_counter() / 2);
410 if (fn.usage_counter() == 0) {
411 if (FLAG_log_code_drop) {
412 const String& name = String::Handle(fn.name());
413 OS::Print("Detaching code for function %s\n", name.ToCString());
414 }
415 fn.DetachCode();
416 }
417 }
418 }
419 }
420
421
422 void PageSpace::TryDetachingCode() {
423 // Try to collect code if enough time has passed since the last attempt.
424 const int64_t start = OS::GetCurrentTimeMicros();
425 const int64_t last_code_collection_in_us =
426 page_space_controller_.last_code_collection_in_us();
427 if ((start - last_code_collection_in_us) >
428 FLAG_code_collection_interval_in_us) {
429 if (FLAG_log_code_drop) {
430 OS::Print("Trying to detach code.\n");
431 }
432 Isolate* isolate = Isolate::Current();
433 CodeDetacherVisitor code_detacher(isolate);
434 heap_->IterateObjects(&code_detacher);
435 page_space_controller_.set_last_code_collection_in_us(start);
436 }
437 }
438
439
381 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 440 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
382 // MarkSweep is not reentrant. Make sure that is the case. 441 // MarkSweep is not reentrant. Make sure that is the case.
383 ASSERT(!sweeping_); 442 ASSERT(!sweeping_);
384 sweeping_ = true; 443 sweeping_ = true;
385 Isolate* isolate = Isolate::Current(); 444 Isolate* isolate = Isolate::Current();
445 if (FLAG_collect_code) {
446 TryDetachingCode();
447 }
448
386 NoHandleScope no_handles(isolate); 449 NoHandleScope no_handles(isolate);
387 450
388 if (FLAG_print_free_list_before_gc) { 451 if (FLAG_print_free_list_before_gc) {
389 OS::Print("Data Freelist (before GC):\n"); 452 OS::Print("Data Freelist (before GC):\n");
390 freelist_[HeapPage::kData].Print(); 453 freelist_[HeapPage::kData].Print();
391 OS::Print("Executable Freelist (before GC):\n"); 454 OS::Print("Executable Freelist (before GC):\n");
392 freelist_[HeapPage::kExecutable].Print(); 455 freelist_[HeapPage::kExecutable].Print();
393 } 456 }
394 457
395 if (FLAG_verify_before_gc) { 458 if (FLAG_verify_before_gc) {
396 OS::PrintErr("Verifying before MarkSweep..."); 459 OS::PrintErr("Verifying before MarkSweep...");
397 heap_->Verify(); 460 heap_->Verify();
398 OS::PrintErr(" done.\n"); 461 OS::PrintErr(" done.\n");
399 } 462 }
400 463
401 int64_t start = OS::GetCurrentTimeMicros(); 464 const int64_t start = OS::GetCurrentTimeMicros();
402 465
403 // Mark all reachable old-gen objects. 466 // Mark all reachable old-gen objects.
404 GCMarker marker(heap_); 467 GCMarker marker(heap_);
405 marker.MarkObjects(isolate, this, invoke_api_callbacks); 468 marker.MarkObjects(isolate, this, invoke_api_callbacks);
406 469
407 int64_t mid1 = OS::GetCurrentTimeMicros(); 470 int64_t mid1 = OS::GetCurrentTimeMicros();
408 471
409 // Reset the bump allocation page to unused. 472 // Reset the bump allocation page to unused.
410 // Reset the freelists and setup sweeping. 473 // Reset the freelists and setup sweeping.
411 freelist_[HeapPage::kData].Reset(); 474 freelist_[HeapPage::kData].Reset();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 546
484 547
485 PageSpaceController::PageSpaceController(int heap_growth_ratio, 548 PageSpaceController::PageSpaceController(int heap_growth_ratio,
486 int heap_growth_rate, 549 int heap_growth_rate,
487 int garbage_collection_time_ratio) 550 int garbage_collection_time_ratio)
488 : is_enabled_(false), 551 : is_enabled_(false),
489 grow_heap_(heap_growth_rate), 552 grow_heap_(heap_growth_rate),
490 heap_growth_ratio_(heap_growth_ratio), 553 heap_growth_ratio_(heap_growth_ratio),
491 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), 554 desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
492 heap_growth_rate_(heap_growth_rate), 555 heap_growth_rate_(heap_growth_rate),
493 garbage_collection_time_ratio_(garbage_collection_time_ratio) { 556 garbage_collection_time_ratio_(garbage_collection_time_ratio),
557 last_code_collection_in_us_(OS::GetCurrentTimeMicros()) {
494 } 558 }
495 559
496 560
497 PageSpaceController::~PageSpaceController() {} 561 PageSpaceController::~PageSpaceController() {}
498 562
499 563
500 bool PageSpaceController::CanGrowPageSpace(intptr_t size_in_bytes) { 564 bool PageSpaceController::CanGrowPageSpace(intptr_t size_in_bytes) {
501 size_in_bytes = Utils::RoundUp(size_in_bytes, PageSpace::kPageSize); 565 size_in_bytes = Utils::RoundUp(size_in_bytes, PageSpace::kPageSize);
502 intptr_t size_in_pages = size_in_bytes / PageSpace::kPageSize; 566 intptr_t size_in_pages = size_in_bytes / PageSpace::kPageSize;
503 if (!is_enabled_) { 567 if (!is_enabled_) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 return 0; 650 return 0;
587 } else { 651 } else {
588 ASSERT(total_time >= gc_time); 652 ASSERT(total_time >= gc_time);
589 int result= static_cast<int>((static_cast<double>(gc_time) / 653 int result= static_cast<int>((static_cast<double>(gc_time) /
590 static_cast<double>(total_time)) * 100); 654 static_cast<double>(total_time)) * 100);
591 return result; 655 return result;
592 } 656 }
593 } 657 }
594 658
595 } // namespace dart 659 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/stub_code.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698