Simplify extraction logic of receiver in ir call interpreter

This commit is contained in:
Ivan Kylchik
2020-04-08 14:26:23 +03:00
parent 2189fe5796
commit be42ae470d
3 changed files with 36 additions and 32 deletions
@@ -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()
@@ -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<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
"kotlin.BooleanArray" -> Primitive(BooleanArray(size) { i -> this[i].toString().toBoolean() }, type)
else -> Primitive<Array<*>>(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
}
}
@@ -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<IrProperty>().mapNotNull { it.getter }.single { it.descriptor.equalTo(descriptor) }
return irClass.declarations.filterIsInstance<IrFunction>().singleOrNull { it.descriptor.equalTo(descriptor) }
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
val functions = irClass.declarations.filterIsInstance<IrFunction>()
return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) }
}
}