[evaluator] consider arguments of super-calls

Code generation for the intrinsic `jvmDebuggerInvokeSpecialIntrinsic`
includes dispatch receiver, but ignores arguments
passed to a super-call. This change passes arguments in the IR
representation in an array, and during the codegen the array is
unpacked and the bytecode is generated for the elements,
right before generating the actual `INVOKESPECIAL`.

#KT-63848 fixed


Merge-request: KT-MR-13270
Merged-by: Alexander Kuznetsov <Aleksander.Kuznetsov@jetbrains.com>
This commit is contained in:
Alexander Kuznetsov
2023-11-29 23:28:44 +00:00
committed by Space Team
parent f3b3dcee9e
commit 0f65ba4843
3 changed files with 31 additions and 0 deletions
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.codegen.*
import org.jetbrains.kotlin.backend.jvm.ir.getBooleanConstArgument
import org.jetbrains.kotlin.backend.jvm.ir.getStringConstArgument
import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.org.objectweb.asm.Type
@@ -31,10 +33,27 @@ object JvmDebuggerInvokeSpecial : IntrinsicMethod() {
val name = expression.getStringConstArgument(1)
val descriptor = expression.getStringConstArgument(2)
val isInterface = expression.getBooleanConstArgument(3)
val argsArray = expression.getValueArgument(4) as? IrBlock
expression.dispatchReceiver!!.accept(codegen, data).materialize()
argsArray?.let { generateArgs(it, codegen, data) }
codegen.mv.invokespecial(owner, name, descriptor, isInterface)
return MaterialValue(codegen, Type.getReturnType(descriptor), expression.type)
}
// statements:
// val arr = arrayOfNulls<Any?>(N)
// arr[0] = expr1
// arr[1] = expr2
// ...
// arr[N-1] = exprN
// arr
private fun generateArgs(array: IrBlock, codegen: ExpressionCodegen, data: BlockInfo) {
// ignore first and last statements
for (i in 1..<array.statements.size - 1) {
// generate bytecode for expr1, expr2, ..., exprN
(array.statements[i] as IrCall).getValueArgument(1)!!.accept(codegen, data).materialize()
}
}
}
@@ -539,6 +539,17 @@ internal class ReflectiveAccessLowering(
putValueArgument(1, builder.irString(jvmSignature.asmMethod.name))
putValueArgument(2, builder.irString(jvmSignature.asmMethod.descriptor))
putValueArgument(3, builder.irFalse())
// A workaround to pass the initial call arguments. Elements of this array
// will be extracted and passed to the bytecode generator right before
// generating the bytecode for invokeSpecial itself.
val args = with(context.irBuiltIns) {
builder.irArray(arrayClass.typeWith(anyNType)) {
for (i in 0 until expression.valueArgumentsCount) {
add(expression.getValueArgument(i)!!)
}
}
}
putValueArgument(4, args)
}
}
@@ -801,6 +801,7 @@ class JvmSymbols(
addValueParameter("name", irBuiltIns.stringType)
addValueParameter("descriptor", irBuiltIns.stringType)
addValueParameter("isInterface", irBuiltIns.booleanType)
addValueParameter("args", irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType))
returnType = irBuiltIns.anyNType
}.symbol