From 7e7a5fe73633507b2fdee666148b8afb3261c1d0 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 27 Mar 2020 20:41:58 +0300 Subject: [PATCH] Add reference to sub class in Complex class This is replacement for instance field --- .../common/interpreter/IrInterpreter.kt | 29 +++---- .../backend/common/interpreter/stack/State.kt | 79 ++++++++++--------- 2 files changed, 52 insertions(+), 56 deletions(-) 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 a145d9ecdc9..affc2fa84da 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 @@ -268,7 +268,7 @@ class IrInterpreter(irModule: IrModuleFragment) { private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): Code { if (irFunction.body == null) { val receiver = data.getVariableState(irFunction.symbol.getReceiver()!!) as Complex - val instance = receiver.instance!! + val instance = receiver.getOriginal() val functionImplementation = instance.getIrFunction(irFunction.descriptor) if (functionImplementation?.body == null) throw NoSuchMethodException("Method \"${irFunction.name}\" wasn't implemented") @@ -283,7 +283,7 @@ class IrInterpreter(irModule: IrModuleFragment) { private suspend fun calculateOverridden(owner: IrSimpleFunction, data: Frame): Code { val variableDescriptor = owner.symbol.getReceiver()!! - val superQualifier = (data.getVariableState(variableDescriptor) as? Complex)?.superType + val superQualifier = (data.getVariableState(variableDescriptor) as? Complex)?.superClass if (superQualifier == null) { // superQualifier is null for exception state => find method in builtins return calculateBuiltIns(owner.getLastOverridden() as IrSimpleFunction, data) @@ -298,7 +298,7 @@ class IrInterpreter(irModule: IrModuleFragment) { val overriddenOwner = overridden.owner return when { overriddenOwner.body != null -> overriddenOwner.interpret(newStates) - superQualifier.superType == null -> calculateBuiltIns(overriddenOwner, newStates) + superQualifier.superClass == null -> calculateBuiltIns(overriddenOwner, newStates) else -> calculateOverridden(overriddenOwner, newStates) }.apply { data.pushReturnValue(newStates) } } @@ -313,7 +313,7 @@ class IrInterpreter(irModule: IrModuleFragment) { val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { it.original.type } - val argsValues = args.map { (it as? Complex)?.instance ?: (it as Primitive<*>).value } + val argsValues = args.map { (it as? Complex)?.getOriginal() ?: (it as Primitive<*>).value } val signature = CompileTimeFunction(methodName, argsType.map { it.toString() }) val result = when (argsType.size) { @@ -376,7 +376,7 @@ class IrInterpreter(irModule: IrModuleFragment) { val dispatchReceiver = rawDispatchReceiver?.let { data.popReturnValue() } val irFunctionReceiver = when (expression.superQualifierSymbol) { null -> dispatchReceiver - else -> (dispatchReceiver as Complex).superType?.takeIf { it.irClass.isSubclassOf(expression.superQualifierSymbol!!.owner) } + else -> (dispatchReceiver as Complex).superClass?.takeIf { it.irClass.isSubclassOf(expression.superQualifierSymbol!!.owner) } } // it is important firstly to add receiver, then arguments; this order is used in builtin method call val irFunction = irFunctionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner @@ -400,7 +400,7 @@ class IrInterpreter(irModule: IrModuleFragment) { irFunction.takeIf { it.isInline }?.typeParameters?.forEachIndexed { index, typeParameter -> if (typeParameter.isReified) { - val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner, mutableListOf()) + val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner) newFrame.addVar(Variable(typeParameter.descriptor, typeArgumentState)) } } @@ -497,30 +497,25 @@ class IrInterpreter(irModule: IrModuleFragment) { return Code.NEXT } - val state = Common(parent, mutableListOf()) + val state = Common(parent) newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body constructorCall.getBody()?.interpret(newFrame)?.checkForReturn(newFrame, data) { return it } val returnedState = newFrame.popReturnValue() as Complex - data.pushReturnValue(if (isPrimary) state.apply { superType = returnedState } else returnedState.apply { setStatesFrom(state) }) + data.pushReturnValue(if (isPrimary) state.apply { this.setSuperClassInstance(returnedState) } else returnedState.apply { setStatesFrom(state) }) return Code.NEXT } private suspend fun interpretConstructorCall(constructorCall: IrConstructorCall, data: Frame): Code { - return interpretConstructor(constructorCall, data).apply { - // constructor can return primitive object; fot example, when create array by constructor - (data.peekReturnValue() as? Complex)?.let { it.setInstanceRecursive(it) } - } + return interpretConstructor(constructorCall, data) } private suspend fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall, data: Frame): Code { - return interpretConstructor(enumConstructorCall, data).apply { - (data.peekReturnValue() as Complex).let { it.setInstanceRecursive(it) } - } + return interpretConstructor(enumConstructorCall, data) } private suspend fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code { if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) { - val anyAsStateObject = Common(irBuiltIns.anyClass.owner, mutableListOf()) + val anyAsStateObject = Common(irBuiltIns.anyClass.owner) data.pushReturnValue(anyAsStateObject) return Code.NEXT } @@ -665,7 +660,7 @@ class IrInterpreter(irModule: IrModuleFragment) { data.pushReturnValue(Wrapper.getCompanionObject(owner)) return Code.NEXT } - val objectState = Common(owner, mutableListOf()).apply { this.instance = this } + val objectState = Common(owner) data.pushReturnValue(objectState) return Code.NEXT } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt index 363372bec10..7929619863d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt @@ -96,17 +96,16 @@ class Primitive(var value: T, val type: IrType) : State { } } -abstract class Complex(override val irClass: IrClass, override val fields: MutableList) : State { - var superType: Complex? = null - var instance: Complex? = null - - fun setInstanceRecursive(instance: Complex) { - this.instance = instance - superType?.setInstanceRecursive(instance) +abstract class Complex( + override val irClass: IrClass, override val fields: MutableList, var superClass: Complex?, var subClass: Complex? +) : State { + fun setSuperClassInstance(superClass: Complex) { + this.superClass = superClass + superClass.subClass = this } - fun getReceiver(): DeclarationDescriptor { - return irClass.thisReceiver!!.descriptor + fun getOriginal(): Complex { + return subClass?.getOriginal() ?: this } fun irClassFqName(): String { @@ -130,7 +129,12 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab } } -class Common(override val irClass: IrClass, override val fields: MutableList) : Complex(irClass, fields) { +class Common private constructor( + override val irClass: IrClass, override val fields: MutableList, superClass: Complex?, subClass: Complex? +) : Complex(irClass, fields, superClass, subClass) { + + constructor(irClass: IrClass) : this(irClass, mutableListOf(), null, null) + fun getToStringFunction(): IrFunctionImpl { return irClass.declarations.filterIsInstance() .filter { it.descriptor.name.asString() == "toString" } @@ -138,24 +142,22 @@ class Common(override val irClass: IrClass, override val fields: MutableList = mutableListOf() + // irFunction is anonymous declaration, but irCall will contain descriptor of invoke method from Function interface private val invokeDescriptor = irClass.declarations.single { it.nameForIrSerialization.asString() == "invoke" }.descriptor @@ -301,7 +305,7 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Comple } override fun copy(): State { - return Lambda(irFunction, irClass).apply { this@apply.instance = this@Lambda.instance } + return Lambda(irFunction, irClass) } override fun toString(): String { @@ -310,18 +314,17 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Comple } class ExceptionState private constructor( - override val irClass: IrClass, override val fields: MutableList, stackTrace: List -) : Complex(irClass, fields) { + override val irClass: IrClass, override val fields: MutableList, stackTrace: List, subClass: Complex? = null +) : Complex(irClass, fields, null, subClass) { + private lateinit var exceptionFqName: String private val exceptionHierarchy = mutableListOf() private val messageProperty = irClass.getPropertyByName("message") private val causeProperty = irClass.getPropertyByName("cause") - private val stackTrace: List + private val stackTrace: List = stackTrace.reversed() init { - instance = this - this.stackTrace = stackTrace.reversed() if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName() if (fields.none { it.descriptor.equalTo(messageProperty.descriptor) }) { @@ -331,7 +334,7 @@ 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).superType + while (wrapperSuperType != null && wrapperSuperType !is Wrapper) wrapperSuperType = (wrapperSuperType as Common).superClass setUpCauseIfNeeded(wrapperSuperType as? Wrapper) } @@ -351,6 +354,13 @@ class ExceptionState private constructor( } } + data class ExceptionData(val state: ExceptionState) : Throwable() { + override val message: String? = state.getMessage().value + override fun fillInStackTrace() = this + + override fun toString(): String = state.getMessageWithName() + } + private fun setUpCauseIfNeeded(wrapper: Wrapper?) { val cause = (wrapper?.value as? Throwable)?.cause as? ExceptionData setCause(cause?.state) @@ -376,7 +386,7 @@ class ExceptionState private constructor( } fun getMessage(): Primitive = getState(messageProperty.descriptor) as Primitive - fun getMessageWithName(): String = getMessage().value?.let { "$exceptionFqName: $it" } ?: exceptionFqName + private fun getMessageWithName(): String = getMessage().value?.let { "$exceptionFqName: $it" } ?: exceptionFqName fun getCause(): ExceptionState? = getState(causeProperty.descriptor)?.let { if (it is ExceptionState) it else null } @@ -394,7 +404,7 @@ class ExceptionState private constructor( fun getThisAsCauseForException() = ExceptionData(this) override fun copy(): State { - return ExceptionState(irClass, fields, stackTrace).apply { this@apply.instance = this@ExceptionState.instance } + return ExceptionState(irClass, fields, stackTrace, subClass ?: this) } companion object { @@ -443,12 +453,3 @@ class ExceptionState private constructor( } } } - -// TODO remove this data class and make ExceptionState a child of Throwable -// this is possible by converting Complex to an interface -data class ExceptionData(val state: ExceptionState) : Throwable() { - override val message: String? = state.getMessage().value - override fun fillInStackTrace() = this - - override fun toString(): String = state.getMessageWithName() -} \ No newline at end of file