From f9607292b5df1c6f31cc00ea58993a603f160428 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Tue, 3 Aug 2021 15:38:07 +0300 Subject: [PATCH] Add additional useful ir classes into IrInterpreterEnvironment --- .../kotlin/ir/interpreter/CallInterceptor.kt | 2 +- .../kotlin/ir/interpreter/IrInterpreter.kt | 7 ++--- .../interpreter/IrInterpreterEnvironment.kt | 31 +++++++++++++++---- .../state/reflection/KClassState.kt | 4 +-- .../state/reflection/KFunctionState.kt | 6 ++-- .../state/reflection/KParameterState.kt | 2 +- .../state/reflection/KPropertyState.kt | 8 ++--- .../state/reflection/KTypeParameterState.kt | 2 +- .../state/reflection/KTypeState.kt | 5 ++- .../state/reflection/ReflectionState.kt | 12 ------- 10 files changed, 41 insertions(+), 38 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt index ddf298d5fe3..ae4f14f30a9 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt @@ -88,7 +88,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : } irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray() -> { // array constructor doesn't have body so must be treated separately - callStack.addVariable(Variable(irConstructor.symbol, KTypeState(constructorCall.type, irBuiltIns.anyClass.owner))) + callStack.addVariable(Variable(irConstructor.symbol, KTypeState(constructorCall.type, environment.kTypeClass.owner))) verify(handleIntrinsicMethods(irConstructor)) { "Unsupported intrinsic constructor: ${irConstructor.render()}" } } irClass.defaultType.isUnsignedType() -> { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index e641bb71c9f..56d1b8ff1a7 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -176,7 +176,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val reifiedTypeArguments = irFunction.typeParameters.filter { it.isReified } .map { val reifiedType = call.getTypeArgument(it.index)!!.getTypeIfReified(callStack) - Variable(it.symbol, KTypeState(reifiedType, irBuiltIns.anyClass.owner)) + Variable(it.symbol, KTypeState(reifiedType, environment.kTypeClass.owner)) } callStack.newFrame(irFunction) @@ -191,9 +191,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } } irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) } irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) } - // TODO: if using KTypeState then it's class must be corresponding // `call.type` is used in check cast and emptyArray - callStack.addVariable(Variable(irFunction.symbol, KTypeState(call.type, irBuiltIns.anyClass.owner))) + callStack.addVariable(Variable(irFunction.symbol, KTypeState(call.type, environment.kTypeClass.owner))) // 6. store reified type parameters reifiedTypeArguments.forEach { callStack.addVariable(it) } @@ -597,7 +596,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal fun List.addToFields() { (0 until propertyReference.typeArgumentsCount).forEach { index -> - val kTypeState = KTypeState(propertyReference.getTypeArgument(index)!!, irBuiltIns.anyClass.owner) + val kTypeState = KTypeState(propertyReference.getTypeArgument(index)!!, environment.kTypeClass.owner) propertyState.fields += Variable(this[index].symbol, kTypeState) } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt index 9b74a9e4012..b1c41000f89 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.interpreter import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy import org.jetbrains.kotlin.ir.interpreter.stack.CallStack import org.jetbrains.kotlin.ir.interpreter.state.Common @@ -15,11 +16,15 @@ import org.jetbrains.kotlin.ir.interpreter.state.Complex import org.jetbrains.kotlin.ir.interpreter.state.Primitive import org.jetbrains.kotlin.ir.interpreter.state.State import org.jetbrains.kotlin.ir.interpreter.state.Wrapper +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.typeOrNull import org.jetbrains.kotlin.ir.util.isSubclassOf +import org.jetbrains.kotlin.ir.util.nameForIrSerialization class IrInterpreterEnvironment( val irBuiltIns: IrBuiltIns, @@ -30,6 +35,20 @@ class IrInterpreterEnvironment( internal var mapOfEnums = mutableMapOf() internal var mapOfObjects = mutableMapOf() internal var javaClassToIrClass = mutableMapOf, IrClass>() + private var functionCache = mutableMapOf() + + internal val kTypeParameterClass by lazy { irBuiltIns.kClassClass.getIrClassOfReflectionFromList("typeParameters")!! } + internal val kParameterClass by lazy { irBuiltIns.kFunctionClass.getIrClassOfReflectionFromList("parameters")!! } + internal val kTypeProjectionClass by lazy { kTypeClass.getIrClassOfReflectionFromList("arguments")!! } + internal val kTypeClass: IrClassSymbol by lazy { + // here we use fallback to `Any` because `KType` cannot be found on JS/Native by this way + // but still this class is used to represent type arguments in interpreter + irBuiltIns.kClassClass.getIrClassOfReflectionFromList("supertypes") ?: irBuiltIns.anyClass + } + + init { + mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner) + } private data class CacheFunctionSignature( val symbol: IrFunctionSymbol, @@ -43,12 +62,6 @@ class IrInterpreterEnvironment( val fromDelegatingCall: Boolean ) - private var functionCache = mutableMapOf() - - init { - mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner) - } - private constructor(environment: IrInterpreterEnvironment) : this(environment.irBuiltIns, configuration = environment.configuration) { irExceptions.addAll(environment.irExceptions) mapOfEnums = environment.mapOfEnums @@ -102,4 +115,10 @@ class IrInterpreterEnvironment( ?: Wrapper(value, this.javaClassToIrClass[value::class.java]!!, this) } } + + private fun IrClassSymbol.getIrClassOfReflectionFromList(name: String): IrClassSymbol? { + val property = this.owner.declarations.singleOrNull { it.nameForIrSerialization.asString() == name } as? IrProperty + val list = property?.getter?.returnType as? IrSimpleType + return list?.arguments?.single()?.typeOrNull?.classOrNull + } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KClassState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KClassState.kt index 8d94bf448ab..ad7d9ba69d7 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KClassState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KClassState.kt @@ -74,14 +74,14 @@ internal class KClassState(val classReference: IrClass, override val irClass: Ir fun getTypeParameters(callInterceptor: CallInterceptor): List { if (_typeParameters != null) return _typeParameters!! - val kTypeParameterIrClass = irClass.getIrClassOfReflectionFromList("typeParameters") + val kTypeParameterIrClass = callInterceptor.environment.kTypeParameterClass.owner _typeParameters = classReference.typeParameters.map { KTypeParameterProxy(KTypeParameterState(it, kTypeParameterIrClass), callInterceptor) } return _typeParameters!! } fun getSupertypes(callInterceptor: CallInterceptor): List { if (_supertypes != null) return _supertypes!! - val kTypeIrClass = irClass.getIrClassOfReflectionFromList("supertypes") + val kTypeIrClass = callInterceptor.environment.kTypeClass.owner _supertypes = (classReference.superTypes.map { it } + callInterceptor.irBuiltIns.anyType).toSet() .map { KTypeProxy(KTypeState(it, kTypeIrClass), callInterceptor) } return _supertypes!! diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt index 18463ef459e..8604c2d44c7 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KFunctionState.kt @@ -118,7 +118,7 @@ internal class KFunctionState( fun getParameters(callInterceptor: CallInterceptor): List { if (_parameters != null) return _parameters!! - val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters") + val kParameterIrClass = callInterceptor.environment.kParameterClass.owner var index = 0 val instanceParameter = irFunction.dispatchReceiverParameter ?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), callInterceptor) } @@ -131,14 +131,14 @@ internal class KFunctionState( fun getReturnType(callInterceptor: CallInterceptor): KType { if (_returnType != null) return _returnType!! - val kTypeIrClass = irClass.getIrClassOfReflection("returnType") + val kTypeIrClass = callInterceptor.environment.kTypeClass.owner _returnType = KTypeProxy(KTypeState(irFunction.returnType, kTypeIrClass), callInterceptor) return _returnType!! } fun getTypeParameters(callInterceptor: CallInterceptor): List { if (_typeParameters != null) return _typeParameters!! - val kTypeParametersIrClass = irClass.getIrClassOfReflectionFromList("typeParameters") + val kTypeParametersIrClass = callInterceptor.environment.kTypeParameterClass.owner _typeParameters = irClass.typeParameters.map { KTypeParameterProxy(KTypeParameterState(it, kTypeParametersIrClass), callInterceptor) } return _typeParameters!! } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt index fdeb8976e3e..3f3b5d51211 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KParameterState.kt @@ -18,7 +18,7 @@ internal class KParameterState( fun getType(callInterceptor: CallInterceptor): KType { if (_type != null) return _type!! - val kTypeIrClass = irClass.getIrClassOfReflection("type") + val kTypeIrClass = callInterceptor.environment.kTypeClass.owner _type = KTypeProxy(KTypeState(irParameter.type, kTypeIrClass), callInterceptor) return _type!! } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt index 3bc17dd0e29..cf33b1c63ca 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KPropertyState.kt @@ -25,14 +25,12 @@ internal class KPropertyState(val property: IrProperty, override val irClass: Ir private var _returnType: KType? = null fun convertGetterToKFunctionState(environment: IrInterpreterEnvironment): KFunctionState { - val getterClass = irClass.getIrClassOfReflection("getter") - val functionType = getterClass.superTypes.single { it.classOrNull?.owner?.name?.asString() == "Function1" } - return KFunctionState(property.getter!!, functionType.classOrNull!!.owner, environment) + return KFunctionState(property.getter!!, environment.irBuiltIns.functionN(1), environment) } fun getParameters(callInterceptor: CallInterceptor): List { if (_parameters != null) return _parameters!! - val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters") + val kParameterIrClass = callInterceptor.environment.kParameterClass.owner var index = 0 val instanceParameter = property.getter?.dispatchReceiverParameter?.takeIf { receiver == null } ?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), callInterceptor) } @@ -44,7 +42,7 @@ internal class KPropertyState(val property: IrProperty, override val irClass: Ir fun getReturnType(callInterceptor: CallInterceptor): KType { if (_returnType != null) return _returnType!! - val kTypeIrClass = irClass.getIrClassOfReflection("returnType") + val kTypeIrClass = callInterceptor.environment.kTypeClass.owner _returnType = KTypeProxy(KTypeState(property.getter!!.returnType, kTypeIrClass), callInterceptor) return _returnType!! } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeParameterState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeParameterState.kt index 2e0fb3bc5cb..46705486b3d 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeParameterState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeParameterState.kt @@ -16,7 +16,7 @@ internal class KTypeParameterState(val irTypeParameter: IrTypeParameter, overrid fun getUpperBounds(callInterceptor: CallInterceptor): List { if (_upperBounds != null) return _upperBounds!! - val kTypeIrClass = irClass.getIrClassOfReflectionFromList("upperBounds") + val kTypeIrClass = callInterceptor.environment.kTypeClass.owner _upperBounds = irTypeParameter.superTypes.map { KTypeProxy(KTypeState(it, kTypeIrClass), callInterceptor) } return _upperBounds!! } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt index 8516b788b73..88ffe706957 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KClassProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy -import org.jetbrains.kotlin.ir.interpreter.state.Wrapper import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.types.Variance import kotlin.reflect.KClassifier @@ -26,7 +25,7 @@ internal class KTypeState(val irType: IrType, override val irClass: IrClass) : R _classifier = when (val classifier = irType.classifierOrFail.owner) { is IrClass -> KClassProxy(KClassState(classifier, callInterceptor.irBuiltIns.kClassClass.owner), callInterceptor) is IrTypeParameter -> { - val kTypeParameterIrClass = callInterceptor.irBuiltIns.kClassClass.owner.getIrClassOfReflectionFromList("typeParameters") + val kTypeParameterIrClass = callInterceptor.environment.kTypeParameterClass.owner KTypeParameterProxy(KTypeParameterState(classifier, kTypeParameterIrClass), callInterceptor) } else -> TODO() @@ -36,7 +35,7 @@ internal class KTypeState(val irType: IrType, override val irClass: IrClass) : R fun getArguments(callInterceptor: CallInterceptor): List { if (_arguments != null) return _arguments!! - callInterceptor.environment.javaClassToIrClass += KTypeProjection::class.java to irClass.getIrClassOfReflectionFromList("arguments") + callInterceptor.environment.javaClassToIrClass += KTypeProjection::class.java to callInterceptor.environment.kTypeProjectionClass.owner _arguments = (irType as IrSimpleType).arguments .map { when (it.getVariance()) { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt index 83c73bcb419..e61e298fa5f 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/ReflectionState.kt @@ -27,18 +27,6 @@ internal abstract class ReflectionState : State { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null - protected fun IrClass.getIrClassOfReflectionFromList(name: String): IrClass { - val property = this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty - val list = property.getter!!.returnType as IrSimpleType - return list.arguments.single().typeOrNull!!.classOrNull!!.owner - } - - protected fun IrClass.getIrClassOfReflection(name: String): IrClass { - val property = this.declarations.single { it.nameForIrSerialization.asString() == name } as IrProperty - val type = property.getter!!.returnType as IrSimpleType - return type.classOrNull!!.owner - } - private fun renderReceivers(dispatchReceiver: IrType?, extensionReceiver: IrType?): String { return buildString { if (dispatchReceiver != null) {