Skip to content

Commit 0fab083

Browse files
rmacnak-googlecommit-bot@chromium.org
authored andcommitted
[vm, isolate] Merge heaps without evacuating new-space.
Change-Id: I03d65e866215f243f2ab6a4a1d9d41625be4d56f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148682 Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent cfe45b6 commit 0fab083

11 files changed

+81
-60
lines changed

runtime/vm/dart_api_impl.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,12 +1309,10 @@ Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
13091309
{
13101310
TransitionNativeToVM native_to_vm(thread);
13111311

1312-
// Ensure new space is empty and there are no threads running.
1312+
// Ensure there are no helper threads running.
13131313
BackgroundCompiler::Stop(isolate);
1314-
isolate->heap()->new_space()->Evacuate();
13151314
isolate->heap()->WaitForMarkerTasks(thread);
13161315
isolate->heap()->WaitForSweeperTasks(thread);
1317-
RELEASE_ASSERT(isolate->heap()->new_space()->UsedInWords() == 0);
13181316
RELEASE_ASSERT(isolate->heap()->old_space()->tasks() == 0);
13191317
}
13201318

@@ -1344,7 +1342,7 @@ Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
13441342
// Merge the heap from [spawning_group] to [group].
13451343
{
13461344
SafepointOperationScope safepoint_scope(thread);
1347-
group->heap()->MergeOtherHeap(isolate->group()->heap());
1345+
group->heap()->MergeFrom(isolate->group()->heap());
13481346
}
13491347

13501348
spawning_group->UnregisterIsolate(isolate);

runtime/vm/heap/freelist.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,13 @@ FreeListElement* FreeList::TryAllocateLargeLocked(intptr_t minimum_size) {
377377
return NULL;
378378
}
379379

380-
void FreeList::MergeOtherFreelist(FreeList* other, bool is_protected) {
380+
void FreeList::MergeFrom(FreeList* donor, bool is_protected) {
381381
// The [other] free list is from a dying isolate. There are no other threads
382382
// accessing it, so there is no need to lock here.
383383
MutexLocker ml(&mutex_);
384384
for (intptr_t i = 0; i < (kNumLists + 1); ++i) {
385-
FreeListElement* other_head = other->free_lists_[i];
386-
if (other_head != nullptr) {
385+
FreeListElement* donor_head = donor->free_lists_[i];
386+
if (donor_head != nullptr) {
387387
// If we didn't have a freelist element before we have to set the bit now,
388388
// since we will get 1+ elements from [other].
389389
FreeListElement* old_head = free_lists_[i];
@@ -392,7 +392,7 @@ void FreeList::MergeOtherFreelist(FreeList* other, bool is_protected) {
392392
}
393393

394394
// Chain other's list in.
395-
FreeListElement* last = other_head;
395+
FreeListElement* last = donor_head;
396396
while (last->next() != nullptr) {
397397
last = last->next();
398398
}
@@ -406,12 +406,12 @@ void FreeList::MergeOtherFreelist(FreeList* other, bool is_protected) {
406406
VirtualMemory::Protect(reinterpret_cast<void*>(last), sizeof(*last),
407407
VirtualMemory::kReadExecute);
408408
}
409-
free_lists_[i] = other_head;
409+
free_lists_[i] = donor_head;
410410
}
411411
}
412412

413413
last_free_small_size_ =
414-
Utils::Maximum(last_free_small_size_, other->last_free_small_size_);
414+
Utils::Maximum(last_free_small_size_, donor->last_free_small_size_);
415415
}
416416

417417
} // namespace dart

runtime/vm/heap/freelist.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class FreeList {
157157
void set_end(uword value) { end_ = value; }
158158
void AddUnaccountedSize(intptr_t size) { unaccounted_size_ += size; }
159159

160-
void MergeOtherFreelist(FreeList* freelist, bool is_protected);
160+
void MergeFrom(FreeList* donor, bool is_protected);
161161

162162
private:
163163
static const int kNumLists = 128;

runtime/vm/heap/heap.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -739,19 +739,19 @@ void Heap::CollectOnNthAllocation(intptr_t num_allocations) {
739739
gc_on_nth_allocation_ = num_allocations;
740740
}
741741

742-
void Heap::MergeOtherHeap(Heap* other) {
743-
ASSERT(!other->gc_new_space_in_progress_);
744-
ASSERT(!other->gc_old_space_in_progress_);
745-
ASSERT(!other->read_only_);
746-
ASSERT(other->new_space()->UsedInWords() == 0);
747-
ASSERT(other->old_space()->tasks() == 0);
742+
void Heap::MergeFrom(Heap* donor) {
743+
ASSERT(!donor->gc_new_space_in_progress_);
744+
ASSERT(!donor->gc_old_space_in_progress_);
745+
ASSERT(!donor->read_only_);
746+
ASSERT(donor->old_space()->tasks() == 0);
748747

749-
old_space_.MergeOtherPageSpace(other->old_space());
748+
new_space_.MergeFrom(donor->new_space());
749+
old_space_.MergeFrom(donor->old_space());
750750

751751
for (intptr_t i = 0; i < kNumWeakSelectors; ++i) {
752752
// The new space rehashing should not be necessary.
753-
new_weak_tables_[i]->MergeOtherWeakTable(other->new_weak_tables_[i]);
754-
old_weak_tables_[i]->MergeOtherWeakTable(other->old_weak_tables_[i]);
753+
new_weak_tables_[i]->MergeFrom(donor->new_weak_tables_[i]);
754+
old_weak_tables_[i]->MergeFrom(donor->old_weak_tables_[i]);
755755
}
756756
}
757757

runtime/vm/heap/heap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ class Heap {
307307

308308
void CollectOnNthAllocation(intptr_t num_allocations);
309309

310-
void MergeOtherHeap(Heap* other);
310+
void MergeFrom(Heap* donor);
311311

312312
private:
313313
class GCStats : public ValueObject {

runtime/vm/heap/pages.cc

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,54 +1437,53 @@ static void EnsureEqualImagePages(OldPage* pages, OldPage* other_pages) {
14371437
#endif
14381438
}
14391439

1440-
void PageSpace::MergeOtherPageSpace(PageSpace* other) {
1441-
other->AbandonBumpAllocation();
1440+
void PageSpace::MergeFrom(PageSpace* donor) {
1441+
donor->AbandonBumpAllocation();
14421442

1443-
ASSERT(other->tasks_ == 0);
1444-
ASSERT(other->concurrent_marker_tasks_ == 0);
1445-
ASSERT(other->phase_ == kDone);
1446-
DEBUG_ASSERT(other->iterating_thread_ == nullptr);
1447-
ASSERT(other->marker_ == nullptr);
1443+
ASSERT(donor->tasks_ == 0);
1444+
ASSERT(donor->concurrent_marker_tasks_ == 0);
1445+
ASSERT(donor->phase_ == kDone);
1446+
DEBUG_ASSERT(donor->iterating_thread_ == nullptr);
1447+
ASSERT(donor->marker_ == nullptr);
14481448

14491449
for (intptr_t i = 0; i < num_freelists_; ++i) {
1450-
ASSERT(other->freelists_[i].top() == 0);
1451-
ASSERT(other->freelists_[i].end() == 0);
1450+
ASSERT(donor->freelists_[i].top() == 0);
1451+
ASSERT(donor->freelists_[i].end() == 0);
14521452
const bool is_protected =
14531453
FLAG_write_protect_code && i == OldPage::kExecutable;
1454-
freelists_[i].MergeOtherFreelist(&other->freelists_[i], is_protected);
1455-
other->freelists_[i].Reset();
1454+
freelists_[i].MergeFrom(&donor->freelists_[i], is_protected);
1455+
donor->freelists_[i].Reset();
14561456
}
14571457

14581458
// The freelist locks will be taken in MergeOtherFreelist above, and the
14591459
// locking order is the freelist locks are taken before the page list locks,
14601460
// so don't take the pages lock until after MergeOtherFreelist.
14611461
MutexLocker ml(&pages_lock_);
1462-
MutexLocker ml2(&other->pages_lock_);
1462+
MutexLocker ml2(&donor->pages_lock_);
14631463

1464-
AppendList(&pages_, &pages_tail_, &other->pages_, &other->pages_tail_);
1465-
AppendList(&exec_pages_, &exec_pages_tail_, &other->exec_pages_,
1466-
&other->exec_pages_tail_);
1467-
AppendList(&large_pages_, &large_pages_tail_, &other->large_pages_,
1468-
&other->large_pages_tail_);
1464+
AppendList(&pages_, &pages_tail_, &donor->pages_, &donor->pages_tail_);
1465+
AppendList(&exec_pages_, &exec_pages_tail_, &donor->exec_pages_,
1466+
&donor->exec_pages_tail_);
1467+
AppendList(&large_pages_, &large_pages_tail_, &donor->large_pages_,
1468+
&donor->large_pages_tail_);
14691469
// We intentionall do not merge [image_pages_] beause [this] and [other] have
14701470
// the same mmap()ed image page areas.
1471-
EnsureEqualImagePages(image_pages_, other->image_pages_);
1471+
EnsureEqualImagePages(image_pages_, donor->image_pages_);
14721472

14731473
// We intentionaly do not increase [max_capacity_in_words_] because this can
14741474
// lead [max_capacity_in_words_] to become larger and larger and eventually
14751475
// wrap-around and become negative.
1476-
allocated_black_in_words_ += other->allocated_black_in_words_;
1477-
gc_time_micros_ += other->gc_time_micros_;
1478-
collections_ += other->collections_;
1476+
allocated_black_in_words_ += donor->allocated_black_in_words_;
1477+
gc_time_micros_ += donor->gc_time_micros_;
1478+
collections_ += donor->collections_;
14791479

1480-
usage_.capacity_in_words += other->usage_.capacity_in_words;
1481-
usage_.used_in_words += other->usage_.used_in_words;
1482-
usage_.external_in_words += other->usage_.external_in_words;
1480+
usage_.capacity_in_words += donor->usage_.capacity_in_words;
1481+
usage_.used_in_words += donor->usage_.used_in_words;
1482+
usage_.external_in_words += donor->usage_.external_in_words;
14831483

1484-
page_space_controller_.MergeOtherPageSpaceController(
1485-
&other->page_space_controller_);
1484+
page_space_controller_.MergeFrom(&donor->page_space_controller_);
14861485

1487-
ASSERT(FLAG_concurrent_mark || other->enable_concurrent_mark_ == false);
1486+
ASSERT(FLAG_concurrent_mark || donor->enable_concurrent_mark_ == false);
14881487
}
14891488

14901489
PageSpaceController::PageSpaceController(Heap* heap,
@@ -1697,11 +1696,10 @@ void PageSpaceController::RecordUpdate(SpaceUsage before,
16971696
}
16981697
}
16991698

1700-
void PageSpaceController::MergeOtherPageSpaceController(
1701-
PageSpaceController* other) {
1702-
last_usage_.capacity_in_words += other->last_usage_.capacity_in_words;
1703-
last_usage_.used_in_words += other->last_usage_.used_in_words;
1704-
last_usage_.external_in_words += other->last_usage_.external_in_words;
1699+
void PageSpaceController::MergeFrom(PageSpaceController* donor) {
1700+
last_usage_.capacity_in_words += donor->last_usage_.capacity_in_words;
1701+
last_usage_.used_in_words += donor->last_usage_.used_in_words;
1702+
last_usage_.external_in_words += donor->last_usage_.external_in_words;
17051703
}
17061704

17071705
void PageSpaceGarbageCollectionHistory::AddGarbageCollectionTime(int64_t start,

runtime/vm/heap/pages.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class PageSpaceController {
239239
friend class PageSpace; // For MergeOtherPageSpaceController
240240

241241
void RecordUpdate(SpaceUsage before, SpaceUsage after, const char* reason);
242-
void MergeOtherPageSpaceController(PageSpaceController* other);
242+
void MergeFrom(PageSpaceController* donor);
243243

244244
void RecordUpdate(SpaceUsage before,
245245
SpaceUsage after,
@@ -482,7 +482,7 @@ class PageSpace {
482482

483483
bool IsObjectFromImagePages(ObjectPtr object);
484484

485-
void MergeOtherPageSpace(PageSpace* other);
485+
void MergeFrom(PageSpace* donor);
486486

487487
private:
488488
// Ids for time and data records in Heap::GCStats.

runtime/vm/heap/scavenger.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,19 @@ void SemiSpace::AddList(NewPage* head, NewPage* tail) {
673673
tail_ = tail;
674674
}
675675

676+
void SemiSpace::MergeFrom(SemiSpace* donor) {
677+
for (NewPage* page = donor->head_; page != nullptr; page = page->next()) {
678+
page->Release();
679+
}
680+
681+
AddList(donor->head_, donor->tail_);
682+
capacity_in_words_ += donor->capacity_in_words_;
683+
684+
donor->head_ = nullptr;
685+
donor->tail_ = nullptr;
686+
donor->capacity_in_words_ = 0;
687+
}
688+
676689
// The initial estimate of how many words we can scavenge per microsecond (usage
677690
// before / scavenge time). This is a conservative value observed running
678691
// Flutter on a Nexus 4. After the first scavenge, we instead use a value based
@@ -1578,4 +1591,13 @@ void Scavenger::Evacuate() {
15781591
ASSERT((UsedInWords() == 0) || failed_to_promote_);
15791592
}
15801593

1594+
void Scavenger::MergeFrom(Scavenger* donor) {
1595+
MutexLocker ml(&space_lock_);
1596+
MutexLocker ml2(&donor->space_lock_);
1597+
to_->MergeFrom(donor->to_);
1598+
1599+
external_size_ += donor->external_size_;
1600+
donor->external_size_ = 0;
1601+
}
1602+
15811603
} // namespace dart

runtime/vm/heap/scavenger.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ class SemiSpace {
183183
NewPage* head() const { return head_; }
184184

185185
void AddList(NewPage* head, NewPage* tail);
186+
void MergeFrom(SemiSpace* donor);
186187

187188
private:
188189
// Size of NewPages in this semi-space.
@@ -279,6 +280,8 @@ class Scavenger {
279280
// Promote all live objects.
280281
void Evacuate();
281282

283+
void MergeFrom(Scavenger* donor);
284+
282285
int64_t UsedInWords() const {
283286
MutexLocker ml(&space_lock_);
284287
return to_->capacity_in_words();

runtime/vm/heap/weak_table.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,10 @@ void WeakTable::Rehash() {
132132
free(old_data);
133133
}
134134

135-
void WeakTable::MergeOtherWeakTable(WeakTable* other) {
136-
for (intptr_t i = 0; i < other->size(); i++) {
137-
if (other->IsValidEntryAtExclusive(i)) {
138-
SetValueExclusive(other->ObjectAtExclusive(i), ValueIndex(i));
135+
void WeakTable::MergeFrom(WeakTable* donor) {
136+
for (intptr_t i = 0; i < donor->size(); i++) {
137+
if (donor->IsValidEntryAtExclusive(i)) {
138+
SetValueExclusive(donor->ObjectAtExclusive(i), ValueIndex(i));
139139
}
140140
}
141141
}

runtime/vm/heap/weak_table.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class WeakTable {
130130

131131
void Reset();
132132

133-
void MergeOtherWeakTable(WeakTable* other);
133+
void MergeFrom(WeakTable* donor);
134134

135135
private:
136136
enum {

0 commit comments

Comments
 (0)