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

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
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"
(...skipping 11 matching lines...) Expand all
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, false,
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 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 page = page->next(); 379 page = page->next();
378 } 380 }
379 page = large_pages_; 381 page = large_pages_;
380 while (page != NULL) { 382 while (page != NULL) {
381 page->WriteProtect(read_only); 383 page->WriteProtect(read_only);
382 page = page->next(); 384 page = page->next();
383 } 385 }
384 } 386 }
385 387
386 388
387 class CodeDetacherVisitor : public ObjectVisitor { 389 bool PageSpace::ShouldTryCollectingCode() {
388 public:
389 explicit CodeDetacherVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
390
391 virtual void VisitObject(RawObject* obj);
392
393 private:
394 static bool MayDetachCode(const Function& fn);
395 DISALLOW_COPY_AND_ASSIGN(CodeDetacherVisitor);
396 };
397
398
399 bool CodeDetacherVisitor::MayDetachCode(const Function& fn) {
400 return fn.HasCode() && // Not already detached.
401 !fn.HasOptimizedCode() &&
402 !fn.HasBreakpoint() &&
403 (fn.usage_counter() > 0);
404 }
405
406
407 void CodeDetacherVisitor::VisitObject(RawObject* raw_obj) {
408 Isolate* isolate = Isolate::Current();
409 HANDLESCOPE(isolate);
410 const Object& obj = Object::Handle(raw_obj);
411 if (obj.GetClassId() == kFunctionCid) {
412 const Function& fn = Function::Cast(obj);
413 if (CodeDetacherVisitor::MayDetachCode(fn)) {
414 fn.set_usage_counter(fn.usage_counter() / 2);
415 if (fn.usage_counter() == 0) {
416 if (FLAG_log_code_drop) {
417 const String& name = String::Handle(fn.name());
418 OS::Print("Detaching code for function %s\n", name.ToCString());
419 }
420 fn.DetachCode();
421 }
422 }
423 }
424 }
425
426
427 void PageSpace::TryDetachingCode() {
428 // Try to collect code if enough time has passed since the last attempt. 390 // Try to collect code if enough time has passed since the last attempt.
429 const int64_t start = OS::GetCurrentTimeMicros(); 391 const int64_t start = OS::GetCurrentTimeMicros();
430 const int64_t last_code_collection_in_us = 392 const int64_t last_code_collection_in_us =
431 page_space_controller_.last_code_collection_in_us(); 393 page_space_controller_.last_code_collection_in_us();
394
432 if ((start - last_code_collection_in_us) > 395 if ((start - last_code_collection_in_us) >
433 FLAG_code_collection_interval_in_us) { 396 FLAG_code_collection_interval_in_us) {
434 if (FLAG_log_code_drop) { 397 if (FLAG_log_code_drop) {
435 OS::Print("Trying to detach code.\n"); 398 OS::Print("Trying to detach code.\n");
436 } 399 }
437 Isolate* isolate = Isolate::Current();
438 CodeDetacherVisitor code_detacher(isolate);
439 heap_->IterateObjects(&code_detacher);
440 page_space_controller_.set_last_code_collection_in_us(start); 400 page_space_controller_.set_last_code_collection_in_us(start);
401 return true;
441 } 402 }
403 return false;
442 } 404 }
443 405
444 406
445 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 407 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
446 // MarkSweep is not reentrant. Make sure that is the case. 408 // MarkSweep is not reentrant. Make sure that is the case.
447 ASSERT(!sweeping_); 409 ASSERT(!sweeping_);
448 sweeping_ = true; 410 sweeping_ = true;
449 Isolate* isolate = Isolate::Current(); 411 Isolate* isolate = Isolate::Current();
450 if (FLAG_collect_code) {
451 TryDetachingCode();
452 }
453 412
454 NoHandleScope no_handles(isolate); 413 NoHandleScope no_handles(isolate);
455 414
456 if (FLAG_print_free_list_before_gc) { 415 if (FLAG_print_free_list_before_gc) {
457 OS::Print("Data Freelist (before GC):\n"); 416 OS::Print("Data Freelist (before GC):\n");
458 freelist_[HeapPage::kData].Print(); 417 freelist_[HeapPage::kData].Print();
459 OS::Print("Executable Freelist (before GC):\n"); 418 OS::Print("Executable Freelist (before GC):\n");
460 freelist_[HeapPage::kExecutable].Print(); 419 freelist_[HeapPage::kExecutable].Print();
461 } 420 }
462 421
463 if (FLAG_verify_before_gc) { 422 if (FLAG_verify_before_gc) {
464 OS::PrintErr("Verifying before MarkSweep..."); 423 OS::PrintErr("Verifying before MarkSweep...");
465 heap_->Verify(); 424 heap_->Verify();
466 OS::PrintErr(" done.\n"); 425 OS::PrintErr(" done.\n");
467 } 426 }
468 427
469 const int64_t start = OS::GetCurrentTimeMicros(); 428 const int64_t start = OS::GetCurrentTimeMicros();
470 429
471 // Mark all reachable old-gen objects. 430 // Mark all reachable old-gen objects.
431 bool try_collecting_code = FLAG_collect_code && ShouldTryCollectingCode();
Ivan Posva 2013/11/19 19:24:48 collect_code and ShouldCollectCode() please.
zra 2013/11/22 17:18:54 Done.
472 GCMarker marker(heap_); 432 GCMarker marker(heap_);
473 marker.MarkObjects(isolate, this, invoke_api_callbacks); 433 marker.MarkObjects(isolate, this, invoke_api_callbacks, try_collecting_code);
474 434
475 int64_t mid1 = OS::GetCurrentTimeMicros(); 435 int64_t mid1 = OS::GetCurrentTimeMicros();
476 436
477 // Reset the bump allocation page to unused. 437 // Reset the bump allocation page to unused.
478 // Reset the freelists and setup sweeping. 438 // Reset the freelists and setup sweeping.
479 freelist_[HeapPage::kData].Reset(); 439 freelist_[HeapPage::kData].Reset();
480 freelist_[HeapPage::kExecutable].Reset(); 440 freelist_[HeapPage::kExecutable].Reset();
481 441
482 int64_t mid2 = OS::GetCurrentTimeMicros(); 442 int64_t mid2 = OS::GetCurrentTimeMicros();
483 443
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 return 0; 615 return 0;
656 } else { 616 } else {
657 ASSERT(total_time >= gc_time); 617 ASSERT(total_time >= gc_time);
658 int result= static_cast<int>((static_cast<double>(gc_time) / 618 int result= static_cast<int>((static_cast<double>(gc_time) /
659 static_cast<double>(total_time)) * 100); 619 static_cast<double>(total_time)) * 100);
660 return result; 620 return result;
661 } 621 }
662 } 622 }
663 623
664 } // namespace dart 624 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698