Skip to content

Commit ef4e39a

Browse files
aamCommit Queue
authored andcommitted
[vm/shared] Ensure exclusive execution of shared field initialization.
Add a mutex to guard execution of vm:shared field initialization. TEST=isolate_group_shared_init_test BUG=dartbug.com/60699 Change-Id: If544351fc26bfcc7fb9703954efe785989d488bc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431742 Commit-Queue: Alexander Aprelev <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 903d77c commit ef4e39a

File tree

16 files changed

+1362
-1198
lines changed

16 files changed

+1362
-1198
lines changed

runtime/vm/compiler/asm_intrinsifier_riscv.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,20 +2035,20 @@ void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
20352035
__ LoadImmediate(A0, target::ToRawSmi(0));
20362036
__ ret();
20372037
#elif XLEN == 64
2038-
__ ld(A0, Address(THR, target::Thread::next_task_id_offset()));
2038+
__ LoadFromOffset(A0, THR, target::Thread::next_task_id_offset());
20392039
__ addi(A1, A0, 1);
2040-
__ sd(A1, Address(THR, target::Thread::next_task_id_offset()));
2040+
__ StoreToOffset(A1, THR, target::Thread::next_task_id_offset());
20412041
__ SmiTag(A0); // Ignore loss of precision.
20422042
__ ret();
20432043
#else
2044-
__ lw(T0, Address(THR, target::Thread::next_task_id_offset()));
2045-
__ lw(T1, Address(THR, target::Thread::next_task_id_offset() + 4));
2044+
__ LoadFromOffset(T0, THR, target::Thread::next_task_id_offset());
2045+
__ LoadFromOffset(T1, THR, target::Thread::next_task_id_offset() + 4);
20462046
__ SmiTag(A0, T0); // Ignore loss of precision.
20472047
__ addi(T2, T0, 1);
20482048
__ sltu(T3, T2, T0); // Carry.
20492049
__ add(T1, T1, T3);
2050-
__ sw(T2, Address(THR, target::Thread::next_task_id_offset()));
2051-
__ sw(T1, Address(THR, target::Thread::next_task_id_offset() + 4));
2050+
__ StoreToOffset(T2, THR, target::Thread::next_task_id_offset());
2051+
__ StoreToOffset(T1, THR, target::Thread::next_task_id_offset() + 4);
20522052
__ ret();
20532053
#endif
20542054
}

runtime/vm/compiler/backend/il.cc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4574,10 +4574,7 @@ void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
45744574
original_field.EnsureInitializerFunction();
45754575
}
45764576
stub = field().is_shared()
4577-
? (field().is_final()
4578-
? object_store
4579-
->init_shared_late_final_static_field_stub()
4580-
: object_store->init_shared_late_static_field_stub())
4577+
? object_store->init_shared_late_static_field_stub()
45814578
: (field().is_final()
45824579
? object_store->init_late_final_static_field_stub()
45834580
: object_store->init_late_static_field_stub());

runtime/vm/compiler/runtime_offsets_extracted.h

Lines changed: 1144 additions & 1144 deletions
Large diffs are not rendered by default.

runtime/vm/compiler/stub_code_compiler.cc

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,26 @@ void StubCodeCompiler::GenerateInitLateStaticFieldStub(bool is_final,
9191

9292
__ EnterStubFrame();
9393

94+
if (FLAG_experimental_shared_data && is_shared) {
95+
// Since initialization of shared fields has to be guarded by
96+
// a mutex, do the initialization in the runtime.
97+
__ PushObject(NullObject()); // Make room for the result
98+
__ PushRegister(kFieldReg);
99+
__ CallRuntime(kInitializeSharedFieldRuntimeEntry, /*argument_count=*/1);
100+
__ PopRegister(kFieldReg);
101+
__ PopRegister(kResultReg);
102+
__ LeaveStubFrame();
103+
__ Ret();
104+
return;
105+
}
106+
94107
Label throw_since_no_isolate_is_present;
95108
if (FLAG_experimental_shared_data) {
96-
if (!is_shared) {
97-
// This stub is also called from mutator thread running without an
98-
// isolate and attempts to load value from isolate static field.
99-
__ LoadIsolate(kScratchReg);
100-
__ BranchIfZero(kScratchReg, &throw_since_no_isolate_is_present);
101-
}
109+
ASSERT(!is_shared);
110+
// This stub is also called from mutator thread running without an
111+
// isolate and attempts to load value from isolate static field.
112+
__ LoadIsolate(kScratchReg);
113+
__ BranchIfZero(kScratchReg, &throw_since_no_isolate_is_present);
102114
}
103115

104116
__ Comment("Calling initializer function");
@@ -143,20 +155,19 @@ void StubCodeCompiler::GenerateInitLateStaticFieldStub(bool is_final,
143155
}
144156

145157
if (FLAG_experimental_shared_data) {
146-
if (!is_shared) {
158+
ASSERT(!is_shared);
147159
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
148-
// We are jumping over LeaveStubFrame so restore LR state to match one
149-
// at the jump point.
150-
__ set_lr_state(compiler::LRState::OnEntry().EnterFrame());
160+
// We are jumping over LeaveStubFrame so restore LR state to match one
161+
// at the jump point.
162+
__ set_lr_state(compiler::LRState::OnEntry().EnterFrame());
151163
#endif // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
152-
// Throw FieldAccessError
153-
__ Bind(&throw_since_no_isolate_is_present);
154-
__ PushObject(NullObject()); // Make room for (unused) result.
155-
__ PushRegister(kFieldReg);
156-
__ CallRuntime(kStaticFieldAccessedWithoutIsolateErrorRuntimeEntry,
157-
/*argument_count=*/1);
158-
__ Breakpoint();
159-
}
164+
// Throw FieldAccessError
165+
__ Bind(&throw_since_no_isolate_is_present);
166+
__ PushObject(NullObject()); // Make room for (unused) result.
167+
__ PushRegister(kFieldReg);
168+
__ CallRuntime(kStaticFieldAccessedWithoutIsolateErrorRuntimeEntry,
169+
/*argument_count=*/1);
170+
__ Breakpoint();
160171
}
161172
}
162173

@@ -172,10 +183,6 @@ void StubCodeCompiler::GenerateInitSharedLateStaticFieldStub() {
172183
GenerateInitLateStaticFieldStub(/*is_final=*/false, /*is_shared=*/true);
173184
}
174185

175-
void StubCodeCompiler::GenerateInitSharedLateFinalStaticFieldStub() {
176-
GenerateInitLateStaticFieldStub(/*is_final=*/true, /*is_shared=*/true);
177-
}
178-
179186
void StubCodeCompiler::GenerateInitInstanceFieldStub() {
180187
__ EnterStubFrame();
181188
__ PushObject(NullObject()); // Make room for result.

runtime/vm/compiler/stub_code_compiler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ class StubCodeCompiler {
190190

191191
// Common function for generating InitLateStaticField,
192192
// InitLateFinalStaticField, InitSharedLateStaticField,
193-
// InitSharedLateFinalStaticField,
194193
void GenerateInitLateStaticFieldStub(bool is_final, bool is_shared);
195194

196195
// Common function for generating InitLateInstanceField and

runtime/vm/isolate.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
354354
kernel_data_lib_cache_mutex_(),
355355
kernel_data_class_cache_mutex_(),
356356
kernel_constants_mutex_(),
357+
shared_field_initializer_rwlock_(),
357358
field_list_mutex_(),
358359
boxed_field_list_(GrowableObjectArray::null()),
359360
program_lock_(new SafepointRwLock(SafepointLevel::kGCAndDeopt)),
@@ -890,6 +891,7 @@ void IsolateGroup::FreeStaticField(const Field& field) {
890891
const intptr_t field_id = field.field_id();
891892
if (field.is_shared()) {
892893
shared_field_table()->Free(field_id);
894+
shared_initial_field_table()->Free(field_id);
893895
} else {
894896
initial_field_table()->Free(field_id);
895897
sentinel_field_table()->Free(field_id);

runtime/vm/isolate.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,10 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
534534
Mutex* initializer_functions_mutex() { return &initializer_functions_mutex_; }
535535
#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)
536536

537+
SafepointRwLock* shared_field_initializer_rwlock() {
538+
return &shared_field_initializer_rwlock_;
539+
}
540+
537541
SafepointRwLock* program_lock() { return program_lock_.get(); }
538542

539543
static inline IsolateGroup* Current() {
@@ -936,6 +940,9 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
936940
Mutex initializer_functions_mutex_;
937941
#endif // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)
938942

943+
// Ensure exclusive execution of shared field initializers.
944+
SafepointRwLock shared_field_initializer_rwlock_;
945+
939946
// Protect access to boxed_field_list_.
940947
Mutex field_list_mutex_;
941948
// List of fields that became boxed and that trigger deoptimization.

runtime/vm/object.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13430,7 +13430,6 @@ TypePtr Class::GetInstantiationOf(Zone* zone, const Type& type) const {
1343013430
}
1343113431

1343213432
void Field::SetStaticValue(const Object& value) const {
13433-
ASSERT(!is_shared());
1343413433
auto thread = Thread::Current();
1343513434
ASSERT(thread->IsDartMutatorThread());
1343613435
ASSERT(value.IsNull() || value.IsSentinel() || value.IsInstance());
@@ -13440,7 +13439,11 @@ void Field::SetStaticValue(const Object& value) const {
1344013439
ASSERT(id >= 0);
1344113440

1344213441
SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
13443-
thread->isolate()->field_table()->SetAt(id, value.ptr());
13442+
if (is_shared()) {
13443+
thread->isolate_group()->shared_field_table()->SetAt(id, value.ptr());
13444+
} else {
13445+
thread->isolate()->field_table()->SetAt(id, value.ptr());
13446+
}
1344413447
}
1344513448

1344613449
static StaticTypeExactnessState TrivialTypeExactnessFor(const Class& cls) {

runtime/vm/object.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13399,7 +13399,9 @@ void Field::SetOffset(intptr_t host_offset_in_bytes,
1339913399

1340013400
ObjectPtr Field::StaticValue() const {
1340113401
ASSERT(is_static()); // Valid only for static dart fields.
13402-
return Isolate::Current()->field_table()->At(field_id());
13402+
return is_shared()
13403+
? IsolateGroup::Current()->shared_field_table()->At(field_id())
13404+
: Isolate::Current()->field_table()->At(field_id());
1340313405
}
1340413406

1340513407
inline intptr_t Field::field_id() const {

runtime/vm/object_store.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ class ObjectPointerVisitor;
268268
RW(Code, init_late_instance_field_stub) \
269269
RW(Code, init_late_final_instance_field_stub) \
270270
RW(Code, init_shared_late_static_field_stub) \
271-
RW(Code, init_shared_late_final_static_field_stub) \
272271
RW(Code, call_closure_no_such_method_stub) \
273272
RW(Code, default_tts_stub) \
274273
RW(Code, default_nullable_tts_stub) \
@@ -383,7 +382,6 @@ class ObjectPointerVisitor;
383382
DO(init_late_instance_field_stub, InitLateInstanceField) \
384383
DO(init_late_final_instance_field_stub, InitLateFinalInstanceField) \
385384
DO(init_shared_late_static_field_stub, InitSharedLateStaticField) \
386-
DO(init_shared_late_final_static_field_stub, InitSharedLateFinalStaticField) \
387385
DO(await_stub, Await) \
388386
DO(await_with_type_check_stub, AwaitWithTypeCheck) \
389387
DO(clone_suspend_state_stub, CloneSuspendState) \

0 commit comments

Comments
 (0)