Simplify extraction logic of receiver in ir call interpreter
This commit is contained in:
+14
-20
@@ -228,14 +228,14 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): ExecutionResult {
|
private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): ExecutionResult {
|
||||||
if (irFunction.body == null) {
|
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 instance = receiver.getOriginal()
|
||||||
|
|
||||||
val functionImplementation = instance.getIrFunction(irFunction.descriptor)
|
val functionImplementation = instance.getIrFunction(irFunction.descriptor)
|
||||||
if (functionImplementation?.body == null) throw NoSuchMethodException("Method \"${irFunction.name}\" wasn't implemented")
|
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 arguments = functionImplementation.valueParameters.map { Variable(it.descriptor, data.getVariableState(it.descriptor)) }
|
||||||
val newFrame = InterpreterFrame()
|
val newFrame = InterpreterFrame()
|
||||||
newFrame.addVar(Variable(functionImplementation.symbol.getReceiver()!!, instance))
|
newFrame.addVar(Variable(functionImplementation.getReceiver()!!, instance))
|
||||||
newFrame.addAll(arguments)
|
newFrame.addAll(arguments)
|
||||||
return functionImplementation.interpret(newFrame).apply { data.pushReturnValue(newFrame) }
|
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 {
|
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
|
val superQualifier = (data.getVariableState(variableDescriptor) as? Complex)?.superClass
|
||||||
if (superQualifier == null) {
|
if (superQualifier == null) {
|
||||||
// superQualifier is null for exception state => find method in builtins
|
// superQualifier is null for exception state => find method in builtins
|
||||||
@@ -251,7 +251,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
val overridden = owner.overriddenSymbols.single()
|
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)
|
owner.valueParameters.zip(overridden.owner.valueParameters)
|
||||||
.map { Variable(it.second.descriptor, data.getVariableState(it.first.descriptor)) }
|
.map { Variable(it.second.descriptor, data.getVariableState(it.first.descriptor)) }
|
||||||
.forEach { newStates.addVar(it) }
|
.forEach { newStates.addVar(it) }
|
||||||
@@ -323,7 +323,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
): ExecutionResult {
|
): ExecutionResult {
|
||||||
// if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver
|
// if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver
|
||||||
val receiverAsFirstArgument = when (expression.dispatchReceiver?.type?.isFunction()) {
|
val receiverAsFirstArgument = when (expression.dispatchReceiver?.type?.isFunction()) {
|
||||||
true -> listOfNotNull(irFunction.symbol.getExtensionReceiver())
|
true -> listOfNotNull(irFunction.getExtensionReceiver())
|
||||||
else -> listOf()
|
else -> listOf()
|
||||||
}
|
}
|
||||||
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
val valueParametersDescriptors = receiverAsFirstArgument + irFunction.descriptor.valueParameters
|
||||||
@@ -349,24 +349,18 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
rawDispatchReceiver?.interpret(data)?.check { return it }
|
rawDispatchReceiver?.interpret(data)?.check { return it }
|
||||||
val dispatchReceiver = rawDispatchReceiver?.let { data.popReturnValue() }
|
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
|
// extension receiver processing
|
||||||
val rawExtensionReceiver = expression.extensionReceiver
|
val rawExtensionReceiver = expression.extensionReceiver
|
||||||
rawExtensionReceiver?.interpret(data)?.check { return it }
|
rawExtensionReceiver?.interpret(data)?.check { return it }
|
||||||
val extensionReceiver = rawExtensionReceiver?.let { data.popReturnValue() }
|
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 }
|
interpretValueParameters(expression, irFunction, data, newFrame).check { return it }
|
||||||
|
|
||||||
@@ -777,7 +771,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
is Wrapper -> returnValue.value.toString()
|
is Wrapper -> returnValue.value.toString()
|
||||||
is Common -> {
|
is Common -> {
|
||||||
val toStringFun = returnValue.getToStringFunction()
|
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)
|
val executionResult = toStringFun.body?.let { toStringFun.interpret(newFrame) } ?: calculateOverridden(toStringFun, newFrame)
|
||||||
if (executionResult.returnLabel != ReturnLabel.NEXT) return executionResult
|
if (executionResult.returnLabel != ReturnLabel.NEXT) return executionResult
|
||||||
(newFrame.popReturnValue() as Primitive<*>).value.toString()
|
(newFrame.popReturnValue() as Primitive<*>).value.toString()
|
||||||
|
|||||||
+19
-7
@@ -16,11 +16,11 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
|||||||
import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor
|
import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
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.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||||
|
import org.jetbrains.kotlin.ir.util.isInterface
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||||
@@ -32,15 +32,15 @@ fun IrMemberAccessExpression.getThisAsReceiver(): DeclarationDescriptor {
|
|||||||
return (this.symbol.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter
|
return (this.symbol.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunctionSymbol.getDispatchReceiver(): DeclarationDescriptor? {
|
fun IrFunction.getDispatchReceiver(): DeclarationDescriptor? {
|
||||||
return (this.descriptor.containingDeclaration as? ClassDescriptor)?.thisAsReceiverParameter
|
return (this.symbol.descriptor.containingDeclaration as? ClassDescriptor)?.thisAsReceiverParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunctionSymbol.getExtensionReceiver(): DeclarationDescriptor? {
|
fun IrFunction.getExtensionReceiver(): DeclarationDescriptor? {
|
||||||
return this.owner.extensionReceiverParameter?.descriptor
|
return this.extensionReceiverParameter?.descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunctionSymbol.getReceiver(): DeclarationDescriptor? {
|
fun IrFunction.getReceiver(): DeclarationDescriptor? {
|
||||||
return this.getDispatchReceiver() ?: this.getExtensionReceiver()
|
return this.getDispatchReceiver() ?: this.getExtensionReceiver()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ private fun DeclarationDescriptor.isSubtypeOf(other: DeclarationDescriptor): Boo
|
|||||||
|
|
||||||
private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean {
|
private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): Boolean {
|
||||||
return (this is VariableDescriptor && other is VariableDescriptor && this.name == other.name) ||
|
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.valueParameters.map { it.type.toString() } == other.valueParameters.map { it.type.toString() } &&
|
||||||
this.name == other.name)
|
this.name == other.name)
|
||||||
}
|
}
|
||||||
@@ -222,3 +222,15 @@ fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
|
|||||||
else -> Primitive<Array<*>>(this.toTypedArray(), 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
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-5
@@ -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.equalTo
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
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.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
@@ -40,9 +39,8 @@ abstract class Complex(
|
|||||||
fun setStatesFrom(state: Complex) = state.fields.forEach { setState(it) }
|
fun setStatesFrom(state: Complex) = state.fields.forEach { setState(it) }
|
||||||
|
|
||||||
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||||
if (descriptor is PropertyGetterDescriptor)
|
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
||||||
return irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }.single { it.descriptor.equalTo(descriptor) }
|
val functions = irClass.declarations.filterIsInstance<IrFunction>()
|
||||||
|
return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) }
|
||||||
return irClass.declarations.filterIsInstance<IrFunction>().singleOrNull { it.descriptor.equalTo(descriptor) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user