Get rid of abstract and fake override checks in ir call interpretation

For now interpreter will find necessary method for interpretation in
one step instead of checking is this method abstract or fake override
This commit is contained in:
Ivan Kylchik
2020-05-10 21:05:46 +03:00
parent 80d83f8703
commit 0c1f2edbf2
8 changed files with 81 additions and 101 deletions
@@ -164,51 +164,6 @@ class IrInterpreter(irModule: IrModuleFragment) {
return IntrinsicEvaluator().evaluate(irFunction, stack) { this.interpret() } return IntrinsicEvaluator().evaluate(irFunction, stack) { this.interpret() }
} }
private suspend fun calculateAbstract(irFunction: IrFunction): ExecutionResult {
if (irFunction.body == null) {
val receiver = stack.getVariableState(irFunction.getReceiver()!!) as Complex
val instance = receiver.getOriginal()
val functionImplementation = instance.getIrFunction(irFunction.descriptor)
if (functionImplementation?.body == null) throw InterpreterMethodNotFoundException("Method \"${irFunction.name}\" wasn't implemented")
val valueArguments = mutableListOf<Variable>()
valueArguments.add(Variable(functionImplementation.getReceiver()!!, instance))
functionImplementation.valueParameters
.map { Variable(it.descriptor, stack.getVariableState(it.descriptor)) }
.forEach { valueArguments.add(it) }
return stack.newFrame(asSubFrame = true, initPool = valueArguments) {
functionImplementation.interpret()
}
}
return irFunction.body!!.interpret()
}
private suspend fun calculateOverridden(owner: IrSimpleFunction): ExecutionResult {
val variableDescriptor = owner.getReceiver()!!
val superQualifier = (stack.getVariableState(variableDescriptor) as? Complex)?.superClass
if (superQualifier == null) {
// superQualifier is null for exception state => find method in builtins
return calculateBuiltIns(owner.getLastOverridden() as IrSimpleFunction)
}
val overridden = owner.overriddenSymbols.single()
val valueArguments = mutableListOf<Variable>()
valueArguments.add(Variable(overridden.owner.getReceiver()!!, superQualifier))
owner.valueParameters.zip(overridden.owner.valueParameters)
.map { Variable(it.second.descriptor, stack.getVariableState(it.first.descriptor)) }
.forEach { valueArguments.add(it) }
return stack.newFrame(asSubFrame = true, initPool = valueArguments) {
val overriddenOwner = overridden.owner
return@newFrame when {
overriddenOwner.body != null -> overriddenOwner.interpret()
superQualifier.superClass == null -> calculateBuiltIns(overriddenOwner)
else -> calculateOverridden(overriddenOwner)
}
}
}
private suspend fun calculateBuiltIns(irFunction: IrFunction): ExecutionResult { private suspend fun calculateBuiltIns(irFunction: IrFunction): ExecutionResult {
val descriptor = irFunction.descriptor val descriptor = irFunction.descriptor
val methodName = when (val property = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol) { val methodName = when (val property = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol) {
@@ -286,7 +241,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
return stack.newFrame(asSubFrame = true, initPool = pool) { return stack.newFrame(asSubFrame = true, initPool = pool) {
for (i in valueArguments.indices) { for (i in valueArguments.indices) {
(valueArguments[i] ?: defaultValues[i])?.interpret()?.check { return@newFrame it } (valueArguments[i] ?: defaultValues[i])?.interpret()?.check { return@newFrame it }
?: stack.pushReturnValue(listOf<Any?>().toPrimitiveStateArray(expression.getVarargType(i)!!)) ?: stack.pushReturnValue(listOf<Any?>().toPrimitiveStateArray(expression.getVarargType(i)!!)) // if vararg is empty
with(Variable(valueParametersDescriptors[i], stack.popReturnValue())) { with(Variable(valueParametersDescriptors[i], stack.popReturnValue())) {
stack.addVar(this) //must add value argument in current stack because it can be used later as default argument stack.addVar(this) //must add value argument in current stack because it can be used later as default argument
@@ -309,9 +264,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
rawExtensionReceiver?.interpret()?.check { return it } rawExtensionReceiver?.interpret()?.check { return it }
val extensionReceiver = rawExtensionReceiver?.let { stack.popReturnValue() } val extensionReceiver = rawExtensionReceiver?.let { stack.popReturnValue() }
// find correct ir function // get correct ir function
val functionReceiver = dispatchReceiver?.getFunctionReceiver(expression.superQualifierSymbol?.owner) val irFunction = dispatchReceiver?.getIrFunctionByIrCall(expression) ?: expression.symbol.owner
val irFunction = functionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner val functionReceiver = dispatchReceiver.getCorrectReceiverByFunction(irFunction)
// it is important firstly to add receiver, then arguments; this order is used in builtin method call // it is important firstly to add receiver, then arguments; this order is used in builtin method call
irFunction.getDispatchReceiver()?.let { functionReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } } irFunction.getDispatchReceiver()?.let { functionReceiver?.let { receiver -> valueArguments.add(Variable(it, receiver)) } }
@@ -332,9 +287,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
return@newFrame when { return@newFrame when {
dispatchReceiver is Wrapper && !isInlineOnly -> dispatchReceiver.getMethod(irFunction).invokeMethod(irFunction) dispatchReceiver is Wrapper && !isInlineOnly -> dispatchReceiver.getMethod(irFunction).invokeMethod(irFunction)
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction) irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction)
irFunction.isAbstract() -> calculateAbstract(irFunction) //abstract check must be before fake overridden check irFunction.body == null || dispatchReceiver is Primitive<*> -> calculateBuiltIns(irFunction) // 'is Primitive' because of js char and long
irFunction.isFakeOverridden() -> calculateOverridden(irFunction as IrSimpleFunction)
irFunction.body == null || dispatchReceiver is Primitive<*> -> calculateBuiltIns(irFunction) // is Primitive because of js char and long
else -> irFunction.interpret() else -> irFunction.interpret()
} }
} }
@@ -730,7 +683,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
is Common -> { is Common -> {
val toStringFun = returnValue.getToStringFunction() val toStringFun = returnValue.getToStringFunction()
stack.newFrame(initPool = mutableListOf(Variable(toStringFun.getReceiver()!!, returnValue))) { stack.newFrame(initPool = mutableListOf(Variable(toStringFun.getReceiver()!!, returnValue))) {
toStringFun.body?.let { toStringFun.interpret() } ?: calculateOverridden(toStringFun) toStringFun.body?.let { toStringFun.interpret() } ?: calculateBuiltIns(toStringFun)
}.check { executionResult -> return executionResult } }.check { executionResult -> return executionResult }
stack.popReturnValue().asString() stack.popReturnValue().asString()
} }
@@ -12,20 +12,15 @@ import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
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.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.*
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.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
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
// main purpose is to get receiver from constructor call // main purpose is to get receiver from constructor call
@@ -50,7 +45,7 @@ fun IrFunctionAccessExpression.getBody(): IrBody? {
} }
fun DeclarationDescriptor.equalTo(other: DeclarationDescriptor): Boolean { fun DeclarationDescriptor.equalTo(other: DeclarationDescriptor): Boolean {
return this.isSubtypeOf(other) || this.hasSameNameAs(other) || this == other return this.isEqualByReceiverTo(other) || this.hasSameNameAs(other) || this == other
} }
private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescriptor): Boolean { private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescriptor): Boolean {
@@ -60,14 +55,14 @@ private fun WrappedReceiverParameterDescriptor.isEqualTo(other: DeclarationDescr
} }
} }
private fun DeclarationDescriptor.isSubtypeOf(other: DeclarationDescriptor): Boolean { private fun DeclarationDescriptor.isEqualByReceiverTo(other: DeclarationDescriptor): Boolean {
if (this !is ReceiverParameterDescriptor || other !is ReceiverParameterDescriptor) return false if (this !is ReceiverParameterDescriptor || other !is ReceiverParameterDescriptor) return false
return when { return when {
this is WrappedReceiverParameterDescriptor && other is WrappedReceiverParameterDescriptor -> this is WrappedReceiverParameterDescriptor && other is WrappedReceiverParameterDescriptor ->
this.isEqualTo(other) || other.isEqualTo(this) this.isEqualTo(other) || other.isEqualTo(this)
this is WrappedReceiverParameterDescriptor -> this.isEqualTo(other) this is WrappedReceiverParameterDescriptor -> this.isEqualTo(other)
other is WrappedReceiverParameterDescriptor -> other.isEqualTo(this) other is WrappedReceiverParameterDescriptor -> other.isEqualTo(this)
this.value is ImplicitClassReceiver && other.value is ImplicitClassReceiver -> this.value.type.isSubtypeOf(other.value.type) 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 this.value is ExtensionReceiver && other.value is ExtensionReceiver -> this.value == other.value
else -> false else -> false
} }
@@ -81,14 +76,6 @@ private fun DeclarationDescriptor.hasSameNameAs(other: DeclarationDescriptor): B
this.name == other.name) this.name == other.name)
} }
fun IrFunction.isAbstract(): Boolean {
return (this as? IrSimpleFunction)?.modality == Modality.ABSTRACT
}
fun IrFunction.isFakeOverridden(): Boolean {
return this.isFakeOverride
}
fun State.toIrExpression(expression: IrExpression): IrExpression { fun State.toIrExpression(expression: IrExpression): IrExpression {
val start = expression.startOffset val start = expression.startOffset
val end = expression.endOffset val end = expression.endOffset
@@ -177,7 +164,7 @@ fun getPrimitiveClass(fqName: String, asObject: Boolean = false): Class<*>? {
} }
fun IrType.getFqName(): String? { fun IrType.getFqName(): String? {
return this.classOrNull?.owner?.fqNameForIrSerialization?.asString() return this.classOrNull?.owner?.fqNameWhenAvailable?.asString()
} }
fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> { fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> {
@@ -202,13 +189,9 @@ fun IrFunction.getArgsForMethodInvocation(args: List<Variable>): List<Any?> {
} }
fun IrFunction.getLastOverridden(): IrFunction { fun IrFunction.getLastOverridden(): IrFunction {
if (this !is IrFunctionImpl) return this if (this !is IrSimpleFunction) return this
var function = this as IrFunctionImpl return generateSequence(listOf(this)) { it.firstOrNull()?.overriddenSymbols?.map { it.owner } }.flatten().last()
while (function.overriddenSymbols.isNotEmpty()) {
function = function.overriddenSymbols.first().owner as IrFunctionImpl
}
return function
} }
fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> { fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
@@ -225,18 +208,6 @@ fun List<Any?>.toPrimitiveStateArray(type: IrType): Primitive<*> {
} }
} }
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
}
}
fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? { fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
val varargType = this.symbol.owner.valueParameters[index].varargElementType ?: return null val varargType = this.symbol.owner.valueParameters[index].varargElementType ?: return null
varargType.classOrNull?.let { return this.symbol.owner.valueParameters[index].type } varargType.classOrNull?.let { return this.symbol.owner.valueParameters[index].type }
@@ -268,4 +239,12 @@ fun State?.extractNonLocalDeclarations(): List<Variable> {
this ?: return listOf() this ?: return listOf()
val state = this.takeIf { it !is Complex } ?: (this as Complex).getOriginal() val state = this.takeIf { it !is Complex } ?: (this as Complex).getOriginal()
return state.fields.filterNot { it.descriptor.containingDeclaration == state.irClass.descriptor } return state.fields.filterNot { it.descriptor.containingDeclaration == state.irClass.descriptor }
}
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
} }
@@ -137,7 +137,7 @@ object RegexReplace : IntrinsicBase() {
object EnumHashCode : IntrinsicBase() { object EnumHashCode : IntrinsicBase() {
override fun equalTo(irFunction: IrFunction): Boolean { override fun equalTo(irFunction: IrFunction): Boolean {
val fqName = irFunction.fqNameWhenAvailable.toString() val fqName = irFunction.fqNameWhenAvailable.toString()
return fqName.endsWith(".hashCode") && irFunction.parentAsClass.isEnumClass return fqName == "kotlin.Enum.hashCode"
} }
override suspend fun evaluate( override suspend fun evaluate(
@@ -5,12 +5,14 @@
package org.jetbrains.kotlin.backend.common.interpreter.state package org.jetbrains.kotlin.backend.common.interpreter.state
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
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.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
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.isInterface import org.jetbrains.kotlin.ir.util.isInterface
class Common private constructor( class Common private constructor(
@@ -42,10 +44,11 @@ class Common private constructor(
return owner return owner
} }
fun getToStringFunction(): IrFunctionImpl { fun getToStringFunction(): IrFunction {
return irClass.declarations.filterIsInstance<IrFunction>() return irClass.declarations.filterIsInstance<IrFunction>()
.filter { it.descriptor.name.asString() == "toString" } .filter { it.descriptor.name.asString() == "toString" }
.first { it.descriptor.valueParameters.isEmpty() } as IrFunctionImpl .first { it.descriptor.valueParameters.isEmpty() }
.let { getOverridden(it as IrSimpleFunction, this) }
} }
override fun copy(): State { override fun copy(): State {
@@ -6,12 +6,17 @@
package org.jetbrains.kotlin.backend.common.interpreter.state 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.getLastOverridden
import org.jetbrains.kotlin.backend.common.interpreter.getCorrectReceiverByFunction
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.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
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.isInterface
abstract class Complex( abstract class Complex(
override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex? override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex?
@@ -47,9 +52,45 @@ abstract class Complex(
} }
} }
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter } val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
val functions = irClass.declarations.filterIsInstance<IrFunction>() val functions = irClass.declarations.filterIsInstance<IrFunction>()
return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) } return (propertyGetters + functions).singleOrNull { it.descriptor.equalTo(descriptor) }
} }
private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? {
return when {
superIrClass == null -> this.getOriginal()
superIrClass.isInterface -> {
val interfaceState = Common(superIrClass)
(this.copy() as Complex).setSuperClassInstance(interfaceState)
interfaceState
}
else -> this.superClass
}
}
protected fun getOverridden(owner: IrSimpleFunction, qualifier: State?): IrSimpleFunction {
if (!owner.isFakeOverride) return owner
if (qualifier == null || qualifier is ExceptionState || (qualifier as? Complex)?.superClass == null) {
return owner.getLastOverridden() as IrSimpleFunction
}
val overriddenOwner = owner.overriddenSymbols.single().owner
return when {
overriddenOwner.body != null -> overriddenOwner
else -> getOverridden(overriddenOwner, qualifier.superClass!!)
}
}
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
val receiver = getThisOrSuperReceiver(expression.superQualifierSymbol?.owner) ?: return null
val irFunction = receiver.getIrFunction(expression.symbol.descriptor) ?: return null
return when (irFunction.body) {
null -> getOverridden(irFunction as IrSimpleFunction, this.getCorrectReceiverByFunction(irFunction))
else -> irFunction
}
}
} }
@@ -7,9 +7,9 @@ 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.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.expressions.IrCall
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.nameForIrSerialization import org.jetbrains.kotlin.ir.util.nameForIrSerialization
@@ -23,8 +23,8 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State
throw UnsupportedOperationException("Method setState is not supported in Lambda class") throw UnsupportedOperationException("Method setState is not supported in Lambda class")
} }
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
return if (invokeDescriptor.equalTo(descriptor)) irFunction else null return if (invokeDescriptor.equalTo(expression.symbol.descriptor)) irFunction else null
} }
override fun copy(): State { override fun copy(): State {
@@ -5,14 +5,16 @@
package org.jetbrains.kotlin.backend.common.interpreter.state package org.jetbrains.kotlin.backend.common.interpreter.state
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
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
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.isFakeOverride
class Primitive<T>(var value: T, val type: IrType) : State { class Primitive<T>(var value: T, val type: IrType) : State {
override val fields: MutableList<Variable> = mutableListOf() override val fields: MutableList<Variable> = mutableListOf()
@@ -31,12 +33,14 @@ class Primitive<T>(var value: T, val type: IrType) : State {
return Primitive(value, type) return Primitive(value, type)
} }
override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
val descriptor = expression.symbol.descriptor
// must add property's getter to declaration's list because they are not present in ir class for primitives // must add property's getter to declaration's list because they are not present in ir class for primitives
val declarations = irClass.declarations.map { if (it is IrProperty) it.getter else it } val declarations = irClass.declarations.map { if (it is IrProperty) it.getter else it }
return declarations.filterIsInstance<IrFunction>() return declarations.filterIsInstance<IrFunction>()
.filter { it.descriptor.name == descriptor.name } .filter { it.descriptor.name == descriptor.name }
.firstOrNull { it.descriptor.valueParameters.map { it.type } == descriptor.valueParameters.map { it.type } } .firstOrNull { it.descriptor.valueParameters.map { it.type } == descriptor.valueParameters.map { it.type } }
?.let { if (it.isFakeOverride) it.getLastOverridden() else it }
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@@ -8,9 +8,9 @@ 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.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
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.expressions.IrCall
interface State { interface State {
val fields: MutableList<Variable> val fields: MutableList<Variable>
@@ -31,7 +31,7 @@ interface State {
*/ */
fun copy(): State fun copy(): State
fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? fun getIrFunctionByIrCall(expression: IrCall): IrFunction?
} }
fun State.asInt() = (this as Primitive<*>).value as Int fun State.asInt() = (this as Primitive<*>).value as Int