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 172aaf0ce52..801edeb039e 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 @@ -39,9 +39,9 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn is IrSimpleFunction -> unfoldFunction(element, environment) is IrConstructor -> unfoldConstructor(element, callStack) is IrCall -> unfoldCall(element, callStack) - is IrConstructorCall -> unfoldConstructorCall(element, environment) - is IrEnumConstructorCall -> unfoldEnumConstructorCall(element, callStack) - is IrDelegatingConstructorCall -> unfoldDelegatingConstructorCall(element, callStack) + is IrConstructorCall -> unfoldConstructorCall(element, callStack) + is IrEnumConstructorCall -> unfoldConstructorCall(element, callStack) + is IrDelegatingConstructorCall -> unfoldConstructorCall(element, callStack) is IrInstanceInitializerCall -> unfoldInstanceInitializerCall(element, callStack) is IrField -> unfoldField(element, callStack) is IrBody -> unfoldBody(element, callStack) @@ -113,23 +113,9 @@ private fun unfoldCall(call: IrCall, callStack: CallStack) { unfoldValueParameters(call, callStack) } -private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, environment: IrInterpreterEnvironment) { - val callStack = environment.callStack - val constructor = constructorCall.symbol.owner - val irClass = constructor.parentAsClass +// This function is responsible for IrConstructorCall, IrDelegatingConstructorCall and IrEnumConstructorCall +private fun unfoldConstructorCall(constructorCall: IrFunctionAccessExpression, callStack: CallStack) { unfoldValueParameters(constructorCall, callStack) - // this state is used to create object once - val state = if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, callStack.getStackTrace()) else Common(irClass) - if (irClass.isObject) environment.mapOfObjects[irClass.symbol] = state // must set object's state here to avoid cyclic evaluation - callStack.addVariable(Variable(constructorCall.getThisReceiver(), state)) -} - -private fun unfoldEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall, callStack: CallStack) { - unfoldValueParameters(enumConstructorCall, callStack) -} - -private fun unfoldDelegatingConstructorCall(delegatingConstructorCall: IrFunctionAccessExpression, callStack: CallStack) { - unfoldValueParameters(delegatingConstructorCall, callStack) } private fun unfoldValueParameters(expression: IrFunctionAccessExpression, callStack: CallStack) { 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 92cc3121541..5df049130d7 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 @@ -204,9 +204,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal if (dispatchReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) dispatchReceiver.loadOuterClassesInto(callStack) // 6. load up values onto stack - if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame() if (dispatchReceiver is StateWithClosure) callStack.loadUpValues(dispatchReceiver) if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver) + if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame() callInterceptor.interceptCall(call, irFunction, args) { callStack.addInstruction(CompoundInstruction(irFunction)) @@ -243,7 +243,16 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val irClass = constructor.parentAsClass val receiverSymbol = constructor.dispatchReceiverParameter?.symbol - val objectState = callStack.getState(constructorCall.getThisReceiver()) + // this check is used to be sure that object will be created once + val objectState = when (constructorCall) { + !is IrConstructorCall -> callStack.getState(constructorCall.getThisReceiver()) + else -> (if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, callStack.getStackTrace()) else Common(irClass)) + .apply { + // must set object's state here, before actual initialization, to avoid cyclic evaluation + if (irClass.isObject) environment.mapOfObjects[irClass.symbol] = this + } + } + if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure) val outerClass = receiverSymbol?.let { callStack.getState(it) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt index d374810d27e..7225e100960 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt @@ -49,6 +49,10 @@ internal interface Complex : State { } fun loadOuterClassesInto(callStack: CallStack) { - generateSequence(outerClass) { (it.state as? Complex)?.outerClass }.forEach { callStack.addVariable(it) } + generateSequence(outerClass) { (it.state as? Complex)?.outerClass } + .forEach { variable -> + callStack.addVariable(variable) + (variable.state as? StateWithClosure)?.let { callStack.loadUpValues(it) } + } } } \ No newline at end of file