[vm/concurrency] Guard against concurrent creation of implicit closure functions
Once we share the program structure across isoltes we have to guard
against concurrent lazy creation of implicit closure functions.
Issue https://github.com/dart-lang/sdk/issues/36097
TEST=Tests using --enable-isolate-groups with JIT sharing.
Change-Id: Ia8addf44106bea1b4777f5044c6c862cc76e354c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175067
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f11ffea..9352916 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -8729,15 +8729,23 @@
if (implicit_closure_function() != Function::null()) {
return implicit_closure_function();
}
+
#if defined(DART_PRECOMPILED_RUNTIME)
// In AOT mode all implicit closures are pre-created.
FATAL("Cannot create implicit closure in AOT!");
return Function::null();
#else
ASSERT(!IsSignatureFunction() && !IsClosureFunction());
+
Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+
+ if (implicit_closure_function() != Function::null()) {
+ return implicit_closure_function();
+ }
+
// Create closure function.
+ Zone* zone = thread->zone();
const String& closure_name = String::Handle(zone, name());
const Function& closure_function = Function::Handle(
zone, NewImplicitClosureFunction(closure_name, *this, token_pos()));
@@ -8917,15 +8925,24 @@
InstancePtr Function::ImplicitStaticClosure() const {
ASSERT(IsImplicitStaticClosureFunction());
- if (implicit_static_closure() == Instance::null()) {
- Zone* zone = Thread::Current()->zone();
- const Context& context = Context::Handle(zone);
- Instance& closure =
- Instance::Handle(zone, Closure::New(Object::null_type_arguments(),
- Object::null_type_arguments(),
- *this, context, Heap::kOld));
- set_implicit_static_closure(closure);
+ if (implicit_static_closure() != Instance::null()) {
+ return implicit_static_closure();
}
+
+ auto thread = Thread::Current();
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+
+ if (implicit_static_closure() != Instance::null()) {
+ return implicit_static_closure();
+ }
+
+ Zone* zone = thread->zone();
+ const auto& null_context = Context::Handle(zone);
+ const auto& closure =
+ Instance::Handle(zone, Closure::New(Object::null_type_arguments(),
+ Object::null_type_arguments(), *this,
+ null_context, Heap::kOld));
+ set_implicit_static_closure(closure);
return implicit_static_closure();
}