44
55#include " vm/object.h"
66
7+ #include " lib/invocation_mirror.h"
78#include " platform/unaligned.h"
89#include " vm/code_patcher.h"
910#include " vm/dart_entry.h"
@@ -41,12 +42,15 @@ void CallSiteResetter::ZeroEdgeCounters(const Function& function) {
4142}
4243
4344CallSiteResetter::CallSiteResetter (Zone* zone)
44- : zone_(zone),
45+ : thread_(Thread::Current()),
46+ zone_(zone),
4547 instrs_(Instructions::Handle(zone)),
4648 pool_(ObjectPool::Handle(zone)),
4749 object_(Object::Handle(zone)),
4850 name_(String::Handle(zone)),
51+ old_cls_(Class::Handle(zone)),
4952 new_cls_(Class::Handle(zone)),
53+ old_lib_(Library::Handle(zone)),
5054 new_lib_(Library::Handle(zone)),
5155 new_function_(Function::Handle(zone)),
5256 new_field_(Field::Handle(zone)),
@@ -840,6 +844,55 @@ void CallSiteResetter::Reset(const ICData& ic) {
840844 }
841845}
842846
847+ #if defined(DART_DYNAMIC_MODULES)
848+ static ArrayPtr PrepareNoSuchMethodErrorArguments (const Function& target,
849+ bool incompatible_arguments) {
850+ InvocationMirror::Kind kind = InvocationMirror::Kind::kMethod ;
851+ if (target.IsImplicitGetterFunction () || target.IsGetterFunction ()) {
852+ kind = InvocationMirror::kGetter ;
853+ } else if (target.IsImplicitSetterFunction () || target.IsSetterFunction ()) {
854+ kind = InvocationMirror::kSetter ;
855+ }
856+ const Class& owner = Class::Handle (target.Owner ());
857+ auto & receiver = Instance::Handle ();
858+ InvocationMirror::Level level;
859+ if (owner.IsTopLevel ()) {
860+ if (incompatible_arguments) {
861+ receiver = target.UserVisibleSignature ();
862+ }
863+ level = InvocationMirror::Level::kTopLevel ;
864+ } else {
865+ receiver = owner.RareType ();
866+ if (target.IsConstructor ()) {
867+ level = InvocationMirror::Level::kConstructor ;
868+ } else {
869+ level = InvocationMirror::Level::kStatic ;
870+ }
871+ }
872+ const auto & member_name = String::Handle (target.name ());
873+ const auto & invocation_type =
874+ Smi::Handle (Smi::New (InvocationMirror::EncodeType (level, kind)));
875+
876+ // NoSuchMethodError._throwNew takes the following arguments:
877+ // Object receiver,
878+ // String memberName,
879+ // int invocationType,
880+ // int typeArgumentsLength,
881+ // Object? typeArguments,
882+ // List? arguments,
883+ // List? argumentNames
884+ const Array& args = Array::Handle (Array::New (7 ));
885+ args.SetAt (0 , receiver);
886+ args.SetAt (1 , member_name);
887+ args.SetAt (2 , invocation_type);
888+ args.SetAt (3 , Object::smi_zero ());
889+ args.SetAt (4 , Object::null_type_arguments ());
890+ args.SetAt (5 , Object::null_object ());
891+ args.SetAt (6 , Object::null_object ());
892+ return args.ptr ();
893+ }
894+ #endif // defined(DART_DYNAMIC_MODULES)
895+
843896void CallSiteResetter::RebindBytecode (const Bytecode& bytecode) {
844897#if defined(DART_DYNAMIC_MODULES)
845898 pool_ = bytecode.object_pool ();
@@ -858,22 +911,58 @@ void CallSiteResetter::RebindBytecode(const Bytecode& bytecode) {
858911 case KernelBytecode::kUncheckedDirectCall :
859912 case KernelBytecode::kUncheckedDirectCall_Wide : {
860913 const intptr_t idx = KernelBytecode::DecodeD (instr);
861- old_target_ ^= pool_.ObjectAt (idx);
914+ object_ = pool_.ObjectAt (idx);
915+ if (object_.IsArray ()) {
916+ break ;
917+ }
918+ old_target_ ^= object_.ptr ();
862919 args_desc_array_ ^= pool_.ObjectAt (idx + 1 );
863920 ArgumentsDescriptor args_desc (args_desc_array_);
864- name_ = old_target_.name ();
865- new_cls_ = old_target_.Owner ();
866- new_target_ = Resolver::ResolveFunction (zone_, new_cls_, name_);
867- if (new_target_.ptr () != old_target_.ptr ()) {
868- if (!new_target_.IsNull () &&
869- (new_target_.is_static () == old_target_.is_static ()) &&
870- (new_target_.kind () == old_target_.kind ()) &&
871- new_target_.AreValidArguments (args_desc, nullptr )) {
872- pool_.SetObjectAt (idx, new_target_);
921+ // Re-resolve class in case it was deleted.
922+ old_cls_ = old_target_.Owner ();
923+ old_lib_ = old_cls_.library ();
924+ name_ = old_lib_.url ();
925+ new_lib_ = Library::LookupLibrary (thread_, name_);
926+ if (!new_lib_.IsNull ()) {
927+ if (old_cls_.IsTopLevel ()) {
928+ new_cls_ = new_lib_.toplevel_class ();
873929 } else {
930+ name_ = old_cls_.Name ();
931+ new_cls_ = new_lib_.LookupClassAllowPrivate (name_);
932+ }
933+ } else {
934+ new_cls_ = Class::null ();
935+ }
936+ if (!new_cls_.IsNull ()) {
937+ name_ = old_target_.name ();
938+ new_target_ = Resolver::ResolveFunction (zone_, new_cls_, name_);
939+ if (new_target_.IsNull () && Field::IsGetterName (name_)) {
940+ name_ = Field::NameFromGetter (name_);
941+ new_target_ = Resolver::ResolveFunction (zone_, new_cls_, name_);
942+ if (!new_target_.IsNull ()) {
943+ name_ = old_target_.name ();
944+ new_target_ = new_target_.GetMethodExtractor (name_);
945+ }
946+ }
947+ } else {
948+ new_target_ = Function::null ();
949+ }
950+ if (new_target_.ptr () != old_target_.ptr ()) {
951+ if (new_target_.IsNull () ||
952+ (new_target_.is_static () != old_target_.is_static ())) {
874953 VTIR_Print (" Cannot rebind function %s\n " ,
875954 old_target_.ToFullyQualifiedCString ());
955+ object_ = PrepareNoSuchMethodErrorArguments (
956+ old_target_, /* incompatible_arguments=*/ false );
957+ } else if (!new_target_.AreValidArguments (args_desc, nullptr )) {
958+ VTIR_Print (" Cannot rebind function %s - arguments mismatch\n " ,
959+ old_target_.ToFullyQualifiedCString ());
960+ object_ = PrepareNoSuchMethodErrorArguments (
961+ old_target_, /* incompatible_arguments=*/ true );
962+ } else {
963+ object_ = new_target_.ptr ();
876964 }
965+ pool_.SetObjectAt (idx, object_);
877966 }
878967 break ;
879968 }
0 commit comments