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

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
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, 500000,
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.CurrentCode() != Code::null()) && // Not already detached.
srdjan 2013/10/23 15:58:13 fn.HasCode()
zra 2013/10/23 17:39:37 Done.
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 =
426 page_space_controller_.last_code_collection();
427 if ((start - last_code_collection) > FLAG_code_collection_interval) {
428 if (FLAG_log_code_drop) {
429 OS::Print("Trying to detach code.\n");
430 }
431 Isolate* isolate = Isolate::Current();
432 CodeDetacherVisitor code_detacher(isolate);
433 heap_->IterateObjects(&code_detacher);
434 page_space_controller_.set_last_code_collection(start);
435 }
436 }
437
438
381 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 439 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
382 // MarkSweep is not reentrant. Make sure that is the case. 440 // MarkSweep is not reentrant. Make sure that is the case.
383 ASSERT(!sweeping_); 441 ASSERT(!sweeping_);
384 sweeping_ = true; 442 sweeping_ = true;
385 Isolate* isolate = Isolate::Current(); 443 Isolate* isolate = Isolate::Current();
444 if (FLAG_collect_code) {
445 TryDetachingCode();
446 }
447
386 NoHandleScope no_handles(isolate); 448 NoHandleScope no_handles(isolate);
387 449
388 if (FLAG_print_free_list_before_gc) { 450 if (FLAG_print_free_list_before_gc) {
389 OS::Print("Data Freelist (before GC):\n"); 451 OS::Print("Data Freelist (before GC):\n");
390 freelist_[HeapPage::kData].Print(); 452 freelist_[HeapPage::kData].Print();
391 OS::Print("Executable Freelist (before GC):\n"); 453 OS::Print("Executable Freelist (before GC):\n");
392 freelist_[HeapPage::kExecutable].Print(); 454 freelist_[HeapPage::kExecutable].Print();
393 } 455 }
394 456
395 if (FLAG_verify_before_gc) { 457 if (FLAG_verify_before_gc) {
396 OS::PrintErr("Verifying before MarkSweep..."); 458 OS::PrintErr("Verifying before MarkSweep...");
397 heap_->Verify(); 459 heap_->Verify();
398 OS::PrintErr(" done.\n"); 460 OS::PrintErr(" done.\n");
399 } 461 }
400 462
401 int64_t start = OS::GetCurrentTimeMicros(); 463 const int64_t start = OS::GetCurrentTimeMicros();
402 464
403 // Mark all reachable old-gen objects. 465 // Mark all reachable old-gen objects.
404 GCMarker marker(heap_); 466 GCMarker marker(heap_);
405 marker.MarkObjects(isolate, this, invoke_api_callbacks); 467 marker.MarkObjects(isolate, this, invoke_api_callbacks);
406 468
407 int64_t mid1 = OS::GetCurrentTimeMicros(); 469 int64_t mid1 = OS::GetCurrentTimeMicros();
408 470
409 // Reset the bump allocation page to unused. 471 // Reset the bump allocation page to unused.
410 // Reset the freelists and setup sweeping. 472 // Reset the freelists and setup sweeping.
411 freelist_[HeapPage::kData].Reset(); 473 freelist_[HeapPage::kData].Reset();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 545
484 546
485 PageSpaceController::PageSpaceController(int heap_growth_ratio, 547 PageSpaceController::PageSpaceController(int heap_growth_ratio,
486 int heap_growth_rate, 548 int heap_growth_rate,
487 int garbage_collection_time_ratio) 549 int garbage_collection_time_ratio)
488 : is_enabled_(false), 550 : is_enabled_(false),
489 grow_heap_(heap_growth_rate), 551 grow_heap_(heap_growth_rate),
490 heap_growth_ratio_(heap_growth_ratio), 552 heap_growth_ratio_(heap_growth_ratio),
491 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), 553 desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
492 heap_growth_rate_(heap_growth_rate), 554 heap_growth_rate_(heap_growth_rate),
493 garbage_collection_time_ratio_(garbage_collection_time_ratio) { 555 garbage_collection_time_ratio_(garbage_collection_time_ratio),
556 last_code_collection_(OS::GetCurrentTimeMicros()) {
494 } 557 }
495 558
496 559
497 PageSpaceController::~PageSpaceController() {} 560 PageSpaceController::~PageSpaceController() {}
498 561
499 562
500 bool PageSpaceController::CanGrowPageSpace(intptr_t size_in_bytes) { 563 bool PageSpaceController::CanGrowPageSpace(intptr_t size_in_bytes) {
501 size_in_bytes = Utils::RoundUp(size_in_bytes, PageSpace::kPageSize); 564 size_in_bytes = Utils::RoundUp(size_in_bytes, PageSpace::kPageSize);
502 intptr_t size_in_pages = size_in_bytes / PageSpace::kPageSize; 565 intptr_t size_in_pages = size_in_bytes / PageSpace::kPageSize;
503 if (!is_enabled_) { 566 if (!is_enabled_) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 return 0; 649 return 0;
587 } else { 650 } else {
588 ASSERT(total_time >= gc_time); 651 ASSERT(total_time >= gc_time);
589 int result= static_cast<int>((static_cast<double>(gc_time) / 652 int result= static_cast<int>((static_cast<double>(gc_time) /
590 static_cast<double>(total_time)) * 100); 653 static_cast<double>(total_time)) * 100);
591 return result; 654 return result;
592 } 655 }
593 } 656 }
594 657
595 } // namespace dart 658 } // namespace dart
OLDNEW
« runtime/vm/object.cc ('K') | « runtime/vm/pages.h ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698