| Index: runtime/vm/pages.cc
|
| ===================================================================
|
| --- runtime/vm/pages.cc (revision 40250)
|
| +++ runtime/vm/pages.cc (working copy)
|
| @@ -403,43 +403,69 @@
|
| }
|
|
|
|
|
| +// Provides exclusive access to the pages, and ensures they are walkable.
|
| +class ExclusivePageIterator : ValueObject {
|
| + public:
|
| + explicit ExclusivePageIterator(const PageSpace* space)
|
| + : space_(space), ml_(space->pages_lock_) {
|
| + space_->MakeIterable();
|
| + page_ = space_->pages_;
|
| + if (page_ == NULL) {
|
| + page_ = space_->exec_pages_;
|
| + if (page_ == NULL) {
|
| + page_ = space_->large_pages_;
|
| + }
|
| + }
|
| + }
|
| + HeapPage* page() const { return page_; }
|
| + bool done() const { return page_ == NULL; }
|
| + void Advance() {
|
| + ASSERT(!done());
|
| + page_ = space_->NextPageAnySize(page_);
|
| + }
|
| + private:
|
| + const PageSpace* space_;
|
| + MutexLocker ml_;
|
| + NoGCScope no_gc;
|
| + HeapPage* page_;
|
| +};
|
| +
|
| +
|
| +void PageSpace::MakeIterable() const {
|
| + // TODO(koda): Assert not called from concurrent sweeper task.
|
| + if (bump_top_ < bump_end_) {
|
| + FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_);
|
| + }
|
| +}
|
| +
|
| +
|
| bool PageSpace::Contains(uword addr) const {
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| - HeapPage* page = pages_;
|
| - while (page != NULL) {
|
| - if (page->Contains(addr)) {
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + if (it.page()->Contains(addr)) {
|
| return true;
|
| }
|
| - page = NextPageAnySize(page);
|
| }
|
| return false;
|
| }
|
|
|
|
|
| bool PageSpace::Contains(uword addr, HeapPage::PageType type) const {
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| - HeapPage* page = pages_;
|
| - while (page != NULL) {
|
| - if ((page->type() == type) && page->Contains(addr)) {
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + if ((it.page()->type() == type) && it.page()->Contains(addr)) {
|
| return true;
|
| }
|
| - page = NextPageAnySize(page);
|
| }
|
| return false;
|
| }
|
|
|
|
|
| void PageSpace::StartEndAddress(uword* start, uword* end) const {
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| ASSERT((pages_ != NULL) || (exec_pages_ != NULL) || (large_pages_ != NULL));
|
| *start = static_cast<uword>(~0);
|
| *end = 0;
|
| - for (HeapPage* page = pages_; page != NULL; page = NextPageAnySize(page)) {
|
| - *start = Utils::Minimum(*start, page->object_start());
|
| - *end = Utils::Maximum(*end, page->object_end());
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + *start = Utils::Minimum(*start, it.page()->object_start());
|
| + *end = Utils::Maximum(*end, it.page()->object_end());
|
| }
|
| ASSERT(*start != static_cast<uword>(~0));
|
| ASSERT(*end != 0);
|
| @@ -447,53 +473,36 @@
|
|
|
|
|
| void PageSpace::VisitObjects(ObjectVisitor* visitor) const {
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| - HeapPage* page = pages_;
|
| - while (page != NULL) {
|
| - page->VisitObjects(visitor);
|
| - page = NextPageAnySize(page);
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + it.page()->VisitObjects(visitor);
|
| }
|
| }
|
|
|
|
|
| void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| - HeapPage* page = pages_;
|
| - while (page != NULL) {
|
| - page->VisitObjectPointers(visitor);
|
| - page = NextPageAnySize(page);
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + it.page()->VisitObjectPointers(visitor);
|
| }
|
| }
|
|
|
|
|
| RawObject* PageSpace::FindObject(FindObjectVisitor* visitor,
|
| HeapPage::PageType type) const {
|
| - ASSERT(Isolate::Current()->no_gc_scope_depth() != 0);
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| - HeapPage* page = pages_;
|
| - while (page != NULL) {
|
| - if (page->type() == type) {
|
| - RawObject* obj = page->FindObject(visitor);
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + if (it.page()->type() == type) {
|
| + RawObject* obj = it.page()->FindObject(visitor);
|
| if (obj != Object::null()) {
|
| return obj;
|
| }
|
| }
|
| - page = NextPageAnySize(page);
|
| }
|
| return Object::null();
|
| }
|
|
|
|
|
| void PageSpace::WriteProtect(bool read_only) {
|
| - MutexLocker ml(pages_lock_);
|
| - NoGCScope no_gc;
|
| - HeapPage* page = pages_;
|
| - while (page != NULL) {
|
| - page->WriteProtect(read_only);
|
| - page = NextPageAnySize(page);
|
| + for (ExclusivePageIterator it(this); !it.done(); it.Advance()) {
|
| + it.page()->WriteProtect(read_only);
|
| }
|
| }
|
|
|
| @@ -554,7 +563,9 @@
|
| {
|
| // "pages" is an array [page0, page1, ..., pageN], each page of the form
|
| // {"object_start": "0x...", "objects": [size, class id, size, ...]}
|
| + // TODO(19445): Use ExclusivePageIterator once HeapMap supports large pages.
|
| MutexLocker ml(pages_lock_);
|
| + MakeIterable();
|
| NoGCScope no_gc;
|
| JSONArray all_pages(&heap_map, "pages");
|
| for (HeapPage* page = pages_; page != NULL; page = page->next()) {
|
| @@ -662,6 +673,7 @@
|
| int64_t mid1 = OS::GetCurrentTimeMicros();
|
|
|
| // Abandon the remainder of the bump allocation block.
|
| + MakeIterable();
|
| bump_top_ = 0;
|
| bump_end_ = 0;
|
| // Reset the freelists and setup sweeping.
|
| @@ -672,7 +684,7 @@
|
| int64_t mid3 = 0;
|
|
|
| {
|
| - GCSweeper sweeper(heap_);
|
| + GCSweeper sweeper;
|
|
|
| // During stop-the-world phases we should use bulk lock when adding elements
|
| // to the free list.
|
| @@ -812,10 +824,14 @@
|
| uword result = bump_top_;
|
| bump_top_ += size;
|
| usage_.used_in_words += size >> kWordSizeLog2;
|
| - remaining -= size;
|
| - if (remaining > 0) {
|
| - FreeListElement::AsElement(bump_top_, remaining);
|
| + // Note: Remaining block is unwalkable until MakeIterable is called.
|
| + #ifdef DEBUG
|
| + if (bump_top_ < bump_end_) {
|
| + // Fail fast if we try to walk the remaining block.
|
| + COMPILE_ASSERT(kIllegalCid == 0);
|
| + *reinterpret_cast<uword*>(bump_top_) = 0;
|
| }
|
| + #endif // DEBUG
|
| return result;
|
| }
|
|
|
|
|