Skip to content

Commit 9c4a322

Browse files
aamcommit-bot@chromium.org
authored andcommitted
Reland "[vm/isolates] Introduce fast isolate spawn in AOT."
This reverts commit 922ea3e in patchset 1, fix for assertion triggered in https://ci.chromium.org/b/8883214567628884960 in patchset 2, fix for deadlock around symbols table mutex in patchset 4. Original commit description: 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: I655e337198214c9dfacbe76f7852b941b5a7e910 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143462 Commit-Queue: Alexander Aprelev <[email protected]> Reviewed-by: Ryan Macnak <[email protected]>
1 parent cc8cc92 commit 9c4a322

Some content is hidden

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

57 files changed

+1269
-563
lines changed

runtime/lib/isolate.cc

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ var tests = <IsolateTest>[
196196
'limit': 100,
197197
};
198198
var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
199-
expect(result['gcRootType'], 'object store');
199+
expect(result['gcRootType'], 'isolate_object store');
200200
expect(result['elements'].length, 0);
201201
},
202202
];

runtime/vm/class_finalizer.cc

Lines changed: 1 addition & 1 deletion
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

Lines changed: 16 additions & 2 deletions
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_cached_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
}

runtime/vm/class_table.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,6 @@ class ClassTable {
355355

356356
void Print();
357357

358-
// Used by the generated code.
359-
static intptr_t table_offset() { return OFFSET_OF(ClassTable, table_); }
360-
361-
// Used by the generated code.
362-
static intptr_t shared_class_table_offset() {
363-
return OFFSET_OF(ClassTable, shared_class_table_);
364-
}
365-
366358
#ifndef PRODUCT
367359
// Describes layout of heap stats for code generation. See offset_extractor.cc
368360
struct ArrayLayout {
@@ -387,16 +379,21 @@ class ClassTable {
387379
friend class MarkingWeakVisitor;
388380
friend class Scavenger;
389381
friend class ScavengerWeakVisitor;
382+
friend class Dart;
390383
friend Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
391384
const char* name,
392385
char** error);
386+
friend class Isolate; // for table()
393387
static const int kInitialCapacity = SharedClassTable::kInitialCapacity;
394388
static const int kCapacityIncrement = SharedClassTable::kCapacityIncrement;
395389

396390
void AddOldTable(RawClass** old_table);
397391

398392
void Grow(intptr_t index);
399393

394+
RawClass** table() { return table_.load(); }
395+
void set_table(RawClass** table);
396+
400397
intptr_t top_;
401398
intptr_t capacity_;
402399

runtime/vm/clustered_snapshot.cc

Lines changed: 27 additions & 18 deletions
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"
@@ -235,7 +237,8 @@ class ClassSerializationCluster : public SerializationCluster {
235237
UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(Serializer* s,
236238
intptr_t class_id) {
237239
const auto unboxed_fields_bitmap_host =
238-
s->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(class_id);
240+
s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
241+
class_id);
239242

240243
UnboxedFieldBitmap unboxed_fields_bitmap;
241244
if (unboxed_fields_bitmap_host.IsEmpty() ||
@@ -353,7 +356,7 @@ class ClassDeserializationCluster : public DeserializationCluster {
353356
}
354357
}
355358

356-
auto shared_class_table = d->isolate()->group()->class_table();
359+
auto shared_class_table = d->isolate()->group()->shared_class_table();
357360
for (intptr_t id = start_index_; id < stop_index_; id++) {
358361
RawClass* cls = reinterpret_cast<RawClass*>(d->Ref(id));
359362
Deserializer::InitializeHeader(cls, kClassCid, Class::InstanceSize());
@@ -1205,6 +1208,10 @@ class FieldDeserializationCluster : public DeserializationCluster {
12051208
field.InitializeGuardedListLengthInObjectOffset();
12061209
}
12071210
}
1211+
1212+
Isolate* isolate = Isolate::Current();
1213+
isolate->set_saved_initial_field_table(
1214+
std::shared_ptr<FieldTable>(isolate->field_table()->Clone()));
12081215
}
12091216
};
12101217

@@ -3043,7 +3050,8 @@ class InstanceSerializationCluster : public SerializationCluster {
30433050
const intptr_t next_field_offset = host_next_field_offset_in_words_
30443051
<< kWordSizeLog2;
30453052
const auto unboxed_fields_bitmap =
3046-
s->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(cid_);
3053+
s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
3054+
cid_);
30473055
intptr_t offset = Instance::NextFieldOffset();
30483056
while (offset < next_field_offset) {
30493057
// Skips unboxed fields
@@ -3079,7 +3087,8 @@ class InstanceSerializationCluster : public SerializationCluster {
30793087
<< kWordSizeLog2;
30803088
const intptr_t count = objects_.length();
30813089
const auto unboxed_fields_bitmap =
3082-
s->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(cid_);
3090+
s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
3091+
cid_);
30833092
for (intptr_t i = 0; i < count; i++) {
30843093
RawInstance* instance = objects_[i];
30853094
AutoTraceObject(instance);
@@ -3137,7 +3146,8 @@ class InstanceDeserializationCluster : public DeserializationCluster {
31373146
Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
31383147

31393148
const auto unboxed_fields_bitmap =
3140-
d->isolate()->group()->class_table()->GetUnboxedFieldsMapAt(cid_);
3149+
d->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
3150+
cid_);
31413151
for (intptr_t id = start_index_; id < stop_index_; id++) {
31423152
RawInstance* instance = reinterpret_cast<RawInstance*>(d->Ref(id));
31433153
bool is_canonical = d->Read<bool>();
@@ -5542,7 +5552,7 @@ static const char* kObjectStoreFieldNames[] = {
55425552
#undef DECLARE_OBJECT_STORE_FIELD
55435553
};
55445554

5545-
void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
5555+
void Serializer::WriteProgramSnapshot(intptr_t num_base_objects,
55465556
ObjectStore* object_store) {
55475557
NoSafepointScope no_safepoint;
55485558

@@ -5553,7 +5563,7 @@ void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
55535563
AddBaseObject(base_objects.At(i));
55545564
}
55555565
} else {
5556-
// Base objects carried over from WriteVMIsolateSnapshot.
5566+
// Base objects carried over from WriteVMSnapshot.
55575567
num_base_objects_ += num_base_objects;
55585568
next_ref_index_ += num_base_objects;
55595569
}
@@ -5834,7 +5844,7 @@ void Deserializer::ReadDispatchTable() {
58345844
}
58355845
ASSERT(repeat_count == 0);
58365846

5837-
I->set_dispatch_table(table);
5847+
I->group()->set_dispatch_table(table);
58385848
#endif
58395849
}
58405850

@@ -6217,7 +6227,7 @@ void Deserializer::ReadVMSnapshot() {
62176227
}
62186228
}
62196229

6220-
void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
6230+
void Deserializer::ReadProgramSnapshot(ObjectStore* object_store) {
62216231
Array& refs = Array::Handle();
62226232
Prepare();
62236233

@@ -6255,22 +6265,21 @@ void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
62556265
thread()->isolate()->class_table()->CopySizesFromClassObjects();
62566266
heap_->old_space()->EvaluateAfterLoading();
62576267

6258-
#if defined(DEBUG)
62596268
Isolate* isolate = thread()->isolate();
6269+
#if defined(DEBUG)
62606270
isolate->ValidateClassTable();
62616271
isolate->heap()->Verify();
62626272
#endif
62636273

62646274
for (intptr_t i = 0; i < num_clusters_; i++) {
62656275
clusters_[i]->PostLoad(refs, kind_, zone_);
62666276
}
6267-
object_store->PostLoad();
6277+
isolate->isolate_object_store()->PreallocateObjects();
62686278

62696279
// Setup native resolver for bootstrap impl.
62706280
Bootstrap::SetupNativeResolver();
62716281
}
62726282

6273-
62746283
#if !defined(DART_PRECOMPILED_RUNTIME)
62756284
FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
62766285
uint8_t** vm_snapshot_data_buffer,
@@ -6345,8 +6354,8 @@ intptr_t FullSnapshotWriter::WriteVMSnapshot() {
63456354
return num_objects;
63466355
}
63476356

6348-
void FullSnapshotWriter::WriteIsolateSnapshot(intptr_t num_base_objects) {
6349-
TIMELINE_DURATION(thread(), Isolate, "WriteIsolateSnapshot");
6357+
void FullSnapshotWriter::WriteProgramSnapshot(intptr_t num_base_objects) {
6358+
TIMELINE_DURATION(thread(), Isolate, "WriteProgramSnapshot");
63506359

63516360
Serializer serializer(thread(), kind_, isolate_snapshot_data_buffer_, alloc_,
63526361
kInitialSize, isolate_image_writer_, /*vm=*/false,
@@ -6365,7 +6374,7 @@ void FullSnapshotWriter::WriteIsolateSnapshot(intptr_t num_base_objects) {
63656374
serializer.WriteVersionAndFeatures(false);
63666375
// Isolate snapshot roots are:
63676376
// - the object store
6368-
serializer.WriteIsolateSnapshot(num_base_objects, object_store);
6377+
serializer.WriteProgramSnapshot(num_base_objects, object_store);
63696378
serializer.FillHeader(serializer.kind());
63706379
clustered_isolate_size_ = serializer.bytes_written();
63716380

@@ -6396,7 +6405,7 @@ void FullSnapshotWriter::WriteFullSnapshot() {
63966405
}
63976406

63986407
if (isolate_snapshot_data_buffer() != NULL) {
6399-
WriteIsolateSnapshot(num_base_objects);
6408+
WriteProgramSnapshot(num_base_objects);
64006409
}
64016410

64026411
if (FLAG_print_snapshot_sizes) {
@@ -6559,7 +6568,7 @@ RawApiError* FullSnapshotReader::ReadVMSnapshot() {
65596568
return ApiError::null();
65606569
}
65616570

6562-
RawApiError* FullSnapshotReader::ReadIsolateSnapshot() {
6571+
RawApiError* FullSnapshotReader::ReadProgramSnapshot() {
65636572
SnapshotHeaderReader header_reader(kind_, buffer_, size_);
65646573
intptr_t offset = 0;
65656574
char* error =
@@ -6585,7 +6594,7 @@ RawApiError* FullSnapshotReader::ReadIsolateSnapshot() {
65856594
}
65866595

65876596
auto object_store = thread_->isolate()->object_store();
6588-
deserializer.ReadIsolateSnapshot(object_store);
6597+
deserializer.ReadProgramSnapshot(object_store);
65896598

65906599
#if defined(DART_PRECOMPILED_RUNTIME)
65916600
if (FLAG_use_bare_instructions) {

runtime/vm/clustered_snapshot.h

Lines changed: 6 additions & 6 deletions
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);

runtime/vm/code_patcher.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ class CodePatcher : public AllStatic {
6161
const Code& caller_code,
6262
const Object& data,
6363
const Code& target);
64+
static void PatchInstanceCallAtWithMutatorsStopped(Thread* thread,
65+
uword return_address,
66+
const Code& caller_code,
67+
const Object& data,
68+
const Code& target);
6469

6570
// Return target of an unoptimized static call and its ICData object
6671
// (calls target via a stub).
@@ -78,6 +83,11 @@ class CodePatcher : public AllStatic {
7883
const Code& caller_code,
7984
const Object& data,
8085
const Code& target);
86+
static void PatchSwitchableCallAtWithMutatorsStopped(Thread* thread,
87+
uword return_address,
88+
const Code& caller_code,
89+
const Object& data,
90+
const Code& target);
8191
static RawObject* GetSwitchableCallDataAt(uword return_address,
8292
const Code& caller_code);
8393
static RawCode* GetSwitchableCallTargetAt(uword return_address,

0 commit comments

Comments
 (0)