Skip to content

Commit 61c0960

Browse files
aamcommit-bot@chromium.org
authored and
commit-bot@chromium.org
committed
[vm/isolates] Introduce fast isolate spawn in AOT.
Speed up is achieved by sharing most of the dart code, object store and class table between isolates in single isolate group. So instead of bootstrapping isolate from the snapshot, isolate is initialized by setting pointers to existing data structures already set up for first isolate, and only few isolate-specific structures (moved to newly introducted isolate_object_store) are created. To allow for safe cross-isolate switchable call site, type test cache mutations additional synchronization via RunWithStoppedMutators(that relies on safepoints) was added. Besides switchable call sites, no other mutation to the dart code is done in AOT, which allows such sharing. Bug: #37835 Bug: #36097 Change-Id: I64c86525f4ef9cb30567a49a106bfe700355942b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136780 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
1 parent 23a8788 commit 61c0960

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1108
-560
lines changed

runtime/lib/isolate.cc

+4
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,11 @@ class SpawnIsolateTask : public ThreadPool::Task {
167167
return;
168168
}
169169

170+
#if defined(DART_PRECOMPILED_RUNTIME)
171+
isolate = CreateWithinExistingIsolateGroupAOT(group, name, &error);
172+
#else
170173
isolate = CreateWithinExistingIsolateGroup(group, name, &error);
174+
#endif
171175
parent_isolate_->DecrementSpawnCount();
172176
parent_isolate_ = nullptr;
173177
if (isolate == nullptr) {

runtime/observatory/tests/service/get_retaining_path_rpc_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ var tests = <IsolateTest>[
193193
'limit': 100,
194194
};
195195
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
196-
expect(result['gcRootType'], 'object store');
196+
expect(result['gcRootType'], 'isolate_object store');
197197
expect(result['elements'].length, 0);
198198
},
199199
];

runtime/vm/class_finalizer.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,7 @@ void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
15191519
// The [HeapIterationScope] also safepoints all threads.
15201520
HeapIterationScope his(T);
15211521

1522-
IG->class_table()->Remap(old_to_new_cid);
1522+
IG->shared_class_table()->Remap(old_to_new_cid);
15231523
IG->ForEachIsolate(
15241524
[&](Isolate* I) {
15251525
I->set_remapping_cids(true);

runtime/vm/class_table.cc

+29-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ SharedClassTable::SharedClassTable()
3131
calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>))));
3232
} else {
3333
// Duplicate the class table from the VM isolate.
34-
auto vm_shared_class_table = Dart::vm_isolate()->group()->class_table();
34+
auto vm_shared_class_table =
35+
Dart::vm_isolate()->group()->shared_class_table();
3536
capacity_ = vm_shared_class_table->capacity_;
3637
// Note that [calloc] will zero-initialize the memory.
3738
RelaxedAtomic<intptr_t>* table = reinterpret_cast<RelaxedAtomic<intptr_t>*>(
@@ -71,6 +72,13 @@ SharedClassTable::~SharedClassTable() {
7172
NOT_IN_PRODUCT(free(trace_allocation_table_.load()));
7273
}
7374

75+
void ClassTable::set_table(RawClass** table) {
76+
Isolate* isolate = Isolate::Current();
77+
ASSERT(isolate != nullptr);
78+
table_.store(table);
79+
isolate->set_class_table_table(table);
80+
}
81+
7482
ClassTable::ClassTable(SharedClassTable* shared_class_table)
7583
: top_(kNumPredefinedCids),
7684
capacity_(0),
@@ -81,6 +89,9 @@ ClassTable::ClassTable(SharedClassTable* shared_class_table)
8189
ASSERT(kInitialCapacity >= kNumPredefinedCids);
8290
capacity_ = kInitialCapacity;
8391
// Note that [calloc] will zero-initialize the memory.
92+
// Don't use set_table because caller is supposed to set up isolates
93+
// cached copy when constructing ClassTable. Isolate::Current might not
94+
// be available at this point yet.
8495
table_.store(static_cast<RawClass**>(calloc(capacity_, sizeof(RawClass*))));
8596
} else {
8697
// Duplicate the class table from the VM isolate.
@@ -100,6 +111,9 @@ ClassTable::ClassTable(SharedClassTable* shared_class_table)
100111
table[kDynamicCid] = vm_class_table->At(kDynamicCid);
101112
table[kVoidCid] = vm_class_table->At(kVoidCid);
102113
table[kNeverCid] = vm_class_table->At(kNeverCid);
114+
// Don't use set_table because caller is supposed to set up isolates
115+
// cached copy when constructing ClassTable. Isolate::Current might not
116+
// be available at this point yet.
103117
table_.store(table);
104118
}
105119
}
@@ -226,7 +240,7 @@ void ClassTable::Grow(intptr_t new_capacity) {
226240
new_table[i] = 0;
227241
}
228242
old_class_tables_->Add(old_table);
229-
table_.store(new_table);
243+
set_table(new_table);
230244

231245
capacity_ = new_capacity;
232246
}
@@ -374,6 +388,19 @@ void ClassTable::CopySizesFromClassObjects() {
374388
}
375389
}
376390

391+
void ClassTable::CopyFrom(ClassTable* class_table) {
392+
capacity_ = class_table->Capacity();
393+
top_ = class_table->NumCids();
394+
auto old_table = class_table->table_.load();
395+
auto new_table =
396+
static_cast<RawClass**>(malloc(capacity_ * sizeof(RawClass*))); // NOLINT
397+
for (intptr_t i = 0; i < capacity_; i++) {
398+
new_table[i] = old_table[i];
399+
}
400+
old_class_tables_->Add(table_.load());
401+
set_table(new_table);
402+
}
403+
377404
void ClassTable::Validate() {
378405
Class& cls = Class::Handle();
379406
for (intptr_t cid = kNumPredefinedCids; cid < top_; cid++) {

runtime/vm/class_table.h

+7-8
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ class ClassTable {
340340
void AllocateIndex(intptr_t index);
341341
void Unregister(intptr_t index);
342342

343+
void CopyFrom(ClassTable* class_table);
344+
343345
void Remap(intptr_t* old_to_new_cids);
344346

345347
void VisitObjectPointers(ObjectPointerVisitor* visitor);
@@ -353,14 +355,6 @@ class ClassTable {
353355

354356
void Print();
355357

356-
// Used by the generated code.
357-
static intptr_t table_offset() { return OFFSET_OF(ClassTable, table_); }
358-
359-
// Used by the generated code.
360-
static intptr_t shared_class_table_offset() {
361-
return OFFSET_OF(ClassTable, shared_class_table_);
362-
}
363-
364358
#ifndef PRODUCT
365359
// Describes layout of heap stats for code generation. See offset_extractor.cc
366360
struct ArrayLayout {
@@ -385,16 +379,21 @@ class ClassTable {
385379
friend class MarkingWeakVisitor;
386380
friend class Scavenger;
387381
friend class ScavengerWeakVisitor;
382+
friend class Dart;
388383
friend Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
389384
const char* name,
390385
char** error);
386+
friend class Isolate; // for table()
391387
static const int kInitialCapacity = SharedClassTable::kInitialCapacity;
392388
static const int kCapacityIncrement = SharedClassTable::kCapacityIncrement;
393389

394390
void AddOldTable(RawClass** old_table);
395391

396392
void Grow(intptr_t index);
397393

394+
RawClass** table() { return table_.load(); }
395+
void set_table(RawClass** table);
396+
398397
intptr_t top_;
399398
intptr_t capacity_;
400399

runtime/vm/clustered_snapshot.cc

+27-18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
#include <memory>
6+
57
#include "vm/clustered_snapshot.h"
68

79
#include "platform/assert.h"
@@ -231,7 +233,8 @@ class ClassSerializationCluster : public SerializationCluster {
231233
UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(Serializer* s,
232234
intptr_t class_id) {
233235
const auto unboxed_fields_bitmap_host =
234-
s->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(class_id);
236+
s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
237+
class_id);
235238

236239
UnboxedFieldBitmap unboxed_fields_bitmap;
237240
if (unboxed_fields_bitmap_host.IsEmpty() ||
@@ -349,7 +352,7 @@ class ClassDeserializationCluster : public DeserializationCluster {
349352
}
350353
}
351354

352-
auto shared_class_table = d->isolate()->group()->class_table();
355+
auto shared_class_table = d->isolate()->group()->shared_class_table();
353356
for (intptr_t id = start_index_; id < stop_index_; id++) {
354357
RawClass* cls = reinterpret_cast<RawClass*>(d->Ref(id));
355358
Deserializer::InitializeHeader(cls, kClassCid, Class::InstanceSize());
@@ -1201,6 +1204,10 @@ class FieldDeserializationCluster : public DeserializationCluster {
12011204
field.InitializeGuardedListLengthInObjectOffset();
12021205
}
12031206
}
1207+
1208+
Isolate* isolate = Isolate::Current();
1209+
isolate->set_saved_initial_field_table(
1210+
std::shared_ptr<FieldTable>(isolate->field_table()->Clone()));
12041211
}
12051212
};
12061213

@@ -3022,7 +3029,8 @@ class InstanceSerializationCluster : public SerializationCluster {
30223029
const intptr_t next_field_offset = host_next_field_offset_in_words_
30233030
<< kWordSizeLog2;
30243031
const auto unboxed_fields_bitmap =
3025-
s->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(cid_);
3032+
s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
3033+
cid_);
30263034
intptr_t offset = Instance::NextFieldOffset();
30273035
while (offset < next_field_offset) {
30283036
// Skips unboxed fields
@@ -3058,7 +3066,8 @@ class InstanceSerializationCluster : public SerializationCluster {
30583066
<< kWordSizeLog2;
30593067
const intptr_t count = objects_.length();
30603068
const auto unboxed_fields_bitmap =
3061-
s->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(cid_);
3069+
s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
3070+
cid_);
30623071
for (intptr_t i = 0; i < count; i++) {
30633072
RawInstance* instance = objects_[i];
30643073
AutoTraceObject(instance);
@@ -3116,7 +3125,8 @@ class InstanceDeserializationCluster : public DeserializationCluster {
31163125
Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
31173126

31183127
const auto unboxed_fields_bitmap =
3119-
d->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(cid_);
3128+
d->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
3129+
cid_);
31203130
for (intptr_t id = start_index_; id < stop_index_; id++) {
31213131
RawInstance* instance = reinterpret_cast<RawInstance*>(d->Ref(id));
31223132
bool is_canonical = d->Read<bool>();
@@ -5521,7 +5531,7 @@ static const char* kObjectStoreFieldNames[] = {
55215531
#undef DECLARE_OBJECT_STORE_FIELD
55225532
};
55235533

5524-
void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
5534+
void Serializer::WriteProgramSnapshot(intptr_t num_base_objects,
55255535
ObjectStore* object_store) {
55265536
NoSafepointScope no_safepoint;
55275537

@@ -5532,7 +5542,7 @@ void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
55325542
AddBaseObject(base_objects.At(i));
55335543
}
55345544
} else {
5535-
// Base objects carried over from WriteVMIsolateSnapshot.
5545+
// Base objects carried over from WriteVMSnapshot.
55365546
num_base_objects_ += num_base_objects;
55375547
next_ref_index_ += num_base_objects;
55385548
}
@@ -5813,7 +5823,7 @@ void Deserializer::ReadDispatchTable() {
58135823
}
58145824
ASSERT(repeat_count == 0);
58155825

5816-
I->set_dispatch_table(table);
5826+
I->group()->set_dispatch_table(table);
58175827
#endif
58185828
}
58195829

@@ -6196,7 +6206,7 @@ void Deserializer::ReadVMSnapshot() {
61966206
}
61976207
}
61986208

6199-
void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
6209+
void Deserializer::ReadProgramSnapshot(ObjectStore* object_store) {
62006210
Array& refs = Array::Handle();
62016211
Prepare();
62026212

@@ -6234,22 +6244,21 @@ void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
62346244
thread()->isolate()->class_table()->CopySizesFromClassObjects();
62356245
heap_->old_space()->EvaluateAfterLoading();
62366246

6237-
#if defined(DEBUG)
62386247
Isolate* isolate = thread()->isolate();
6248+
#if defined(DEBUG)
62396249
isolate->ValidateClassTable();
62406250
isolate->heap()->Verify();
62416251
#endif
62426252

62436253
for (intptr_t i = 0; i < num_clusters_; i++) {
62446254
clusters_[i]->PostLoad(refs, kind_, zone_);
62456255
}
6246-
object_store->PostLoad();
6256+
isolate->isolate_object_store()->PreallocateObjects();
62476257

62486258
// Setup native resolver for bootstrap impl.
62496259
Bootstrap::SetupNativeResolver();
62506260
}
62516261

6252-
62536262
#if !defined(DART_PRECOMPILED_RUNTIME)
62546263
FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
62556264
uint8_t** vm_snapshot_data_buffer,
@@ -6324,8 +6333,8 @@ intptr_t FullSnapshotWriter::WriteVMSnapshot() {
63246333
return num_objects;
63256334
}
63266335

6327-
void FullSnapshotWriter::WriteIsolateSnapshot(intptr_t num_base_objects) {
6328-
TIMELINE_DURATION(thread(), Isolate, "WriteIsolateSnapshot");
6336+
void FullSnapshotWriter::WriteProgramSnapshot(intptr_t num_base_objects) {
6337+
TIMELINE_DURATION(thread(), Isolate, "WriteProgramSnapshot");
63296338

63306339
Serializer serializer(thread(), kind_, isolate_snapshot_data_buffer_, alloc_,
63316340
kInitialSize, isolate_image_writer_, /*vm=*/false,
@@ -6344,7 +6353,7 @@ void FullSnapshotWriter::WriteIsolateSnapshot(intptr_t num_base_objects) {
63446353
serializer.WriteVersionAndFeatures(false);
63456354
// Isolate snapshot roots are:
63466355
// - the object store
6347-
serializer.WriteIsolateSnapshot(num_base_objects, object_store);
6356+
serializer.WriteProgramSnapshot(num_base_objects, object_store);
63486357
serializer.FillHeader(serializer.kind());
63496358
clustered_isolate_size_ = serializer.bytes_written();
63506359

@@ -6375,7 +6384,7 @@ void FullSnapshotWriter::WriteFullSnapshot() {
63756384
}
63766385

63776386
if (isolate_snapshot_data_buffer() != NULL) {
6378-
WriteIsolateSnapshot(num_base_objects);
6387+
WriteProgramSnapshot(num_base_objects);
63796388
}
63806389

63816390
if (FLAG_print_snapshot_sizes) {
@@ -6538,7 +6547,7 @@ RawApiError* FullSnapshotReader::ReadVMSnapshot() {
65386547
return ApiError::null();
65396548
}
65406549

6541-
RawApiError* FullSnapshotReader::ReadIsolateSnapshot() {
6550+
RawApiError* FullSnapshotReader::ReadProgramSnapshot() {
65426551
SnapshotHeaderReader header_reader(kind_, buffer_, size_);
65436552
intptr_t offset = 0;
65446553
char* error =
@@ -6564,7 +6573,7 @@ RawApiError* FullSnapshotReader::ReadIsolateSnapshot() {
65646573
}
65656574

65666575
auto object_store = thread_->isolate()->object_store();
6567-
deserializer.ReadIsolateSnapshot(object_store);
6576+
deserializer.ReadProgramSnapshot(object_store);
65686577

65696578
#if defined(DART_PRECOMPILED_RUNTIME)
65706579
if (FLAG_use_bare_instructions) {

runtime/vm/clustered_snapshot.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class Serializer : public ThreadStackResource {
157157
}
158158

159159
intptr_t WriteVMSnapshot(const Array& symbols);
160-
void WriteIsolateSnapshot(intptr_t num_base_objects,
160+
void WriteProgramSnapshot(intptr_t num_base_objects,
161161
ObjectStore* object_store);
162162

163163
void AddVMIsolateBaseObjects();
@@ -539,7 +539,7 @@ class Deserializer : public ThreadStackResource {
539539
// message otherwise.
540540
RawApiError* VerifyImageAlignment();
541541

542-
void ReadIsolateSnapshot(ObjectStore* object_store);
542+
void ReadProgramSnapshot(ObjectStore* object_store);
543543
void ReadVMSnapshot();
544544

545545
void AddVMIsolateBaseObjects();
@@ -682,7 +682,7 @@ class FullSnapshotWriter {
682682
Isolate* isolate() const { return thread_->isolate(); }
683683
Heap* heap() const { return isolate()->heap(); }
684684

685-
// Writes a full snapshot of the Isolate.
685+
// Writes a full snapshot of the program(VM isolate, regular isolate group).
686686
void WriteFullSnapshot();
687687

688688
intptr_t VmIsolateSnapshotSize() const { return vm_isolate_snapshot_size_; }
@@ -692,8 +692,8 @@ class FullSnapshotWriter {
692692
// Writes a snapshot of the VM Isolate.
693693
intptr_t WriteVMSnapshot();
694694

695-
// Writes a full snapshot of a regular Dart Isolate.
696-
void WriteIsolateSnapshot(intptr_t num_base_objects);
695+
// Writes a full snapshot of regular Dart isolate group.
696+
void WriteProgramSnapshot(intptr_t num_base_objects);
697697

698698
Thread* thread_;
699699
Snapshot::Kind kind_;
@@ -724,7 +724,7 @@ class FullSnapshotReader {
724724
~FullSnapshotReader() {}
725725

726726
RawApiError* ReadVMSnapshot();
727-
RawApiError* ReadIsolateSnapshot();
727+
RawApiError* ReadProgramSnapshot();
728728

729729
private:
730730
RawApiError* ConvertToApiError(char* message);

0 commit comments

Comments
 (0)