diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt index 7835561cabb..facb499a38b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt @@ -60,7 +60,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : ) return interpreter.withNewCallStack(irCall) { this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall)) - valueArguments.forEach { this@withNewCallStack.environment.callStack.addVariable(it) } + valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it.state) } }.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt index 801edeb039e..d6cbe622c67 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt @@ -157,31 +157,34 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callSt val valueParametersSymbols = irFunction.valueParameters.map { it.symbol } - // interpret defaults for null arguments (at the end) - (expression.valueArgumentsCount - 1 downTo 0).forEach { index -> - if (expression.getValueArgument(index) != null) return@forEach - callStack.addInstruction(SimpleInstruction(valueParametersSymbols[index].owner)) - - getDefaultForParameterAt(index) - ?.let { callStack.addInstruction(CompoundInstruction(it)) } - ?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing - callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it))) - } - } - - // interpret not null arguments (after evaluation of arguments) - expression.dispatchReceiver?.let { callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!)) } - expression.extensionReceiver?.let { callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!)) } - (0 until expression.valueArgumentsCount).forEach { - if (expression.getValueArgument(it) != null) callStack.addInstruction(SimpleInstruction(irFunction.valueParameters[it])) - } - // evaluate arguments - (expression.valueArgumentsCount - 1 downTo 0).forEach { - callStack.addInstruction(CompoundInstruction(expression.getValueArgument(it))) + (expression.valueArgumentsCount - 1 downTo 0).forEach { index -> + when { + expression.getValueArgument(index) != null -> { + // interpret arguments that were passed + callStack.addInstruction(SimpleInstruction(irFunction.valueParameters[index])) + callStack.addInstruction(CompoundInstruction(expression.getValueArgument(index))) + } + else -> { + // interpret defaults for null arguments + callStack.addInstruction(SimpleInstruction(valueParametersSymbols[index].owner)) + + getDefaultForParameterAt(index) + ?.let { callStack.addInstruction(CompoundInstruction(it)) } + ?: expression.getVarargType(index)?.let { // case when value parameter is vararg and it is missing + callStack.addInstruction(SimpleInstruction(IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it))) + } + } + } + } + expression.extensionReceiver?.let { + callStack.addInstruction(SimpleInstruction(irFunction.extensionReceiverParameter!!)) + callStack.addInstruction(CompoundInstruction(it)) + } + expression.dispatchReceiver?.let { + callStack.addInstruction(SimpleInstruction(irFunction.dispatchReceiverParameter!!)) + callStack.addInstruction(CompoundInstruction(it)) } - expression.extensionReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) } - expression.dispatchReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) } } private fun unfoldInstanceInitializerCall(instanceInitializerCall: IrInstanceInitializerCall, callStack: CallStack) { @@ -378,7 +381,7 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ val toStringCall = state.createToStringIrCall() callStack.newSubFrame(toStringCall) callStack.addInstruction(SimpleInstruction(toStringCall)) - callStack.addVariable(Variable(toStringCall.symbol.owner.dispatchReceiverParameter!!.symbol, state)) + callStack.pushState(state) } } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index 46c183aeef1..f318b1eb95c 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -164,6 +164,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal // outer classes can be used in default args evaluation if (isReceiver() && state is Complex) state.loadOuterClassesInto(callStack) + callStack.pushState(state) } private fun interpretCall(call: IrCall) { @@ -176,9 +177,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val owner = call.symbol.owner // 1. load evaluated arguments from stack - val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.getState(it) } - val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.getState(it) } - val valueArguments = owner.valueParameters.map { callStack.getState(it.symbol) }.toMutableList() + val valueArguments = owner.valueParameters.map { callStack.popState() }.reversed().toMutableList() + val extensionReceiver = owner.getExtensionReceiver()?.let { callStack.popState() } + val dispatchReceiver = owner.getDispatchReceiver()?.let { callStack.popState() } // 2. get correct function for interpretation val irFunction = dispatchReceiver?.getIrFunctionByIrCall(call) ?: call.symbol.owner @@ -199,7 +200,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal // 4. store arguments in memory (remap args on actual names) irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } } - irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: valueArguments.removeFirst())) } + irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) } irFunction.valueParameters.forEach { callStack.addVariable(Variable(it.symbol, valueArguments.removeFirst())) } // 5. store reified type parameters @@ -240,7 +241,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal private fun interpretConstructorCall(constructorCall: IrFunctionAccessExpression) { val constructor = constructorCall.symbol.owner - val valueArguments = constructor.valueParameters.map { callStack.getState(it.symbol) } + val valueArguments = constructor.valueParameters.map { callStack.popState() }.reversed() val irClass = constructor.parentAsClass val receiverSymbol = constructor.dispatchReceiverParameter?.symbol @@ -255,7 +256,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal } if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure) - val outerClass = receiverSymbol?.let { callStack.getState(it) } + val outerClass = receiverSymbol?.let { callStack.popState() } callStack.dropSubFrame() callStack.newFrame(constructor) @@ -603,8 +604,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal private fun interpretFunctionReference(reference: IrFunctionReference) { val irFunction = reference.symbol.owner - val dispatchReceiver = reference.dispatchReceiver?.let { callStack.getState(irFunction.getDispatchReceiver()!!) } - val extensionReceiver = reference.extensionReceiver?.let { callStack.getState(irFunction.getExtensionReceiver()!!) } + val dispatchReceiver = reference.dispatchReceiver?.let { callStack.popState() } + val extensionReceiver = reference.extensionReceiver?.let { callStack.popState() } callStack.dropSubFrame() @@ -618,10 +619,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal } private fun interpretPropertyReference(propertyReference: IrPropertyReference) { - val receiverSymbol = propertyReference.getter?.owner?.let { it.getDispatchReceiver() ?: it.getExtensionReceiver() } // 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.getState(receiverSymbol!!) } + ?.let { callStack.popState() } callStack.dropSubFrame() val propertyState = KPropertyState(propertyReference, receiver) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt index 994e91c9dca..4148c48d0ab 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt @@ -83,13 +83,13 @@ internal class KFunctionState( val dispatchParameter = irFunction.dispatchReceiverParameter val extensionParameter = irFunction.extensionReceiverParameter - if (dispatchParameter != null && getField(dispatchParameter.symbol) == null) { + if (dispatchParameter != null) { dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol) - (this@impl.valueParameters as MutableList).add(dispatchParameter) + if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(dispatchParameter) } - if (extensionParameter != null && getField(extensionParameter.symbol) == null) { + if (extensionParameter != null) { extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol) - (this@impl.valueParameters as MutableList).add(extensionParameter) + if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList).add(extensionParameter) } irFunction.valueParameters.forEach { putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol))