Add additional useful ir classes into IrInterpreterEnvironment

This commit is contained in:
Ivan Kylchik
2021-08-03 15:38:07 +03:00
committed by TeamCityServer
parent b46a42be33
commit f9607292b5
10 changed files with 41 additions and 38 deletions
@@ -88,7 +88,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
} }
irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray() -> { irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray() -> {
// array constructor doesn't have body so must be treated separately // 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()}" } verify(handleIntrinsicMethods(irConstructor)) { "Unsupported intrinsic constructor: ${irConstructor.render()}" }
} }
irClass.defaultType.isUnsignedType() -> { irClass.defaultType.isUnsignedType() -> {
@@ -176,7 +176,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
val reifiedTypeArguments = irFunction.typeParameters.filter { it.isReified } val reifiedTypeArguments = irFunction.typeParameters.filter { it.isReified }
.map { .map {
val reifiedType = call.getTypeArgument(it.index)!!.getTypeIfReified(callStack) 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) 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.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) } irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) } 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 // `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 // 6. store reified type parameters
reifiedTypeArguments.forEach { callStack.addVariable(it) } reifiedTypeArguments.forEach { callStack.addVariable(it) }
@@ -597,7 +596,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
fun List<IrTypeParameter>.addToFields() { fun List<IrTypeParameter>.addToFields() {
(0 until propertyReference.typeArgumentsCount).forEach { index -> (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) propertyState.fields += Variable(this[index].symbol, kTypeState)
} }
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.interpreter
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment 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.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
import org.jetbrains.kotlin.ir.interpreter.state.Common 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.Primitive
import org.jetbrains.kotlin.ir.interpreter.state.State import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.state.Wrapper 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.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol 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.IrType
import org.jetbrains.kotlin.ir.types.classOrNull 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.isSubclassOf
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
class IrInterpreterEnvironment( class IrInterpreterEnvironment(
val irBuiltIns: IrBuiltIns, val irBuiltIns: IrBuiltIns,
@@ -30,6 +35,20 @@ class IrInterpreterEnvironment(
internal var mapOfEnums = mutableMapOf<IrSymbol, Complex>() internal var mapOfEnums = mutableMapOf<IrSymbol, Complex>()
internal var mapOfObjects = mutableMapOf<IrSymbol, Complex>() internal var mapOfObjects = mutableMapOf<IrSymbol, Complex>()
internal var javaClassToIrClass = mutableMapOf<Class<*>, IrClass>() internal var javaClassToIrClass = mutableMapOf<Class<*>, IrClass>()
private var functionCache = mutableMapOf<CacheFunctionSignature, IrFunctionSymbol>()
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( private data class CacheFunctionSignature(
val symbol: IrFunctionSymbol, val symbol: IrFunctionSymbol,
@@ -43,12 +62,6 @@ class IrInterpreterEnvironment(
val fromDelegatingCall: Boolean val fromDelegatingCall: Boolean
) )
private var functionCache = mutableMapOf<CacheFunctionSignature, IrFunctionSymbol>()
init {
mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner)
}
private constructor(environment: IrInterpreterEnvironment) : this(environment.irBuiltIns, configuration = environment.configuration) { private constructor(environment: IrInterpreterEnvironment) : this(environment.irBuiltIns, configuration = environment.configuration) {
irExceptions.addAll(environment.irExceptions) irExceptions.addAll(environment.irExceptions)
mapOfEnums = environment.mapOfEnums mapOfEnums = environment.mapOfEnums
@@ -102,4 +115,10 @@ class IrInterpreterEnvironment(
?: Wrapper(value, this.javaClassToIrClass[value::class.java]!!, this) ?: 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
}
} }
@@ -74,14 +74,14 @@ internal class KClassState(val classReference: IrClass, override val irClass: Ir
fun getTypeParameters(callInterceptor: CallInterceptor): List<KTypeParameter> { fun getTypeParameters(callInterceptor: CallInterceptor): List<KTypeParameter> {
if (_typeParameters != null) return _typeParameters!! 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) } _typeParameters = classReference.typeParameters.map { KTypeParameterProxy(KTypeParameterState(it, kTypeParameterIrClass), callInterceptor) }
return _typeParameters!! return _typeParameters!!
} }
fun getSupertypes(callInterceptor: CallInterceptor): List<KType> { fun getSupertypes(callInterceptor: CallInterceptor): List<KType> {
if (_supertypes != null) return _supertypes!! 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() _supertypes = (classReference.superTypes.map { it } + callInterceptor.irBuiltIns.anyType).toSet()
.map { KTypeProxy(KTypeState(it, kTypeIrClass), callInterceptor) } .map { KTypeProxy(KTypeState(it, kTypeIrClass), callInterceptor) }
return _supertypes!! return _supertypes!!
@@ -118,7 +118,7 @@ internal class KFunctionState(
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> { fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
if (_parameters != null) return _parameters!! if (_parameters != null) return _parameters!!
val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters") val kParameterIrClass = callInterceptor.environment.kParameterClass.owner
var index = 0 var index = 0
val instanceParameter = irFunction.dispatchReceiverParameter val instanceParameter = irFunction.dispatchReceiverParameter
?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), callInterceptor) } ?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), callInterceptor) }
@@ -131,14 +131,14 @@ internal class KFunctionState(
fun getReturnType(callInterceptor: CallInterceptor): KType { fun getReturnType(callInterceptor: CallInterceptor): KType {
if (_returnType != null) return _returnType!! if (_returnType != null) return _returnType!!
val kTypeIrClass = irClass.getIrClassOfReflection("returnType") val kTypeIrClass = callInterceptor.environment.kTypeClass.owner
_returnType = KTypeProxy(KTypeState(irFunction.returnType, kTypeIrClass), callInterceptor) _returnType = KTypeProxy(KTypeState(irFunction.returnType, kTypeIrClass), callInterceptor)
return _returnType!! return _returnType!!
} }
fun getTypeParameters(callInterceptor: CallInterceptor): List<KTypeParameter> { fun getTypeParameters(callInterceptor: CallInterceptor): List<KTypeParameter> {
if (_typeParameters != null) return _typeParameters!! 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) } _typeParameters = irClass.typeParameters.map { KTypeParameterProxy(KTypeParameterState(it, kTypeParametersIrClass), callInterceptor) }
return _typeParameters!! return _typeParameters!!
} }
@@ -18,7 +18,7 @@ internal class KParameterState(
fun getType(callInterceptor: CallInterceptor): KType { fun getType(callInterceptor: CallInterceptor): KType {
if (_type != null) return _type!! if (_type != null) return _type!!
val kTypeIrClass = irClass.getIrClassOfReflection("type") val kTypeIrClass = callInterceptor.environment.kTypeClass.owner
_type = KTypeProxy(KTypeState(irParameter.type, kTypeIrClass), callInterceptor) _type = KTypeProxy(KTypeState(irParameter.type, kTypeIrClass), callInterceptor)
return _type!! return _type!!
} }
@@ -25,14 +25,12 @@ internal class KPropertyState(val property: IrProperty, override val irClass: Ir
private var _returnType: KType? = null private var _returnType: KType? = null
fun convertGetterToKFunctionState(environment: IrInterpreterEnvironment): KFunctionState { fun convertGetterToKFunctionState(environment: IrInterpreterEnvironment): KFunctionState {
val getterClass = irClass.getIrClassOfReflection("getter") return KFunctionState(property.getter!!, environment.irBuiltIns.functionN(1), environment)
val functionType = getterClass.superTypes.single { it.classOrNull?.owner?.name?.asString() == "Function1" }
return KFunctionState(property.getter!!, functionType.classOrNull!!.owner, environment)
} }
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> { fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
if (_parameters != null) return _parameters!! if (_parameters != null) return _parameters!!
val kParameterIrClass = irClass.getIrClassOfReflectionFromList("parameters") val kParameterIrClass = callInterceptor.environment.kParameterClass.owner
var index = 0 var index = 0
val instanceParameter = property.getter?.dispatchReceiverParameter?.takeIf { receiver == null } val instanceParameter = property.getter?.dispatchReceiverParameter?.takeIf { receiver == null }
?.let { KParameterProxy(KParameterState(kParameterIrClass, it, index++, KParameter.Kind.INSTANCE), callInterceptor) } ?.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 { fun getReturnType(callInterceptor: CallInterceptor): KType {
if (_returnType != null) return _returnType!! if (_returnType != null) return _returnType!!
val kTypeIrClass = irClass.getIrClassOfReflection("returnType") val kTypeIrClass = callInterceptor.environment.kTypeClass.owner
_returnType = KTypeProxy(KTypeState(property.getter!!.returnType, kTypeIrClass), callInterceptor) _returnType = KTypeProxy(KTypeState(property.getter!!.returnType, kTypeIrClass), callInterceptor)
return _returnType!! return _returnType!!
} }
@@ -16,7 +16,7 @@ internal class KTypeParameterState(val irTypeParameter: IrTypeParameter, overrid
fun getUpperBounds(callInterceptor: CallInterceptor): List<KType> { fun getUpperBounds(callInterceptor: CallInterceptor): List<KType> {
if (_upperBounds != null) return _upperBounds!! 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) } _upperBounds = irTypeParameter.superTypes.map { KTypeProxy(KTypeState(it, kTypeIrClass), callInterceptor) }
return _upperBounds!! return _upperBounds!!
} }
@@ -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.KClassProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy 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.ir.types.*
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import kotlin.reflect.KClassifier 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) { _classifier = when (val classifier = irType.classifierOrFail.owner) {
is IrClass -> KClassProxy(KClassState(classifier, callInterceptor.irBuiltIns.kClassClass.owner), callInterceptor) is IrClass -> KClassProxy(KClassState(classifier, callInterceptor.irBuiltIns.kClassClass.owner), callInterceptor)
is IrTypeParameter -> { is IrTypeParameter -> {
val kTypeParameterIrClass = callInterceptor.irBuiltIns.kClassClass.owner.getIrClassOfReflectionFromList("typeParameters") val kTypeParameterIrClass = callInterceptor.environment.kTypeParameterClass.owner
KTypeParameterProxy(KTypeParameterState(classifier, kTypeParameterIrClass), callInterceptor) KTypeParameterProxy(KTypeParameterState(classifier, kTypeParameterIrClass), callInterceptor)
} }
else -> TODO() else -> TODO()
@@ -36,7 +35,7 @@ internal class KTypeState(val irType: IrType, override val irClass: IrClass) : R
fun getArguments(callInterceptor: CallInterceptor): List<KTypeProjection> { fun getArguments(callInterceptor: CallInterceptor): List<KTypeProjection> {
if (_arguments != null) return _arguments!! 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 _arguments = (irType as IrSimpleType).arguments
.map { .map {
when (it.getVariance()) { when (it.getVariance()) {
@@ -27,18 +27,6 @@ internal abstract class ReflectionState : State {
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null 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 { private fun renderReceivers(dispatchReceiver: IrType?, extensionReceiver: IrType?): String {
return buildString { return buildString {
if (dispatchReceiver != null) { if (dispatchReceiver != null) {