[vm/resolve] Move class finalization out of lookup and resolve function methods.
This is to make sure that lookup can be done without getting a safepoint, which might be needed if class needs to be finalized.
Change-Id: I6ed52a56d53369327df0b85d7b04cf41a46ac690
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/159188
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 532f2f6..0bed69c 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -64,10 +64,12 @@
args.SetAt(6, argument_names);
const Library& libcore = Library::Handle(Library::CoreLibrary());
- const Class& NoSuchMethodError =
+ const Class& cls =
Class::Handle(libcore.LookupClass(Symbols::NoSuchMethodError()));
- const Function& throwNew = Function::Handle(
- NoSuchMethodError.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
+ const auto& error = cls.EnsureIsFinalized(Thread::Current());
+ ASSERT(error == Error::null());
+ const Function& throwNew =
+ Function::Handle(cls.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
const Object& result =
Object::Handle(DartEntry::InvokeFunction(throwNew, args));
ASSERT(result.IsError());
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 20c0e5e..c5faf2a 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -71,6 +71,8 @@
// Now compile the two functions 'A.foo' and 'A.moo'
String& function_moo_name = String::Handle(String::New("moo"));
+ const auto& error = cls.EnsureIsFinalized(thread);
+ EXPECT(error == Error::null());
Function& function_moo =
Function::Handle(cls.LookupStaticFunction(function_moo_name));
EXPECT(CompilerTest::TestCompileFunction(function_moo));
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 174c252..173652f 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -895,8 +895,10 @@
// ensure no arity mismatch crashes.
target_name_ = call_site_.target_name();
args_desc_ = call_site_.arguments_descriptor();
- target_ = Resolver::ResolveDynamicForReceiverClass(
- cls_, target_name_, ArgumentsDescriptor(args_desc_));
+ if (cls_.EnsureIsFinalized(thread_) == Error::null()) {
+ target_ = Resolver::ResolveDynamicForReceiverClass(
+ cls_, target_name_, ArgumentsDescriptor(args_desc_));
+ }
if (!target_.IsNull()) {
if (num_checked_arguments == 1) {
call_site_.AddReceiverCheck(cids[0], target_, entry_usage);
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 5890545..9196b2d 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -538,9 +538,10 @@
if (receiver_maybe_null) {
const Class& null_class =
Class::Handle(zone(), isolate()->object_store()->null_class());
- const Function& target = Function::Handle(
- zone(),
- Resolver::ResolveDynamicAnyArgs(zone(), null_class, method_name));
+ Function& target = Function::Handle(zone());
+ if (null_class.EnsureIsFinalized(thread()) == Error::null()) {
+ target = Resolver::ResolveDynamicAnyArgs(zone(), null_class, method_name);
+ }
if (!target.IsNull()) {
return ToCheck::kCheckCid;
}
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 3eddad6..83edc77 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -301,10 +301,14 @@
// Nothing to do if type is already non-nullable.
return;
}
+ Thread* thread = Thread::Current();
const Class& null_class =
- Class::Handle(Isolate::Current()->object_store()->null_class());
- const Function& target = Function::Handle(Resolver::ResolveDynamicAnyArgs(
- Thread::Current()->zone(), null_class, function_name));
+ Class::Handle(thread->isolate()->object_store()->null_class());
+ Function& target = Function::Handle();
+ if (Error::Handle(null_class.EnsureIsFinalized(thread)).IsNull()) {
+ target = Resolver::ResolveDynamicAnyArgs(thread->zone(), null_class,
+ function_name);
+ }
if (target.IsNull()) {
// If the selector is not defined on Null, we can propagate non-nullness.
CompileType* type = TypeOf(receiver);
diff --git a/runtime/vm/compiler/cha_test.cc b/runtime/vm/compiler/cha_test.cc
index 1cd26e9..2e3d38f 100644
--- a/runtime/vm/compiler/cha_test.cc
+++ b/runtime/vm/compiler/cha_test.cc
@@ -38,6 +38,7 @@
const Class& class_a =
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
EXPECT(!class_a.IsNull());
+ EXPECT(class_a.EnsureIsFinalized(thread) == Error::null());
const Class& class_b =
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "B"))));
@@ -46,10 +47,12 @@
const Class& class_c =
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "C"))));
EXPECT(!class_c.IsNull());
+ EXPECT(class_c.EnsureIsFinalized(thread) == Error::null());
const Class& class_d =
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "D"))));
EXPECT(!class_d.IsNull());
+ EXPECT(class_d.EnsureIsFinalized(thread) == Error::null());
const String& function_foo_name = String::Handle(String::New("foo"));
const String& function_bar_name = String::Handle(String::New("bar"));
@@ -74,7 +77,7 @@
Function::Handle(class_d.LookupDynamicFunction(function_bar_name));
EXPECT(!class_d_bar.IsNull());
- CHA cha(Thread::Current());
+ CHA cha(thread);
EXPECT(cha.HasSubclasses(kInstanceCid));
EXPECT(!cha.HasSubclasses(kSmiCid));
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 5ed4c10..ac59909 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1058,7 +1058,9 @@
const auto& parent = Function::Handle(Z, function.parent_function());
const auto& func_name = String::Handle(Z, parent.name());
const auto& owner = Class::Handle(Z, parent.Owner());
- function = owner.LookupFunction(func_name);
+ if (owner.EnsureIsFinalized(thread_) == Error::null()) {
+ function = owner.LookupFunction(func_name);
+ }
}
Object& options = Object::Handle(Z);
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 4d6eb95..69890d2 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -1452,7 +1452,10 @@
cls.raw() == scoped_function_class_.raw()) {
return scoped_function_.raw();
}
- FunctionPtr function = cls.LookupFunction(name);
+ FunctionPtr function = Function::null();
+ if (cls.EnsureIsFinalized(thread_) == Error::null()) {
+ function = cls.LookupFunction(name);
+ }
if (function == Function::null()) {
// When requesting a getter, also return method extractors.
if (Field::IsGetterName(name)) {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 671deaf..c2d252c 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2454,11 +2454,16 @@
return instructions;
}
-static Function& GetNoSuchMethodOrDie(Zone* zone, const Class& klass) {
+static Function& GetNoSuchMethodOrDie(Thread* thread,
+ Zone* zone,
+ const Class& klass) {
Function& nsm_function = Function::Handle(zone);
Class& iterate_klass = Class::Handle(zone, klass.raw());
while (!iterate_klass.IsNull()) {
- nsm_function = iterate_klass.LookupDynamicFunction(Symbols::NoSuchMethod());
+ if (iterate_klass.EnsureIsFinalized(thread) == Error::null()) {
+ nsm_function =
+ iterate_klass.LookupDynamicFunction(Symbols::NoSuchMethod());
+ }
if (!nsm_function.IsNull() && nsm_function.NumParameters() == 2 &&
nsm_function.NumTypeParameters() == 0) {
break;
@@ -2511,6 +2516,8 @@
const Class& mirror_class =
Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror()));
ASSERT(!mirror_class.IsNull());
+ const auto& error = mirror_class.EnsureIsFinalized(thread());
+ ASSERT(error == Error::null());
const Function& allocation_function = Function::ZoneHandle(
Z, mirror_class.LookupStaticFunction(
Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
@@ -2544,17 +2551,19 @@
// method.
Function& function = Function::Handle(Z);
while (!klass.IsNull()) {
- function = klass.LookupDynamicFunction(method_name);
- if (!function.IsNull()) {
- Function& target =
- Function::ZoneHandle(Z, function.ImplicitClosureFunction());
- ASSERT(!target.IsNull());
- // Generate inline code for allocation closure object with context
- // which captures `this`.
- return BuildImplicitClosureCreation(target);
+ if (klass.EnsureIsFinalized(thread()) == Error::null()) {
+ function = klass.LookupDynamicFunction(method_name);
+ if (!function.IsNull()) {
+ Function& target =
+ Function::ZoneHandle(Z, function.ImplicitClosureFunction());
+ ASSERT(!target.IsNull());
+ // Generate inline code for allocation closure object with context
+ // which captures `this`.
+ return BuildImplicitClosureCreation(target);
+ }
+ function = klass.LookupDynamicFunction(getter_name);
+ if (!function.IsNull()) break;
}
- function = klass.LookupDynamicFunction(getter_name);
- if (!function.IsNull()) break;
klass = klass.SuperClass();
}
@@ -2575,7 +2584,7 @@
/* argument_names = */ Object::empty_array(), actuals_array,
/* build_rest_of_actuals = */ Fragment());
- Function& nsm_function = GetNoSuchMethodOrDie(Z, parent_klass);
+ Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, parent_klass);
instructions +=
StaticCall(position, Function::ZoneHandle(Z, nsm_function.raw()),
/* argument_count = */ 2, ICData::kNSMDispatch);
@@ -2603,8 +2612,10 @@
const String& setter_name = ReadNameAsSetterName(); // read name.
- Function& function =
- Function::Handle(Z, H.LookupDynamicFunction(klass, setter_name));
+ Function& function = Function::Handle(Z);
+ if (klass.EnsureIsFinalized(thread()) == Error::null()) {
+ function = H.LookupDynamicFunction(klass, setter_name);
+ }
Fragment instructions(MakeTemp());
LocalVariable* value = MakeTemporary(); // this holds RHS value
@@ -2631,7 +2642,7 @@
SkipInterfaceMemberNameReference(); // skip target_reference.
- Function& nsm_function = GetNoSuchMethodOrDie(Z, klass);
+ Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, klass);
instructions +=
StaticCall(position, Function::ZoneHandle(Z, nsm_function.raw()),
/* argument_count = */ 2, ICData::kNSMDispatch);
@@ -3219,7 +3230,7 @@
SkipInterfaceMemberNameReference(); // skip target_reference.
- Function& nsm_function = GetNoSuchMethodOrDie(Z, klass);
+ Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, klass);
instructions += StaticCall(TokenPosition::kNoSource,
Function::ZoneHandle(Z, nsm_function.raw()),
/* argument_count = */ 2, ICData::kNSMDispatch);
@@ -3858,9 +3869,11 @@
const Class& map_class =
Class::Handle(Z, Library::LookupCoreClass(Symbols::Map()));
- const Function& factory_method = Function::ZoneHandle(
- Z, map_class.LookupFactory(
- Library::PrivateCoreLibName(Symbols::MapLiteralFactory())));
+ Function& factory_method = Function::ZoneHandle(Z);
+ if (map_class.EnsureIsFinalized(H.thread()) == Error::null()) {
+ factory_method = map_class.LookupFactory(
+ Library::PrivateCoreLibName(Symbols::MapLiteralFactory()));
+ }
return instructions +
StaticCall(position, factory_method, 2, ICData::kStatic);
@@ -3964,6 +3977,8 @@
if (position != NULL) *position = TokenPosition::kNoSource;
const Class& future = Class::Handle(Z, I->object_store()->future_class());
ASSERT(!future.IsNull());
+ const auto& error = future.EnsureIsFinalized(thread());
+ ASSERT(error == Error::null());
const Function& constructor =
Function::ZoneHandle(Z, future.LookupFunction(Symbols::FutureValue()));
ASSERT(!constructor.IsNull());
@@ -4500,6 +4515,8 @@
const Class& klass = Class::ZoneHandle(
Z, Library::LookupCoreClass(Symbols::FallThroughError()));
ASSERT(!klass.IsNull());
+ const auto& error = klass.EnsureIsFinalized(thread());
+ ASSERT(error == Error::null());
GrowableHandlePtrArray<const String> pieces(Z, 3);
pieces.Add(Symbols::FallThroughError());
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 712deec..eae3173 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -444,6 +444,8 @@
Z, Library::LookupCoreClass(Symbols::LateInitializationError()));
ASSERT(!klass.IsNull());
+ const auto& error = klass.EnsureIsFinalized(thread_);
+ ASSERT(error == Error::null());
const Function& throw_new =
Function::ZoneHandle(Z, klass.LookupStaticFunctionAllowPrivate(
H.DartSymbolObfuscate("_throwNew")));
@@ -671,6 +673,8 @@
const Class& klass = Class::ZoneHandle(
Z, Library::LookupCoreClass(Symbols::NoSuchMethodError()));
ASSERT(!klass.IsNull());
+ const auto& error = klass.EnsureIsFinalized(H.thread());
+ ASSERT(error == Error::null());
const Function& throw_function = Function::ZoneHandle(
Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNew()));
ASSERT(!throw_function.IsNull());
@@ -1552,6 +1556,8 @@
const Class& klass =
Class::ZoneHandle(Z, Library::LookupCoreClass(Symbols::AssertionError()));
ASSERT(!klass.IsNull());
+ const auto& error = klass.EnsureIsFinalized(H.thread());
+ ASSERT(error == Error::null());
const Function& target = Function::ZoneHandle(
Z, klass.LookupStaticFunctionAllowPrivate(Symbols::EvaluateAssertion()));
ASSERT(!target.IsNull());
@@ -1904,6 +1910,8 @@
const Class& mirror_class =
Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror()));
ASSERT(!mirror_class.IsNull());
+ const auto& error = mirror_class.EnsureIsFinalized(H.thread());
+ ASSERT(error == Error::null());
const Function& allocation_function = Function::ZoneHandle(
Z, mirror_class.LookupStaticFunction(
Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
@@ -2637,6 +2645,8 @@
const Class& mirror_class =
Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror()));
ASSERT(!mirror_class.IsNull());
+ const auto& error = mirror_class.EnsureIsFinalized(H.thread());
+ ASSERT(error == Error::null());
const Function& allocation_function = Function::ZoneHandle(
Z, mirror_class.LookupStaticFunction(Library::PrivateCoreLibName(
Symbols::AllocateInvocationMirrorForClosure())));
@@ -2648,6 +2658,8 @@
const Class& klass = Class::ZoneHandle(
Z, Library::LookupCoreClass(Symbols::NoSuchMethodError()));
ASSERT(!klass.IsNull());
+ const auto& error = klass.EnsureIsFinalized(H.thread());
+ ASSERT(error == Error::null());
const Function& throw_function = Function::ZoneHandle(
Z,
klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNewInvocation()));
@@ -3566,6 +3578,8 @@
const Class& klass = Class::ZoneHandle(
Z, Library::LookupCoreClass(Symbols::AssertionError()));
ASSERT(!klass.IsNull());
+ const auto& error = klass.EnsureIsFinalized(H.thread());
+ ASSERT(error == Error::null());
throw_new_null_assertion_ =
&Function::ZoneHandle(Z, klass.LookupStaticFunctionAllowPrivate(
Symbols::ThrowNewNullAssertion()));
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 1785105..b185b81 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -623,6 +623,8 @@
} else {
ASSERT(IsClass(enclosing));
Class& klass = Class::Handle(Z, LookupClassByKernelClass(enclosing));
+ const auto& error = klass.EnsureIsFinalized(thread_);
+ ASSERT(error == Error::null());
Function& function = Function::ZoneHandle(
Z, klass.LookupFunctionAllowPrivate(procedure_name));
CheckStaticLookup(function);
@@ -646,6 +648,8 @@
const Class& owner,
NameIndex constructor) {
ASSERT(IsConstructor(constructor));
+ const auto& error = owner.EnsureIsFinalized(thread_);
+ ASSERT(error == Error::null());
Function& function = Function::Handle(
Z, owner.LookupConstructorAllowPrivate(DartConstructorName(constructor)));
CheckStaticLookup(function);
@@ -663,6 +667,8 @@
String& new_name =
String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces));
+ const auto& error = owner.EnsureIsFinalized(thread_);
+ ASSERT(error == Error::null());
FunctionPtr function = owner.LookupConstructorAllowPrivate(new_name);
ASSERT(function != Object::null());
return function;
@@ -672,9 +678,10 @@
const String& method_name) {
NameIndex kernel_class = EnclosingName(target);
Class& klass = Class::Handle(Z, LookupClassByKernelClass(kernel_class));
-
- Function& function =
- Function::Handle(Z, klass.LookupFunctionAllowPrivate(method_name));
+ Function& function = Function::Handle(Z);
+ if (klass.EnsureIsFinalized(thread_) == Error::null()) {
+ function = klass.LookupFunctionAllowPrivate(method_name);
+ }
#ifdef DEBUG
if (function.IsNull()) {
THR_Print("Unable to find \'%s\' in %s\n", method_name.ToCString(),
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index fc900fa..219dc7c 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -36,6 +36,8 @@
Class& cls =
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
EXPECT(!cls.IsNull());
+ const auto& error = cls.EnsureIsFinalized(thread);
+ EXPECT(error == Error::null());
String& function_foo_name = String::Handle(String::New("foo"));
Function& function_foo =
Function::Handle(cls.LookupStaticFunction(function_foo_name));
@@ -75,6 +77,8 @@
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
EXPECT(!cls.IsNull());
String& function_foo_name = String::Handle(String::New("foo"));
+ const auto& error = cls.EnsureIsFinalized(thread);
+ EXPECT(error == Error::null());
Function& func =
Function::Handle(cls.LookupStaticFunction(function_foo_name));
EXPECT(!func.HasCode());
@@ -116,6 +120,8 @@
Class& cls =
Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
EXPECT(!cls.IsNull());
+ const auto& error = cls.EnsureIsFinalized(thread);
+ EXPECT(error == Error::null());
String& function_foo_name = String::Handle(String::New("foo"));
Function& func =
Function::Handle(cls.LookupStaticFunction(function_foo_name));
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 95ae9bb..e867ce4 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2828,6 +2828,11 @@
"cls_type must be a Type object which represents a Class");
}
+ const auto& error = klass.EnsureIsFinalized(Thread::Current());
+ if (error != Error::null()) {
+ return Api::NewHandle(T, error);
+ }
+
const String& func_name = Api::UnwrapStringHandle(Z, function_name);
if (func_name.IsNull()) {
RETURN_TYPE_ERROR(Z, function_name, String);
@@ -4330,8 +4335,10 @@
const String& constr_name,
int num_args) {
// The constructor must be present in the interface.
- const Function& constructor =
- Function::Handle(cls.LookupFunctionAllowPrivate(constr_name));
+ Function& constructor = Function::Handle();
+ if (cls.EnsureIsFinalized(Thread::Current()) == Error::null()) {
+ constructor = cls.LookupFunctionAllowPrivate(constr_name);
+ }
if (constructor.IsNull() ||
(!constructor.IsGenerativeConstructor() && !constructor.IsFactory())) {
const String& lookup_class_name = String::Handle(cls.Name());
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 8cb10d9..96081a8 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -335,6 +335,9 @@
Class& invocation_mirror_class = Class::Handle(core_lib.LookupClass(
String::Handle(core_lib.PrivateName(Symbols::InvocationMirror()))));
ASSERT(!invocation_mirror_class.IsNull());
+ Thread* thread = Thread::Current();
+ const auto& error = invocation_mirror_class.EnsureIsFinalized(thread);
+ ASSERT(error == Error::null());
const String& function_name =
String::Handle(core_lib.PrivateName(Symbols::AllocateInvocationMirror()));
const Function& allocation_function = Function::Handle(
@@ -363,7 +366,6 @@
if (function.IsNull()) {
ASSERT(!FLAG_lazy_dispatchers);
// If noSuchMethod(invocation) is not found, call Object::noSuchMethod.
- Thread* thread = Thread::Current();
function = Resolver::ResolveDynamicForReceiverClass(
Class::Handle(thread->zone(),
thread->isolate()->object_store()->object_class()),
@@ -643,6 +645,9 @@
const int kNumArguments = 1; // Receiver.
ArgumentsDescriptor args_desc(Array::Handle(
ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArguments)));
+ const Class& receiver_class = Class::Handle(receiver.clazz());
+ const auto& error = receiver_class.EnsureIsFinalized(Thread::Current());
+ ASSERT(error == Error::null());
const Function& function = Function::Handle(
Resolver::ResolveDynamic(receiver, Symbols::toString(), args_desc));
ASSERT(!function.IsNull());
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 2ea406b..5f37ada 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -3991,8 +3991,11 @@
(library_url() != nullptr ? library_url() : script_url())));
return LanguageError::New(msg);
}
- const Function& func =
- Function::Handle(zone, cls.LookupStaticFunctionAllowPrivate(func_name));
+ Function& func = Function::Handle(zone);
+ const auto& error = cls.EnsureIsFinalized(thread);
+ if (error == Error::null()) {
+ func = cls.LookupStaticFunctionAllowPrivate(func_name);
+ }
if (func.IsNull()) {
const String& msg = String::Handle(
zone, String::NewFormatted(
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 25c9549..cc72376 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3598,6 +3598,9 @@
const Function& closure_function =
Function::Handle(ImplicitClosureFunction());
const Class& owner = Class::Handle(closure_function.Owner());
+ if (owner.EnsureIsFinalized(Thread::Current()) != Error::null()) {
+ return Function::null();
+ }
Function& result = Function::Handle(owner.LookupDynamicFunction(getter_name));
if (result.IsNull()) {
result = CreateMethodExtractor(getter_name);
@@ -3947,10 +3950,13 @@
args.SetAt(6, argument_names);
const Library& libcore = Library::Handle(Library::CoreLibrary());
- const Class& NoSuchMethodError =
+ const Class& cls =
Class::Handle(libcore.LookupClass(Symbols::NoSuchMethodError()));
- const Function& throwNew = Function::Handle(
- NoSuchMethodError.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
+ ASSERT(!cls.IsNull());
+ const auto& error = cls.EnsureIsFinalized(Thread::Current());
+ ASSERT(error == Error::null());
+ const Function& throwNew =
+ Function::Handle(cls.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
return DartEntry::InvokeFunction(throwNew, args);
}
@@ -3966,10 +3972,12 @@
args.SetAt(3, dst_name);
const Library& libcore = Library::Handle(Library::CoreLibrary());
- const Class& TypeError =
+ const Class& cls =
Class::Handle(libcore.LookupClassAllowPrivate(Symbols::TypeError()));
- const Function& throwNew = Function::Handle(
- TypeError.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
+ const auto& error = cls.EnsureIsFinalized(Thread::Current());
+ ASSERT(error == Error::null());
+ const Function& throwNew =
+ Function::Handle(cls.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
return DartEntry::InvokeFunction(throwNew, args);
}
@@ -5337,9 +5345,7 @@
FunctionPtr Class::LookupFunction(const String& name, MemberKind kind) const {
ASSERT(!IsNull());
Thread* thread = Thread::Current();
- if (EnsureIsFinalized(thread) != Error::null()) {
- return Function::null();
- }
+ RELEASE_ASSERT(is_finalized());
REUSABLE_ARRAY_HANDLESCOPE(thread);
REUSABLE_FUNCTION_HANDLESCOPE(thread);
Array& funcs = thread->ArrayHandle();
@@ -5389,9 +5395,7 @@
MemberKind kind) const {
ASSERT(!IsNull());
Thread* thread = Thread::Current();
- if (EnsureIsFinalized(thread) != Error::null()) {
- return Function::null();
- }
+ RELEASE_ASSERT(is_finalized());
REUSABLE_ARRAY_HANDLESCOPE(thread);
REUSABLE_FUNCTION_HANDLESCOPE(thread);
REUSABLE_STRING_HANDLESCOPE(thread);
@@ -9033,6 +9037,8 @@
const auto& parent = Function::Handle(zone, parent_function());
const auto& func_name = String::Handle(zone, parent.name());
const auto& owner = Class::Handle(zone, parent.Owner());
+ const auto& error = owner.EnsureIsFinalized(Thread::Current());
+ ASSERT(error == Error::null());
auto& target = Function::Handle(zone, owner.LookupFunction(func_name));
if (!target.IsNull() && (target.raw() != parent.raw())) {
@@ -13974,11 +13980,13 @@
class_str = String::New(class_name);
cls = lib.LookupClassAllowPrivate(class_str);
if (!cls.IsNull()) {
- func_str = String::New(function_name);
- if (function_name[0] == '.') {
- func_str = String::Concat(class_str, func_str);
+ if (cls.EnsureIsFinalized(thread) == Error::null()) {
+ func_str = String::New(function_name);
+ if (function_name[0] == '.') {
+ func_str = String::Concat(class_str, func_str);
+ }
+ func = cls.LookupFunctionAllowPrivate(func_str);
}
- func = cls.LookupFunctionAllowPrivate(func_str);
}
}
if (!func.IsNull()) {
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 26a5c3a..37b39ac 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -191,6 +191,8 @@
const Library& core_lib = Library::Handle(core_library());
const String& mangled = String::ZoneHandle(core_lib.PrivateName(name));
const Class& cls = Class::Handle(object_class());
+ const auto& error = cls.EnsureIsFinalized(Thread::Current());
+ ASSERT(error == Error::null());
const Function& result = Function::Handle(cls.LookupDynamicFunction(mangled));
ASSERT(!result.IsNull());
return result.raw();
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 2d3b16e..68f2de9 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3709,6 +3709,8 @@
}
static FunctionPtr GetFunction(const Class& cls, const char* name) {
+ const auto& error = cls.EnsureIsFinalized(Thread::Current());
+ EXPECT(error == Error::null());
const Function& result = Function::Handle(
cls.LookupDynamicFunction(String::Handle(String::New(name))));
EXPECT(!result.IsNull());
@@ -3716,6 +3718,8 @@
}
static FunctionPtr GetStaticFunction(const Class& cls, const char* name) {
+ const auto& error = cls.EnsureIsFinalized(Thread::Current());
+ EXPECT(error == Error::null());
const Function& result = Function::Handle(
cls.LookupStaticFunction(String::Handle(String::New(name))));
EXPECT(!result.IsNull());
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index a17e9c6..cf921ac 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1373,9 +1373,11 @@
ASSERT(function_name.IsSymbol());
const Class& receiver_class = Class::Handle(zone, receiver.clazz());
- Function& target_function = Function::Handle(
- zone, Resolver::ResolveDynamicForReceiverClass(
- receiver_class, function_name, arguments_descriptor));
+ Function& target_function = Function::Handle(zone);
+ if (receiver_class.EnsureIsFinalized(thread) == Error::null()) {
+ target_function = Resolver::ResolveDynamicForReceiverClass(
+ receiver_class, function_name, arguments_descriptor);
+ }
ObjectStore* store = thread->isolate()->object_store();
if (target_function.raw() == store->simple_instance_of_function()) {
@@ -1742,16 +1744,19 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-static FunctionPtr Resolve(Zone* zone,
+static FunctionPtr Resolve(Thread* thread,
+ Zone* zone,
const Class& receiver_class,
const String& name,
const Array& descriptor) {
ASSERT(name.IsSymbol());
ArgumentsDescriptor args_desc(descriptor);
- Function& target_function =
- Function::Handle(zone, Resolver::ResolveDynamicForReceiverClass(
- receiver_class, name, args_desc));
+ Function& target_function = Function::Handle(zone);
+ if (receiver_class.EnsureIsFinalized(thread) == Error::null()) {
+ target_function = Resolver::ResolveDynamicForReceiverClass(receiver_class,
+ name, args_desc);
+ }
if (target_function.IsNull()) {
target_function = InlineCacheMissHelper(receiver_class, descriptor, name);
@@ -1777,7 +1782,8 @@
const auto& old_receiver_class =
Class::Handle(zone_, isolate_->class_table()->At(old_expected_cid));
const auto& old_target = Function::Handle(
- zone_, Resolve(zone_, old_receiver_class, name_, args_descriptor_));
+ zone_,
+ Resolve(thread_, zone_, old_receiver_class, name_, args_descriptor_));
const ICData& ic_data = ICData::Handle(
zone_, ICData::New(caller_function_, name_, args_descriptor_,
@@ -2052,7 +2058,7 @@
UNREACHABLE();
}
const Class& cls = Class::Handle(zone_, receiver_.clazz());
- return Resolve(zone_, cls, name_, args_descriptor_);
+ return Resolve(thread_, zone_, cls, name_, args_descriptor_);
}
void SwitchableCallHandler::HandleMiss(const Object& old_data,
@@ -2169,15 +2175,17 @@
const Array& arg_desc = Array::CheckedHandle(zone, arguments.ArgAt(2));
ArgumentsDescriptor arguments_descriptor(arg_desc);
- Function& target_function = Function::Handle(
- zone,
- Resolver::ResolveDynamic(receiver, target_name, arguments_descriptor));
+ const Class& receiver_class = Class::Handle(zone, receiver.clazz());
+ Function& target_function = Function::Handle(zone);
+ if (receiver_class.EnsureIsFinalized(thread) == Error::null()) {
+ target_function =
+ Resolver::ResolveDynamic(receiver, target_name, arguments_descriptor);
+ }
// TODO(regis): In order to substitute 'simple_instance_of_function', the 2nd
// arg to the call, the type, is needed.
if (target_function.IsNull()) {
- const Class& receiver_class = Class::Handle(zone, receiver.clazz());
target_function =
InlineCacheMissHelper(receiver_class, arg_desc, target_name);
}
@@ -2190,6 +2198,7 @@
// invoking noSuchMethod when lazy dispatchers are disabled. Returns the
// result of the invocation or an Error.
static ObjectPtr InvokeCallThroughGetterOrNoSuchMethod(
+ Thread* thread,
Zone* zone,
const Instance& receiver,
const String& target_name,
@@ -2222,7 +2231,9 @@
// We don't generate dyn:* forwarders for method extractors so there is no
// need to try to find a dyn:get:foo first (see assertion below)
if (function.IsNull()) {
- function = cls.LookupDynamicFunction(function_name);
+ if (cls.EnsureIsFinalized(thread) == Error::null()) {
+ function = cls.LookupDynamicFunction(function_name);
+ }
}
if (!function.IsNull()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -2280,7 +2291,9 @@
while (!cls.IsNull()) {
// If there is a function with the target name but mismatched arguments
// we need to call `receiver.noSuchMethod()`.
- function = cls.LookupDynamicFunction(target_name);
+ if (cls.EnsureIsFinalized(thread) == Error::null()) {
+ function = cls.LookupDynamicFunction(target_name);
+ }
if (!function.IsNull()) {
ASSERT(!function.AreValidArguments(args_desc, NULL));
break; // mismatch, invoke noSuchMethod
@@ -2359,10 +2372,10 @@
target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
}
- const auto& result = Object::Handle(
- zone,
- InvokeCallThroughGetterOrNoSuchMethod(
- zone, receiver, target_name, orig_arguments, orig_arguments_desc));
+ const auto& result =
+ Object::Handle(zone, InvokeCallThroughGetterOrNoSuchMethod(
+ thread, zone, receiver, target_name,
+ orig_arguments, orig_arguments_desc));
ThrowIfError(result);
arguments.SetReturn(result);
}
@@ -2417,7 +2430,7 @@
// Failing to find the method could be due to the lack of lazy invoke field
// dispatchers, so attempt a deeper search before calling noSuchMethod.
result = InvokeCallThroughGetterOrNoSuchMethod(
- zone, receiver, original_function_name, orig_arguments,
+ thread, zone, receiver, original_function_name, orig_arguments,
orig_arguments_desc);
} else {
result = DartEntry::InvokeNoSuchMethod(receiver, original_function_name,