From 487c5957588035fea2d52019010d6fc0e41d03f2 Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 10 Dec 2024 21:48:58 +0000 Subject: [PATCH] [vm] Handle non-Smi lengths during heap snapshot writing. This applies to List/Map/Set, which have logical lengths that are initialized by Dart constructors. It does not apply to Array/String/TypedData, which have physical lengths that must always be initialized before the next safepoint. TEST=ci Bug: https://github.com/dart-lang/sdk/issues/55689 Change-Id: If132405249e4e49920b0f4f63f85ebeb49e23671 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400020 Reviewed-by: Alexander Aprelev Commit-Queue: Ryan Macnak --- runtime/vm/object_graph.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc index ac0c2805963..42b72691c0a 100644 --- a/runtime/vm/object_graph.cc +++ b/runtime/vm/object_graph.cc @@ -1120,6 +1120,13 @@ class Pass2Visitor : public ObjectVisitor, writer_(writer), object_slots_(object_slots) {} + // A safepoint might occur between the allocation stub creating an object and + // filling it with nulls and the instance initializer running and populating a + // length field. + static intptr_t SmiValueOrZero(SmiPtr smi) { + return smi->IsSmi() ? Smi::Value(smi) : 0; + } + void VisitObject(ObjectPtr obj) override { if (obj->IsPseudoObject()) return; @@ -1171,16 +1178,16 @@ class Pass2Visitor : public ObjectVisitor, Smi::Value(static_cast(obj)->untag()->length())); } else if (cid == kGrowableObjectArrayCid) { writer_->WriteUnsigned(kLengthData); - writer_->WriteUnsigned(Smi::Value( + writer_->WriteUnsigned(SmiValueOrZero( static_cast(obj)->untag()->length())); } else if (cid == kMapCid || cid == kConstMapCid) { writer_->WriteUnsigned(kLengthData); writer_->WriteUnsigned( - Smi::Value(static_cast(obj)->untag()->used_data())); + SmiValueOrZero(static_cast(obj)->untag()->used_data())); } else if (cid == kSetCid || cid == kConstSetCid) { writer_->WriteUnsigned(kLengthData); writer_->WriteUnsigned( - Smi::Value(static_cast(obj)->untag()->used_data())); + SmiValueOrZero(static_cast(obj)->untag()->used_data())); } else if (cid == kObjectPoolCid) { writer_->WriteUnsigned(kLengthData); writer_->WriteUnsigned(static_cast(obj)->untag()->length_);