diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt index 1b79b60ad00..ddf298d5fe3 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt @@ -103,7 +103,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : val objectClass = expression.symbol.owner when { Wrapper.mustBeHandledWithWrapper(objectClass) -> { - val result = Wrapper.getCompanionObject(objectClass) + val result = Wrapper.getCompanionObject(objectClass, environment) environment.mapOfObjects[expression.symbol] = result callStack.pushState(result) } @@ -115,7 +115,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : val enumClass = enumEntry.symbol.owner.parentAsClass when { Wrapper.mustBeHandledWithWrapper(enumClass) -> { - val enumEntryName = enumEntry.name.asString().toState(environment.irBuiltIns.stringType) + val enumEntryName = environment.convertToState(enumEntry.name.asString(), environment.irBuiltIns.stringType) val valueOfFun = enumClass.declarations.single { it.nameForIrSerialization.asString() == "valueOf" } as IrFunction Wrapper.getEnumEntry(enumClass).invokeMethod(valueOfFun, listOf(enumEntryName)) environment.mapOfEnums[enumEntry.symbol] = callStack.popState() as Complex @@ -128,7 +128,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : val field = expression.symbol.owner verify(field.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && field.isStatic) verify(field.initializer?.expression !is IrConst<*>) - callStack.pushState(Wrapper.getStaticGetter(field).invokeWithArguments().toState(field.type)) + callStack.pushState(environment.convertToState(Wrapper.getStaticGetter(field).invokeWithArguments(), field.type)) } private fun MethodHandle?.invokeMethod(irFunction: IrFunction, args: List) { @@ -136,7 +136,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : val argsForMethodInvocation = irFunction.getArgsForMethodInvocation(this@DefaultCallInterceptor, this.type(), args) withExceptionHandler(environment) { val result = this.invokeWithArguments(argsForMethodInvocation) // TODO if null return Unit - callStack.pushState(result.toState(result.getType(irFunction.returnType))) + callStack.pushState(environment.convertToState(result, result.getType(irFunction.returnType))) } } @@ -173,7 +173,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : else -> throw InterpreterError("Unsupported number of arguments for invocation as builtin function: $methodName") } // TODO check "result is Unit" - callStack.pushState(result.toState(result.getType(irFunction.returnType))) + callStack.pushState(environment.convertToState(result, result.getType(irFunction.returnType))) } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt index 791a41417d5..86df2dc9113 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt @@ -366,7 +366,7 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ is Int -> value.toUInt().toString() else -> (value as Number).toLong().toULong().toString() } - return callStack.pushState(result.toState(environment.irBuiltIns.stringType)) + return callStack.pushState(environment.convertToState(result, environment.irBuiltIns.stringType)) } val toStringCall = state.createToStringIrCall() callStack.addInstruction(SimpleInstruction(toStringCall)) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index a617f1f50d6..e641bb71c9f 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -463,17 +463,18 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal } IrTypeOperator.SAFE_CAST -> { when { - !isErased && !state.isSubtypeOf(typeOperand) -> callStack.pushState(null.toState(irBuiltIns.nothingNType)) + !isErased && !state.isSubtypeOf(typeOperand) -> + callStack.pushState(environment.convertToState(null, irBuiltIns.nothingNType)) else -> callStack.pushState(state) } } IrTypeOperator.INSTANCEOF -> { val isInstance = isErased || state.isSubtypeOf(typeOperand) - callStack.pushState(isInstance.toState(irBuiltIns.booleanType)) + callStack.pushState(environment.convertToState(isInstance, irBuiltIns.booleanType)) } IrTypeOperator.NOT_INSTANCEOF -> { val isInstance = isErased || state.isSubtypeOf(typeOperand) - callStack.pushState((!isInstance).toState(irBuiltIns.booleanType)) + callStack.pushState(environment.convertToState((!isInstance), irBuiltIns.booleanType)) } IrTypeOperator.IMPLICIT_NOTNULL -> { when { @@ -564,7 +565,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal } } - callStack.pushState(result.reversed().joinToString(separator = "").toState(expression.type)) + callStack.pushState(environment.convertToState(result.reversed().joinToString(separator = ""), expression.type)) } private fun interpretFunctionExpression(expression: IrFunctionExpression) { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt index acbc67b78b2..9b74a9e4012 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreterEnvironment.kt @@ -8,11 +8,17 @@ 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.interpreter.proxy.Proxy 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.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.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.isSubclassOf class IrInterpreterEnvironment( @@ -23,6 +29,7 @@ class IrInterpreterEnvironment( internal val irExceptions = mutableListOf() internal var mapOfEnums = mutableMapOf() internal var mapOfObjects = mutableMapOf() + internal var javaClassToIrClass = mutableMapOf, IrClass>() private data class CacheFunctionSignature( val symbol: IrFunctionSymbol, @@ -80,4 +87,19 @@ class IrInterpreterEnvironment( functionCache[CacheFunctionSignature(symbol, hasDispatchReceiver, hasExtensionReceiver, fromDelegatingCall)] = newFunction return newFunction } + + /** + * Convert object from outer world to state + */ + internal fun convertToState(value: Any?, irType: IrType): State { + return when (value) { + is Proxy -> value.state + is State -> value + is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double, is Array<*>, is ByteArray, + is CharArray, is ShortArray, is IntArray, is LongArray, is FloatArray, is DoubleArray, is BooleanArray -> Primitive(value, irType) + null -> Primitive.nullStateOfType(irType) + else -> irType.classOrNull?.owner?.let { Wrapper(value, it, this) } + ?: Wrapper(value, this.javaClassToIrClass[value::class.java]!!, this) + } + } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index 7beb8468f1c..dfe53032332 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException -import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy import org.jetbrains.kotlin.ir.interpreter.proxy.wrap import org.jetbrains.kotlin.ir.interpreter.stack.CallStack import org.jetbrains.kotlin.ir.interpreter.state.* @@ -43,20 +42,6 @@ internal fun IrFunction.getReceiver(): IrSymbol? = this.getDispatchReceiver() ?: internal fun IrFunctionAccessExpression.getThisReceiver(): IrValueSymbol = this.symbol.owner.parentAsClass.thisReceiver!!.symbol -/** - * Convert object from outer world to state - */ -internal fun Any?.toState(irType: IrType): State { - return when (this) { - is Proxy -> this.state - is State -> this - is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double, is Array<*>, is ByteArray, - is CharArray, is ShortArray, is IntArray, is LongArray, is FloatArray, is DoubleArray, is BooleanArray -> Primitive(this, irType) - null -> Primitive.nullStateOfType(irType) - else -> irType.classOrNull?.owner?.let { Wrapper(this, it) } ?: Wrapper(this) - } -} - @Suppress("UNCHECKED_CAST") internal fun IrConst.toPrimitive(): Primitive = when { type.isByte() -> Primitive((value as Number).toByte() as T, type) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt index 47a0927f282..129a877d42a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt @@ -44,7 +44,7 @@ internal object EmptyArray : IntrinsicBase() { override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { val returnType = environment.callStack.getState(irFunction.symbol) as KTypeState - environment.callStack.pushState(emptyArray().toState(returnType.irType)) + environment.callStack.pushState(environment.convertToState(emptyArray(), returnType.irType)) } } @@ -73,7 +73,7 @@ internal object ArrayOfNulls : IntrinsicBase() { arguments = listOf(makeTypeProjection(typeArgument.irType, Variance.INVARIANT)) } - environment.callStack.pushState(array.toState(returnType)) + environment.callStack.pushState(environment.convertToState(array, returnType)) } } @@ -103,7 +103,7 @@ internal object EnumValues : IntrinsicBase() { val enumClass = getEnumClass(irFunction, environment) val enumEntries = enumClass.declarations.filterIsInstance().map { environment.mapOfEnums[it.symbol] } - environment.callStack.pushState(enumEntries.toTypedArray().toState(irFunction.returnType)) + environment.callStack.pushState(environment.convertToState(enumEntries.toTypedArray(), irFunction.returnType)) } } @@ -169,14 +169,14 @@ internal object EnumIntrinsics : IntrinsicBase() { val ordinalSymbol = enumEntry.irClass.getOriginalPropertyByName("ordinal").symbol val other = callStack.getState(irFunction.valueParameters.single().symbol) val compareTo = enumEntry.getField(ordinalSymbol)!!.asInt().compareTo(other.getField(ordinalSymbol)!!.asInt()) - callStack.pushState(compareTo.toState(irFunction.returnType)) + callStack.pushState(environment.convertToState(compareTo, irFunction.returnType)) } // TODO "clone" -> throw exception "equals" -> { val other = callStack.getState(irFunction.valueParameters.single().symbol) - callStack.pushState((enumEntry === other).toState(irFunction.returnType)) + callStack.pushState(environment.convertToState((enumEntry === other), irFunction.returnType)) } - "hashCode" -> callStack.pushState(enumEntry.hashCode().toState(irFunction.returnType)) + "hashCode" -> callStack.pushState(environment.convertToState(enumEntry.hashCode(), irFunction.returnType)) "toString" -> { val nameSymbol = enumEntry.irClass.getOriginalPropertyByName("name").symbol callStack.pushState(enumEntry.getField(nameSymbol)!!) @@ -197,11 +197,11 @@ internal object JsPrimitives : IntrinsicBase() { "kotlin.Long." -> { val low = environment.callStack.getState(irFunction.valueParameters[0].symbol).asInt() val high = environment.callStack.getState(irFunction.valueParameters[1].symbol).asInt() - environment.callStack.pushState((high.toLong().shl(32) + low).toState(irFunction.returnType)) + environment.callStack.pushState(environment.convertToState((high.toLong().shl(32) + low), irFunction.returnType)) } "kotlin.Char." -> { val value = environment.callStack.getState(irFunction.valueParameters[0].symbol).asInt() - environment.callStack.pushState(value.toChar().toState(irFunction.returnType)) + environment.callStack.pushState(environment.convertToState(value.toChar(), irFunction.returnType)) } } } @@ -276,7 +276,7 @@ internal object SourceLocation : IntrinsicBase() { } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { - environment.callStack.pushState(environment.callStack.getFileAndPositionInfo().toState(irFunction.returnType)) + environment.callStack.pushState(environment.convertToState(environment.callStack.getFileAndPositionInfo(), irFunction.returnType)) } } @@ -329,6 +329,6 @@ internal object DataClassArrayToString : IntrinsicBase() { override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { val array = environment.callStack.getState(irFunction.valueParameters.single().symbol) as Primitive<*> - environment.callStack.pushState(arrayToString(array.value).toState(irFunction.returnType)) + environment.callStack.pushState(environment.convertToState(arrayToString(array.value), irFunction.returnType)) } } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt index 17cf057cbc0..bdd94d15749 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.interpreter.getDispatchReceiver import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.Common import org.jetbrains.kotlin.ir.interpreter.state.State -import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.util.isFakeOverriddenFromAny internal class CommonProxy private constructor(override val state: Common, override val callInterceptor: CallInterceptor) : Proxy { @@ -84,8 +83,9 @@ internal class CommonProxy private constructor(override val state: Common, overr ?: return@newProxyInstance commonProxy.fallbackIfMethodNotFound(method) val valueArguments = mutableListOf() valueArguments += Variable(irFunction.getDispatchReceiver()!!, commonProxy.state) - valueArguments += irFunction.valueParameters - .mapIndexed { index, parameter -> Variable(parameter.symbol, args[index].toState(parameter.type)) } + valueArguments += irFunction.valueParameters.mapIndexed { index, parameter -> + Variable(parameter.symbol, callInterceptor.environment.convertToState(args[index], parameter.type)) + } callInterceptor.interceptProxy(irFunction, valueArguments, method.returnType) } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt index 8ae628a0150..54114544551 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt @@ -19,6 +19,8 @@ import java.lang.invoke.MethodType internal interface Proxy { val state: State val callInterceptor: CallInterceptor + val environment + get() = callInterceptor.environment override fun equals(other: Any?): Boolean override fun hashCode(): Int diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt index c1575fadac0..c846ab752bc 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KFunctionProxy.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState -import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.isSuspend import org.jetbrains.kotlin.ir.util.statements @@ -51,10 +50,14 @@ internal class KFunctionProxy( override fun call(vararg args: Any?): Any? { // TODO check arity var index = 0 - val dispatchReceiver = state.irFunction.dispatchReceiverParameter?.let { Variable(it.symbol, args[index++].toState(it.type)) } - val extensionReceiver = state.irFunction.extensionReceiverParameter?.let { Variable(it.symbol, args[index++].toState(it.type)) } - val valueArguments = listOfNotNull(dispatchReceiver, extensionReceiver) + - state.irFunction.valueParameters.map { parameter -> Variable(parameter.symbol, args[index++].toState(parameter.type)) } + val dispatchReceiver = state.irFunction.dispatchReceiverParameter + ?.let { Variable(it.symbol, environment.convertToState(args[index++], it.type)) } + val extensionReceiver = state.irFunction.extensionReceiverParameter + ?.let { Variable(it.symbol, environment.convertToState(args[index++], it.type)) } + val argsVariables = state.irFunction.valueParameters.map { parameter -> + Variable(parameter.symbol, environment.convertToState(args[index++], parameter.type)) + } + val valueArguments = listOfNotNull(dispatchReceiver, extensionReceiver) + argsVariables return callInterceptor.interceptProxy(state.irFunction, valueArguments) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt index 677682e4458..28997e8fbcf 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty0Proxy.kt @@ -5,20 +5,19 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection +import org.jetbrains.kotlin.ir.interpreter.* import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.exceptions.verify -import org.jetbrains.kotlin.ir.interpreter.getDispatchReceiver import org.jetbrains.kotlin.ir.interpreter.getExtensionReceiver import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.isNull import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState -import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.util.isObject import org.jetbrains.kotlin.ir.util.resolveFakeOverride import kotlin.reflect.* internal open class KProperty0Proxy( - override val state: KPropertyState, override val callInterceptor: CallInterceptor + state: KPropertyState, callInterceptor: CallInterceptor ) : AbstractKPropertyProxy(state, callInterceptor), KProperty0 { override val getter: KProperty0.Getter get() = object : Getter(state.property.getter!!), KProperty0.Getter { @@ -34,7 +33,7 @@ internal open class KProperty0Proxy( return when { // null value <=> property is extension or Primitive; receiver.isNull() <=> nullable extension value == null || receiver.isNull() -> { - val receiverSymbol = getter.getDispatchReceiver() ?: getter.getExtensionReceiver() + val receiverSymbol = getter.getReceiver() val receiverVariable = receiverSymbol?.let { Variable(it, receiver) } callInterceptor.interceptProxy(getter, listOfNotNull(receiverVariable)) } @@ -57,7 +56,7 @@ internal open class KProperty0Proxy( } internal class KMutableProperty0Proxy( - override val state: KPropertyState, override val callInterceptor: CallInterceptor + state: KPropertyState, callInterceptor: CallInterceptor ) : KProperty0Proxy(state, callInterceptor), KMutableProperty0 { override val setter: KMutableProperty0.Setter = object : Setter(state.property.setter!!), KMutableProperty0.Setter { @@ -69,7 +68,7 @@ internal class KMutableProperty0Proxy( verify(state.receiver != null) { "Cannot interpret set method on top level properties" } verify(state.receiver?.irClass?.isObject != true) { "Cannot interpret set method on property of object" } val receiver = state.receiver!! - val newValue = args.single().toState(propertyType) + val newValue = environment.convertToState(args.single(), propertyType) setter.getExtensionReceiver() ?.let { val fieldSymbol = setter.valueParameters.single().symbol diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt index 5ff8d376529..e833b4b9707 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty1Proxy.kt @@ -10,14 +10,13 @@ import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState import org.jetbrains.kotlin.ir.interpreter.state.reflection.KTypeState -import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classifierOrFail import kotlin.reflect.* internal open class KProperty1Proxy( - override val state: KPropertyState, override val callInterceptor: CallInterceptor + state: KPropertyState, callInterceptor: CallInterceptor ) : AbstractKPropertyProxy(state, callInterceptor), KProperty1 { protected fun IrValueParameter.getActualType(): IrType { return when (this.type.classOrNull) { @@ -33,7 +32,7 @@ internal open class KProperty1Proxy( override fun call(vararg args: Any?): Any? { checkArguments(1, args.size) val receiverParameter = (getter.dispatchReceiverParameter ?: getter.extensionReceiverParameter)!! - val receiver = Variable(receiverParameter.symbol, args[0].toState(receiverParameter.getActualType())) + val receiver = Variable(receiverParameter.symbol, environment.convertToState(args[0], receiverParameter.getActualType())) return callInterceptor.interceptProxy(getter, listOf(receiver)) } @@ -52,7 +51,7 @@ internal open class KProperty1Proxy( } internal class KMutableProperty1Proxy( - override val state: KPropertyState, override val callInterceptor: CallInterceptor + state: KPropertyState, callInterceptor: CallInterceptor ) : KProperty1Proxy(state, callInterceptor), KMutableProperty1 { override val setter: KMutableProperty1.Setter = object : Setter(state.property.setter!!), KMutableProperty1.Setter { @@ -61,9 +60,9 @@ internal class KMutableProperty1Proxy( override fun call(vararg args: Any?) { checkArguments(2, args.size) val receiverParameter = (setter.dispatchReceiverParameter ?: setter.extensionReceiverParameter)!! - val receiver = Variable(receiverParameter.symbol, args[0].toState(receiverParameter.getActualType())) + val receiver = Variable(receiverParameter.symbol, environment.convertToState(args[0], receiverParameter.getActualType())) val valueParameter = setter.valueParameters.single() - val value = Variable(valueParameter.symbol, args[1].toState(valueParameter.getActualType())) + val value = Variable(valueParameter.symbol, environment.convertToState(args[1], valueParameter.getActualType())) callInterceptor.interceptProxy(setter, listOf(receiver, value)) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt index de7a2897dcc..3e7a78c0a10 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/reflection/KProperty2Proxy.kt @@ -8,11 +8,10 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection import org.jetbrains.kotlin.ir.interpreter.CallInterceptor import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState -import org.jetbrains.kotlin.ir.interpreter.toState import kotlin.reflect.* internal open class KProperty2Proxy( - override val state: KPropertyState, override val callInterceptor: CallInterceptor + state: KPropertyState, callInterceptor: CallInterceptor ) : AbstractKPropertyProxy(state, callInterceptor), KProperty2 { override val getter: KProperty2.Getter get() = object : Getter(state.property.getter!!), KProperty2.Getter { @@ -20,8 +19,10 @@ internal open class KProperty2Proxy( override fun call(vararg args: Any?): Any? { checkArguments(2, args.size) - val dispatch = Variable(getter.dispatchReceiverParameter!!.symbol, args[0].toState(getter.dispatchReceiverParameter!!.type)) - val extension = Variable(getter.extensionReceiverParameter!!.symbol, args[1].toState(getter.extensionReceiverParameter!!.type)) + val dispatchParameter = getter.dispatchReceiverParameter!! + val extensionReceiverParameter = getter.extensionReceiverParameter!! + val dispatch = Variable(dispatchParameter.symbol, environment.convertToState(args[0], dispatchParameter.type)) + val extension = Variable(extensionReceiverParameter.symbol, environment.convertToState(args[1], extensionReceiverParameter.type)) return callInterceptor.interceptProxy(getter, listOf(dispatch, extension)) } @@ -40,7 +41,7 @@ internal open class KProperty2Proxy( } internal class KMutableProperty2Proxy( - override val state: KPropertyState, override val callInterceptor: CallInterceptor + state: KPropertyState, callInterceptor: CallInterceptor ) : KProperty2Proxy(state, callInterceptor), KMutableProperty2 { override val setter: KMutableProperty2.Setter get() = object : Setter(state.property.setter!!), KMutableProperty2.Setter { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt index e057959f084..ebd22cdc877 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/ExceptionState.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.interpreter.state import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.interpreter.getOriginalPropertyByName import org.jetbrains.kotlin.ir.interpreter.stack.Variable -import org.jetbrains.kotlin.ir.interpreter.toState import org.jetbrains.kotlin.ir.util.isSubclassOf import kotlin.math.min @@ -104,7 +103,7 @@ internal class ExceptionState private constructor( val messageProperty = irClass.getOriginalPropertyByName("message") val causeProperty = irClass.getOriginalPropertyByName("cause") - val messageVar = Variable(messageProperty.symbol, exception.message.toState(messageProperty.getter!!.returnType)) + val messageVar = Variable(messageProperty.symbol, Primitive(exception.message, messageProperty.getter!!.returnType)) val causeVar = exception.cause?.let { Variable(causeProperty.symbol, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" })) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt index 9b9d5fc1b5c..9b14f2805e2 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt @@ -22,7 +22,7 @@ import java.util.* import kotlin.collections.HashMap import kotlin.collections.LinkedHashMap -internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex { +internal class Wrapper(val value: Any, override val irClass: IrClass, environment: IrInterpreterEnvironment) : Complex { override val fields: MutableList = mutableListOf() override var superWrapperClass: Wrapper? = null @@ -37,29 +37,28 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex val nodeClass = javaClass.declaredClasses.single { it.name.contains("\$Node") } val mutableMap = irClass.superTypes.mapNotNull { it.classOrNull?.owner } .single { it.name == StandardNames.FqNames.mutableMap.shortName() } - javaClassToIrClass += nodeClass to mutableMap.declarations.filterIsInstance().single() + environment.javaClassToIrClass += nodeClass to mutableMap.declarations.filterIsInstance().single() } javaClass == LinkedHashMap::class.java -> { val entryClass = javaClass.declaredClasses.single { it.name.contains("\$Entry") } val mutableMap = irClass.superTypes.mapNotNull { it.classOrNull?.owner } .single { it.name == StandardNames.FqNames.mutableMap.shortName() } - javaClassToIrClass += entryClass to mutableMap.declarations.filterIsInstance().single() + environment.javaClassToIrClass += entryClass to mutableMap.declarations.filterIsInstance().single() } javaClass.canonicalName == "java.util.Collections.SingletonMap" -> { - javaClassToIrClass += AbstractMap.SimpleEntry::class.java to irClass.declarations.filterIsInstance().single() - javaClassToIrClass += AbstractMap.SimpleImmutableEntry::class.java to irClass.declarations.filterIsInstance().single() + val irClassMapEntry = irClass.declarations.filterIsInstance().single() + environment.javaClassToIrClass += AbstractMap.SimpleEntry::class.java to irClassMapEntry + environment.javaClassToIrClass += AbstractMap.SimpleImmutableEntry::class.java to irClassMapEntry } } - if (javaClassToIrClass[value::class.java].let { it == null || irClass.isSubclassOf(it) }) { + if (environment.javaClassToIrClass[value::class.java].let { it == null || irClass.isSubclassOf(it) }) { // second condition guarantees that implementation class will not be replaced with its interface // for example: map will store ArrayList instead of just List // this is needed for parallel calculations - javaClassToIrClass[value::class.java] = irClass + environment.javaClassToIrClass[value::class.java] = irClass } } - constructor(value: Any) : this(value, javaClassToIrClass[value::class.java]!!) - override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null fun getMethod(irFunction: IrFunction): MethodHandle? { @@ -91,7 +90,6 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex companion object { private val companionObjectValue = mapOf("kotlin.text.Regex\$Companion" to Regex.Companion) - private val javaClassToIrClass = mutableMapOf, IrClass>() // TODO remove later; used for tests only private val intrinsicClasses = setOf( @@ -110,10 +108,6 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex "Array.kotlin.collections.copyToArrayOfAny(Boolean)" to "kotlin.collections.CollectionsKt", ) - fun associateJavaClassWithIrClass(javaClass: Class<*>, irClass: IrClass) { - javaClassToIrClass += javaClass to irClass - } - private fun IrDeclarationWithName.getSignature(): String { val fqName = this.fqName return when (this) { @@ -154,10 +148,10 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType) } - fun getCompanionObject(irClass: IrClass): Wrapper { + fun getCompanionObject(irClass: IrClass, environment: IrInterpreterEnvironment): Wrapper { val objectName = irClass.internalName() val objectValue = companionObjectValue[objectName] ?: throw InternalError("Companion object $objectName cannot be interpreted") - return Wrapper(objectValue, irClass) + return Wrapper(objectValue, irClass, environment) } fun getConstructorMethod(irConstructor: IrFunction): MethodHandle? { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt index 30961549bc7..8516b788b73 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/reflection/KTypeState.kt @@ -36,7 +36,7 @@ internal class KTypeState(val irType: IrType, override val irClass: IrClass) : R fun getArguments(callInterceptor: CallInterceptor): List { if (_arguments != null) return _arguments!! - Wrapper.associateJavaClassWithIrClass(KTypeProjection::class.java, irClass.getIrClassOfReflectionFromList("arguments")) + callInterceptor.environment.javaClassToIrClass += KTypeProjection::class.java to irClass.getIrClassOfReflectionFromList("arguments") _arguments = (irType as IrSimpleType).arguments .map { when (it.getVariance()) {