diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt index 547735a50c1..ff7c03fe885 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt @@ -281,6 +281,10 @@ class IrInterpreter(irModule: IrModuleFragment) { val isLocal = (dispatchReceiver as? Complex)?.getOriginal()?.irClass?.isLocal ?: irFunction.isLocal if (isLocal) valueArguments.addAll(dispatchReceiver.extractNonLocalDeclarations()) + if (functionReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) { + generateSequence(functionReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { valueArguments.add(it) } + } + return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) { // inline only methods are not presented in lookup table, so must be interpreted instead of execution val isInlineOnly = irFunction.hasAnnotation(FqName("kotlin.internal.InlineOnly")) @@ -321,20 +325,24 @@ class IrInterpreter(irModule: IrModuleFragment) { interpretValueParameters(constructorCall, owner, valueArguments).check { return it } - val parent = owner.parent as IrClass - val typeArguments = getTypeArguments(parent, constructorCall) { stack.getVariableState(it) } + stack.getAllTypeArguments() - if (parent.hasAnnotation(evaluateIntrinsicAnnotation)) { + val irClass = owner.parent as IrClass + val typeArguments = getTypeArguments(irClass, constructorCall) { stack.getVariableState(it) } + stack.getAllTypeArguments() + if (irClass.hasAnnotation(evaluateIntrinsicAnnotation)) { return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) } - .apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // can be exception + .apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // 'as?' because can be exception } - if (parent.defaultType.isArray() || parent.defaultType.isPrimitiveArray()) { + if (irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray()) { // array constructor doesn't have body so must be treated separately return stack.newFrame(initPool = valueArguments) { handleIntrinsicMethods(owner) } } - val state = Common(parent).apply { this.typeArguments.addAll(typeArguments) } - if (parent.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations + val state = Common(irClass).apply { this.typeArguments.addAll(typeArguments) } + if (irClass.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations + if (irClass.isInner) { + constructorCall.dispatchReceiver!!.interpret().check { return it } + state.outerClass = Variable(constructorCall.symbol.owner.dispatchReceiverParameter!!.descriptor, stack.popReturnValue()) + } valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body return stack.newFrame(initPool = valueArguments + state.typeArguments) { val statements = constructorCall.getBody()!!.statements diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Common.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Common.kt index dcd3e2a1f5f..3fa4490e590 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Common.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Common.kt @@ -5,22 +5,19 @@ package org.jetbrains.kotlin.backend.common.interpreter.state -import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization -import org.jetbrains.kotlin.ir.util.isFakeOverride import org.jetbrains.kotlin.ir.util.isInterface class Common private constructor( - override val irClass: IrClass, override val fields: MutableList, override val typeArguments: MutableList, - superClass: Complex?, subClass: Complex? -) : Complex(irClass, fields, superClass, subClass) { + override val irClass: IrClass, override val fields: MutableList +) : Complex(irClass, fields) { - constructor(irClass: IrClass) : this(irClass, mutableListOf(), mutableListOf(), null, null) + constructor(irClass: IrClass) : this(irClass, mutableListOf()) fun setSuperClassRecursive() { var thisClass: Common? = this @@ -51,9 +48,7 @@ class Common private constructor( .let { getOverridden(it as IrSimpleFunction, this) } } - override fun copy(): State { - return Common(irClass, fields, typeArguments, superClass, subClass ?: this) - } + override fun copy() = Common(irClass, fields).copyFrom(this) override fun toString(): String { return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)" diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt index ede24906e49..a81d7ecacee 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt @@ -18,10 +18,11 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.isInterface -abstract class Complex( - override val irClass: IrClass, override val fields: MutableList, var superClass: Complex?, var subClass: Complex? -) : State { - abstract val typeArguments: MutableList +abstract class Complex(override val irClass: IrClass, override val fields: MutableList) : State { + var superClass: Complex? = null + var subClass: Complex? = null + val typeArguments: MutableList = mutableListOf() + var outerClass: Variable? = null fun setSuperClassInstance(superClass: Complex) { if (this.irClass == superClass.irClass) { @@ -52,6 +53,14 @@ abstract class Complex( } } + protected fun copyFrom(other: Complex): State { + this.superClass = other.superClass + this.subClass = other.subClass ?: other + this.typeArguments.addAll(other.typeArguments) + this.outerClass = other.outerClass + return this + } + private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { val propertyGetters = irClass.declarations.filterIsInstance().mapNotNull { it.getter } val functions = irClass.declarations.filterIsInstance() diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/ExceptionState.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/ExceptionState.kt index 5a56f6bf84c..63b30b3e8bb 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/ExceptionState.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/ExceptionState.kt @@ -16,9 +16,8 @@ import org.jetbrains.kotlin.ir.util.nameForIrSerialization import kotlin.math.min class ExceptionState private constructor( - override val irClass: IrClass, override val fields: MutableList, stackTrace: List, subClass: Complex? = null -) : Complex(irClass, fields, null, subClass) { - override val typeArguments: MutableList = mutableListOf() + override val irClass: IrClass, override val fields: MutableList, stackTrace: List +) : Complex(irClass, fields) { private lateinit var exceptionFqName: String private val exceptionHierarchy = mutableListOf() @@ -106,9 +105,7 @@ class ExceptionState private constructor( fun getThisAsCauseForException() = ExceptionData(this) - override fun copy(): State { - return ExceptionState(irClass, fields, stackTrace, subClass ?: this) - } + override fun copy() = ExceptionState(irClass, fields, stackTrace).copyFrom(this) companion object { private fun IrClass.getPropertyByName(name: String): IrProperty { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt index 71fc223461f..8ed4d3b168d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt @@ -34,15 +34,11 @@ import java.lang.invoke.MethodHandle import java.lang.invoke.MethodHandles import java.lang.invoke.MethodType -class Wrapper private constructor( - val value: Any, override val irClass: IrClass, subClass: Complex?, override val typeArguments: MutableList -) : Complex(irClass, mutableListOf(), null, subClass) { +class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass, mutableListOf()) { private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe() private val receiverClass = irClass.defaultType.getClass(true) - constructor(value: Any, irClass: IrClass) : this(value, irClass, null, mutableListOf()) - fun getMethod(irFunction: IrFunction): MethodHandle? { if (irFunction.getEvaluateIntrinsicValue()?.isEmpty() == true) return null // this method will handle IntrinsicEvaluator // if function is actually a getter, then use "get${property.name.capitalize()}" as method name @@ -198,9 +194,7 @@ class Wrapper private constructor( } } - override fun copy(): State { - return Wrapper(value, irClass, subClass ?: this, typeArguments) - } + override fun copy() = Wrapper(value, irClass).copyFrom(this) override fun toString(): String { return "Wrapper(obj='$typeFqName', value=$value)"