[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:
committed by
Space Team
parent
f3b3dcee9e
commit
0f65ba4843
+19
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user