Move static cache from Wrapper into non-static container in environment

By this change it is possible to run multiple test in parallel
without running out of memory.
This commit is contained in:
Ivan Kylchik
2021-08-02 14:30:25 +03:00
committed by TeamCityServer
parent 3932acf843
commit 44e1b61e6c
15 changed files with 84 additions and 79 deletions
@@ -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<State>) {
@@ -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)))
}
}
@@ -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))
@@ -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) {
@@ -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<IrClass>()
internal var mapOfEnums = mutableMapOf<IrSymbol, Complex>()
internal var mapOfObjects = mutableMapOf<IrSymbol, Complex>()
internal var javaClassToIrClass = mutableMapOf<Class<*>, 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)
}
}
}
@@ -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 <T> IrConst<T>.toPrimitive(): Primitive<T> = when {
type.isByte() -> Primitive((value as Number).toByte() as T, type)
@@ -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<Any?>().toState(returnType.irType))
environment.callStack.pushState(environment.convertToState(emptyArray<Any?>(), 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<IrEnumEntry>().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.<init>" -> {
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.<init>" -> {
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))
}
}
@@ -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<Variable>()
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)
}
}
@@ -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
@@ -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)
}
@@ -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<Any?> {
override val getter: KProperty0.Getter<Any?>
get() = object : Getter(state.property.getter!!), KProperty0.Getter<Any?> {
@@ -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<Any?> {
override val setter: KMutableProperty0.Setter<Any?> =
object : Setter(state.property.setter!!), KMutableProperty0.Setter<Any?> {
@@ -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
@@ -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<Any?, Any?> {
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<Any?, Any?> {
override val setter: KMutableProperty1.Setter<Any?, Any?> =
object : Setter(state.property.setter!!), KMutableProperty1.Setter<Any?, Any?> {
@@ -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))
}
@@ -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<Any?, Any?, Any?> {
override val getter: KProperty2.Getter<Any?, Any?, Any?>
get() = object : Getter(state.property.getter!!), KProperty2.Getter<Any?, Any?, Any?> {
@@ -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<Any?, Any?, Any?> {
override val setter: KMutableProperty2.Setter<Any?, Any?, Any?>
get() = object : Setter(state.property.setter!!), KMutableProperty2.Setter<Any?, Any?, Any?> {
@@ -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" }))
}
@@ -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<Variable> = 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<IrClass>().single()
environment.javaClassToIrClass += nodeClass to mutableMap.declarations.filterIsInstance<IrClass>().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<IrClass>().single()
environment.javaClassToIrClass += entryClass to mutableMap.declarations.filterIsInstance<IrClass>().single()
}
javaClass.canonicalName == "java.util.Collections.SingletonMap" -> {
javaClassToIrClass += AbstractMap.SimpleEntry::class.java to irClass.declarations.filterIsInstance<IrClass>().single()
javaClassToIrClass += AbstractMap.SimpleImmutableEntry::class.java to irClass.declarations.filterIsInstance<IrClass>().single()
val irClassMapEntry = irClass.declarations.filterIsInstance<IrClass>().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<String, Any>("kotlin.text.Regex\$Companion" to Regex.Companion)
private val javaClassToIrClass = mutableMapOf<Class<*>, 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? {
@@ -36,7 +36,7 @@ internal class KTypeState(val irType: IrType, override val irClass: IrClass) : R
fun getArguments(callInterceptor: CallInterceptor): List<KTypeProjection> {
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()) {