[vm] Delay allocating the ObjectIdRing until the first service request or response.

Avoids GC overhead when the VM service is not in use.

Change-Id: Ic2e752c17fdd01045e30dd62e16f20896a9fc64e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/146440
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2020-05-06 19:19:52 +00:00 committed by commit-bot@chromium.org
parent f6d0f462fb
commit 147f0e3d94
10 changed files with 35 additions and 22 deletions

View file

@ -296,8 +296,9 @@ void Become::FollowForwardingPointers(Thread* thread) {
isolate_group->ForEachIsolate(
[&](Isolate* isolate) {
ObjectIdRing* ring = isolate->object_id_ring();
ASSERT(ring != NULL);
ring->VisitPointers(&pointer_visitor);
if (ring != nullptr) {
ring->VisitPointers(&pointer_visitor);
}
},
/*at_safepoint=*/true);
#endif // !PRODUCT

View file

@ -418,7 +418,10 @@ void CompactorTask::RunEnteredIsolateGroup() {
TIMELINE_FUNCTION_GC_DURATION(thread, "ForwardObjectIdRing");
isolate_group_->ForEachIsolate(
[&](Isolate* isolate) {
isolate->object_id_ring()->VisitPointers(compactor_);
ObjectIdRing* ring = isolate->object_id_ring();
if (ring != nullptr) {
ring->VisitPointers(compactor_);
}
},
/*at_safepoint=*/true);
break;

View file

@ -1475,9 +1475,6 @@ Isolate::Isolate(IsolateGroup* isolate_group,
#undef ISOLATE_METRIC_CONSTRUCTORS
reload_every_n_stack_overflow_checks_(FLAG_reload_every),
#endif // !defined(PRODUCT)
#if !defined(PRODUCT)
object_id_ring_(new ObjectIdRing()),
#endif
start_time_micros_(OS::GetCurrentMonotonicMicros()),
random_(),
mutex_(NOT_IN_PRODUCT("Isolate::mutex_")),
@ -2780,7 +2777,10 @@ void IsolateGroup::VisitStackPointers(ObjectPointerVisitor* visitor,
void IsolateGroup::VisitObjectIdRingPointers(ObjectPointerVisitor* visitor) {
#if !defined(PRODUCT)
for (Isolate* isolate : isolates_) {
isolate->object_id_ring()->VisitPointers(visitor);
ObjectIdRing* ring = isolate->object_id_ring();
if (ring != nullptr) {
ring->VisitPointers(visitor);
}
}
#endif // !defined(PRODUCT)
}
@ -2840,6 +2840,15 @@ intptr_t IsolateGroup::GetClassSizeForHeapWalkAt(intptr_t cid) {
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
}
#if !defined(PRODUCT)
ObjectIdRing* Isolate::EnsureObjectIdRing() {
if (object_id_ring_ == nullptr) {
object_id_ring_ = new ObjectIdRing();
}
return object_id_ring_;
}
#endif // !defined(PRODUCT)
void Isolate::AddPendingDeopt(uword fp, uword pc) {
// GrowableArray::Add is not atomic and may be interrupt by a profiler
// stack walk.

View file

@ -955,7 +955,8 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
}
#if !defined(PRODUCT)
ObjectIdRing* object_id_ring() { return object_id_ring_; }
ObjectIdRing* object_id_ring() const { return object_id_ring_; }
ObjectIdRing* EnsureObjectIdRing();
#endif // !defined(PRODUCT)
void AddPendingDeopt(uword fp, uword pc);

View file

@ -41,7 +41,7 @@ JSONStream::JSONStream(intptr_t buf_size)
ObjectIdRing* ring = NULL;
Isolate* isolate = Isolate::Current();
if (isolate != NULL) {
ring = isolate->object_id_ring();
ring = isolate->EnsureObjectIdRing();
}
default_id_zone_.Init(ring, ObjectIdRing::kAllocateId);
}

View file

@ -86,16 +86,16 @@ void ObjectIdRing::PrintJSON(JSONStream* js) {
}
}
ObjectIdRing::ObjectIdRing(int32_t capacity) {
ASSERT(capacity > 0);
ObjectIdRing::ObjectIdRing() {
serial_num_ = 0;
wrapped_ = false;
table_ = NULL;
SetCapacityAndMaxSerial(capacity, kMaxId);
SetCapacityAndMaxSerial(kDefaultCapacity, kMaxId);
}
void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity,
int32_t max_serial) {
ASSERT(capacity > 0);
ASSERT(max_serial <= kMaxId);
capacity_ = capacity;
if (table_ != NULL) {

View file

@ -39,7 +39,7 @@ class ObjectIdRing {
static const int32_t kInvalidId = -1;
static const int32_t kDefaultCapacity = 8192;
explicit ObjectIdRing(int32_t capacity = kDefaultCapacity);
ObjectIdRing();
~ObjectIdRing();
// Adds the argument to the ring and returns its id. Note we do not allow

View file

@ -52,7 +52,7 @@ class ObjectIdRingTestHelper {
// Test that serial number wrapping works.
ISOLATE_UNIT_TEST_CASE(ObjectIdRingSerialWrapTest) {
Isolate* isolate = Isolate::Current();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
ObjectIdRingTestHelper::SetCapacityAndMaxSerial(ring, 2, 4);
intptr_t id;
ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
@ -137,7 +137,7 @@ TEST_CASE(ObjectIdRingScavengeMoveTest) {
EXPECT_EQ(3, list_length);
Isolate* isolate = thread->isolate();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
{
@ -196,7 +196,7 @@ TEST_CASE(ObjectIdRingScavengeMoveTest) {
// Test that the ring table is updated with nulls when the old GC collects.
ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
Isolate* isolate = thread->isolate();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
intptr_t raw_obj_id1 = -1;
@ -241,7 +241,7 @@ ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
// overridden by new entries.
ISOLATE_UNIT_TEST_CASE(ObjectIdRingExpiredEntryTest) {
Isolate* isolate = Isolate::Current();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
// Insert an object and check we can look it up.
String& obj = String::Handle(String::New("I will expire"));

View file

@ -1685,8 +1685,7 @@ static ObjectPtr LookupObjectId(Thread* thread,
return Object::null();
}
ObjectIdRing* ring = thread->isolate()->object_id_ring();
ASSERT(ring != NULL);
ObjectIdRing* ring = thread->isolate()->EnsureObjectIdRing();
intptr_t id = -1;
if (!GetIntegerId(arg, &id)) {
*kind = ObjectIdRing::kInvalid;

View file

@ -186,7 +186,7 @@ ISOLATE_UNIT_TEST_CASE(Service_IsolateStickyError) {
ISOLATE_UNIT_TEST_CASE(Service_IdZones) {
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
const String& test_a = String::Handle(zone, String::New("a"));
const String& test_b = String::Handle(zone, String::New("b"));
@ -384,7 +384,7 @@ ISOLATE_UNIT_TEST_CASE(Service_PcDescriptors) {
const PcDescriptors& descriptors =
PcDescriptors::Handle(code_c.pc_descriptors());
EXPECT(!descriptors.IsNull());
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
intptr_t id = ring->GetIdForObject(descriptors.raw());
// Build a mock message handler and wrap it in a dart port.
@ -455,7 +455,7 @@ ISOLATE_UNIT_TEST_CASE(Service_LocalVarDescriptors) {
const LocalVarDescriptors& descriptors =
LocalVarDescriptors::Handle(code_c.GetLocalVarDescriptors());
// Generate an ID for this object.
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing* ring = isolate->EnsureObjectIdRing();
intptr_t id = ring->GetIdForObject(descriptors.raw());
// Build a mock message handler and wrap it in a dart port.