From be42ae470ddfcfe0e1020738565cc188eca1d696 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Wed, 8 Apr 2020 14:26:23 +0300 Subject: [PATCH] Simplify extraction logic of receiver in ir call interpreter --- .../common/interpreter/IrInterpreter.kt | 34 ++++++++----------- .../backend/common/interpreter/Utils.kt | 26 ++++++++++---- .../common/interpreter/state/Complex.kt | 8 ++--- 3 files changed, 36 insertions(+), 32 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 65f29347105..02038a9dda9 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 @@ -228,14 +228,14 @@ class IrInterpreter(irModule: IrModuleFragment) { private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): ExecutionResult { if (irFunction.body == null) { - val receiver = data.getVariableState(irFunction.symbol.getReceiver()!!) as Complex + val receiver = data.getVariableState(irFunction.getReceiver()!!) as Complex val instance = receiver.getOriginal() val functionImplementation = instance.getIrFunction(irFunction.descriptor) if (functionImplementation?.body == null) throw NoSuchMethodException("Method \"${irFunction.name}\" wasn't implemented") val arguments = functionImplementation.valueParameters.map { Variable(it.descriptor, data.getVariableState(it.descriptor)) } val newFrame = InterpreterFrame() - newFrame.addVar(Variable(functionImplementation.symbol.getReceiver()!!, instance)) + newFrame.addVar(Variable(functionImplementation.getReceiver()!!, instance)) newFrame.addAll(arguments) return functionImplementation.interpret(newFrame).apply { data.pushReturnValue(newFrame) } } @@ -243,7 +243,7 @@ class IrInterpreter(irModule: IrModuleFragment) { } private suspend fun calculateOverridden(owner: IrSimpleFunction, data: Frame): ExecutionResult { - val variableDescriptor = owner.symbol.getReceiver()!! + val variableDescriptor = owner.getReceiver()!! val superQualifier = (data.getVariableState(variableDescriptor) as? Complex)?.superClass if (superQualifier == null) { // superQualifier is null for exception state => find method in builtins @@ -251,7 +251,7 @@ class IrInterpreter(irModule: IrModuleFragment) { } val overridden = owner.overriddenSymbols.single() - val newStates = InterpreterFrame(mutableListOf(Variable(overridden.getReceiver()!!, superQualifier))) + val newStates = InterpreterFrame(mutableListOf(Variable(overridden.owner.getReceiver()!!, superQualifier))) owner.valueParameters.zip(overridden.owner.valueParameters) .map { Variable(it.second.descriptor, data.getVariableState(it.first.descriptor)) } .forEach { newStates.addVar(it) } @@ -323,7 +323,7 @@ class IrInterpreter(irModule: IrModuleFragment) { ): ExecutionResult { // if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver val receiverAsFirstArgument = when (expression.dispatchReceiver?.type?.isFunction()) { - true -> listOfNotNull(irFunction.symbol.getExtensionReceiver()) + true -> listOfNotNull(irFunction.getExtensionReceiver()) else -> listOf() } val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters @@ -349,24 +349,18 @@ class IrInterpreter(irModule: IrModuleFragment) { rawDispatchReceiver?.interpret(data)?.check { return it } val dispatchReceiver = rawDispatchReceiver?.let { data.popReturnValue() } - val superQualifier = expression.superQualifierSymbol - val irFunctionReceiver = when { - superQualifier == null -> dispatchReceiver - superQualifier.owner.isInterface -> null - else -> (dispatchReceiver as Complex).superClass - } - // 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 - irFunctionReceiver?.let { receiverState -> - // dispatch receiver is null if irFunction is lambda and so there is no need to add it as variable in frame - irFunction.symbol.getDispatchReceiver()?.let { newFrame.addVar(Variable(it, receiverState)) } - } - // extension receiver processing val rawExtensionReceiver = expression.extensionReceiver rawExtensionReceiver?.interpret(data)?.check { return it } val extensionReceiver = rawExtensionReceiver?.let { data.popReturnValue() } - extensionReceiver?.let { newFrame.addVar(Variable(irFunction.symbol.getExtensionReceiver()!!, it)) } + + // find correct ir function + val functionReceiver = dispatchReceiver?.getFunctionReceiver(expression.superQualifierSymbol?.owner) + val irFunction = functionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner + + // it is important firstly to add receiver, then arguments; this order is used in builtin method call + irFunction.getDispatchReceiver()?.let { functionReceiver?.let { receiver -> newFrame.addVar(Variable(it, receiver)) } } + irFunction.getExtensionReceiver()?.let { extensionReceiver?.let { receiver -> newFrame.addVar(Variable(it, receiver)) } } interpretValueParameters(expression, irFunction, data, newFrame).check { return it } @@ -777,7 +771,7 @@ class IrInterpreter(irModule: IrModuleFragment) { is Wrapper -> returnValue.value.toString() is Common -> { val toStringFun = returnValue.getToStringFunction() - val newFrame = InterpreterFrame(mutableListOf(Variable(toStringFun.symbol.getReceiver()!!, returnValue))) + val newFrame = InterpreterFrame(mutableListOf(Variable(toStringFun.getReceiver()!!, returnValue))) val executionResult = toStringFun.body?.let { toStringFun.interpret(newFrame) } ?: calculateOverridden(toStringFun, newFrame) if (executionResult.returnLabel != ReturnLabel.NEXT) return executionResult (newFrame.popReturnValue() as Primitive<*>).value.toString() 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 94afb7ec9fd..fe2197f5b69 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 @@ -16,11 +16,11 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl 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.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.isFakeOverride +import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver @@ -32,15 +32,15 @@ fun IrMemberAccessExpression.getThisAsReceiver(): DeclarationDescriptor { return (this.symbol.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter } -fun IrFunctionSymbol.getDispatchReceiver(): DeclarationDescriptor? { - return (this.descriptor.containingDeclaration as? ClassDescriptor)?.thisAsReceiverParameter +fun IrFunction.getDispatchReceiver(): DeclarationDescriptor? { + return (this.symbol.descriptor.containingDeclaration as? ClassDescriptor)?.thisAsReceiverParameter } -fun IrFunctionSymbol.getExtensionReceiver(): DeclarationDescriptor? { - return this.owner.extensionReceiverParameter?.descriptor +fun IrFunction.getExtensionReceiver(): DeclarationDescriptor? { + return this.extensionReceiverParameter?.descriptor } -fun IrFunctionSymbol.getReceiver(): DeclarationDescriptor? { +fun IrFunction.getReceiver(): DeclarationDescriptor? { return this.getDispatchReceiver() ?: this.getExtensionReceiver() } @@ -74,7 +74,7 @@ private fun DeclarationDescriptor.isSubtypeOf(other: DeclarationDescriptor): Boo private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean { return (this is VariableDescriptor && other is VariableDescriptor && this.name == other.name) || - (this is FunctionDescriptor && other is FunctionDescriptor && + (this is FunctionDescriptor && other is FunctionDescriptor && //this == other this.valueParameters.map { it.type.toString() } == other.valueParameters.map { it.type.toString() } && this.name == other.name) } @@ -221,4 +221,16 @@ fun List.toPrimitiveStateArray(type: IrType): Primitive<*> { "kotlin.BooleanArray" -> Primitive(BooleanArray(size) { i -> this[i].toString().toBoolean() }, type) else -> Primitive>(this.toTypedArray(), type) } +} + +fun State?.getFunctionReceiver(superIrClass: IrClass?): State? { + return when { + superIrClass == null -> this + superIrClass.isInterface -> { + val interfaceState = Common(superIrClass) + (this!!.copy() as Complex).setSuperClassInstance(interfaceState) + interfaceState + } + else -> (this as Complex).superClass + } } \ 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 fb4b41e7f71..b93f69d125f 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 @@ -8,7 +8,6 @@ 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.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrProperty @@ -40,9 +39,8 @@ abstract class Complex( fun setStatesFrom(state: Complex) = state.fields.forEach { setState(it) } override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { - if (descriptor is PropertyGetterDescriptor) - return irClass.declarations.filterIsInstance().mapNotNull { it.getter }.single { it.descriptor.equalTo(descriptor) } - - return irClass.declarations.filterIsInstance().singleOrNull { it.descriptor.equalTo(descriptor) } + val propertyGetters = irClass.declarations.filterIsInstance().mapNotNull { it.getter } + val functions = irClass.declarations.filterIsInstance() + return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) } } } \ No newline at end of file