Simplify logic of interpreting invoke method for lambdas
For now will be created separate invoke method that will contains a call to lambda. This way it is clearer and more intuitive
This commit is contained in:
committed by
TeamCityServer
parent
06a8156376
commit
b44fd1a6fe
@@ -4,7 +4,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":compiler:ir.tree"))
|
||||
compileOnly(project(":compiler:ir.tree.impl"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
}
|
||||
|
||||
|
||||
+2
-53
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.ir.interpreter.proxy.wrap
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.ReflectionState
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
@@ -36,7 +33,6 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.lang.invoke.MethodHandle
|
||||
|
||||
internal interface CallInterceptor {
|
||||
@@ -75,8 +71,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
receiver is Wrapper && !isInlineOnly -> receiver.getMethod(irFunction).invokeMethod(irFunction, args)
|
||||
Wrapper.mustBeHandledWithWrapper(irFunction) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction, args)
|
||||
handleIntrinsicMethods(irFunction) -> return
|
||||
receiver is KFunctionState && call.symbol.owner.name == OperatorNameConventions.INVOKE -> handleInvoke(call, receiver, args)
|
||||
receiver is ReflectionState -> Wrapper.getReflectionMethod(irFunction).invokeMethod(irFunction, args)
|
||||
receiver.mustBeHandledAsReflection(call) -> Wrapper.getReflectionMethod(irFunction).invokeMethod(irFunction, args)
|
||||
receiver is Primitive<*> -> calculateBuiltIns(irFunction, args) // check for js char, js long and get field for primitives
|
||||
irFunction.body == null ->
|
||||
irFunction.trySubstituteFunctionBody() ?: irFunction.tryCalculateLazyConst() ?: calculateBuiltIns(irFunction, args)
|
||||
@@ -84,52 +79,6 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
}
|
||||
}
|
||||
|
||||
// TODO unite this logic with interpretCall
|
||||
private fun handleInvoke(call: IrCall, functionState: KFunctionState, args: List<State>) {
|
||||
val invokedFunction = functionState.irFunction
|
||||
|
||||
var index = 1 // drop first arg that is reference to function
|
||||
val dispatchReceiver = invokedFunction.dispatchReceiverParameter?.let { functionState.getField(it.symbol) ?: args[index++] }
|
||||
val extensionReceiver = invokedFunction.extensionReceiverParameter?.let { functionState.getField(it.symbol) ?: args[index++] }
|
||||
val valueArguments = invokedFunction.valueParameters.map { args[index++] }
|
||||
|
||||
val function = when (val symbol = invokedFunction.symbol) {
|
||||
is IrSimpleFunctionSymbol -> {
|
||||
val irCall = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, invokedFunction.returnType, symbol)
|
||||
val actualFunction = dispatchReceiver?.getIrFunctionByIrCall(irCall) ?: invokedFunction
|
||||
callStack.newFrame(actualFunction)
|
||||
callStack.addInstruction(SimpleInstruction(actualFunction))
|
||||
callStack.addVariable(Variable(actualFunction.symbol, KTypeState(call.type, irBuiltIns.anyClass.owner)))
|
||||
|
||||
actualFunction
|
||||
}
|
||||
is IrConstructorSymbol -> {
|
||||
val irConstructorCall = IrConstructorCallImpl.fromSymbolOwner(invokedFunction.returnType, symbol)
|
||||
callStack.newSubFrame(irConstructorCall)
|
||||
callStack.addInstruction(SimpleInstruction(irConstructorCall))
|
||||
callStack.addVariable(Variable(invokedFunction.parentAsClass.thisReceiver!!.symbol, Common(invokedFunction.parentAsClass)))
|
||||
|
||||
invokedFunction
|
||||
}
|
||||
else -> TODO("unsupported symbol $symbol for invoke")
|
||||
}
|
||||
|
||||
function.dispatchReceiverParameter?.let { callStack.addVariable(Variable(it.symbol, dispatchReceiver!!)) }
|
||||
function.extensionReceiverParameter?.let { callStack.addVariable(Variable(it.symbol, extensionReceiver!!)) }
|
||||
function.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) }
|
||||
if (invokedFunction.symbol is IrConstructorSymbol) return
|
||||
|
||||
callStack.loadUpValues(functionState)
|
||||
if (extensionReceiver is StateWithClosure) callStack.loadUpValues(extensionReceiver)
|
||||
if (dispatchReceiver is Complex && function.parentClassOrNull?.isInner == true) {
|
||||
generateSequence(dispatchReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { callStack.addVariable(it) }
|
||||
}
|
||||
|
||||
this.interceptCall(call, function, listOfNotNull(dispatchReceiver, extensionReceiver) + valueArguments) {
|
||||
callStack.addInstruction(CompoundInstruction(function))
|
||||
}
|
||||
}
|
||||
|
||||
override fun interceptConstructor(constructorCall: IrFunctionAccessExpression, args: List<State>, defaultAction: () -> Unit) {
|
||||
val receiver = callStack.getState(constructorCall.getThisReceiver())
|
||||
val irConstructor = constructorCall.symbol.owner
|
||||
@@ -275,4 +224,4 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
val expression = this.correspondingPropertySymbol?.owner?.backingField?.initializer?.expression
|
||||
return expression?.apply { callStack.addInstruction(CompoundInstruction(this)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,18 +585,18 @@ class IrInterpreter private constructor(
|
||||
}
|
||||
|
||||
private fun interpretFunctionReference(reference: IrFunctionReference) {
|
||||
val function = KFunctionState(reference)
|
||||
val irFunction = function.irFunction
|
||||
val irFunction = reference.symbol.owner
|
||||
|
||||
val dispatchReceiver = reference.dispatchReceiver?.let { callStack.getState(irFunction.getDispatchReceiver()!!) }
|
||||
val extensionReceiver = reference.extensionReceiver?.let { callStack.getState(irFunction.getExtensionReceiver()!!) }
|
||||
|
||||
callStack.dropSubFrame()
|
||||
// receivers in fields are used in comparison of two functions in KFunctionProxy
|
||||
dispatchReceiver?.let { function.fields += Variable(irFunction.getDispatchReceiver()!!, it) }
|
||||
extensionReceiver?.let { function.fields += Variable(irFunction.getExtensionReceiver()!!, it) }
|
||||
function.upValues += function.fields
|
||||
|
||||
val function = KFunctionState(
|
||||
reference,
|
||||
dispatchReceiver?.let { Variable(irFunction.getDispatchReceiver()!!, it) },
|
||||
extensionReceiver?.let { Variable(irFunction.getExtensionReceiver()!!, it) }
|
||||
)
|
||||
if (irFunction.isLocal) callStack.storeUpValues(function)
|
||||
callStack.pushState(function)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
import java.lang.invoke.MethodType
|
||||
|
||||
@@ -269,4 +270,4 @@ internal fun IrType.getOnlyName(): String {
|
||||
|
||||
internal fun IrFieldAccessExpression.accessesTopLevelOrObjectField(): Boolean {
|
||||
return this.receiver == null || (this.receiver?.type?.classifierOrNull?.owner as? IrClass)?.isObject == true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.ReflectionState
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal interface State {
|
||||
val fields: MutableList<Variable>
|
||||
@@ -74,4 +77,8 @@ internal fun State.checkNullability(
|
||||
return null
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
internal fun State?.mustBeHandledAsReflection(call: IrCall): Boolean {
|
||||
return this is ReflectionState && !(this is KFunctionState && call.symbol.owner.name == OperatorNameConventions.INVOKE)
|
||||
}
|
||||
+99
-6
@@ -5,32 +5,125 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.state.reflection
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
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.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.putArgument
|
||||
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
|
||||
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
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.StateWithClosure
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.KTypeParameter
|
||||
|
||||
internal class KFunctionState(val irFunction: IrFunction, override val irClass: IrClass) : ReflectionState(), StateWithClosure {
|
||||
internal class KFunctionState(
|
||||
val irFunction: IrFunction, override val irClass: IrClass, override val fields: MutableList<Variable>,
|
||||
) : ReflectionState(), StateWithClosure {
|
||||
override val upValues: MutableList<Variable> = mutableListOf()
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
private var _parameters: List<KParameter>? = null
|
||||
private var _returnType: KType? = null
|
||||
private var _typeParameters: List<KTypeParameter>? = null
|
||||
|
||||
constructor(functionReference: IrFunctionReference) : this(functionReference.symbol.owner, functionReference.type.classOrNull!!.owner)
|
||||
private val functionClass: IrClass
|
||||
val invokeSymbol: IrFunctionSymbol
|
||||
|
||||
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 = IrFactoryImpl.createClass(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
object : IrDeclarationOriginImpl("TEMP_CLASS_FOR_INTERPRETER") {}, IrClassSymbolImpl(),
|
||||
Name.identifier("Function\$0"), ClassKind.CLASS, DescriptorVisibilities.PRIVATE, Modality.FINAL
|
||||
).apply {
|
||||
parent = irFunction.parent
|
||||
}
|
||||
|
||||
functionClass.superTypes += irClass.defaultType
|
||||
functionClass.declarations += IrFunctionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
object : IrDeclarationOriginImpl("TEMP_FUNCTION_FOR_INTERPRETER") {}, IrSimpleFunctionSymbolImpl(),
|
||||
OperatorNameConventions.INVOKE, DescriptorVisibilities.PUBLIC, Modality.FINAL, irFunction.returnType,
|
||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = true, isInfix = false, isExpect = false
|
||||
).apply impl@{
|
||||
parent = functionClass
|
||||
overriddenSymbols = listOf(invokeFunction.symbol)
|
||||
|
||||
dispatchReceiverParameter = invokeFunction.dispatchReceiverParameter?.deepCopyWithSymbols(initialParent = this)
|
||||
valueParameters = mutableListOf()
|
||||
|
||||
val call = when (val symbol = irFunction.symbol) {
|
||||
is IrSimpleFunctionSymbol -> IrCallImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
irFunction.returnType, symbol, irFunction.typeParameters.size, irFunction.valueParameters.size
|
||||
)
|
||||
is IrConstructorSymbol -> IrConstructorCallImpl.fromSymbolOwner(irFunction.returnType, symbol)
|
||||
else -> TODO("Unsupported symbol $symbol for invoke")
|
||||
}.apply {
|
||||
val dispatchParameter = irFunction.dispatchReceiverParameter
|
||||
val extensionParameter = irFunction.extensionReceiverParameter
|
||||
|
||||
if (dispatchParameter != null && getField(dispatchParameter.symbol) == null) {
|
||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchParameter.type, dispatchParameter.symbol)
|
||||
(this@impl.valueParameters as MutableList).add(dispatchParameter)
|
||||
}
|
||||
if (extensionParameter != null && getField(extensionParameter.symbol) == null) {
|
||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionParameter.type, extensionParameter.symbol)
|
||||
(this@impl.valueParameters as MutableList).add(extensionParameter)
|
||||
}
|
||||
irFunction.valueParameters.forEach {
|
||||
putArgument(it, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.type, it.symbol))
|
||||
(this@impl.valueParameters as MutableList).add(it)
|
||||
}
|
||||
}
|
||||
|
||||
body = IrBlockBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, this.returnType, this.symbol, call))
|
||||
)
|
||||
|
||||
invokeSymbol = this.symbol
|
||||
}
|
||||
}
|
||||
|
||||
constructor(irFunction: IrFunction, irClass: IrClass) : this(irFunction, irClass, mutableListOf())
|
||||
|
||||
constructor(functionReference: IrFunctionReference, dispatchReceiver: Variable?, extensionReceiver: Variable?) : this(
|
||||
functionReference.symbol.owner,
|
||||
functionReference.type.classOrNull!!.owner,
|
||||
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))
|
||||
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)
|
||||
}
|
||||
|
||||
fun getParameters(callInterceptor: CallInterceptor): List<KParameter> {
|
||||
if (_parameters != null) return _parameters!!
|
||||
|
||||
@@ -59,6 +59,7 @@ Exception java.lang.ClassCastException: kotlin.Int cannot be cast to kotlin.Stri
|
||||
const val stringList = getIntList<List<String>>().<!WAS_NOT_EVALUATED: `
|
||||
Exception java.lang.ClassCastException: kotlin.Int cannot be cast to kotlin.String
|
||||
at ClassCastExceptionKt.stringList.<anonymous>(classCastException.kt:54)
|
||||
at ClassCastExceptionKt.stringList.Function$0.invoke(classCastException.kt:0)
|
||||
at StandardKt.kotlin.let(Standard.kt:32)
|
||||
at ClassCastExceptionKt.<clinit>(classCastException.kt:53)`!>let {
|
||||
it[0].length
|
||||
@@ -66,6 +67,7 @@ Exception java.lang.ClassCastException: kotlin.Int cannot be cast to kotlin.Stri
|
||||
const val nullableStringList = getStringNullableList<List<String>>().<!WAS_NOT_EVALUATED: `
|
||||
Exception java.lang.NullPointerException
|
||||
at ClassCastExceptionKt.nullableStringList.<anonymous>(classCastException.kt)
|
||||
at ClassCastExceptionKt.nullableStringList.Function$0.invoke(classCastException.kt:0)
|
||||
at StandardKt.kotlin.let(Standard.kt:32)
|
||||
at ClassCastExceptionKt.<clinit>(classCastException.kt:56)`!>let { it[0].length }<!>
|
||||
const val nullableStringLength = <!WAS_NOT_EVALUATED: `
|
||||
|
||||
Reference in New Issue
Block a user