Skip to content

Commit ffbbdb5

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[vm, service] Treat the object id ring as strong during major GC.
The id ring was treated as a strong root during minor GC and a weak root during major GC. Before mark-through-new-space, new-space objects could not be collected during a major GC, so in practice the policy was that the id ring was strong for all new-space objects. After mark-through-new-space, new-space object can be collected during a major GC, so service ids could expire very quickly, especially for object just created using the service protocol and not otherwise reachable from the Dart program. Given that service id zones have still not been implemented, this makes it impossible to reliably interact with such an object. TEST=ci Bug: flutter/flutter#148704 Change-Id: I0f15c00414f996fad49bcb137c7f1c15bb4955c4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/367440 Reviewed-by: Derek Xu <[email protected]> Reviewed-by: Alexander Aprelev <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent e5e2c92 commit ffbbdb5

File tree

3 files changed

+16
-47
lines changed

3 files changed

+16
-47
lines changed

runtime/vm/heap/marker.cc

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,8 @@ void GCMarker::Epilogue() {}
699699

700700
enum RootSlices {
701701
kIsolate = 0,
702-
kNumFixedRootSlices = 1,
702+
kObjectIdRing = 1,
703+
kNumFixedRootSlices = 2,
703704
};
704705

705706
void GCMarker::ResetSlices() {
@@ -727,6 +728,12 @@ void GCMarker::IterateRoots(ObjectPointerVisitor* visitor) {
727728
visitor, ValidationPolicy::kDontValidateFrames);
728729
break;
729730
}
731+
case kObjectIdRing: {
732+
TIMELINE_FUNCTION_GC_DURATION(Thread::Current(),
733+
"ProcessObjectIdTable");
734+
isolate_group_->VisitObjectIdRingPointers(visitor);
735+
break;
736+
}
730737
}
731738

732739
MonitorLocker ml(&root_slices_monitor_);
@@ -740,7 +747,6 @@ void GCMarker::IterateRoots(ObjectPointerVisitor* visitor) {
740747
enum WeakSlices {
741748
kWeakHandles = 0,
742749
kWeakTables,
743-
kObjectIdRing,
744750
kRememberedSet,
745751
kNumWeakSlices,
746752
};
@@ -759,9 +765,6 @@ void GCMarker::IterateWeakRoots(Thread* thread) {
759765
case kWeakTables:
760766
ProcessWeakTables(thread);
761767
break;
762-
case kObjectIdRing:
763-
ProcessObjectIdTable(thread);
764-
break;
765768
case kRememberedSet:
766769
ProcessRememberedSet(thread);
767770
break;
@@ -851,39 +854,6 @@ void GCMarker::ProcessRememberedSet(Thread* thread) {
851854
store_buffer->PushBlock(writing, StoreBuffer::kIgnoreThreshold);
852855
}
853856

854-
class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor {
855-
public:
856-
explicit ObjectIdRingClearPointerVisitor(IsolateGroup* isolate_group)
857-
: ObjectPointerVisitor(isolate_group) {}
858-
859-
void VisitPointers(ObjectPtr* first, ObjectPtr* last) override {
860-
for (ObjectPtr* current = first; current <= last; current++) {
861-
ObjectPtr obj = *current;
862-
ASSERT(obj->IsHeapObject());
863-
if (!obj->untag()->IsMarked()) {
864-
// Object has become garbage. Replace it will null.
865-
*current = Object::null();
866-
}
867-
}
868-
}
869-
870-
#if defined(DART_COMPRESSED_POINTERS)
871-
void VisitCompressedPointers(uword heap_base,
872-
CompressedObjectPtr* first,
873-
CompressedObjectPtr* last) override {
874-
UNREACHABLE(); // ObjectIdRing is not compressed.
875-
}
876-
#endif
877-
};
878-
879-
void GCMarker::ProcessObjectIdTable(Thread* thread) {
880-
#ifndef PRODUCT
881-
TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessObjectIdTable");
882-
ObjectIdRingClearPointerVisitor visitor(isolate_group_);
883-
isolate_group_->VisitObjectIdRingPointers(&visitor);
884-
#endif // !PRODUCT
885-
}
886-
887857
class ParallelMarkTask : public ThreadPool::Task {
888858
public:
889859
ParallelMarkTask(GCMarker* marker,

runtime/vm/heap/marker.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class GCMarker {
6262
void ProcessWeakHandles(Thread* thread);
6363
void ProcessWeakTables(Thread* thread);
6464
void ProcessRememberedSet(Thread* thread);
65-
void ProcessObjectIdTable(Thread* thread);
6665

6766
// Called by anyone: finalize and accumulate stats from 'visitor'.
6867
template <class MarkingVisitorType>

runtime/vm/object_id_ring_test.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ TEST_CASE(ObjectIdRingScavengeMoveTest) {
195195
EXPECT_EQ(3, list_length);
196196
}
197197

198-
// Test that the ring table is updated with nulls when the old GC collects.
198+
// Test that the ring table is updated when major GC runs.
199199
ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
200200
Isolate* isolate = thread->isolate();
201201
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
@@ -229,16 +229,16 @@ ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
229229
UntaggedObject::ToAddr(raw_obj2));
230230
// Exit scope. Freeing String handle.
231231
}
232-
// Force a GC. No reference exist to the old string anymore. It should be
233-
// collected and the object id ring will now return the null object for
234-
// those ids.
232+
// Force a GC. No other reference to the old string exists, but the service id
233+
// should keep it alive.
235234
GCTestHelper::CollectOldSpace();
236235
ObjectPtr raw_object_moved1 = ring->GetObjectForId(raw_obj_id1, &kind);
237-
EXPECT_EQ(ObjectIdRing::kCollected, kind);
238-
EXPECT_EQ(Object::null(), raw_object_moved1);
236+
EXPECT_EQ(ObjectIdRing::kValid, kind);
237+
EXPECT(raw_object_moved1->IsOneByteString());
239238
ObjectPtr raw_object_moved2 = ring->GetObjectForId(raw_obj_id2, &kind);
240-
EXPECT_EQ(ObjectIdRing::kCollected, kind);
241-
EXPECT_EQ(Object::null(), raw_object_moved2);
239+
EXPECT_EQ(ObjectIdRing::kValid, kind);
240+
EXPECT(raw_object_moved2->IsOneByteString());
241+
EXPECT_EQ(raw_object_moved1, raw_object_moved2);
242242
}
243243

244244
// Test that the ring table correctly reports an entry as expired when it is

0 commit comments

Comments
 (0)