Implement simple cache for dynamically created wrapper for lambda
This commit is contained in:
committed by
TeamCityServer
parent
6482abc602
commit
09c31b0900
@@ -573,7 +573,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
}
|
||||
|
||||
private fun interpretFunctionExpression(expression: IrFunctionExpression) {
|
||||
val function = KFunctionState(expression.function, expression.type.classOrNull!!.owner)
|
||||
val function = KFunctionState(expression.function, expression.type.classOrNull!!.owner, environment)
|
||||
if (expression.function.isLocal) callStack.storeUpValues(function)
|
||||
callStack.pushState(function)
|
||||
}
|
||||
@@ -586,6 +586,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
|
||||
val function = KFunctionState(
|
||||
reference,
|
||||
environment,
|
||||
dispatchReceiver?.let { Variable(irFunction.getDispatchReceiver()!!, it) },
|
||||
extensionReceiver?.let { Variable(irFunction.getExtensionReceiver()!!, it) }
|
||||
)
|
||||
|
||||
+3
@@ -7,10 +7,12 @@ 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.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Common
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.Complex
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
|
||||
@@ -22,6 +24,7 @@ class IrInterpreterEnvironment(
|
||||
internal val irExceptions = mutableListOf<IrClass>()
|
||||
internal var mapOfEnums = mutableMapOf<IrSymbol, Complex>()
|
||||
internal var mapOfObjects = mutableMapOf<IrSymbol, Complex>()
|
||||
internal var cachedLambdasAndReferences = mutableMapOf<IrFunctionSymbol, IrFunctionSymbol>()
|
||||
|
||||
init {
|
||||
mapOfObjects[irBuiltIns.unitClass] = Common(irBuiltIns.unitClass.owner)
|
||||
|
||||
+1
-1
@@ -222,7 +222,7 @@ internal object ArrayConstructor : IntrinsicBase() {
|
||||
|
||||
val initSymbol = irFunction.valueParameters[1].symbol
|
||||
val state = callStack.getState(initSymbol).let {
|
||||
(it as? KFunctionState) ?: (it as KPropertyState).convertGetterToKFunctionState()
|
||||
(it as? KFunctionState) ?: (it as KPropertyState).convertGetterToKFunctionState(environment)
|
||||
}
|
||||
// if property was converted, then we must replace symbol in memory to get correct receiver later
|
||||
callStack.setState(initSymbol, state)
|
||||
|
||||
+8
-2
@@ -51,7 +51,10 @@ internal class KClassState(val classReference: IrClass, override val irClass: Ir
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
is IrFunction -> KFunctionProxy(KFunctionState(it, callInterceptor.irBuiltIns), callInterceptor)
|
||||
is IrFunction -> {
|
||||
val irClass = callInterceptor.irBuiltIns.kFunctionN(it.valueParameters.size)
|
||||
KFunctionProxy(KFunctionState(it, irClass, callInterceptor.environment), callInterceptor)
|
||||
}
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
@@ -62,7 +65,10 @@ internal class KClassState(val classReference: IrClass, override val irClass: Ir
|
||||
if (_constructors != null) return _constructors!!
|
||||
_constructors = classReference.declarations
|
||||
.filterIsInstance<IrConstructor>()
|
||||
.map { KFunctionProxy(KFunctionState(it, callInterceptor.irBuiltIns), callInterceptor) }
|
||||
.map {
|
||||
val irClass = callInterceptor.irBuiltIns.kFunctionN(it.valueParameters.size)
|
||||
KFunctionProxy(KFunctionState(it, irClass, callInterceptor.environment), callInterceptor)
|
||||
}
|
||||
return _constructors!!
|
||||
}
|
||||
|
||||
|
||||
+61
-47
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.state.reflection
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -14,10 +13,6 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.putArgument
|
||||
import org.jetbrains.kotlin.ir.interpreter.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
|
||||
import org.jetbrains.kotlin.ir.interpreter.TEMP_FUNCTION_FOR_INTERPRETER
|
||||
import org.jetbrains.kotlin.ir.interpreter.createTempClass
|
||||
import org.jetbrains.kotlin.ir.interpreter.createTempFunction
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KParameterProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeParameterProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy
|
||||
@@ -34,72 +29,91 @@ import kotlin.reflect.KType
|
||||
import kotlin.reflect.KTypeParameter
|
||||
|
||||
internal class KFunctionState(
|
||||
val irFunction: IrFunction, override val irClass: IrClass, override val fields: MutableList<Variable>,
|
||||
val irFunction: IrFunction,
|
||||
override val irClass: IrClass,
|
||||
environment: IrInterpreterEnvironment,
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
) : ReflectionState(), StateWithClosure {
|
||||
override val upValues: MutableList<Variable> = mutableListOf()
|
||||
private var _parameters: List<KParameter>? = null
|
||||
private var _returnType: KType? = null
|
||||
private var _typeParameters: List<KTypeParameter>? = null
|
||||
|
||||
private val functionClass: IrClass
|
||||
val invokeSymbol: IrFunctionSymbol
|
||||
val invokeSymbol: IrFunctionSymbol = environment.cachedLambdasAndReferences
|
||||
.getOrDefault(
|
||||
irFunction.symbol,
|
||||
createInvokeFunction(
|
||||
irFunction,
|
||||
irClass,
|
||||
irFunction.dispatchReceiverParameter?.let { getField(it.symbol) } != null,
|
||||
irFunction.extensionReceiverParameter?.let { getField(it.symbol) } != null
|
||||
).symbol
|
||||
)
|
||||
|
||||
init {
|
||||
val invokeFunction = irClass.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == OperatorNameConventions.INVOKE }
|
||||
// TODO do we need new class here? if yes, do we need different names for temp classes?
|
||||
functionClass = createTempClass(Name.identifier("Function\$0")).apply { parent = irFunction.parent }
|
||||
companion object {
|
||||
fun createInvokeFunction(
|
||||
irFunction: IrFunction, irClass: IrClass, hasDispatchReceiver: Boolean, hasExtensionReceiver: Boolean
|
||||
): IrSimpleFunction {
|
||||
val invokeFunction = irClass.declarations
|
||||
.filterIsInstance<IrSimpleFunction>()
|
||||
.single { it.name == OperatorNameConventions.INVOKE }
|
||||
// TODO do we need new class here? if yes, do we need different names for temp classes?
|
||||
val functionClass = createTempClass(Name.identifier("Function\$0")).apply { parent = irFunction.parent }
|
||||
|
||||
functionClass.superTypes += irClass.defaultType
|
||||
functionClass.declarations += createTempFunction(
|
||||
OperatorNameConventions.INVOKE, irFunction.returnType, TEMP_FUNCTION_FOR_INTERPRETER
|
||||
).apply impl@{
|
||||
parent = functionClass
|
||||
overriddenSymbols = listOf(invokeFunction.symbol)
|
||||
functionClass.superTypes += irClass.defaultType
|
||||
val newFunctionToInvoke = createTempFunction(
|
||||
OperatorNameConventions.INVOKE, irFunction.returnType, TEMP_FUNCTION_FOR_INTERPRETER
|
||||
).apply impl@{
|
||||
parent = functionClass
|
||||
overriddenSymbols = listOf(invokeFunction.symbol)
|
||||
|
||||
dispatchReceiverParameter = invokeFunction.dispatchReceiverParameter?.deepCopyWithSymbols(initialParent = this)
|
||||
valueParameters = mutableListOf()
|
||||
dispatchReceiverParameter = invokeFunction.dispatchReceiverParameter?.deepCopyWithSymbols(initialParent = this)
|
||||
valueParameters = mutableListOf()
|
||||
|
||||
val call = when (irFunction) {
|
||||
is IrSimpleFunction -> irFunction.createCall()
|
||||
is IrConstructor -> irFunction.createConstructorCall()
|
||||
else -> TODO("Unsupported symbol $symbol for invoke")
|
||||
}.apply {
|
||||
val dispatchParameter = irFunction.dispatchReceiverParameter
|
||||
val extensionParameter = irFunction.extensionReceiverParameter
|
||||
val call = when (irFunction) {
|
||||
is IrSimpleFunction -> irFunction.createCall()
|
||||
is IrConstructor -> irFunction.createConstructorCall()
|
||||
else -> TODO("Unsupported symbol $symbol for invoke")
|
||||
}.apply {
|
||||
val dispatchParameter = irFunction.dispatchReceiverParameter
|
||||
val extensionParameter = irFunction.extensionReceiverParameter
|
||||
|
||||
if (dispatchParameter != null) {
|
||||
dispatchReceiver = dispatchParameter.createGetValue()
|
||||
if (getField(dispatchParameter.symbol) == null) (this@impl.valueParameters as MutableList) += dispatchParameter
|
||||
}
|
||||
if (extensionParameter != null) {
|
||||
extensionReceiver = extensionParameter.createGetValue()
|
||||
if (getField(extensionParameter.symbol) == null) (this@impl.valueParameters as MutableList) += extensionParameter
|
||||
}
|
||||
irFunction.valueParameters.forEach {
|
||||
putArgument(it, it.createGetValue())
|
||||
(this@impl.valueParameters as MutableList) += it
|
||||
if (dispatchParameter != null) {
|
||||
dispatchReceiver = dispatchParameter.createGetValue()
|
||||
if (!hasDispatchReceiver) (this@impl.valueParameters as MutableList) += dispatchParameter
|
||||
}
|
||||
if (extensionParameter != null) {
|
||||
extensionReceiver = extensionParameter.createGetValue()
|
||||
if (!hasExtensionReceiver) (this@impl.valueParameters as MutableList) += extensionParameter
|
||||
}
|
||||
irFunction.valueParameters.forEach {
|
||||
putArgument(it, it.createGetValue())
|
||||
(this@impl.valueParameters as MutableList) += it
|
||||
}
|
||||
}
|
||||
|
||||
body = listOf(this.createReturn(call)).wrapWithBlockBody()
|
||||
}
|
||||
|
||||
body = listOf(this.createReturn(call)).wrapWithBlockBody()
|
||||
invokeSymbol = this.symbol
|
||||
functionClass.declarations += newFunctionToInvoke
|
||||
return newFunctionToInvoke
|
||||
}
|
||||
}
|
||||
|
||||
constructor(irFunction: IrFunction, irClass: IrClass) : this(irFunction, irClass, mutableListOf())
|
||||
|
||||
constructor(functionReference: IrFunctionReference, dispatchReceiver: Variable?, extensionReceiver: Variable?) : this(
|
||||
constructor(
|
||||
functionReference: IrFunctionReference,
|
||||
environment: IrInterpreterEnvironment,
|
||||
dispatchReceiver: Variable?,
|
||||
extensionReceiver: Variable?
|
||||
) : this(
|
||||
functionReference.symbol.owner,
|
||||
functionReference.type.classOrNull!!.owner,
|
||||
environment,
|
||||
listOfNotNull(dispatchReceiver, extensionReceiver).toMutableList()
|
||||
) {
|
||||
// receivers are used in comparison of two functions in KFunctionProxy
|
||||
upValues += fields
|
||||
}
|
||||
|
||||
constructor(irFunction: IrFunction, irBuiltIns: IrBuiltIns) :
|
||||
this(irFunction, irBuiltIns.kFunctionN(irFunction.valueParameters.size), mutableListOf())
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
if (expression.symbol.owner.name == OperatorNameConventions.INVOKE) return invokeSymbol.owner
|
||||
return super.getIrFunctionByIrCall(expression)
|
||||
|
||||
+3
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KParameterProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KTypeProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||
@@ -23,10 +24,10 @@ internal class KPropertyState(val property: IrProperty, override val irClass: Ir
|
||||
private var _parameters: List<KParameter>? = null
|
||||
private var _returnType: KType? = null
|
||||
|
||||
fun convertGetterToKFunctionState(): KFunctionState {
|
||||
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)
|
||||
return KFunctionState(property.getter!!, functionType.classOrNull!!.owner, environment)
|
||||
}
|
||||
|
||||
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
|
||||
|
||||
Reference in New Issue
Block a user