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() -> {
// 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() -> {
@@ -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<IrTypeParameter>.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)
}
}
@@ -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<IrSymbol, Complex>()
internal var mapOfObjects = mutableMapOf<IrSymbol, Complex>()
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(
val symbol: IrFunctionSymbol,
@@ -43,12 +62,6 @@ class IrInterpreterEnvironment(
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) {
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
}
}
@@ -74,14 +74,14 @@ internal class KClassState(val classReference: IrClass, override val irClass: Ir
fun getTypeParameters(callInterceptor: CallInterceptor): List<KTypeParameter> {
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<KType> {
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!!
@@ -118,7 +118,7 @@ internal class KFunctionState(
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
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<KTypeParameter> {
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!!
}
@@ -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!!
}
@@ -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<KParameter> {
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!!
}
@@ -16,7 +16,7 @@ internal class KTypeParameterState(val irTypeParameter: IrTypeParameter, overrid
fun getUpperBounds(callInterceptor: CallInterceptor): List<KType> {
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!!
}
@@ -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<KTypeProjection> {
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()) {
@@ -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) {