From 6808151af7630dc655b3f3e35476b59cfea0cc37 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 28 Aug 2020 13:36:11 +0300 Subject: [PATCH] Remove method getOriginal from Complex class Common class no longer contains Common super classes, all fields are now inside one single object. --- .../kotlin/ir/interpreter/IrInterpreter.kt | 49 ++++++------ .../jetbrains/kotlin/ir/interpreter/Utils.kt | 11 +-- .../kotlin/ir/interpreter/state/Common.kt | 31 ++------ .../kotlin/ir/interpreter/state/Complex.kt | 76 +++++-------------- .../ir/interpreter/state/ExceptionState.kt | 4 +- 5 files changed, 54 insertions(+), 117 deletions(-) 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 0e2217f3a4e..03a17915d28 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 @@ -89,7 +89,13 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map } } - internal class Proxy(val state: Common, val interpreter: IrInterpreter) { + /** + * calledFromBuiltIns - used to avoid cyclic calls. For example: + * override fun toString(): String { + * return super.toString() + * } + */ + internal class Proxy(val state: Common, val interpreter: IrInterpreter, private val calledFromBuiltIns: Boolean = false) { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false @@ -98,7 +104,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map val valueArguments = mutableListOf() val equalsFun = state.getEqualsFunction() - if (equalsFun.isFakeOverriddenFromAny()) return this.state.getOriginal() === other.state.getOriginal() + if (equalsFun.isFakeOverriddenFromAny() || calledFromBuiltIns) return this.state === other.state equalsFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) } valueArguments.add(Variable(equalsFun.valueParameters.single().symbol, other.state)) @@ -114,7 +120,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map override fun hashCode(): Int { val valueArguments = mutableListOf() val hashCodeFun = state.getHashCodeFunction() - if (hashCodeFun.isFakeOverriddenFromAny()) return System.identityHashCode(state.getOriginal()) + if (hashCodeFun.isFakeOverriddenFromAny() || calledFromBuiltIns) return System.identityHashCode(state) hashCodeFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) } return with(interpreter) { @@ -128,8 +134,8 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map override fun toString(): String { val valueArguments = mutableListOf() val toStringFun = state.getToStringFunction() - if (toStringFun.isFakeOverriddenFromAny()) { - return "${state.getOriginal().irClass.internalName()}@" + System.identityHashCode(state).toString(16).padStart(8, '0') + if (toStringFun.isFakeOverriddenFromAny() || calledFromBuiltIns) { + return "${state.irClass.internalName()}@" + hashCode().toString(16).padStart(8, '0') } toStringFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) } @@ -142,12 +148,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map } } - internal fun State.wrapAsProxyIfNeeded(): Any? { + internal fun State.wrapAsProxyIfNeeded(calledFromBuiltIns: Boolean = false): Any? { return when (this) { is ExceptionState -> this.getThisAsCauseForException() is Wrapper -> this.value is Primitive<*> -> this.value - is Common -> Proxy(this, this@IrInterpreter) + is Common -> Proxy(this, this@IrInterpreter, calledFromBuiltIns) is Lambda -> this // TODO as Proxy else -> throw AssertionError("${this::class} is unsupported as argument for wrap function") } @@ -250,7 +256,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map val receiverType = irFunction.dispatchReceiverParameter?.type val argsType = listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type } - val argsValues = args.map { it.wrapAsProxyIfNeeded() } + val argsValues = args.map { it.wrapAsProxyIfNeeded(methodName !in setOf("plus", IrBuiltIns.OperatorNames.EQEQ)) } fun IrType.getOnlyName(): String { return when { @@ -351,12 +357,10 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map rawExtensionReceiver?.interpret()?.check { return it } val extensionReceiver = rawExtensionReceiver?.let { stack.popReturnValue() }?.checkNullability(expression.extensionReceiver?.type) - // get correct ir function val irFunction = dispatchReceiver?.getIrFunctionByIrCall(expression) ?: expression.symbol.owner - val functionReceiver = dispatchReceiver.getCorrectReceiverByFunction(irFunction) // it is important firstly to add receiver, then arguments; this order is used in builtin method call - irFunction.getDispatchReceiver()?.let { functionReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } } + irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } } irFunction.getExtensionReceiver()?.let { extensionReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } } interpretValueParameters(expression, irFunction, valueArguments).check { return it } @@ -365,11 +369,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map if (dispatchReceiver is Complex) valueArguments.addAll(dispatchReceiver.typeArguments) if (extensionReceiver is Complex) valueArguments.addAll(extensionReceiver.typeArguments) - val isLocal = (dispatchReceiver as? Complex)?.getOriginal()?.irClass?.isLocal ?: irFunction.isLocal - if (isLocal) valueArguments.addAll(dispatchReceiver.extractNonLocalDeclarations()) + if (dispatchReceiver?.irClass?.isLocal == true || irFunction.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) } + if (dispatchReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) { + generateSequence(dispatchReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { valueArguments.add(it) } } return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) { @@ -469,7 +474,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map for (i in 1 until statements.size) statements[i].interpret().check { return@newFrame it } - stack.pushReturnValue(state.apply { this.setSuperClassInstance(returnedState) }) + stack.pushReturnValue(state.apply { this.copyFieldsFrom(returnedState) }) Next } } @@ -661,7 +666,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map val objectState = when { objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getCompanionObject(objectClass) - else -> Common(objectClass).apply { setSuperClassRecursive() } // TODO test type arguments + else -> Common(objectClass) // TODO test type arguments } mapOfObjects[objectClass.symbol] = objectState stack.pushReturnValue(objectState) @@ -769,7 +774,6 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map is Primitive<*> -> arrayToList(result.value) is Common -> when { result.irClass.defaultType.isUnsignedArray() -> arrayToList((result.fields.single().state as Primitive<*>).value) - result.irClass.defaultType.isUnsigned() -> listOf(result) else -> listOf(Proxy(result, this)) } else -> listOf(result) @@ -782,15 +786,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map val storageProperty = owner.declarations.filterIsInstance().first { it.name.asString() == "storage" } val primitiveArray = args.map { when (it) { - is Common -> (it.fields.single().state as Primitive<*>).value // is unsigned number - else -> it // is primitive number + is Proxy -> (it.state.fields.single().state as Primitive<*>).value // is unsigned number + else -> it // is primitive number } } val unsignedArray = primitiveArray.toPrimitiveStateArray(storageProperty.backingField!!.type) - Common(owner).apply { - setSuperClassRecursive() - fields.add(Variable(storageProperty.symbol, unsignedArray)) - } + Common(owner).apply { fields.add(Variable(storageProperty.symbol, unsignedArray)) } } else -> args.toPrimitiveStateArray(expression.type).apply { if (expression.type.isArray()) { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index b078e124a4b..0053a503b89 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt @@ -180,16 +180,7 @@ internal fun getTypeArguments( internal fun State?.extractNonLocalDeclarations(): List { this ?: return listOf() - val state = this.takeIf { it !is Complex } ?: (this as Complex).getOriginal() - return state.fields.filter { it.symbol !is IrFieldSymbol } -} - -internal fun State?.getCorrectReceiverByFunction(irFunction: IrFunction): State? { - if (this !is Complex) return this - - val original: Complex? = this.getOriginal() - val other = irFunction.parentClassOrNull?.thisReceiver ?: return this - return generateSequence(original) { it.superClass }.firstOrNull { it.irClass.thisReceiver == other } ?: this + return this.fields.filter { it.symbol !is IrFieldSymbol } } internal fun IrFunction.getCapitalizedFileName() = this.file.name.replace(".kt", "Kt").capitalizeAsciiOnly() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Common.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Common.kt index ae9c8d93240..2d66c53cc15 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Common.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Common.kt @@ -6,9 +6,7 @@ package org.jetbrains.kotlin.ir.interpreter.state import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.interpreter.isInterface import org.jetbrains.kotlin.ir.interpreter.stack.Variable -import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization internal class Common private constructor( @@ -17,29 +15,12 @@ internal class Common private constructor( constructor(irClass: IrClass) : this(irClass, mutableListOf()) - fun setSuperClassRecursive() { - var thisClass: Common? = this - while (thisClass != null) { - val superClass = thisClass.irClass.superTypes.filterNot { it.isInterface() }.singleOrNull() - val superClassOwner = superClass?.classOrNull?.owner - val superClassState = superClassOwner?.let { Common(it) } - superClassState?.let { thisClass!!.setSuperClassInstance(it) } - - if (superClass == null && thisClass.irClass.superTypes.isNotEmpty()) { - // cover the case when super type implement an interface and so doesn't have explicit any as super class - thisClass.setSuperClassInstance(Common(getAnyClassRecursive())) - } - thisClass = superClassState - } - } - - private fun getAnyClassRecursive(): IrClass { - var owner = irClass.superTypes.first().classOrNull!!.owner - while (owner.superTypes.isNotEmpty()) owner = owner.superTypes.first().classOrNull!!.owner - return owner - } - override fun toString(): String { - return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)" + return "Common(obj='${irClass.fqNameForIrSerialization}', values=$fields)" + } + + fun copyFieldsFrom(state: Complex) { + this.fields.addAll(state.fields) + superWrapperClass = state.superWrapperClass ?: state as? Wrapper } } \ No newline at end of file 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 fa610d3c217..4c190ab715a 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 @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.ir.interpreter.state -import org.jetbrains.kotlin.ir.interpreter.getCorrectReceiverByFunction import org.jetbrains.kotlin.ir.interpreter.getLastOverridden import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.declarations.IrClass @@ -14,83 +13,50 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.types.isNullableAny -import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization -import org.jetbrains.kotlin.ir.util.isInterface -import org.jetbrains.kotlin.ir.util.overrides +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.Name internal abstract class Complex(override val irClass: IrClass, override val fields: MutableList) : State { - var superClass: Complex? = null - var subClass: Complex? = null - val interfaces: MutableList = mutableListOf() // filled lazily, as needed + var superWrapperClass: Wrapper? = null override val typeArguments: MutableList = mutableListOf() var outerClass: Variable? = null - fun setSuperClassInstance(superClass: Complex) { - if (this.irClass == superClass.irClass) { - // if superClass is just secondary constructor instance, then copy properties that isn't already present in instance - superClass.fields.forEach { if (!this.contains(it)) fields.add(it) } - this.superClass = superClass.superClass - superClass.superClass?.subClass = this - } else { - this.superClass = superClass - superClass.subClass = this - } - } - - fun getOriginal(): Complex { - return subClass?.getOriginal() ?: this - } - fun irClassFqName(): String { return irClass.fqNameForIrSerialization.toString() } - private fun contains(variable: Variable) = fields.any { it.symbol == variable.symbol } - - private fun getIrFunction(symbol: IrFunctionSymbol): IrFunction? { - val propertyGetters = irClass.declarations.filterIsInstance().mapNotNull { it.getter } - val propertySetters = irClass.declarations.filterIsInstance().mapNotNull { it.setter } - val functions = irClass.declarations.filterIsInstance() + private fun IrClass.getIrFunction(symbol: IrFunctionSymbol): IrFunction? { + val propertyGetters = this.declarations.filterIsInstance().mapNotNull { it.getter } + val propertySetters = this.declarations.filterIsInstance().mapNotNull { it.setter } + val functions = this.declarations.filterIsInstance() return (propertyGetters + propertySetters + functions).firstOrNull { if (it is IrSimpleFunction) it.overrides(symbol.owner as IrSimpleFunction) else it == symbol.owner } } - private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? { + private fun getThisOrSuperReceiver(superIrClass: IrClass?): IrClass? { return when { - superIrClass == null -> this.getOriginal() - superIrClass.isInterface -> Common(superIrClass).apply { - interfaces.add(this) - this.subClass = this@Complex - } - else -> this.superClass + superIrClass == null -> this.irClass + superIrClass.isInterface -> superIrClass + else -> irClass.superTypes.map { it.classOrNull?.owner }.singleOrNull { it?.isInterface == false } } } - protected fun getOverridden(owner: IrSimpleFunction, qualifier: State?): IrSimpleFunction { - if (!owner.isFakeOverride) return owner - if (qualifier == null || qualifier is ExceptionState || (qualifier as? Complex)?.superClass == null) { - return owner.getLastOverridden() as IrSimpleFunction - } + protected fun getOverridden(owner: IrSimpleFunction): IrSimpleFunction { + if (!owner.isFakeOverride || owner.body != null || owner.parentAsClass.defaultType.isAny()) return owner - val overriddenOwner = owner.overriddenSymbols.single().owner - return when { - overriddenOwner.body != null -> overriddenOwner - else -> getOverridden(overriddenOwner, qualifier.superClass!!) - } + val overriddenOwner = owner.overriddenSymbols.singleOrNull { !it.owner.parentAsClass.isInterface }?.owner + return overriddenOwner?.let { getOverridden(it) } ?: owner.getLastOverridden() as IrSimpleFunction } override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null - val irFunction = receiver.getIrFunction(expression.symbol) ?: return null - - return when (irFunction.body) { - null -> getOverridden(irFunction as IrSimpleFunction, this.getCorrectReceiverByFunction(irFunction)) - else -> irFunction - } + return getOverridden(irFunction as IrSimpleFunction) } fun getEqualsFunction(): IrSimpleFunction { @@ -100,20 +66,20 @@ internal abstract class Complex(override val irClass: IrClass, override val fiel it.name == Name.identifier("equals") && it.dispatchReceiverParameter != null && it.valueParameters.size == 1 && it.valueParameters[0].type.isNullableAny() } - return getOverridden(equalsFun, this) + return getOverridden(equalsFun) } fun getHashCodeFunction(): IrSimpleFunction { return irClass.declarations.filterIsInstance() .filter { it.name.asString() == "hashCode" } .first { it.valueParameters.isEmpty() } - .let { getOverridden(it, this) } + .let { getOverridden(it) } } fun getToStringFunction(): IrSimpleFunction { return irClass.declarations.filterIsInstance() .filter { it.name.asString() == "toString" } .first { it.valueParameters.isEmpty() } - .let { getOverridden(it, this) } + .let { getOverridden(it) } } } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt index 1fdd552da07..f8d50924b16 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt @@ -35,9 +35,7 @@ internal class ExceptionState private constructor( } constructor(common: Common, stackTrace: List) : this(common.irClass, common.fields, stackTrace) { - var wrapperSuperType: Complex? = common - while (wrapperSuperType != null && wrapperSuperType !is Wrapper) wrapperSuperType = (wrapperSuperType as Common).superClass - setUpCauseIfNeeded(wrapperSuperType as? Wrapper) + setUpCauseIfNeeded(common.superWrapperClass) } constructor(wrapper: Wrapper, stackTrace: List) : this(wrapper.value as Throwable, wrapper.irClass, stackTrace) {