[vm] Represent the slow object copy from_to table with a heap array.
- Greatly reduces the size of the root set, thus reducing pauses for scavenges or marking that occur during a copy.
- Reduces the memory overhead of the from_to table from 6 words per object to 2 words per object.
TEST=ci
Change-Id: Icf81f4b25adff22590a9c84c40068e35dd4d502b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/246305
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index 43c35b3..560a7a7 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -471,27 +471,30 @@
public:
explicit SlowForwardMap(Thread* thread)
: ForwardMapBase(thread),
- from_to_(thread->zone(), 20),
+ from_to_transition_(thread->zone(), 2),
+ from_to_(GrowableObjectArray::Handle(thread->zone(),
+ GrowableObjectArray::New(2))),
transferables_from_to_(thread->zone(), 0) {
- from_to_.Resize(2);
- from_to_[0] = &Object::null_object();
- from_to_[1] = &Object::null_object();
+ from_to_transition_.Resize(2);
+ from_to_transition_[0] = &PassiveObject::Handle();
+ from_to_transition_[1] = &PassiveObject::Handle();
+ from_to_.Add(Object::null_object());
+ from_to_.Add(Object::null_object());
fill_cursor_ = 2;
}
ObjectPtr ForwardedObject(ObjectPtr object) {
const intptr_t id = GetObjectId(object);
if (id == 0) return Marker();
- return from_to_[id + 1]->ptr();
+ return from_to_.At(id + 1);
}
- void Insert(ObjectPtr from, ObjectPtr to, intptr_t size) {
- ASSERT(ForwardedObject(from) == Marker());
- const auto id = from_to_.length();
- SetObjectId(from, id);
- from_to_.Resize(id + 2);
- from_to_[id] = &Object::Handle(Z, from);
- from_to_[id + 1] = &Object::Handle(Z, to);
+ void Insert(const Object& from, const Object& to, intptr_t size) {
+ ASSERT(ForwardedObject(from.ptr()) == Marker());
+ const auto id = from_to_.Length();
+ SetObjectId(from.ptr(), id);
+ from_to_.Add(from);
+ from_to_.Add(to);
allocated_bytes += size;
}
@@ -537,7 +540,8 @@
friend class SlowObjectCopy;
friend class ObjectGraphCopier;
- GrowableArray<const Object*> from_to_;
+ GrowableArray<const PassiveObject*> from_to_transition_;
+ GrowableObjectArray& from_to_;
GrowableArray<const TransferableTypedData*> transferables_from_to_;
GrowableArray<const ExternalTypedData*> external_typed_data_;
GrowableArray<const Object*> objects_to_rehash_;
@@ -560,6 +564,7 @@
class_table_(thread->isolate_group()->class_table()),
new_space_(heap_->new_space()),
tmp_(Object::Handle(thread->zone())),
+ to_(Object::Handle(thread->zone())),
expando_cid_(Class::GetClassId(
thread->isolate_group()->object_store()->expando_class())) {}
~ObjectCopyBase() {}
@@ -681,6 +686,7 @@
ClassTable* class_table_;
Scavenger* new_space_;
Object& tmp_;
+ Object& to_;
intptr_t expando_cid_;
const char* exception_msg_ = nullptr;
@@ -990,9 +996,10 @@
if (size == 0) {
size = from.ptr().untag()->HeapSize();
}
- ObjectPtr to = AllocateObject(cid, size);
- slow_forward_map_.Insert(from.ptr(), to, size);
- UpdateLengthField(cid, from.ptr(), to);
+ to_ = AllocateObject(cid, size);
+ UpdateLengthField(cid, from.ptr(), to_.ptr());
+ slow_forward_map_.Insert(from, to_, size); // SAFEPOINT
+ ObjectPtr to = to_.ptr();
if (cid == kArrayCid && !Heap::IsAllocatableInNewSpace(size)) {
to.untag()->SetCardRememberedBitUnsynchronized();
}
@@ -1678,16 +1685,16 @@
Object& to = Object::Handle(Z);
while (true) {
if (slow_forward_map_.fill_cursor_ ==
- slow_forward_map_.from_to_.length()) {
+ slow_forward_map_.from_to_.Length()) {
break;
}
// Run fixpoint to copy all objects.
while (slow_forward_map_.fill_cursor_ <
- slow_forward_map_.from_to_.length()) {
+ slow_forward_map_.from_to_.Length()) {
const intptr_t index = slow_forward_map_.fill_cursor_;
- from = slow_forward_map_.from_to_[index]->ptr();
- to = slow_forward_map_.from_to_[index + 1]->ptr();
+ from = slow_forward_map_.from_to_.At(index);
+ to = slow_forward_map_.from_to_.At(index + 1);
CopyObject(from, to);
slow_forward_map_.fill_cursor_ += 2;
if (exception_msg_ != nullptr) {
@@ -1915,6 +1922,8 @@
/*compact=*/true);
}
+ ObjectifyFromToObjects();
+
// Fast copy failed due to
// - either failure to allocate into new space
// - or failure to copy object which we cannot copy
@@ -2021,20 +2030,28 @@
void HandlifyFromToObjects() {
auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
-
- const intptr_t cursor = fast_forward_map.fill_cursor_;
const intptr_t length = fast_forward_map.raw_from_to_.length();
-
- slow_forward_map.from_to_.Resize(length);
- for (intptr_t i = 2; i < length; i += 2) {
- slow_forward_map.from_to_[i] =
- i < cursor ? nullptr
- : &Object::Handle(Z, fast_forward_map.raw_from_to_[i]);
- slow_forward_map.from_to_[i + 1] =
- &Object::Handle(Z, fast_forward_map.raw_from_to_[i + 1]);
+ slow_forward_map.from_to_transition_.Resize(length);
+ for (intptr_t i = 0; i < length; i++) {
+ slow_forward_map.from_to_transition_[i] =
+ &PassiveObject::Handle(Z, fast_forward_map.raw_from_to_[i]);
}
+ ASSERT(slow_forward_map.from_to_transition_.length() == length);
fast_forward_map.raw_from_to_.Clear();
}
+ void ObjectifyFromToObjects() {
+ auto& from_to_transition =
+ slow_object_copy_.slow_forward_map_.from_to_transition_;
+ auto& from_to = slow_object_copy_.slow_forward_map_.from_to_;
+ intptr_t length = from_to_transition.length();
+ from_to = GrowableObjectArray::New(length, Heap::kOld);
+ for (intptr_t i = 0; i < length; i++) {
+ from_to.Add(*from_to_transition[i]);
+ }
+ ASSERT(from_to.Length() == length);
+ from_to_transition.Clear();
+ }
+
void ThrowException(const char* exception_msg) {
const auto& msg_obj = String::Handle(Z, String::New(exception_msg));
const auto& args = Array::Handle(Z, Array::New(1));