09cd42db1c
Also, cleanup duplicate constant kTagBitsSizeTagPos. TEST=ci Change-Id: I83465af0cc8e93880ddae7d161151b397f8ec8c5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/487101 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
197 lines
6.3 KiB
C++
197 lines
6.3 KiB
C++
// 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(BecomeForwardOldToOld) {
|
|
TestBecomeForward(Heap::kOld, Heap::kOld);
|
|
}
|
|
|
|
ISOLATE_UNIT_TEST_CASE(BecomeForwardNewToNew) {
|
|
TestBecomeForward(Heap::kNew, Heap::kNew);
|
|
}
|
|
|
|
ISOLATE_UNIT_TEST_CASE(BecomeForwardOldToNew) {
|
|
TestBecomeForward(Heap::kOld, Heap::kNew);
|
|
}
|
|
|
|
ISOLATE_UNIT_TEST_CASE(BecomeForwardNewToOld) {
|
|
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) {
|
|
thread->set_forward_table_new(new WeakTable());
|
|
thread->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;
|
|
thread->forward_table_old()->SetValueExclusive(before_obj.ptr(), id);
|
|
EXPECT_EQ(id,
|
|
thread->forward_table_old()->GetValueExclusive(before_obj.ptr()));
|
|
EXPECT_EQ(no_id,
|
|
thread->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,
|
|
thread->forward_table_old()->GetValueExclusive(before_obj.ptr()));
|
|
EXPECT_EQ(id,
|
|
thread->forward_table_old()->GetValueExclusive(after_obj.ptr()));
|
|
|
|
thread->set_forward_table_new(nullptr);
|
|
thread->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
|