From 7a19906705323b86aa833069845253d08229cd83 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Wed, 10 Jun 2020 23:47:18 +0300 Subject: [PATCH] Change all usages of descriptors in interpreter to usages of ir symbols --- .../interpreter/IrCompileTimeChecker.kt | 7 +- .../common/interpreter/IrInterpreter.kt | 56 +++++++-------- .../backend/common/interpreter/Label.kt | 31 ++++---- .../backend/common/interpreter/Utils.kt | 71 +++++-------------- .../intrinsics/IntrinsicImplementations.kt | 30 ++++---- .../backend/common/interpreter/stack/Frame.kt | 19 +++-- .../backend/common/interpreter/stack/Stack.kt | 28 ++++---- .../common/interpreter/stack/Variable.kt | 13 +--- .../common/interpreter/state/Complex.kt | 16 +++-- .../interpreter/state/ExceptionState.kt | 44 ++++++------ .../common/interpreter/state/Lambda.kt | 12 ++-- .../common/interpreter/state/Primitive.kt | 5 +- .../backend/common/interpreter/state/State.kt | 9 ++- .../common/interpreter/state/Wrapper.kt | 1 - 14 files changed, 154 insertions(+), 188 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrCompileTimeChecker.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrCompileTimeChecker.kt index 94f1edc32b6..ee070d324e7 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrCompileTimeChecker.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrCompileTimeChecker.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.name.FqName @@ -204,7 +205,11 @@ class IrCompileTimeChecker( IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.SAFE_CAST, - IrTypeOperator.IMPLICIT_NOTNULL -> expression.argument.accept(this, data) + IrTypeOperator.IMPLICIT_NOTNULL -> { + val operand = expression.typeOperand.classifierOrNull?.owner + if (operand is IrTypeParameter && !callStack.contains((operand.parent as IrSymbolOwner).symbol)) return false + expression.argument.accept(this, data) + } IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> false else -> false } 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 ab389643ba1..13c01d1d892 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 @@ -56,7 +56,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map irBuiltIns.doubleType null -> irBuiltIns.nothingType else -> when (defaultType.classifierOrNull?.owner) { - is IrTypeParameter -> stack.getVariable(defaultType.classifierOrFail.descriptor).state.irClass.defaultType + is IrTypeParameter -> stack.getVariable(defaultType.classifierOrFail).state.irClass.defaultType else -> defaultType } } @@ -225,7 +225,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map listOfNotNull(irFunction.getExtensionReceiver()) else -> listOf() } - val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters + val valueParametersDescriptors = receiverAsFirstArgument + irFunction.valueParameters.map { it.symbol } val valueArguments = (0 until expression.valueArgumentsCount).map { expression.getValueArgument(it) } val defaultValues = expression.symbol.owner.valueParameters.map { it.defaultValue?.expression } @@ -326,11 +326,11 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map() classProperties.forEach { property -> property.backingField?.initializer?.expression?.interpret()?.check { return it } - val receiver = irClass.descriptor.thisAsReceiverParameter + val receiver = irClass.thisReceiver!!.symbol if (property.backingField?.initializer != null) { val receiverState = stack.getVariable(receiver).state - val property = Variable(property.backingField!!.descriptor, stack.popReturnValue()) - receiverState.setField(property) + val propertyVar = Variable(property.backingField!!.symbol, stack.popReturnValue()) + receiverState.setField(propertyVar) } } @@ -363,9 +363,9 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map { val enumEntryName = it.name.asString().toState(irBuiltIns.stringType) - val enumNameAsVariable = Variable(valueOfFun.valueParameters.first().descriptor, enumEntryName) + val enumNameAsVariable = Variable(valueOfFun.valueParameters.first().symbol, enumEntryName) stack.newFrame(initPool = listOf(enumNameAsVariable)) { Wrapper.getEnumEntry(enumClass)!!.invokeMethod(valueOfFun) } } else -> interpretEnumEntry(it) @@ -601,7 +601,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map { val owner = expression.type.classOrNull!!.owner - val constructor = owner.primaryConstructor!! - val storageParameter = constructor.valueParameters.single() + val storageProperty = owner.declarations.filterIsInstance().first { it.name.asString() == "storage" } + val storageField = storageProperty.backingField!! val primitiveArray = args.map { ((it as Common).fields.single().state as Primitive<*>).value } - val unsignedArray = primitiveArray.toPrimitiveStateArray(storageParameter.type) + val unsignedArray = primitiveArray.toPrimitiveStateArray(storageField.type) Common(owner).apply { setSuperClassRecursive() - fields.add(Variable(storageParameter.descriptor, unsignedArray)) + fields.add(Variable(storageField.symbol, unsignedArray)) } } else -> args.toPrimitiveStateArray(expression.type) @@ -697,7 +697,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map ExecutionResult): ExecutionResult { return when (returnLabel) { ReturnLabel.RETURN -> this @@ -42,18 +43,18 @@ open class ExecutionResultWithoutInfo(override val returnLabel: ReturnLabel) : E } } - fun addInfo(info: String): ExecutionResultWithInfo { - return ExecutionResultWithInfo(returnLabel, info) + fun addOwnerInfo(owner: IrElement): ExecutionResultWithInfoAboutOwner { + return ExecutionResultWithInfoAboutOwner(returnLabel, owner) } } -class ExecutionResultWithInfo(override val returnLabel: ReturnLabel, val info: String) : ExecutionResultWithoutInfo(returnLabel) { +class ExecutionResultWithInfoAboutOwner( + override val returnLabel: ReturnLabel, private val owner: IrElement +) : ExecutionResultWithoutInfoAboutOwner(returnLabel) { override suspend fun getNextLabel(irElement: IrElement, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult { return when (returnLabel) { ReturnLabel.RETURN -> when (irElement) { - is IrCall -> if (info == irElement.symbol.descriptor.toString()) Next else this - is IrReturnableBlock -> if (info == irElement.symbol.descriptor.toString()) Next else this - is IrFunctionImpl -> if (info == irElement.descriptor.toString()) Next else this + is IrCall, is IrReturnableBlock, is IrFunctionImpl, is IrLazyFunction -> if (owner == irElement) Next else this else -> this } ReturnLabel.BREAK_WHEN -> when (irElement) { @@ -61,11 +62,11 @@ class ExecutionResultWithInfo(override val returnLabel: ReturnLabel, val info: S else -> this } ReturnLabel.BREAK_LOOP -> when (irElement) { - is IrWhileLoop -> if ((irElement.label ?: "") == info) Next else this + is IrWhileLoop -> if (owner == irElement) Next else this else -> this } ReturnLabel.CONTINUE -> when (irElement) { - is IrWhileLoop -> if ((irElement.label ?: "") == info) irElement.interpret() else this + is IrWhileLoop -> if (owner == irElement) irElement.interpret() else this else -> this } ReturnLabel.EXCEPTION -> Exception @@ -74,9 +75,9 @@ class ExecutionResultWithInfo(override val returnLabel: ReturnLabel, val info: S } } -object Next : ExecutionResultWithoutInfo(ReturnLabel.NEXT) -object Return : ExecutionResultWithoutInfo(ReturnLabel.RETURN) -object BreakLoop : ExecutionResultWithoutInfo(ReturnLabel.BREAK_LOOP) -object BreakWhen : ExecutionResultWithoutInfo(ReturnLabel.BREAK_WHEN) -object Continue : ExecutionResultWithoutInfo(ReturnLabel.CONTINUE) -object Exception : ExecutionResultWithoutInfo(ReturnLabel.EXCEPTION) \ No newline at end of file +object Next : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.NEXT) +object Return : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.RETURN) +object BreakLoop : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.BREAK_LOOP) +object BreakWhen : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.BREAK_WHEN) +object Continue : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.CONTINUE) +object Exception : ExecutionResultWithoutInfoAboutOwner(ReturnLabel.EXCEPTION) \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt index dc2e3fc813d..32e6f3d0924 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt @@ -9,30 +9,28 @@ import org.jetbrains.kotlin.backend.common.interpreter.builtins.evaluateIntrinsi import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.backend.common.interpreter.state.* import org.jetbrains.kotlin.builtins.UnsignedTypes -import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.utils.addToStdlib.safeAs -fun IrFunction.getDispatchReceiver(): DeclarationDescriptor? { - return (this.symbol.descriptor.containingDeclaration as? ClassDescriptor)?.thisAsReceiverParameter +fun IrFunction.getDispatchReceiver(): IrSymbol? { + return this.dispatchReceiverParameter?.symbol } -fun IrFunction.getExtensionReceiver(): DeclarationDescriptor? { - return this.extensionReceiverParameter?.descriptor +fun IrFunction.getExtensionReceiver(): IrSymbol? { + return this.extensionReceiverParameter?.symbol } -fun IrFunction.getReceiver(): DeclarationDescriptor? { +fun IrFunction.getReceiver(): IrSymbol? { return this.getDispatchReceiver() ?: this.getExtensionReceiver() } @@ -40,39 +38,6 @@ fun IrFunctionAccessExpression.getBody(): IrBody? { return this.symbol.owner.body } -fun DeclarationDescriptor.equalTo(other: DeclarationDescriptor): Boolean { - return this.isEqualByReceiverTo(other) || this.hasSameNameAs(other) || this == other -} - -private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescriptor): Boolean { - return when (val container = this.containingDeclaration) { - is ClassDescriptor -> container == other.containingDeclaration - is FunctionDescriptor -> container.dispatchReceiverParameter == other || container.extensionReceiverParameter == other - else -> false - } -} - -private fun DeclarationDescriptor.isEqualByReceiverTo(other: DeclarationDescriptor): Boolean { - if (this !is ReceiverParameterDescriptor || other !is ReceiverParameterDescriptor) return false - return when { - this is WrappedReceiverParameterDescriptor && other is WrappedReceiverParameterDescriptor -> - this.isEqualTo(other) || other.isEqualTo(this) - this is WrappedReceiverParameterDescriptor -> this.isEqualTo(other) - other is WrappedReceiverParameterDescriptor -> other.isEqualTo(this) - this.value is ImplicitClassReceiver && other.value is ImplicitClassReceiver -> this.value.type == other.value.type - this.value is ExtensionReceiver && other.value is ExtensionReceiver -> this.value == other.value - else -> false - } -} - -private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean { - return (this is VariableDescriptor && other is VariableDescriptor && this.name == other.name) || - (this is TypeParameterDescriptor && other is TypeParameterDescriptor && this.name == other.name) || - (this is FunctionDescriptor && other is FunctionDescriptor && //this == other - this.valueParameters.map { it.type.toString() } == other.valueParameters.map { it.type.toString() } && - this.name == other.name) -} - fun State.toIrExpression(expression: IrExpression): IrExpression { val start = expression.startOffset val end = expression.endOffset @@ -130,14 +95,14 @@ fun IrConst.toPrimitive(): Primitive { fun IrAnnotationContainer?.hasAnnotation(annotation: FqName): Boolean { this ?: return false if (this.annotations.isNotEmpty()) { - return this.annotations.any { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation } + return this.annotations.any { it.symbol.owner.parentAsClass.fqNameWhenAvailable == annotation } } return false } fun IrAnnotationContainer.getAnnotation(annotation: FqName): IrConstructorCall { - return this.annotations.firstOrNull { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation } - ?: ((this as IrFunction).parent as IrClass).annotations.first { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation } + return this.annotations.firstOrNull { it.symbol.owner.parentAsClass.fqNameWhenAvailable == annotation } + ?: ((this as IrFunction).parent as IrClass).annotations.first { it.symbol.owner.parentAsClass.fqNameWhenAvailable == annotation } } fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? { @@ -214,20 +179,20 @@ fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? { } fun getTypeArguments( - container: IrTypeParametersContainer, expression: IrFunctionAccessExpression, mapper: (TypeParameterDescriptor) -> State + container: IrTypeParametersContainer, expression: IrFunctionAccessExpression, mapper: (IrTypeParameterSymbol) -> State ): List { fun IrType.getState(): State { - return this.classOrNull?.owner?.let { Common(it) } ?: mapper(this.classifierOrFail.descriptor as TypeParameterDescriptor) + return this.classOrNull?.owner?.let { Common(it) } ?: mapper(this.classifierOrFail as IrTypeParameterSymbol) } val typeArguments = container.typeParameters.mapIndexed { index, typeParameter -> val typeArgument = expression.getTypeArgument(index)!! - Variable(typeParameter.descriptor, typeArgument.getState()) + Variable(typeParameter.symbol, typeArgument.getState()) }.toMutableList() if (container is IrSimpleFunction) { container.returnType.classifierOrFail.owner.safeAs() - ?.let { typeArguments.add(Variable(it.descriptor, expression.type.getState())) } + ?.let { typeArguments.add(Variable(it.symbol, expression.type.getState())) } } return typeArguments @@ -236,13 +201,13 @@ fun getTypeArguments( fun State?.extractNonLocalDeclarations(): List { this ?: return listOf() val state = this.takeIf { it !is Complex } ?: (this as Complex).getOriginal() - return state.fields.filterNot { it.descriptor.containingDeclaration == state.irClass.descriptor } + return state.fields.filter { it.symbol !is IrFieldSymbol } } fun State?.getCorrectReceiverByFunction(irFunction: IrFunction): State? { if (this !is Complex) return this val original: Complex? = this.getOriginal() - val other = irFunction.dispatchReceiverParameter?.descriptor ?: return this - return generateSequence(original) { it.superClass }.firstOrNull { it.irClass.descriptor.thisAsReceiverParameter.equalTo(other) } ?: this + val other = irFunction.parentClassOrNull?.thisReceiver ?: return this + return generateSequence(original) { it.superClass }.firstOrNull { it.irClass.thisReceiver == other } ?: this } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsics/IntrinsicImplementations.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsics/IntrinsicImplementations.kt index feea363ae81..5321a5d85e0 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsics/IntrinsicImplementations.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsics/IntrinsicImplementations.kt @@ -60,7 +60,7 @@ object ArrayOfNulls : IntrinsicBase() { override suspend fun evaluate( irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult ): ExecutionResult { - val size = stack.getVariable(irFunction.valueParameters.first().descriptor).state.asInt() + val size = stack.getVariable(irFunction.valueParameters.first().symbol).state.asInt() val array = arrayOfNulls(size) stack.pushReturnValue(array.toState(irFunction.returnType)) return Next @@ -77,7 +77,7 @@ object EnumValues : IntrinsicBase() { irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult ): ExecutionResult { val enumClass = when (irFunction.fqNameWhenAvailable.toString()) { - "kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().descriptor).state.irClass + "kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass else -> irFunction.parent as IrClass } @@ -98,10 +98,10 @@ object EnumValueOf : IntrinsicBase() { irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult ): ExecutionResult { val enumClass = when (irFunction.fqNameWhenAvailable.toString()) { - "kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().descriptor).state.irClass + "kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass else -> irFunction.parent as IrClass } - val enumEntryName = stack.getVariable(irFunction.valueParameters.first().descriptor).state.asString() + val enumEntryName = stack.getVariable(irFunction.valueParameters.first().symbol).state.asString() val enumEntry = enumClass.declarations.filterIsInstance().singleOrNull { it.name.asString() == enumEntryName } enumEntry?.interpret()?.check { return it } ?: throw IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName") @@ -125,7 +125,7 @@ object RegexReplace : IntrinsicBase() { val transform = states.filterIsInstance().single().irFunction val matchResultParameter = transform.valueParameters.single() val result = regex.replace(input) { - val itAsState = Variable(matchResultParameter.descriptor, Wrapper(it, matchResultParameter.type.classOrNull!!.owner)) + val itAsState = Variable(matchResultParameter.symbol, Wrapper(it, matchResultParameter.type.classOrNull!!.owner)) runBlocking { stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() } }//.check { return it } stack.popReturnValue().asString() } @@ -160,12 +160,12 @@ object JsPrimitives : IntrinsicBase() { ): ExecutionResult { when (irFunction.fqNameWhenAvailable.toString()) { "kotlin.Long." -> { - val low = stack.getVariable(irFunction.valueParameters[0].descriptor).state.asInt() - val high = stack.getVariable(irFunction.valueParameters[1].descriptor).state.asInt() + val low = stack.getVariable(irFunction.valueParameters[0].symbol).state.asInt() + val high = stack.getVariable(irFunction.valueParameters[1].symbol).state.asInt() stack.pushReturnValue((high.toLong().shl(32) + low).toState(irFunction.returnType)) } "kotlin.Char." -> { - val value = stack.getVariable(irFunction.valueParameters[0].descriptor).state.asInt() + val value = stack.getVariable(irFunction.valueParameters[0].symbol).state.asInt() stack.pushReturnValue(value.toChar().toState(irFunction.returnType)) } } @@ -182,20 +182,22 @@ object ArrayConstructor : IntrinsicBase() { override suspend fun evaluate( irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult ): ExecutionResult { - val sizeDescriptor = irFunction.valueParameters[0].descriptor + val sizeDescriptor = irFunction.valueParameters[0].symbol val size = stack.getVariable(sizeDescriptor).state.asInt() val arrayValue = MutableList(size) { 0 } if (irFunction.valueParameters.size == 2) { - val initDescriptor = irFunction.valueParameters[1].descriptor + val initDescriptor = irFunction.valueParameters[1].symbol val initLambda = stack.getVariable(initDescriptor).state as Lambda val index = initLambda.irFunction.valueParameters.single() + val nonLocalDeclarations = initLambda.extractNonLocalDeclarations() for (i in 0 until size) { - val indexVar = listOf(Variable(index.descriptor, i.toState(index.type))) + val indexVar = listOf(Variable(index.symbol, i.toState(index.type))) // TODO throw exception if label != RETURN - stack.newFrame(asSubFrame = initLambda.irFunction.isLocal || initLambda.irFunction.isInline, initPool = indexVar) { - initLambda.irFunction.body!!.interpret() - }.check(ReturnLabel.RETURN) { return it } + stack.newFrame( + asSubFrame = initLambda.irFunction.isLocal || initLambda.irFunction.isInline, + initPool = nonLocalDeclarations + indexVar + ) { initLambda.irFunction.body!!.interpret() }.check(ReturnLabel.RETURN) { return it } arrayValue[i] = stack.popReturnValue().let { (it as? Wrapper)?.value ?: (it as? Primitive<*>)?.value ?: it } } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt index 5e21096e8e8..31ab87dd341 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt @@ -5,18 +5,16 @@ package org.jetbrains.kotlin.backend.common.interpreter.stack -import org.jetbrains.kotlin.backend.common.interpreter.equalTo import org.jetbrains.kotlin.backend.common.interpreter.state.State -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import kotlin.NoSuchElementException +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol interface Frame { fun addVar(variable: Variable) fun addAll(variables: List) - fun getVariable(variableDescriptor: DeclarationDescriptor): Variable? + fun getVariable(symbol: IrSymbol): Variable? fun getAll(): List - fun contains(descriptor: DeclarationDescriptor): Boolean + fun contains(symbol: IrSymbol): Boolean fun pushReturnValue(state: State) fun pushReturnValue(frame: Frame) // TODO rename to getReturnValueFrom fun peekReturnValue(): State @@ -39,17 +37,16 @@ class InterpreterFrame( pool.addAll(variables) } - override fun getVariable(variableDescriptor: DeclarationDescriptor): Variable? { - return (if (variableDescriptor is TypeParameterDescriptor) typeArguments else pool) - .firstOrNull { it.descriptor.equalTo(variableDescriptor) } + override fun getVariable(symbol: IrSymbol): Variable? { + return (if (symbol is IrTypeParameterSymbol) typeArguments else pool).firstOrNull { it.symbol == symbol } } override fun getAll(): List { return pool } - override fun contains(descriptor: DeclarationDescriptor): Boolean { - return (typeArguments + pool).any { it.descriptor == descriptor } + override fun contains(symbol: IrSymbol): Boolean { + return (typeArguments + pool).any { it.symbol == symbol } } override fun pushReturnValue(state: State) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Stack.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Stack.kt index 04e657c97b0..e48b85b7aaa 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Stack.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Stack.kt @@ -8,10 +8,10 @@ package org.jetbrains.kotlin.backend.common.interpreter.stack import org.jetbrains.kotlin.backend.common.interpreter.ExecutionResult import org.jetbrains.kotlin.backend.common.interpreter.exceptions.InterpreterException import org.jetbrains.kotlin.backend.common.interpreter.state.State -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.name +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.util.file import org.jetbrains.kotlin.ir.util.fileEntry import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable @@ -28,10 +28,10 @@ interface Stack { fun clean() fun addVar(variable: Variable) fun addAll(variables: List) - fun getVariable(variableDescriptor: DeclarationDescriptor): Variable + fun getVariable(symbol: IrSymbol): Variable fun getAll(): List - fun contains(descriptor: DeclarationDescriptor): Boolean + fun contains(symbol: IrSymbol): Boolean fun hasReturnValue(): Boolean fun pushReturnValue(state: State) fun popReturnValue(): State @@ -43,8 +43,8 @@ class StackImpl : Stack { private fun getCurrentFrame() = frameList.last() override suspend fun newFrame(asSubFrame: Boolean, initPool: List, block: suspend () -> ExecutionResult): ExecutionResult { - val typeArgumentsPool = initPool.filter { it.descriptor is TypeParameterDescriptor } - val valueArguments = initPool.filter { it.descriptor !is TypeParameterDescriptor } + val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol } + val valueArguments = initPool.filter { it.symbol !is IrTypeParameterSymbol } val newFrame = InterpreterFrame(valueArguments.toMutableList(), typeArgumentsPool) if (asSubFrame) getCurrentFrame().addSubFrame(newFrame) else frameList.add(FrameContainer(newFrame)) @@ -86,16 +86,16 @@ class StackImpl : Stack { getCurrentFrame().addAll(variables) } - override fun getVariable(variableDescriptor: DeclarationDescriptor): Variable { - return getCurrentFrame().getVariable(variableDescriptor) + override fun getVariable(symbol: IrSymbol): Variable { + return getCurrentFrame().getVariable(symbol) } override fun getAll(): List { return getCurrentFrame().getAll() } - override fun contains(descriptor: DeclarationDescriptor): Boolean { - return getCurrentFrame().contains(descriptor) + override fun contains(symbol: IrSymbol): Boolean { + return getCurrentFrame().contains(symbol) } override fun hasReturnValue(): Boolean { @@ -132,12 +132,12 @@ private class FrameContainer(current: Frame = InterpreterFrame()) { fun addVar(variable: Variable) = getTopFrame().addVar(variable) fun addAll(variables: List) = getTopFrame().addAll(variables) fun getAll() = innerStack.flatMap { it.getAll() } - fun getVariable(variableDescriptor: DeclarationDescriptor): Variable { - return innerStack.firstNotNullResult { it.getVariable(variableDescriptor) } - ?: throw InterpreterException("$variableDescriptor not found") // TODO better message + fun getVariable(symbol: IrSymbol): Variable { + return innerStack.firstNotNullResult { it.getVariable(symbol) } + ?: throw InterpreterException("$symbol not found") // TODO better message } - fun contains(descriptor: DeclarationDescriptor) = innerStack.any { it.contains(descriptor) } + fun contains(symbol: IrSymbol) = innerStack.any { it.contains(symbol) } fun hasReturnValue() = getTopFrame().hasReturnValue() fun pushReturnValue(container: FrameContainer) = getTopFrame().pushReturnValue(container.getTopFrame()) fun pushReturnValue(state: State) = getTopFrame().pushReturnValue(state) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Variable.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Variable.kt index 28514d0ca0a..1840aafb005 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Variable.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Variable.kt @@ -6,15 +6,6 @@ package org.jetbrains.kotlin.backend.common.interpreter.stack import org.jetbrains.kotlin.backend.common.interpreter.state.State -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.ir.symbols.IrSymbol -data class Variable(val descriptor: DeclarationDescriptor, var state: State) { - override fun toString(): String { - val descriptorName = when (descriptor) { - is ReceiverParameterDescriptor -> descriptor.containingDeclaration.name.toString() + "::this" - else -> descriptor.name - } - return "Variable(descriptor=$descriptorName, state=$state)" - } -} \ No newline at end of file +data class Variable(val symbol: IrSymbol, var state: State) \ No newline at end of file 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 3abe4bd9736..a241eb6f9ab 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 @@ -5,18 +5,18 @@ package org.jetbrains.kotlin.backend.common.interpreter.state -import org.jetbrains.kotlin.backend.common.interpreter.equalTo -import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden import org.jetbrains.kotlin.backend.common.interpreter.getCorrectReceiverByFunction +import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction 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.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.util.overrides abstract class Complex(override val irClass: IrClass, override val fields: MutableList) : State { var superClass: Complex? = null @@ -45,12 +45,14 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab return irClass.fqNameForIrSerialization.toString() } - private fun contains(variable: Variable) = fields.any { it.descriptor == variable.descriptor } + private fun contains(variable: Variable) = fields.any { it.symbol == variable.symbol } - private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { + private fun getIrFunction(symbol: IrFunctionSymbol): IrFunction? { val propertyGetters = irClass.declarations.filterIsInstance().mapNotNull { it.getter } val functions = irClass.declarations.filterIsInstance() - return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) } + return (propertyGetters + functions).firstOrNull { + if (it is IrSimpleFunction) it.overrides(symbol.owner as IrSimpleFunction) else it == symbol.owner + } } private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? { @@ -80,7 +82,7 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null - val irFunction = receiver.getIrFunction(expression.symbol.descriptor) ?: return null + val irFunction = receiver.getIrFunction(expression.symbol) ?: return null return when (irFunction.body) { null -> getOverridden(irFunction as IrSimpleFunction, this.getCorrectReceiverByFunction(irFunction)) 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 5dbbcefc4d5..db3c380dcca 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 @@ -5,12 +5,13 @@ package org.jetbrains.kotlin.backend.common.interpreter.state -import org.jetbrains.kotlin.backend.common.interpreter.equalTo +import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.backend.common.interpreter.toState import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrProperty -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.util.isSubclassOf import org.jetbrains.kotlin.ir.util.nameForIrSerialization import kotlin.math.min @@ -21,15 +22,15 @@ class ExceptionState private constructor( private lateinit var exceptionFqName: String private val exceptionHierarchy = mutableListOf() - private val messageProperty = irClass.getPropertyByName("message") - private val causeProperty = irClass.getPropertyByName("cause") + private val messageField = irClass.getFieldByName("message") + private val causeField = irClass.getFieldByName("cause") private val stackTrace: List = stackTrace.reversed() init { if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName() - if (fields.none { it.descriptor.equalTo(messageProperty.descriptor) }) { + if (fields.none { it.symbol == messageField.symbol }) { setMessage() } } @@ -57,7 +58,7 @@ class ExceptionState private constructor( } data class ExceptionData(val state: ExceptionState) : Throwable() { - override val message: String? = state.getMessage().value + override val message: String? = state.getMessage() override fun fillInStackTrace() = this override fun toString(): String = state.getMessageWithName() @@ -66,8 +67,8 @@ class ExceptionState private constructor( private fun setUpCauseIfNeeded(wrapper: Wrapper?) { val cause = (wrapper?.value as? Throwable)?.cause as? ExceptionData setCause(cause?.state) - if (getMessage().value == null && cause != null) { - val causeMessage = cause.state.exceptionFqName + (cause.state.getMessage().value?.let { ": $it" } ?: "") + if (getMessage() == null && cause != null) { + val causeMessage = cause.state.exceptionFqName + (cause.state.getMessage()?.let { ": $it" } ?: "") setMessage(causeMessage) } } @@ -80,21 +81,21 @@ class ExceptionState private constructor( } private fun setMessage(messageValue: String? = null) { - setField(Variable(messageProperty.descriptor, Primitive(messageValue, messageProperty.getter!!.returnType))) + setField(Variable(messageField.symbol, Primitive(messageValue, messageField.type))) } private fun setCause(causeValue: State?) { - setField(Variable(causeProperty.descriptor, causeValue ?: Primitive(null, causeProperty.getter!!.returnType))) + setField(Variable(causeField.symbol, causeValue ?: Primitive(null, causeField.type))) } - fun getMessage(): Primitive = getState(messageProperty.descriptor) as Primitive - private fun getMessageWithName(): String = getMessage().value?.let { "$exceptionFqName: $it" } ?: exceptionFqName + fun getMessage(): String? = (getState(messageField.symbol) as Primitive<*>).value as String? + private fun getMessageWithName(): String = getMessage()?.let { "$exceptionFqName: $it" } ?: exceptionFqName - fun getCause(): ExceptionState? = getState(causeProperty.descriptor)?.let { if (it is ExceptionState) it else null } + fun getCause(): ExceptionState? = getState(causeField.symbol)?.let { if (it is ExceptionState) it else null } fun getFullDescription(): String { // TODO remainder of the stack trace with "..." - val message = getMessage().value.let { if (it?.isNotEmpty() == true) ": $it" else "" } + val message = getMessage().let { if (it?.isNotEmpty() == true) ": $it" else "" } val prefix = if (stackTrace.isNotEmpty()) "\n\t" else "" val postfix = if (stackTrace.size > 10) "\n\t..." else "" val causeMessage = getCause()?.getFullDescription()?.replaceFirst("Exception ", "\nCaused by: ") ?: "" @@ -106,19 +107,18 @@ class ExceptionState private constructor( fun getThisAsCauseForException() = ExceptionData(this) companion object { - private fun IrClass.getPropertyByName(name: String): IrProperty { - val getPropertyFun = this.declarations.firstOrNull { it.nameForIrSerialization.asString().contains("get-$name") } - return (getPropertyFun as? IrFunctionImpl)?.correspondingPropertySymbol?.owner - ?: this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty + private fun IrClass.getFieldByName(name: String): IrField { + val property = this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty + return (property.getter!!.getLastOverridden() as IrSimpleFunction).correspondingPropertySymbol!!.owner.backingField!! } private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List): MutableList { - val messageProperty = irClass.getPropertyByName("message") - val causeProperty = irClass.getPropertyByName("cause") + val messageField = irClass.getFieldByName("message") + val causeField = irClass.getFieldByName("cause") - val messageVar = Variable(messageProperty.descriptor, exception.message.toState(messageProperty.getter!!.returnType)) + val messageVar = Variable(messageField.symbol, exception.message.toState(messageField.type)) val causeVar = exception.cause?.let { - Variable(causeProperty.descriptor, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" })) + Variable(causeField.symbol, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" })) } return listOfNotNull(messageVar, causeVar).toMutableList() } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Lambda.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Lambda.kt index 0cfcd7c07fb..f1381202683 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Lambda.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Lambda.kt @@ -5,22 +5,26 @@ package org.jetbrains.kotlin.backend.common.interpreter.state -import org.jetbrains.kotlin.backend.common.interpreter.equalTo import org.jetbrains.kotlin.backend.common.interpreter.getFqName +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.expressions.IrCall import org.jetbrains.kotlin.ir.util.nameForIrSerialization +import org.jetbrains.kotlin.utils.addToStdlib.cast class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State { 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 + private val invokeSymbol = irClass.declarations + .single { it.nameForIrSerialization.asString() == "invoke" } + .cast() + .getLastOverridden().symbol override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { - return if (invokeDescriptor.equalTo(expression.symbol.descriptor)) irFunction else null + return if (invokeSymbol == expression.symbol) irFunction else null } override fun toString(): String { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Primitive.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Primitive.kt index 52fd5484701..8cf6121158a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Primitive.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Primitive.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.isFakeOverride @@ -20,8 +21,8 @@ class Primitive(var value: T, val type: IrType) : State { override val fields: MutableList = mutableListOf() override val irClass: IrClass = type.classOrNull!!.owner - override fun getState(descriptor: DeclarationDescriptor): State { - return super.getState(descriptor) ?: this + override fun getState(symbol: IrSymbol): State { + return super.getState(symbol) ?: this } override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/State.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/State.kt index 71aa8924d07..6ae82cb25db 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/State.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/State.kt @@ -5,23 +5,22 @@ package org.jetbrains.kotlin.backend.common.interpreter.state -import org.jetbrains.kotlin.backend.common.interpreter.equalTo import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.symbols.IrSymbol interface State { val fields: MutableList val irClass: IrClass - fun getState(descriptor: DeclarationDescriptor): State? { - return fields.firstOrNull { it.descriptor.equalTo(descriptor) }?.state + fun getState(symbol: IrSymbol): State? { + return fields.firstOrNull { it.symbol == symbol }?.state } fun setField(newVar: Variable) { - when (val oldState = fields.firstOrNull { it.descriptor == newVar.descriptor }) { + when (val oldState = fields.firstOrNull { it.symbol == newVar.symbol }) { null -> fields.add(newVar) // newVar isn't present in value list else -> fields[fields.indexOf(oldState)].state = newVar.state // newVar already present } 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 fef25e4439c..36688dc1f63 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 @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.interpreter.getEvaluateIntrinsicValue import org.jetbrains.kotlin.backend.common.interpreter.getFqName import org.jetbrains.kotlin.backend.common.interpreter.getPrimitiveClass import org.jetbrains.kotlin.backend.common.interpreter.hasAnnotation -import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass