Safely unfold callable reference instruction in interpreter

There was an assumption that if receiver exists then parameter will
also exist. This is not true for references marked with `JvmStatic`.
Later in `JvmStaticInObjectLowering` dispatch receiver may be dropped.
This commit is contained in:
Ivan Kylchik
2022-08-18 14:24:11 +03:00
committed by Space
parent 8e17c39cc9
commit 4e740e91f2
6 changed files with 68 additions and 24 deletions
@@ -416,28 +416,21 @@ private fun unfoldComposite(element: IrComposite, callStack: CallStack) {
}
}
private fun unfoldFunctionReference(reference: IrFunctionReference, callStack: CallStack) {
val function = reference.symbol.owner
private fun unfoldCallableReference(reference: IrCallableReference<*>, callStack: CallStack) {
callStack.pushSimpleInstruction(reference)
reference.getArgumentsWithIr().forEach { (parameter, arg) ->
callStack.pushSimpleInstruction(parameter)
callStack.pushCompoundInstruction(arg)
}
}
reference.dispatchReceiver?.let { callStack.pushSimpleInstruction(function.dispatchReceiverParameter!!) }
reference.extensionReceiver?.let { callStack.pushSimpleInstruction(function.extensionReceiverParameter!!) }
reference.extensionReceiver?.let { callStack.pushCompoundInstruction(it) }
reference.dispatchReceiver?.let { callStack.pushCompoundInstruction(it) }
private fun unfoldFunctionReference(reference: IrFunctionReference, callStack: CallStack) {
unfoldCallableReference(reference, callStack)
}
private fun unfoldPropertyReference(propertyReference: IrPropertyReference, callStack: CallStack) {
callStack.pushSimpleInstruction(propertyReference)
val getter = propertyReference.getter?.owner
if (getter != null) {
propertyReference.dispatchReceiver?.let { callStack.pushSimpleInstruction(getter.dispatchReceiverParameter!!) }
propertyReference.extensionReceiver?.let { callStack.pushSimpleInstruction(getter.extensionReceiverParameter!!) }
propertyReference.extensionReceiver?.let { callStack.pushCompoundInstruction(it) }
propertyReference.dispatchReceiver?.let { callStack.pushCompoundInstruction(it) }
}
if (propertyReference.field != null) return callStack.pushSimpleInstruction(propertyReference)
unfoldCallableReference(propertyReference, callStack)
}
private fun unfoldClassReference(classReference: IrClassReference, callStack: CallStack) {
@@ -566,8 +566,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
private fun interpretFunctionReference(reference: IrFunctionReference) {
val irFunction = reference.symbol.owner
val dispatchReceiver = reference.dispatchReceiver?.let { callStack.popState() }
val extensionReceiver = reference.extensionReceiver?.let { callStack.popState() }
val dispatchReceiver = irFunction.getDispatchReceiver()?.let { reference.dispatchReceiver?.let { callStack.popState() } }
val extensionReceiver = irFunction.getExtensionReceiver()?.let { reference.extensionReceiver?.let { callStack.popState() } }
val function = KFunctionState(
reference,
@@ -581,7 +581,11 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
private fun interpretPropertyReference(propertyReference: IrPropertyReference) {
// it is impossible to get KProperty2 through ::, so only one receiver can be not null (or both null)
val receiver = (propertyReference.dispatchReceiver ?: propertyReference.extensionReceiver)?.let { callStack.popState() }
val getter = propertyReference.getter?.owner
val dispatchReceiver = getter?.getDispatchReceiver()?.let { propertyReference.dispatchReceiver?.let { callStack.popState() } }
val extensionReceiver = getter?.getExtensionReceiver()?.let { propertyReference.extensionReceiver?.let { callStack.popState() } }
val receiver = dispatchReceiver ?: extensionReceiver
val propertyState = KPropertyState(propertyReference, receiver)
fun List<IrTypeParameter>.addToFields() {