[vm/interpreter] Fix return value and type arguments in constructor tear-offs
TEST=ci
Change-Id: Ibe1ede1bc1c4e044285ee3b3f75ca138d7596e8a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384682
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
diff --git a/runtime/vm/constants_kbc.cc b/runtime/vm/constants_kbc.cc
index b4ae664..314a9c3 100644
--- a/runtime/vm/constants_kbc.cc
+++ b/runtime/vm/constants_kbc.cc
@@ -34,12 +34,26 @@
#undef SIZE
};
+static const KBCInstr kVMInternal_ImplicitConstructorClosureInstructions[] = {
+ KernelBytecode::kVMInternal_ImplicitConstructorClosure,
+ 0,
+ 0,
+ KernelBytecode::kPush,
+ 0,
+ KernelBytecode::kReturnTOS,
+};
+
+static const KBCInstr
+ kVMInternal_ImplicitConstructorClosure_WideInstructions[] = {
+ KernelBytecode::kTrap,
+};
+
#define DECLARE_INSTRUCTIONS(name, fmt, kind, fmta, fmtb, fmtc) \
static const KBCInstr k##name##Instructions[] = { \
KernelBytecode::k##name, \
KernelBytecode::kReturnTOS, \
};
-INTERNAL_KERNEL_BYTECODES_LIST(DECLARE_INSTRUCTIONS)
+INTERNAL_KERNEL_BYTECODES_WITH_DEFAULT_CODE(DECLARE_INSTRUCTIONS)
#undef DECLARE_INSTRUCTIONS
void KernelBytecode::GetVMInternalBytecodeInstructions(
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 3385e39..8123580 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -204,19 +204,29 @@
// 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 */ \
+ /* 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, ___) \
+
+#define INTERNAL_KERNEL_BYTECODES_WITH_DEFAULT_CODE(V) \
+ V(VMInternal_ImplicitGetter, 0, ORDN, ___, ___, ___) \
+ V(VMInternal_ImplicitSetter, 0, ORDN, ___, ___, ___) \
+ V(VMInternal_ImplicitStaticGetter, 0, ORDN, ___, ___, ___) \
+ V(VMInternal_ImplicitStaticSetter, 0, ORDN, ___, ___, ___) \
+ V(VMInternal_MethodExtractor, 0, ORDN, ___, ___, ___) \
+ V(VMInternal_InvokeClosure, 0, ORDN, ___, ___, ___) \
+ 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) \
- V(VMInternal_ImplicitGetter, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ImplicitSetter, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ImplicitStaticGetter, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ImplicitStaticSetter, 0, ORDN, ___, ___, ___) \
- V(VMInternal_MethodExtractor, 0, ORDN, ___, ___, ___) \
- V(VMInternal_InvokeClosure, 0, ORDN, ___, ___, ___) \
- V(VMInternal_InvokeField, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ForwardDynamicInvocation, 0, ORDN, ___, ___, ___) \
- V(VMInternal_NoSuchMethodDispatcher, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ImplicitStaticClosure, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ImplicitInstanceClosure, 0, ORDN, ___, ___, ___) \
- V(VMInternal_ImplicitConstructorClosure, 0, ORDN, ___, ___, ___) \
+ INTERNAL_KERNEL_BYTECODES_WITH_CUSTOM_CODE(V) \
+ INTERNAL_KERNEL_BYTECODES_WITH_DEFAULT_CODE(V)
#define KERNEL_BYTECODES_LIST(V) \
PUBLIC_KERNEL_BYTECODES_LIST(V) \
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index f0675c7..e5877e7 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -3626,7 +3626,8 @@
}
{
- BYTECODE(VMInternal_ImplicitConstructorClosure, 0);
+ BYTECODE(VMInternal_ImplicitConstructorClosure, D_F);
+
FunctionPtr function = FrameFunction(FP);
ASSERT(Function::KindOf(function) ==
UntaggedFunction::kImplicitClosureFunction);
@@ -3641,13 +3642,51 @@
InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
ObjectPtr* argv = FrameArguments(FP, argc);
+ // Reserve space for the result (instance).
+ *++SP = null_value;
+ ASSERT(SP == FP);
+
+ // Reserve space for receiver.
+ *++SP = null_value;
+ ObjectPtr* call_base = SP;
+ // Copy arguments.
+ for (intptr_t i = receiver_idx + 1; i < argc; i++) {
+ *++SP = argv[i];
+ }
+
ClassPtr cls = Function::Owner(target);
TypeParametersPtr type_params = cls->untag()->type_parameters();
- TypeArgumentsPtr type_args =
- (type_params == null_value)
- ? TypeArguments::null()
- : ((type_args_len > 0) ? TypeArguments::RawCast(argv[0])
- : type_params->untag()->defaults());
+ TypeArgumentsPtr type_args;
+ if (type_params == null_value) {
+ if (type_args_len > 0) {
+ SP[1] = function;
+ goto NoSuchMethodFromPrologue;
+ }
+ type_args = TypeArguments::null();
+ } else {
+ TypeArgumentsPtr delayed_type_arguments =
+ Closure::RawCast(argv[receiver_idx])
+ ->untag()
+ ->delayed_type_arguments();
+ if (delayed_type_arguments != Object::empty_type_arguments().ptr()) {
+ if (type_args_len > 0) {
+ SP[1] = function;
+ goto NoSuchMethodFromPrologue;
+ }
+ type_args = delayed_type_arguments;
+ } else {
+ if (type_args_len > 0) {
+ if (type_args_len !=
+ Smi::Value(type_params->untag()->names()->untag()->length())) {
+ SP[1] = function;
+ goto NoSuchMethodFromPrologue;
+ }
+ type_args = TypeArguments::RawCast(argv[0]);
+ } else {
+ type_args = type_params->untag()->defaults();
+ }
+ }
+ }
SP[1] = target; // Save target.
SP[2] = argdesc_; // Save arguments descriptor.
@@ -3656,9 +3695,8 @@
SP[3] = cls;
SP[4] = type_args;
Exit(thread, FP, SP + 5, pc);
- INVOKE_RUNTIME(DRT_AllocateObject,
- NativeArguments(thread, 2, SP + 3, argv + receiver_idx));
-
+ INVOKE_RUNTIME(DRT_AllocateObject, NativeArguments(thread, 2, SP + 3, FP));
+ call_base[0] = FP[0]; // Copy receiver.
argdesc_ = Array::RawCast(SP[2]);
if (type_args_len > 0) {
@@ -3672,7 +3710,12 @@
argdesc_ = Array::RawCast(SP[2]);
}
- goto TailCallSP1;
+ ObjectPtr* call_top = SP + 1;
+ if (!Invoke(thread, call_base, call_top, &pc, &FP, &SP)) {
+ HANDLE_EXCEPTION;
+ }
+
+ DISPATCH();
}
{