Support passing property as argument to array constructor in interpreter
This commit is contained in:
committed by
TeamCityServer
parent
59fefb6214
commit
3326cbd9c0
+2
-1
@@ -36,6 +36,7 @@ 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 {
|
||||
@@ -74,7 +75,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.asString() == "invoke" -> handleInvoke(call, receiver, args)
|
||||
receiver is KFunctionState && call.symbol.owner.name == OperatorNameConventions.INVOKE -> handleInvoke(call, receiver, args)
|
||||
receiver is ReflectionState -> 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 ->
|
||||
|
||||
+13
-11
@@ -171,9 +171,11 @@ class IrInterpreter private constructor(
|
||||
}
|
||||
|
||||
private fun interpretCall(call: IrCall) {
|
||||
fun IrFunction.mustBeHandledWithSuperOf(state: State?): State? {
|
||||
if (state is Common && this.parent == state.superWrapperClass?.irClass) return state.superWrapperClass
|
||||
return state
|
||||
fun State?.getThisOrSuperReceiver(irFunction: IrFunction): State? {
|
||||
// check if this function must be handled by super wrapper object
|
||||
if (this !is Common || this.superWrapperClass == null || irFunction.parent !is IrClass) return this
|
||||
if (superWrapperClass!!.irClass.isSubclassOf(irFunction.parentAsClass)) return superWrapperClass
|
||||
return this
|
||||
}
|
||||
|
||||
val owner = call.symbol.owner
|
||||
@@ -184,7 +186,7 @@ class IrInterpreter private constructor(
|
||||
|
||||
// 2. get correct function for interpretation
|
||||
val irFunction = dispatchReceiver?.getIrFunctionByIrCall(call) ?: call.symbol.owner
|
||||
val args = listOfNotNull(irFunction.mustBeHandledWithSuperOf(dispatchReceiver), extensionReceiver) + valueArguments
|
||||
val args = listOfNotNull(dispatchReceiver.getThisOrSuperReceiver(irFunction), extensionReceiver) + valueArguments
|
||||
|
||||
callStack.dropSubFrame() // drop intermediate frame that contains variables for default arg evaluation
|
||||
callStack.newFrame(irFunction)
|
||||
@@ -194,11 +196,9 @@ class IrInterpreter private constructor(
|
||||
callStack.addVariable(Variable(irFunction.symbol, KTypeState(call.type, irBuiltIns.anyClass.owner)))
|
||||
|
||||
// 3. store arguments in memory (remap args on actual names)
|
||||
val variables = mutableListOf<Variable>()
|
||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> variables.add(Variable(it, receiver)) } }
|
||||
irFunction.getExtensionReceiver()?.let { variables.add(Variable(it, extensionReceiver ?: valueArguments.removeFirst())) }
|
||||
irFunction.valueParameters.forEach { variables.add(Variable(it.symbol, valueArguments.removeFirst())) }
|
||||
variables.forEach { callStack.addVariable(it) }
|
||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> callStack.addVariable(Variable(it, receiver)) } }
|
||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: valueArguments.removeFirst())) }
|
||||
irFunction.valueParameters.forEach { callStack.addVariable(Variable(it.symbol, valueArguments.removeFirst())) }
|
||||
|
||||
// 4. store reified type parameters
|
||||
irFunction.typeParameters.filter { it.isReified }
|
||||
@@ -592,8 +592,10 @@ class IrInterpreter private constructor(
|
||||
val extensionReceiver = reference.extensionReceiver?.let { callStack.getState(irFunction.getExtensionReceiver()!!) }
|
||||
|
||||
callStack.dropSubFrame()
|
||||
irFunction.getDispatchReceiver()?.let { dispatchReceiver?.let { receiver -> function.fields += Variable(it, receiver) } }
|
||||
irFunction.getExtensionReceiver()?.let { extensionReceiver?.let { receiver -> function.fields += Variable(it, receiver) } }
|
||||
// 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
|
||||
|
||||
if (irFunction.isLocal) callStack.storeUpValues(function)
|
||||
callStack.pushState(function)
|
||||
|
||||
+13
-8
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.interpreter.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
|
||||
@@ -217,19 +218,23 @@ internal object ArrayConstructor : IntrinsicBase() {
|
||||
|
||||
override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List<Instruction> {
|
||||
if (irFunction.valueParameters.size == 1) return listOf(customEvaluateInstruction(irFunction, environment))
|
||||
val callStack = environment.callStack
|
||||
val instructions = mutableListOf<Instruction>(customEvaluateInstruction(irFunction, environment))
|
||||
|
||||
val sizeDescriptor = irFunction.valueParameters[0].symbol
|
||||
val size = environment.callStack.getState(sizeDescriptor).asInt()
|
||||
val sizeSymbol = irFunction.valueParameters[0].symbol
|
||||
val size = callStack.getState(sizeSymbol).asInt()
|
||||
|
||||
val initSymbol = irFunction.valueParameters[1].symbol
|
||||
val function = when (val state = callStack.getState(initSymbol)) {
|
||||
is KFunctionState -> state.irFunction.apply { callStack.loadUpValues(state) }
|
||||
is KPropertyState -> state.property.getter
|
||||
else -> TODO("Unsupported `init` in array constructor: $state")
|
||||
} as IrSimpleFunction
|
||||
|
||||
val initDescriptor = irFunction.valueParameters[1].symbol
|
||||
val initLambda = environment.callStack.getState(initDescriptor) as KFunctionState
|
||||
environment.callStack.loadUpValues(initLambda)
|
||||
val function = initLambda.irFunction as IrSimpleFunction
|
||||
val index = initLambda.irFunction.valueParameters.single()
|
||||
for (i in size - 1 downTo 0) {
|
||||
val call = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, function.returnType, function.symbol)
|
||||
call.putValueArgument(0, IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, index.type, i))
|
||||
val arg = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.intType, i)
|
||||
if (function.correspondingPropertySymbol == null) call.putValueArgument(0, arg) else call.extensionReceiver = arg
|
||||
instructions += CompoundInstruction(call)
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user