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