[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,