blob: 76f325a57a86495927c79fde1a95de6fefe9b289 [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/assert.h"
#include "platform/globals.h"
#include "vm/globals.h"
#include "vm/heap/become.h"
#include "vm/heap/heap.h"
#include "vm/unit_test.h"
namespace dart {
void TestBecomeForward(Heap::Space before_space, Heap::Space after_space) {
// Allocate the container in old space to test the remembered set.
const Array& container = Array::Handle(Array::New(1, Heap::kOld));
const String& before_obj = String::Handle(String::New("old", before_space));
const String& after_obj = String::Handle(String::New("new", after_space));
container.SetAt(0, before_obj);
EXPECT(before_obj.ptr() != after_obj.ptr());
Become become;
become.Add(before_obj, after_obj);
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
EXPECT(container.At(0) == after_obj.ptr());
GCTestHelper::CollectAllGarbage();
EXPECT(before_obj.ptr() == after_obj.ptr());
EXPECT(container.At(0) == after_obj.ptr());
}
ISOLATE_UNIT_TEST_CASE(BecomeFowardOldToOld) {
TestBecomeForward(Heap::kOld, Heap::kOld);
}
ISOLATE_UNIT_TEST_CASE(BecomeFowardNewToNew) {
TestBecomeForward(Heap::kNew, Heap::kNew);
}
ISOLATE_UNIT_TEST_CASE(BecomeFowardOldToNew) {
TestBecomeForward(Heap::kOld, Heap::kNew);
}
ISOLATE_UNIT_TEST_CASE(BecomeFowardNewToOld) {
TestBecomeForward(Heap::kNew, Heap::kOld);
}
ISOLATE_UNIT_TEST_CASE(BecomeForwardPeer) {
Heap* heap = IsolateGroup::Current()->heap();
const Array& before_obj = Array::Handle(Array::New(0, Heap::kOld));
const Array& after_obj = Array::Handle(Array::New(0, Heap::kOld));
EXPECT(before_obj.ptr() != after_obj.ptr());
void* peer = reinterpret_cast<void*>(42);
void* no_peer = reinterpret_cast<void*>(0);
heap->SetPeer(before_obj.ptr(), peer);
EXPECT_EQ(peer, heap->GetPeer(before_obj.ptr()));
EXPECT_EQ(no_peer, heap->GetPeer(after_obj.ptr()));
Become become;
become.Add(before_obj, after_obj);
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
EXPECT_EQ(peer, heap->GetPeer(before_obj.ptr()));
EXPECT_EQ(peer, heap->GetPeer(after_obj.ptr()));
}
ISOLATE_UNIT_TEST_CASE(BecomeForwardObjectId) {
Heap* heap = IsolateGroup::Current()->heap();
const Array& before_obj = Array::Handle(Array::New(0, Heap::kOld));
const Array& after_obj = Array::Handle(Array::New(0, Heap::kOld));
EXPECT(before_obj.ptr() != after_obj.ptr());
intptr_t id = 42;
intptr_t no_id = 0;
heap->SetObjectId(before_obj.ptr(), id);
EXPECT_EQ(id, heap->GetObjectId(before_obj.ptr()));
EXPECT_EQ(no_id, heap->GetObjectId(after_obj.ptr()));
Become become;
become.Add(before_obj, after_obj);
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
EXPECT_EQ(id, heap->GetObjectId(before_obj.ptr()));
EXPECT_EQ(id, heap->GetObjectId(after_obj.ptr()));
}
ISOLATE_UNIT_TEST_CASE(BecomeForwardMessageId) {
Isolate* isolate = Isolate::Current();
isolate->set_forward_table_new(new WeakTable());
isolate->set_forward_table_old(new WeakTable());
const Array& before_obj = Array::Handle(Array::New(0, Heap::kOld));
const Array& after_obj = Array::Handle(Array::New(0, Heap::kOld));
EXPECT(before_obj.ptr() != after_obj.ptr());
intptr_t id = 42;
intptr_t no_id = 0;
isolate->forward_table_old()->SetValueExclusive(before_obj.ptr(), id);
EXPECT_EQ(id,
isolate->forward_table_old()->GetValueExclusive(before_obj.ptr()));
EXPECT_EQ(no_id,
isolate->forward_table_old()->GetValueExclusive(after_obj.ptr()));
Become become;
become.Add(before_obj, after_obj);
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
EXPECT_EQ(id,
isolate->forward_table_old()->GetValueExclusive(before_obj.ptr()));
EXPECT_EQ(id,
isolate->forward_table_old()->GetValueExclusive(after_obj.ptr()));
isolate->set_forward_table_new(nullptr);
isolate->set_forward_table_old(nullptr);
}
ISOLATE_UNIT_TEST_CASE(BecomeForwardRememberedObject) {
const String& new_element = String::Handle(String::New("new", Heap::kNew));
const String& old_element = String::Handle(String::New("old", Heap::kOld));
const Array& before_obj = Array::Handle(Array::New(1, Heap::kOld));
const Array& after_obj = Array::Handle(Array::New(1, Heap::kOld));
before_obj.SetAt(0, new_element);
after_obj.SetAt(0, old_element);
EXPECT(before_obj.ptr()->untag()->IsRemembered());
EXPECT(!after_obj.ptr()->untag()->IsRemembered());
EXPECT(before_obj.ptr() != after_obj.ptr());
Become become;
become.Add(before_obj, after_obj);
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
EXPECT(!after_obj.ptr()->untag()->IsRemembered());
GCTestHelper::CollectAllGarbage();
EXPECT(before_obj.ptr() == after_obj.ptr());
}
ISOLATE_UNIT_TEST_CASE(BecomeForwardRememberedCards) {
const intptr_t length = Heap::kNewAllocatableSize / Array::kBytesPerElement;
ASSERT(Array::UseCardMarkingForAllocation(length));
const Array& card_remembered_array = Array::Handle(Array::New(length));
EXPECT(card_remembered_array.ptr()->untag()->IsCardRemembered());
EXPECT(!card_remembered_array.ptr()->untag()->IsRemembered());
const String& old_element = String::Handle(String::New("old", Heap::kOld));
const String& new_element = String::Handle(String::New("new", Heap::kNew));
card_remembered_array.SetAt(0, old_element);
{
HANDLESCOPE(thread);
EXPECT_STREQ("old",
Object::Handle(card_remembered_array.At(0)).ToCString());
}
Become become;
become.Add(old_element, new_element);
become.Forward();
EXPECT(old_element.ptr() == new_element.ptr());
EXPECT(old_element.ptr()->IsNewObject());
EXPECT(card_remembered_array.ptr()->untag()->IsCardRemembered());
EXPECT(!card_remembered_array.ptr()->untag()->IsRemembered());
{
HANDLESCOPE(thread);
EXPECT_STREQ("new",
Object::Handle(card_remembered_array.At(0)).ToCString());
}
GCTestHelper::CollectAllGarbage();
EXPECT(old_element.ptr() == new_element.ptr());
EXPECT(card_remembered_array.ptr()->untag()->IsCardRemembered());
EXPECT(!card_remembered_array.ptr()->untag()->IsRemembered());
{
HANDLESCOPE(thread);
EXPECT_STREQ("new",
Object::Handle(card_remembered_array.At(0)).ToCString());
}
}
} // namespace dart