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

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

Issue 578443003: Support old-space allocation in generated code (bump block only for now). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 3 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"
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 // TODO(koda): Control growth. 396 // TODO(koda): Control growth.
397 } 397 }
398 398
399 399
400 void PageSpace::FreeExternal(intptr_t size) { 400 void PageSpace::FreeExternal(intptr_t size) {
401 intptr_t size_in_words = size >> kWordSizeLog2; 401 intptr_t size_in_words = size >> kWordSizeLog2;
402 usage_.external_in_words -= size_in_words; 402 usage_.external_in_words -= size_in_words;
403 } 403 }
404 404
405 405
406 // Provides exclusive access to the pages, and ensures they are walkable.
407 class ExclusivePageIterator : ValueObject {
408 public:
409 explicit ExclusivePageIterator(const PageSpace* space)
410 : space_(space), ml_(space->pages_lock_) {
411 space_->MakeIterable();
412 page_ = space_->pages_;
413 if (page_ == NULL) {
414 page_ = space_->exec_pages_;
415 if (page_ == NULL) {
416 page_ = space_->large_pages_;
417 }
418 }
419 }
420 HeapPage* page() const { return page_; }
421 bool done() const { return page_ == NULL; }
422 void Advance() {
423 ASSERT(!done());
424 page_ = space_->NextPageAnySize(page_);
425 }
426 private:
427 const PageSpace* space_;
428 MutexLocker ml_;
429 NoGCScope no_gc;
430 HeapPage* page_;
431 };
432
433
434 void PageSpace::MakeIterable() const {
435 // TODO(koda): Assert not called from concurrent sweeper task.
436 if (bump_top_ < bump_end_) {
437 FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_);
438 }
439 }
440
441
406 bool PageSpace::Contains(uword addr) const { 442 bool PageSpace::Contains(uword addr) const {
407 MutexLocker ml(pages_lock_); 443 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
408 NoGCScope no_gc; 444 if (it.page()->Contains(addr)) {
409 HeapPage* page = pages_;
410 while (page != NULL) {
411 if (page->Contains(addr)) {
412 return true; 445 return true;
413 } 446 }
414 page = NextPageAnySize(page);
415 } 447 }
416 return false; 448 return false;
417 } 449 }
418 450
419 451
420 bool PageSpace::Contains(uword addr, HeapPage::PageType type) const { 452 bool PageSpace::Contains(uword addr, HeapPage::PageType type) const {
421 MutexLocker ml(pages_lock_); 453 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
422 NoGCScope no_gc; 454 if ((it.page()->type() == type) && it.page()->Contains(addr)) {
423 HeapPage* page = pages_;
424 while (page != NULL) {
425 if ((page->type() == type) && page->Contains(addr)) {
426 return true; 455 return true;
427 } 456 }
428 page = NextPageAnySize(page);
429 } 457 }
430 return false; 458 return false;
431 } 459 }
432 460
433 461
434 void PageSpace::StartEndAddress(uword* start, uword* end) const { 462 void PageSpace::StartEndAddress(uword* start, uword* end) const {
435 MutexLocker ml(pages_lock_);
436 NoGCScope no_gc;
437 ASSERT((pages_ != NULL) || (exec_pages_ != NULL) || (large_pages_ != NULL)); 463 ASSERT((pages_ != NULL) || (exec_pages_ != NULL) || (large_pages_ != NULL));
438 *start = static_cast<uword>(~0); 464 *start = static_cast<uword>(~0);
439 *end = 0; 465 *end = 0;
440 for (HeapPage* page = pages_; page != NULL; page = NextPageAnySize(page)) { 466 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
441 *start = Utils::Minimum(*start, page->object_start()); 467 *start = Utils::Minimum(*start, it.page()->object_start());
442 *end = Utils::Maximum(*end, page->object_end()); 468 *end = Utils::Maximum(*end, it.page()->object_end());
443 } 469 }
444 ASSERT(*start != static_cast<uword>(~0)); 470 ASSERT(*start != static_cast<uword>(~0));
445 ASSERT(*end != 0); 471 ASSERT(*end != 0);
446 } 472 }
447 473
448 474
449 void PageSpace::VisitObjects(ObjectVisitor* visitor) const { 475 void PageSpace::VisitObjects(ObjectVisitor* visitor) const {
450 MutexLocker ml(pages_lock_); 476 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
451 NoGCScope no_gc; 477 it.page()->VisitObjects(visitor);
452 HeapPage* page = pages_;
453 while (page != NULL) {
454 page->VisitObjects(visitor);
455 page = NextPageAnySize(page);
456 } 478 }
457 } 479 }
458 480
459 481
460 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 482 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
461 MutexLocker ml(pages_lock_); 483 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
462 NoGCScope no_gc; 484 it.page()->VisitObjectPointers(visitor);
463 HeapPage* page = pages_;
464 while (page != NULL) {
465 page->VisitObjectPointers(visitor);
466 page = NextPageAnySize(page);
467 } 485 }
468 } 486 }
469 487
470 488
471 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor, 489 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor,
472 HeapPage::PageType type) const { 490 HeapPage::PageType type) const {
473 ASSERT(Isolate::Current()->no_gc_scope_depth() != 0); 491 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
474 MutexLocker ml(pages_lock_); 492 if (it.page()->type() == type) {
475 NoGCScope no_gc; 493 RawObject* obj = it.page()->FindObject(visitor);
476 HeapPage* page = pages_;
477 while (page != NULL) {
478 if (page->type() == type) {
479 RawObject* obj = page->FindObject(visitor);
480 if (obj != Object::null()) { 494 if (obj != Object::null()) {
481 return obj; 495 return obj;
482 } 496 }
483 } 497 }
484 page = NextPageAnySize(page);
485 } 498 }
486 return Object::null(); 499 return Object::null();
487 } 500 }
488 501
489 502
490 void PageSpace::WriteProtect(bool read_only) { 503 void PageSpace::WriteProtect(bool read_only) {
491 MutexLocker ml(pages_lock_); 504 for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
492 NoGCScope no_gc; 505 it.page()->WriteProtect(read_only);
493 HeapPage* page = pages_;
494 while (page != NULL) {
495 page->WriteProtect(read_only);
496 page = NextPageAnySize(page);
497 } 506 }
498 } 507 }
499 508
500 509
501 void PageSpace::PrintToJSONObject(JSONObject* object) { 510 void PageSpace::PrintToJSONObject(JSONObject* object) {
502 Isolate* isolate = Isolate::Current(); 511 Isolate* isolate = Isolate::Current();
503 ASSERT(isolate != NULL); 512 ASSERT(isolate != NULL);
504 JSONObject space(object, "old"); 513 JSONObject space(object, "old");
505 space.AddProperty("type", "HeapSpace"); 514 space.AddProperty("type", "HeapSpace");
506 space.AddProperty("id", "heaps/old"); 515 space.AddProperty("id", "heaps/old");
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 heap_map.AddProperty("unit_size_bytes", 556 heap_map.AddProperty("unit_size_bytes",
548 static_cast<intptr_t>(kObjectAlignment)); 557 static_cast<intptr_t>(kObjectAlignment));
549 heap_map.AddProperty("page_size_bytes", kPageSizeInWords * kWordSize); 558 heap_map.AddProperty("page_size_bytes", kPageSizeInWords * kWordSize);
550 { 559 {
551 JSONObject class_list(&heap_map, "class_list"); 560 JSONObject class_list(&heap_map, "class_list");
552 isolate->class_table()->PrintToJSONObject(&class_list); 561 isolate->class_table()->PrintToJSONObject(&class_list);
553 } 562 }
554 { 563 {
555 // "pages" is an array [page0, page1, ..., pageN], each page of the form 564 // "pages" is an array [page0, page1, ..., pageN], each page of the form
556 // {"object_start": "0x...", "objects": [size, class id, size, ...]} 565 // {"object_start": "0x...", "objects": [size, class id, size, ...]}
566 // TODO(19445): Use ExclusivePageIterator once HeapMap supports large pages.
557 MutexLocker ml(pages_lock_); 567 MutexLocker ml(pages_lock_);
568 MakeIterable();
558 NoGCScope no_gc; 569 NoGCScope no_gc;
559 JSONArray all_pages(&heap_map, "pages"); 570 JSONArray all_pages(&heap_map, "pages");
560 for (HeapPage* page = pages_; page != NULL; page = page->next()) { 571 for (HeapPage* page = pages_; page != NULL; page = page->next()) {
561 JSONObject page_container(&all_pages); 572 JSONObject page_container(&all_pages);
562 page_container.AddPropertyF("object_start", 573 page_container.AddPropertyF("object_start",
563 "0x%" Px "", page->object_start()); 574 "0x%" Px "", page->object_start());
564 JSONArray page_map(&page_container, "objects"); 575 JSONArray page_map(&page_container, "objects");
565 HeapMapAsJSONVisitor printer(&page_map); 576 HeapMapAsJSONVisitor printer(&page_map);
566 page->VisitObjects(&printer); 577 page->VisitObjects(&printer);
567 } 578 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 666
656 // Mark all reachable old-gen objects. 667 // Mark all reachable old-gen objects.
657 bool collect_code = FLAG_collect_code && ShouldCollectCode(); 668 bool collect_code = FLAG_collect_code && ShouldCollectCode();
658 GCMarker marker(heap_); 669 GCMarker marker(heap_);
659 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code); 670 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
660 usage_.used_in_words = marker.marked_words(); 671 usage_.used_in_words = marker.marked_words();
661 672
662 int64_t mid1 = OS::GetCurrentTimeMicros(); 673 int64_t mid1 = OS::GetCurrentTimeMicros();
663 674
664 // Abandon the remainder of the bump allocation block. 675 // Abandon the remainder of the bump allocation block.
676 MakeIterable();
665 bump_top_ = 0; 677 bump_top_ = 0;
666 bump_end_ = 0; 678 bump_end_ = 0;
667 // Reset the freelists and setup sweeping. 679 // Reset the freelists and setup sweeping.
668 freelist_[HeapPage::kData].Reset(); 680 freelist_[HeapPage::kData].Reset();
669 freelist_[HeapPage::kExecutable].Reset(); 681 freelist_[HeapPage::kExecutable].Reset();
670 682
671 int64_t mid2 = OS::GetCurrentTimeMicros(); 683 int64_t mid2 = OS::GetCurrentTimeMicros();
672 int64_t mid3 = 0; 684 int64_t mid3 = 0;
673 685
674 { 686 {
675 GCSweeper sweeper(heap_); 687 GCSweeper sweeper;
676 688
677 // During stop-the-world phases we should use bulk lock when adding elements 689 // During stop-the-world phases we should use bulk lock when adding elements
678 // to the free list. 690 // to the free list.
679 MutexLocker mld(freelist_[HeapPage::kData].mutex()); 691 MutexLocker mld(freelist_[HeapPage::kData].mutex());
680 MutexLocker mle(freelist_[HeapPage::kExecutable].mutex()); 692 MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
681 693
682 // Large and executable pages are always swept immediately. 694 // Large and executable pages are always swept immediately.
683 HeapPage* prev_page = NULL; 695 HeapPage* prev_page = NULL;
684 HeapPage* page = large_pages_; 696 HeapPage* page = large_pages_;
685 while (page != NULL) { 697 while (page != NULL) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 } 817 }
806 } 818 }
807 bump_top_ = reinterpret_cast<uword>(block); 819 bump_top_ = reinterpret_cast<uword>(block);
808 bump_end_ = bump_top_ + block_size; 820 bump_end_ = bump_top_ + block_size;
809 remaining = block_size; 821 remaining = block_size;
810 } 822 }
811 ASSERT(remaining >= size); 823 ASSERT(remaining >= size);
812 uword result = bump_top_; 824 uword result = bump_top_;
813 bump_top_ += size; 825 bump_top_ += size;
814 usage_.used_in_words += size >> kWordSizeLog2; 826 usage_.used_in_words += size >> kWordSizeLog2;
815 remaining -= size; 827 // Note: Remaining block is unwalkable until MakeIterable is called.
816 if (remaining > 0) { 828 #ifdef DEBUG
817 FreeListElement::AsElement(bump_top_, remaining); 829 if (bump_top_ < bump_end_) {
830 // Fail fast if we try to walk the remaining block.
831 COMPILE_ASSERT(kIllegalCid == 0);
832 *reinterpret_cast<uword*>(bump_top_) = 0;
818 } 833 }
834 #endif // DEBUG
819 return result; 835 return result;
820 } 836 }
821 837
822 838
823 uword PageSpace::TryAllocateDataBump(intptr_t size, 839 uword PageSpace::TryAllocateDataBump(intptr_t size,
824 GrowthPolicy growth_policy) { 840 GrowthPolicy growth_policy) {
825 return TryAllocateDataBumpInternal(size, growth_policy, false); 841 return TryAllocateDataBumpInternal(size, growth_policy, false);
826 } 842 }
827 843
828 844
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 return 0; 987 return 0;
972 } else { 988 } else {
973 ASSERT(total_time >= gc_time); 989 ASSERT(total_time >= gc_time);
974 int result= static_cast<int>((static_cast<double>(gc_time) / 990 int result= static_cast<int>((static_cast<double>(gc_time) /
975 static_cast<double>(total_time)) * 100); 991 static_cast<double>(total_time)) * 100);
976 return result; 992 return result;
977 } 993 }
978 } 994 }
979 995
980 } // namespace dart 996 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698