diff --git a/runtime/vm/constants_kbc.cc b/runtime/vm/constants_kbc.cc index 314a9c3aaca..353457b2dfd 100644 --- a/runtime/vm/constants_kbc.cc +++ b/runtime/vm/constants_kbc.cc @@ -48,6 +48,17 @@ static const KBCInstr KernelBytecode::kTrap, }; +static const KBCInstr kVMInternal_ImplicitInstanceClosureInstructions[] = { + KernelBytecode::kVMInternal_ImplicitInstanceClosure, + 0, + 0, + KernelBytecode::kReturnTOS, +}; + +static const KBCInstr kVMInternal_ImplicitInstanceClosure_WideInstructions[] = { + KernelBytecode::kTrap, +}; + #define DECLARE_INSTRUCTIONS(name, fmt, kind, fmta, fmtb, fmtc) \ static const KBCInstr k##name##Instructions[] = { \ KernelBytecode::k##name, \ diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h index 0c87121047f..1129d3cdff9 100644 --- a/runtime/vm/constants_kbc.h +++ b/runtime/vm/constants_kbc.h @@ -205,11 +205,14 @@ namespace dart { // These bytecodes are only generated within the VM. Reassigning their // opcodes is not a breaking change. #define INTERNAL_KERNEL_BYTECODES_WITH_CUSTOM_CODE(V) \ - /* VMInternal_ImplicitConstructorClosure uses D_F encoding as it calls */ \ - /* constructor and should be compatible with other ***Call instructions */ \ + /* ImplicitConstructorClosure and ImplicitInstanceClosure instructions */ \ + /* use D_F encoding as they may call target constructor or method and */ \ + /* should be compatible with other ***Call instructions */ \ /* in order to support DecodeArgc when returning from a call. */ \ V(VMInternal_ImplicitConstructorClosure, D_F, ORDN, num, num, ___) \ V(VMInternal_ImplicitConstructorClosure_Wide, D_F, ORDN, num, num, ___) \ + V(VMInternal_ImplicitInstanceClosure, D_F, ORDN, num, num, ___) \ + V(VMInternal_ImplicitInstanceClosure_Wide, D_F, ORDN, num, num, ___) \ #define INTERNAL_KERNEL_BYTECODES_WITH_DEFAULT_CODE(V) \ V(VMInternal_ImplicitGetter, 0, ORDN, ___, ___, ___) \ @@ -221,7 +224,6 @@ namespace dart { V(VMInternal_InvokeField, 0, ORDN, ___, ___, ___) \ V(VMInternal_ForwardDynamicInvocation, 0, ORDN, ___, ___, ___) \ V(VMInternal_ImplicitStaticClosure, 0, ORDN, ___, ___, ___) \ - V(VMInternal_ImplicitInstanceClosure, 0, ORDN, ___, ___, ___) \ V(VMInternal_NoSuchMethodDispatcher, 0, ORDN, ___, ___, ___) \ #define INTERNAL_KERNEL_BYTECODES_LIST(V) \ diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc index 79136356cc8..cadb125fddb 100644 --- a/runtime/vm/interpreter.cc +++ b/runtime/vm/interpreter.cc @@ -3757,7 +3757,7 @@ SwitchDispatch: } { - BYTECODE(VMInternal_ImplicitInstanceClosure, 0); + BYTECODE(VMInternal_ImplicitInstanceClosure, D_F); FunctionPtr function = FrameFunction(FP); ASSERT(Function::KindOf(function) == UntaggedFunction::kImplicitClosureFunction); @@ -3770,10 +3770,60 @@ SwitchDispatch: const intptr_t argc = InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx; ObjectPtr* argv = FrameArguments(FP, argc); + ClosurePtr closure = Closure::RawCast(argv[receiver_idx]); + + TypeParametersPtr type_params = + FunctionType::RawCast(function->untag()->signature()) + ->untag() + ->type_parameters(); + if (type_params == null_value) { + if (type_args_len > 0) { + SP[1] = function; + goto NoSuchMethodFromPrologue; + } + } else { + TypeArgumentsPtr delayed_type_arguments = + closure->untag()->delayed_type_arguments(); + if (delayed_type_arguments != Object::empty_type_arguments().ptr()) { + if (type_args_len > 0) { + SP[1] = function; + goto NoSuchMethodFromPrologue; + } + + // Type arguments. + *++SP = delayed_type_arguments; + ObjectPtr* call_base = SP; + // Captured receiver. + *++SP = closure->untag()->context(); + // Copy the rest of the arguments. + for (intptr_t i = receiver_idx + 1; i < argc; i++) { + *++SP = argv[i]; + } + + const intptr_t new_type_args_len = + Smi::Value(type_params->untag()->names()->untag()->length()); + + SP[1] = target; + SP[2] = 0; // Space for result. + SP[3] = argdesc_; + SP[4] = target; + SP[5] = Smi::New(new_type_args_len); + Exit(thread, FP, SP + 6, pc); + INVOKE_RUNTIME(DRT_AdjustArgumentsDesciptorForImplicitClosure, + NativeArguments(thread, 3, SP + 3, SP + 2)); + argdesc_ = Array::RawCast(SP[2]); + + ObjectPtr* call_top = SP + 1; + if (!Invoke(thread, call_base, call_top, &pc, &FP, &SP)) { + HANDLE_EXCEPTION; + } + + DISPATCH(); + } + } // Replace closure receiver with captured receiver // and call target function. - ClosurePtr closure = Closure::RawCast(argv[receiver_idx]); argv[receiver_idx] = closure->untag()->context(); SP[1] = target; diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index f32d70f64d9..bc563d23a2a 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -1060,10 +1060,6 @@ DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) { if (target.IsGenerativeConstructor()) { // Type arguments are not passed to a generative constructor. type_args_len = 0; - } else { - // No need to adjust arguments descriptor. - arguments.SetReturn(descriptor); - return; } }