Speed up interpreter's stack by using map of variables instead of list
This commit is contained in:
committed by
TeamCityServer
parent
a630273af2
commit
ac2dffa74e
+5
-7
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.ir.interpreter.exceptions.withExceptionHandler
|
||||
import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
|
||||
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.KTypeState
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
@@ -35,7 +34,7 @@ internal interface CallInterceptor {
|
||||
val irBuiltIns: IrBuiltIns
|
||||
val interpreter: IrInterpreter
|
||||
|
||||
fun interceptProxy(irFunction: IrFunction, valueArguments: List<Variable>, expectedResultClass: Class<*> = Any::class.java): Any?
|
||||
fun interceptProxy(irFunction: IrFunction, valueArguments: List<State>, expectedResultClass: Class<*> = Any::class.java): Any?
|
||||
fun interceptCall(call: IrCall, irFunction: IrFunction, args: List<State>, defaultAction: () -> Unit)
|
||||
fun interceptConstructor(constructorCall: IrFunctionAccessExpression, args: List<State>, defaultAction: () -> Unit)
|
||||
fun interceptGetObjectValue(expression: IrGetObjectValue, defaultAction: () -> Unit)
|
||||
@@ -49,11 +48,11 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
override val irBuiltIns: IrBuiltIns = environment.irBuiltIns
|
||||
private val bodyMap: Map<IdSignature, IrBody> = interpreter.bodyMap
|
||||
|
||||
override fun interceptProxy(irFunction: IrFunction, valueArguments: List<Variable>, expectedResultClass: Class<*>): Any? {
|
||||
override fun interceptProxy(irFunction: IrFunction, valueArguments: List<State>, expectedResultClass: Class<*>): Any? {
|
||||
val irCall = irFunction.createCall()
|
||||
return interpreter.withNewCallStack(irCall) {
|
||||
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
|
||||
valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it.state) }
|
||||
valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it) }
|
||||
}.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass)
|
||||
}
|
||||
|
||||
@@ -78,7 +77,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
val irConstructor = constructorCall.symbol.owner
|
||||
val irClass = irConstructor.parentAsClass
|
||||
when {
|
||||
Wrapper.mustBeHandledWithWrapper(irClass) || irClass.fqName.startsWith("java") -> {
|
||||
Wrapper.mustBeHandledWithWrapper(irClass) -> {
|
||||
Wrapper.getConstructorMethod(irConstructor).invokeMethod(irConstructor, args)
|
||||
when {
|
||||
irClass.isSubclassOfThrowable() -> (receiver as ExceptionState).copyFieldsFrom(callStack.popState() as Wrapper)
|
||||
@@ -88,12 +87,11 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
|
||||
}
|
||||
irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray() -> {
|
||||
// array constructor doesn't have body so must be treated separately
|
||||
callStack.addVariable(Variable(irConstructor.symbol, KTypeState(constructorCall.type, environment.kTypeClass.owner)))
|
||||
verify(handleIntrinsicMethods(irConstructor)) { "Unsupported intrinsic constructor: ${irConstructor.render()}" }
|
||||
}
|
||||
irClass.defaultType.isUnsignedType() -> {
|
||||
val propertySymbol = irClass.declarations.single { it is IrProperty }.symbol
|
||||
callStack.pushState(receiver.apply { fields += Variable(propertySymbol, args.single()) })
|
||||
callStack.pushState(receiver.apply { this.setField(propertySymbol, args.single()) })
|
||||
}
|
||||
else -> defaultAction()
|
||||
}
|
||||
|
||||
+4
-5
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.verify
|
||||
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.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
@@ -98,7 +97,7 @@ private fun unfoldConstructor(constructor: IrConstructor, callStack: CallStack)
|
||||
irClass.declarations.filterIsInstance<IrProperty>().forEach { property ->
|
||||
val parameter = constructor.valueParameters.singleOrNull { it.name == property.name }
|
||||
val state = parameter?.let { callStack.getState(it.symbol) } ?: Primitive.nullStateOfType(property.getter!!.returnType)
|
||||
receiverState.setField(Variable(property.symbol, state))
|
||||
receiverState.setField(property.symbol, state)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@@ -268,7 +267,7 @@ private fun unfoldGetEnumValue(expression: IrGetEnumValue, environment: IrInterp
|
||||
|
||||
private fun unfoldVariable(variable: IrVariable, callStack: CallStack) {
|
||||
when (variable.initializer) {
|
||||
null -> callStack.addVariable(Variable(variable.symbol))
|
||||
null -> callStack.addVariable(variable.symbol, null)
|
||||
else -> {
|
||||
callStack.addInstruction(SimpleInstruction(variable))
|
||||
callStack.addInstruction(CompoundInstruction(variable.initializer!!))
|
||||
@@ -337,7 +336,7 @@ private fun unfoldCatch(element: IrCatch, callStack: CallStack) {
|
||||
val frameOwner = callStack.currentFrameOwner as IrTry
|
||||
callStack.dropSubFrame() // drop other catch blocks
|
||||
callStack.newSubFrame(element) // new frame with IrTry instruction to interpret finally block at the end
|
||||
callStack.addVariable(Variable(element.catchParameter.symbol, exceptionState))
|
||||
callStack.addVariable(element.catchParameter.symbol, exceptionState)
|
||||
callStack.addInstruction(SimpleInstruction(frameOwner))
|
||||
callStack.addInstruction(CompoundInstruction(element.result))
|
||||
}
|
||||
@@ -360,7 +359,7 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ
|
||||
// TODO this check can be dropped after serialization introduction
|
||||
// for now declarations in unsigned class don't have bodies and must be treated separately
|
||||
if (state.irClass.defaultType.isUnsigned()) {
|
||||
val result = when (val value = (state.fields.single().state as Primitive<*>).value) {
|
||||
val result = when (val value = (state.fields.values.single() as Primitive<*>).value) {
|
||||
is Byte -> value.toUByte().toString()
|
||||
is Short -> value.toUShort().toString()
|
||||
is Int -> value.toUInt().toString()
|
||||
|
||||
+31
-35
@@ -12,12 +12,9 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.verify
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy
|
||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||
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.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
@@ -108,7 +105,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
is IrGetEnumValue -> interpretGetEnumValue(element)
|
||||
is IrEnumEntry -> interpretEnumEntry(element)
|
||||
is IrConst<*> -> interpretConst(element)
|
||||
is IrVariable -> callStack.addVariable(Variable(element.symbol, callStack.popState()))
|
||||
is IrVariable -> callStack.addVariable(element.symbol, callStack.popState())
|
||||
is IrSetValue -> callStack.setState(element.symbol, callStack.popState())
|
||||
is IrTypeOperatorCall -> interpretTypeOperatorCall(element)
|
||||
is IrBranch -> interpretBranch(element)
|
||||
@@ -173,11 +170,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
val args = listOfNotNull(dispatchReceiver.getThisOrSuperReceiver(irFunction), extensionReceiver) + valueArguments
|
||||
|
||||
// 3. evaluate reified type arguments; must do it here, before new frame, because outer type arguments can be loaded at this point
|
||||
val reifiedTypeArguments = irFunction.typeParameters.filter { it.isReified }
|
||||
.map {
|
||||
val reifiedType = call.getTypeArgument(it.index)!!.getTypeIfReified(callStack)
|
||||
Variable(it.symbol, KTypeState(reifiedType, environment.kTypeClass.owner))
|
||||
}
|
||||
val reifiedTypeArguments = environment.loadReifiedTypeArguments(call)
|
||||
|
||||
callStack.newFrame(irFunction)
|
||||
callStack.addInstruction(SimpleInstruction(irFunction))
|
||||
@@ -188,14 +181,14 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
if (irFunction.isLocal) callStack.copyUpValuesFromPreviousFrame()
|
||||
|
||||
// 5. store arguments in memory (remap args on actual names)
|
||||
irFunction.getDispatchReceiver()?.let { callStack.addVariable(Variable(it, dispatchReceiver!!)) }
|
||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(Variable(it, extensionReceiver ?: callStack.getState(it))) }
|
||||
irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) }
|
||||
irFunction.getDispatchReceiver()?.let { callStack.addVariable(it, dispatchReceiver!!) }
|
||||
irFunction.getExtensionReceiver()?.let { callStack.addVariable(it, extensionReceiver ?: callStack.getState(it)) }
|
||||
irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(param.symbol, valueArguments[i]) }
|
||||
// `call.type` is used in check cast and emptyArray
|
||||
callStack.addVariable(Variable(irFunction.symbol, KTypeState(call.type, environment.kTypeClass.owner)))
|
||||
callStack.addVariable(irFunction.symbol, KTypeState(call.type, environment.kTypeClass.owner))
|
||||
|
||||
// 6. store reified type parameters
|
||||
reifiedTypeArguments.forEach { callStack.addVariable(it) }
|
||||
reifiedTypeArguments.forEach { callStack.addVariable(it.key, it.value) }
|
||||
|
||||
// 7. load outer class object
|
||||
if (dispatchReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) dispatchReceiver.loadOuterClassesInto(callStack)
|
||||
@@ -209,7 +202,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
val irClass = field.parentAsClass
|
||||
val receiver = irClass.thisReceiver!!.symbol
|
||||
val receiverState = callStack.getState(receiver)
|
||||
receiverState.setField(Variable(field.correspondingPropertySymbol!!, callStack.popState()))
|
||||
receiverState.setField(field.correspondingPropertySymbol!!, callStack.popState())
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@@ -247,13 +240,15 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
|
||||
if (irClass.isLocal) callStack.storeUpValues(objectState as StateWithClosure)
|
||||
val outerClass = receiverSymbol?.let { callStack.popState() }
|
||||
val returnType = constructorCall.type.getTypeIfReified(callStack)
|
||||
|
||||
callStack.newFrame(constructor)
|
||||
callStack.addInstruction(SimpleInstruction(constructor))
|
||||
if (irClass.isLocal) callStack.loadUpValues(objectState as StateWithClosure)
|
||||
|
||||
callStack.addVariable(Variable(constructorCall.getThisReceiver(), objectState))
|
||||
constructor.valueParameters.forEachIndexed { i, param -> callStack.addVariable(Variable(param.symbol, valueArguments[i])) }
|
||||
callStack.addVariable(constructorCall.getThisReceiver(), objectState)
|
||||
constructor.valueParameters.forEachIndexed { i, param -> callStack.addVariable(param.symbol, valueArguments[i]) }
|
||||
callStack.addVariable(constructor.symbol, KTypeState(returnType, environment.kTypeClass.owner))
|
||||
|
||||
val superReceiver = when (val irStatement = constructor.body?.statements?.get(0)) {
|
||||
null -> null // for jvm
|
||||
@@ -262,16 +257,16 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
is IrBlock -> (irStatement.statements.last() as IrFunctionAccessExpression).getThisReceiver()
|
||||
else -> TODO("${irStatement::class.java} is not supported as first statement in constructor call")
|
||||
}
|
||||
superReceiver?.let { callStack.addVariable(Variable(it, objectState)) }
|
||||
superReceiver?.let { callStack.addVariable(it, objectState) }
|
||||
|
||||
if (outerClass != null) {
|
||||
val outerClassVar = Variable(irClass.parentAsClass.thisReceiver!!.symbol, outerClass)
|
||||
(objectState as Complex).outerClass = outerClassVar
|
||||
val outerClassSymbolToState = irClass.parentAsClass.thisReceiver!!.symbol to outerClass
|
||||
(objectState as Complex).outerClass = outerClassSymbolToState
|
||||
if (superReceiver?.owner?.type != receiverSymbol.owner.type) {
|
||||
// This check is needed to test that this inner class is not subclass of its outer.
|
||||
// If it is true and if we add the next symbol, it will interfere with super symbol in memory.
|
||||
// In other case, we need this variable when inner class has inner super class.
|
||||
callStack.addVariable(Variable(receiverSymbol, outerClass))
|
||||
callStack.addVariable(receiverSymbol, outerClass)
|
||||
// used to get information from outer class
|
||||
objectState.loadOuterClassesInto(callStack, constructorCall.getThisReceiver())
|
||||
}
|
||||
@@ -349,7 +344,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
private fun interpretSetField(expression: IrSetField) {
|
||||
val receiver = (expression.receiver as IrDeclarationReference).symbol
|
||||
val propertySymbol = expression.symbol.owner.correspondingPropertySymbol!!
|
||||
callStack.getState(receiver).apply { this.setField(Variable(propertySymbol, callStack.popState())) }
|
||||
callStack.getState(receiver).apply { this.setField(propertySymbol, callStack.popState()) }
|
||||
}
|
||||
|
||||
private fun interpretGetField(expression: IrGetField) {
|
||||
@@ -427,13 +422,13 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
valueArguments.forEachIndexed { index, irConst -> enumSuperCall.putValueArgument(index, irConst) }
|
||||
}
|
||||
|
||||
val enumClassObject = Variable(enumConstructorCall.getThisReceiver(), Common(enumEntry.correspondingClass ?: enumClass))
|
||||
environment.mapOfEnums[enumEntry.symbol] = enumClassObject.state as Complex
|
||||
val enumClassObject = Common(enumEntry.correspondingClass ?: enumClass)
|
||||
environment.mapOfEnums[enumEntry.symbol] = enumClassObject
|
||||
|
||||
callStack.newSubFrame(enumEntry)
|
||||
callStack.addInstruction(CustomInstruction(cleanEnumSuperCall))
|
||||
callStack.addInstruction(CompoundInstruction(enumInitializer))
|
||||
callStack.addVariable(enumClassObject)
|
||||
callStack.addVariable(enumConstructorCall.getThisReceiver(), enumClassObject)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,10 +490,11 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
val functionClass = invokeFunction.getLastOverridden().parentAsClass
|
||||
|
||||
// receiver will be stored as up value
|
||||
val dispatchReceiver = Variable(invokeFunction.dispatchReceiverParameter!!.symbol, state)
|
||||
val dispatchReceiver = invokeFunction.dispatchReceiverParameter!!.symbol to state
|
||||
val newInvoke = invokeFunction.deepCopyWithSymbols(samClass).apply { dispatchReceiverParameter = null }
|
||||
KFunctionState(newInvoke, functionClass, environment, mutableListOf(dispatchReceiver))
|
||||
.apply { this.funInterface = typeOperand }
|
||||
KFunctionState(newInvoke, functionClass, environment, mutableMapOf(dispatchReceiver)).apply {
|
||||
this.funInterface = typeOperand
|
||||
}
|
||||
}
|
||||
}
|
||||
callStack.pushState(newState)
|
||||
@@ -532,7 +528,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
else -> arrayToList(result.value)
|
||||
}
|
||||
is Common -> when {
|
||||
result.irClass.defaultType.isUnsignedArray() -> arrayToList((result.fields.single().state as Primitive<*>).value)
|
||||
result.irClass.defaultType.isUnsignedArray() -> arrayToList((result.fields.values.single() as Primitive<*>).value)
|
||||
else -> listOf(result.asProxy(callInterceptor))
|
||||
}
|
||||
else -> listOf(result)
|
||||
@@ -545,12 +541,12 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
val storageProperty = owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "storage" }
|
||||
val primitiveArray = args.map {
|
||||
when (it) {
|
||||
is Proxy -> (it.state.fields.single().state as Primitive<*>).value // is unsigned number
|
||||
else -> it // is primitive number
|
||||
is Proxy -> (it.state.fields.values.single() as Primitive<*>).value // is unsigned number
|
||||
else -> it // is primitive number
|
||||
}
|
||||
}
|
||||
val unsignedArray = primitiveArray.toPrimitiveStateArray(storageProperty.backingField!!.type)
|
||||
Common(owner).apply { fields.add(Variable(storageProperty.symbol, unsignedArray)) }
|
||||
Common(owner).apply { setField(storageProperty.symbol, unsignedArray) }
|
||||
}
|
||||
else -> args.toPrimitiveStateArray(expression.type)
|
||||
}
|
||||
@@ -604,8 +600,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
val function = KFunctionState(
|
||||
reference,
|
||||
environment,
|
||||
dispatchReceiver?.let { Variable(irFunction.getDispatchReceiver()!!, it) },
|
||||
extensionReceiver?.let { Variable(irFunction.getExtensionReceiver()!!, it) }
|
||||
dispatchReceiver?.let { irFunction.getDispatchReceiver()!! to it },
|
||||
extensionReceiver?.let { irFunction.getExtensionReceiver()!! to it }
|
||||
)
|
||||
if (irFunction.isLocal) callStack.storeUpValues(function)
|
||||
callStack.pushState(function)
|
||||
@@ -619,7 +615,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal
|
||||
fun List<IrTypeParameter>.addToFields() {
|
||||
(0 until propertyReference.typeArgumentsCount).forEach { index ->
|
||||
val kTypeState = KTypeState(propertyReference.getTypeArgument(index)!!, environment.kTypeClass.owner)
|
||||
propertyState.fields += Variable(this[index].symbol, kTypeState)
|
||||
propertyState.setField(this[index].symbol, kTypeState)
|
||||
}
|
||||
}
|
||||
propertyReference.getter?.owner?.typeParameters?.addToFields()
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ internal fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||
is Complex -> {
|
||||
val stateType = this.irClass.defaultType
|
||||
when {
|
||||
stateType.isUnsignedType() -> (this.fields.single().state as Primitive<*>).value.toIrConst(type, start, end)
|
||||
stateType.isUnsignedType() -> (this.fields.values.single() as Primitive<*>).value.toIrConst(type, start, end)
|
||||
else -> expression
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import java.lang.invoke.MethodType
|
||||
|
||||
val compileTimeAnnotation = FqName("kotlin.CompileTimeCalculation")
|
||||
@@ -265,6 +266,13 @@ internal fun IrType.getTypeIfReified(getType: (IrClassifierSymbol) -> IrType): I
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrInterpreterEnvironment.loadReifiedTypeArguments(expression: IrFunctionAccessExpression): Map<IrTypeParameterSymbol, KTypeState> {
|
||||
return expression.symbol.owner.typeParameters.filter { it.isReified }.map { it.symbol }.keysToMap {
|
||||
val reifiedType = expression.getTypeArgument(it.owner.index)!!.getTypeIfReified(callStack)
|
||||
KTypeState(reifiedType, this.kTypeClass.owner)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrFunctionAccessExpression.getSuperEnumCall(): IrEnumConstructorCall {
|
||||
val name = this.symbol.owner.parentClassOrNull?.fqName
|
||||
if (this is IrEnumConstructorCall && name == "kotlin.Enum") return this
|
||||
|
||||
+2
-6
@@ -274,12 +274,8 @@ internal object ArrayConstructor : IntrinsicBase() {
|
||||
}
|
||||
}
|
||||
|
||||
val state = irFunction.valueParameters.getOrNull(1)?.symbol?.let { environment.callStack.getState(it) as StateWithClosure }
|
||||
val typeFromMemory = (environment.callStack.getState(irFunction.symbol) as KTypeState).irType
|
||||
val type = state?.let {
|
||||
typeFromMemory.getTypeIfReified { typeSymbol -> (it.upValues.single { it.symbol == typeSymbol }.state as KTypeState).irType }
|
||||
}
|
||||
environment.callStack.pushState(arrayValue.toPrimitiveStateArray(type ?: typeFromMemory))
|
||||
val type = (environment.callStack.getState(irFunction.symbol) as KTypeState).irType
|
||||
environment.callStack.pushState(arrayValue.toPrimitiveStateArray(type))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-11
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.interpreter.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.CallInterceptor
|
||||
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.util.isFakeOverriddenFromAny
|
||||
@@ -34,31 +33,31 @@ internal class CommonProxy private constructor(override val state: Common, overr
|
||||
if (this === other) return true
|
||||
if (other == null) return false
|
||||
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val valueArguments = mutableListOf<State>()
|
||||
val equalsFun = state.getEqualsFunction()
|
||||
if (equalsFun.isFakeOverriddenFromAny() || equalsFun.wasAlreadyCalled()) return defaultEquals(other)
|
||||
|
||||
equalsFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
valueArguments.add(Variable(equalsFun.valueParameters.single().symbol, if (other is Proxy) other.state else other as State))
|
||||
equalsFun.getDispatchReceiver()!!.let { valueArguments.add(state) }
|
||||
valueArguments.add(if (other is Proxy) other.state else other as State)
|
||||
|
||||
return callInterceptor.interceptProxy(equalsFun, valueArguments) as Boolean
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val valueArguments = mutableListOf<State>()
|
||||
val hashCodeFun = state.getHashCodeFunction()
|
||||
if (hashCodeFun.isFakeOverriddenFromAny() || hashCodeFun.wasAlreadyCalled()) return defaultHashCode()
|
||||
|
||||
hashCodeFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
hashCodeFun.getDispatchReceiver()!!.let { valueArguments.add(state) }
|
||||
return callInterceptor.interceptProxy(hashCodeFun, valueArguments) as Int
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
val valueArguments = mutableListOf<State>()
|
||||
val toStringFun = state.getToStringFunction()
|
||||
if (toStringFun.isFakeOverriddenFromAny() || toStringFun.wasAlreadyCalled()) return defaultToString()
|
||||
|
||||
toStringFun.getDispatchReceiver()!!.let { valueArguments.add(Variable(it, state)) }
|
||||
toStringFun.getDispatchReceiver()!!.let { valueArguments.add(state) }
|
||||
return callInterceptor.interceptProxy(toStringFun, valueArguments) as String
|
||||
}
|
||||
|
||||
@@ -81,10 +80,9 @@ internal class CommonProxy private constructor(override val state: Common, overr
|
||||
else -> {
|
||||
val irFunction = commonProxy.state.getIrFunction(method)
|
||||
?: return@newProxyInstance commonProxy.fallbackIfMethodNotFound(method)
|
||||
val valueArguments = mutableListOf<Variable>()
|
||||
valueArguments += Variable(irFunction.getDispatchReceiver()!!, commonProxy.state)
|
||||
val valueArguments = mutableListOf<State>(commonProxy.state)
|
||||
valueArguments += irFunction.valueParameters.mapIndexed { index, parameter ->
|
||||
Variable(parameter.symbol, callInterceptor.environment.convertToState(args[index], parameter.type))
|
||||
callInterceptor.environment.convertToState(args[index], parameter.type)
|
||||
}
|
||||
callInterceptor.interceptProxy(irFunction, valueArguments, method.returnType)
|
||||
}
|
||||
|
||||
+3
-6
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
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.hasTheSameFieldsWith
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
@@ -52,12 +51,10 @@ 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, environment.convertToState(args[index++], it.type)) }
|
||||
val extensionReceiver = state.irFunction.extensionReceiverParameter
|
||||
?.let { Variable(it.symbol, environment.convertToState(args[index++], it.type)) }
|
||||
val dispatchReceiver = state.irFunction.dispatchReceiverParameter?.let { environment.convertToState(args[index++], it.type) }
|
||||
val extensionReceiver = state.irFunction.extensionReceiverParameter?.let { environment.convertToState(args[index++], it.type) }
|
||||
val argsVariables = state.irFunction.valueParameters.map { parameter ->
|
||||
Variable(parameter.symbol, environment.convertToState(args[index++], parameter.type))
|
||||
environment.convertToState(args[index++], parameter.type)
|
||||
}
|
||||
val valueArguments = listOfNotNull(dispatchReceiver, extensionReceiver) + argsVariables
|
||||
return callInterceptor.interceptProxy(state.irFunction, valueArguments)
|
||||
|
||||
+6
-13
@@ -5,16 +5,16 @@
|
||||
|
||||
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.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.util.isObject
|
||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.KProperty0
|
||||
|
||||
internal open class KProperty0Proxy(
|
||||
state: KPropertyState, callInterceptor: CallInterceptor
|
||||
@@ -32,11 +32,7 @@ internal open class KProperty0Proxy(
|
||||
val value = receiver.getField(actualPropertySymbol)
|
||||
return when {
|
||||
// null value <=> property is extension or Primitive; receiver.isNull() <=> nullable extension
|
||||
value == null || receiver.isNull() -> {
|
||||
val receiverSymbol = getter.getReceiver()
|
||||
val receiverVariable = receiverSymbol?.let { Variable(it, receiver) }
|
||||
callInterceptor.interceptProxy(getter, listOfNotNull(receiverVariable))
|
||||
}
|
||||
value == null || receiver.isNull() -> callInterceptor.interceptProxy(getter, listOf(receiver))
|
||||
else -> value
|
||||
}
|
||||
}
|
||||
@@ -70,11 +66,8 @@ internal class KMutableProperty0Proxy(
|
||||
val receiver = state.receiver!!
|
||||
val newValue = environment.convertToState(args.single(), propertyType)
|
||||
setter.getExtensionReceiver()
|
||||
?.let {
|
||||
val fieldSymbol = setter.valueParameters.single().symbol
|
||||
callInterceptor.interceptProxy(setter, listOf(Variable(it, receiver), Variable(fieldSymbol, newValue)))
|
||||
}
|
||||
?: receiver.setField(Variable(state.property.symbol, newValue))
|
||||
?.let { callInterceptor.interceptProxy(setter, listOf(receiver, newValue)) }
|
||||
?: receiver.setField(state.property.symbol, newValue)
|
||||
}
|
||||
|
||||
override fun callBy(args: Map<KParameter, Any?>) {
|
||||
|
||||
+6
-5
@@ -7,13 +7,14 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
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.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
internal open class KProperty1Proxy(
|
||||
state: KPropertyState, callInterceptor: CallInterceptor
|
||||
@@ -32,7 +33,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, environment.convertToState(args[0], receiverParameter.getActualType()))
|
||||
val receiver = environment.convertToState(args[0], receiverParameter.getActualType())
|
||||
return callInterceptor.interceptProxy(getter, listOf(receiver))
|
||||
}
|
||||
|
||||
@@ -60,9 +61,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, environment.convertToState(args[0], receiverParameter.getActualType()))
|
||||
val receiver = environment.convertToState(args[0], receiverParameter.getActualType())
|
||||
val valueParameter = setter.valueParameters.single()
|
||||
val value = Variable(valueParameter.symbol, environment.convertToState(args[1], valueParameter.getActualType()))
|
||||
val value = environment.convertToState(args[1], valueParameter.getActualType())
|
||||
callInterceptor.interceptProxy(setter, listOf(receiver, value))
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -6,9 +6,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 kotlin.reflect.*
|
||||
import kotlin.reflect.KMutableProperty2
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.KProperty2
|
||||
|
||||
internal open class KProperty2Proxy(
|
||||
state: KPropertyState, callInterceptor: CallInterceptor
|
||||
@@ -21,8 +22,8 @@ internal open class KProperty2Proxy(
|
||||
checkArguments(2, args.size)
|
||||
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))
|
||||
val dispatch = environment.convertToState(args[0], dispatchParameter.type)
|
||||
val extension = environment.convertToState(args[1], extensionReceiverParameter.type)
|
||||
return callInterceptor.interceptProxy(getter, listOf(dispatch, extension))
|
||||
}
|
||||
|
||||
|
||||
+12
-15
@@ -25,18 +25,15 @@ internal class CallStack {
|
||||
internal val currentFrameOwner get() = currentFrame.currentSubFrameOwner
|
||||
|
||||
fun newFrame(frameOwner: IrElement, irFile: IrFile? = null) {
|
||||
val newFrame = SubFrame(frameOwner)
|
||||
frames.add(Frame(newFrame, irFile))
|
||||
frames.add(Frame(frameOwner, irFile))
|
||||
}
|
||||
|
||||
fun newFrame(frameOwner: IrFunction) {
|
||||
val newFrame = SubFrame(frameOwner)
|
||||
frames.add(Frame(newFrame, frameOwner.fileOrNull))
|
||||
frames.add(Frame(frameOwner, frameOwner.fileOrNull))
|
||||
}
|
||||
|
||||
fun newSubFrame(frameOwner: IrElement) {
|
||||
val newFrame = SubFrame(frameOwner)
|
||||
currentFrame.addSubFrame(newFrame)
|
||||
currentFrame.addSubFrame(frameOwner)
|
||||
}
|
||||
|
||||
fun dropFrame() {
|
||||
@@ -174,8 +171,12 @@ internal class CallStack {
|
||||
fun popState(): State = currentFrame.popState()
|
||||
fun peekState(): State? = currentFrame.peekState()
|
||||
|
||||
fun addVariable(variable: Variable) {
|
||||
currentFrame.addVariable(variable)
|
||||
fun addVariable(symbol: IrSymbol, state: State?) {
|
||||
currentFrame.addVariable(symbol, state)
|
||||
}
|
||||
|
||||
private fun addVariable(symbol: IrSymbol, variable: Variable) {
|
||||
currentFrame.addVariable(symbol, variable)
|
||||
}
|
||||
|
||||
fun getState(symbol: IrSymbol): State = currentFrame.getState(symbol)
|
||||
@@ -184,19 +185,15 @@ internal class CallStack {
|
||||
|
||||
fun storeUpValues(state: StateWithClosure) {
|
||||
// TODO save only necessary declarations
|
||||
currentFrame.getAll().reversed().forEach { variable ->
|
||||
// TODO replace list with map
|
||||
val index = state.upValues.indexOfFirst { it.symbol == variable.symbol }
|
||||
if (index == -1) state.upValues.add(variable) else state.upValues[index] = variable
|
||||
}
|
||||
currentFrame.copyMemoryInto(state)
|
||||
}
|
||||
|
||||
fun loadUpValues(state: StateWithClosure) {
|
||||
state.upValues.forEach { addVariable(it) }
|
||||
state.upValues.forEach { (symbol, variable) -> addVariable(symbol, variable) }
|
||||
}
|
||||
|
||||
fun copyUpValuesFromPreviousFrame() {
|
||||
frames[frames.size - 2].getAll().forEach { if (!containsVariable(it.symbol)) addVariable(it) }
|
||||
frames[frames.size - 2].copyMemoryInto(currentFrame)
|
||||
}
|
||||
|
||||
fun getStackTrace(): List<String> {
|
||||
|
||||
@@ -11,12 +11,13 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.interpreter.Instruction
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.StateWithClosure
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
|
||||
internal class Frame(subFrame: SubFrame, val irFile: IrFile? = null) {
|
||||
private val innerStack = mutableListOf(subFrame)
|
||||
internal class Frame(subFrameOwner: IrElement, val irFile: IrFile? = null) {
|
||||
private val innerStack = mutableListOf(SubFrame(subFrameOwner))
|
||||
private var currentInstruction: Instruction? = null
|
||||
|
||||
private val currentFrame get() = innerStack.last()
|
||||
@@ -26,8 +27,8 @@ internal class Frame(subFrame: SubFrame, val irFile: IrFile? = null) {
|
||||
const val NOT_DEFINED = "Not defined"
|
||||
}
|
||||
|
||||
fun addSubFrame(frame: SubFrame) {
|
||||
innerStack.add(frame)
|
||||
fun addSubFrame(subFrameOwner: IrElement) {
|
||||
innerStack.add(SubFrame(subFrameOwner))
|
||||
}
|
||||
|
||||
fun removeSubFrame() {
|
||||
@@ -59,8 +60,12 @@ internal class Frame(subFrame: SubFrame, val irFile: IrFile? = null) {
|
||||
fun popState(): State = currentFrame.popState()
|
||||
fun peekState(): State? = currentFrame.peekState()
|
||||
|
||||
fun addVariable(variable: Variable) {
|
||||
currentFrame.addVariable(variable)
|
||||
fun addVariable(symbol: IrSymbol, state: State?) {
|
||||
currentFrame.addVariable(symbol, state)
|
||||
}
|
||||
|
||||
fun addVariable(symbol: IrSymbol, variable: Variable) {
|
||||
currentFrame.addVariable(symbol, variable)
|
||||
}
|
||||
|
||||
fun getState(symbol: IrSymbol): State {
|
||||
@@ -77,7 +82,15 @@ internal class Frame(subFrame: SubFrame, val irFile: IrFile? = null) {
|
||||
|
||||
fun containsVariable(symbol: IrSymbol): Boolean = (innerStack.lastIndex downTo 0).any { innerStack[it].containsVariable(symbol) }
|
||||
|
||||
fun getAll(): List<Variable> = innerStack.flatMap { it.getAll() }
|
||||
fun copyMemoryInto(newFrame: Frame) {
|
||||
this.getAll().forEach { (symbol, variable) -> if (!newFrame.containsVariable(symbol)) newFrame.addVariable(symbol, variable) }
|
||||
}
|
||||
|
||||
fun copyMemoryInto(closure: StateWithClosure) {
|
||||
getAll().reversed().forEach { (symbol, variable) -> closure.upValues[symbol] = variable }
|
||||
}
|
||||
|
||||
private fun getAll(): List<Pair<IrSymbol, Variable>> = innerStack.flatMap { it.getAll() }
|
||||
|
||||
private fun getLineNumberForCurrentInstruction(): String {
|
||||
irFile ?: return ""
|
||||
@@ -105,10 +118,10 @@ internal class Frame(subFrame: SubFrame, val irFile: IrFile? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
internal class SubFrame(val owner: IrElement) {
|
||||
private class SubFrame(val owner: IrElement) {
|
||||
private val instructions = mutableListOf<Instruction>()
|
||||
private val dataStack = DataStack()
|
||||
private val memory = mutableListOf<Variable>()
|
||||
private val memory = mutableMapOf<IrSymbol, Variable>()
|
||||
|
||||
// Methods to work with instruction
|
||||
fun isEmpty() = instructions.isEmpty()
|
||||
@@ -122,18 +135,21 @@ internal class SubFrame(val owner: IrElement) {
|
||||
fun peekState(): State? = dataStack.peek()
|
||||
|
||||
// Methods to work with memory
|
||||
fun addVariable(variable: Variable) {
|
||||
memory.add(0, variable)
|
||||
fun addVariable(symbol: IrSymbol, variable: Variable) {
|
||||
memory[symbol] = variable
|
||||
}
|
||||
|
||||
private fun getVariable(symbol: IrSymbol): Variable? = memory.firstOrNull { it.symbol == symbol }
|
||||
fun containsVariable(symbol: IrSymbol): Boolean = getVariable(symbol) != null
|
||||
fun getState(symbol: IrSymbol): State? = getVariable(symbol)?.state
|
||||
fun addVariable(symbol: IrSymbol, state: State?) {
|
||||
memory[symbol] = Variable(state)
|
||||
}
|
||||
|
||||
fun containsVariable(symbol: IrSymbol): Boolean = memory[symbol] != null
|
||||
fun getState(symbol: IrSymbol): State? = memory[symbol]?.state
|
||||
fun setState(symbol: IrSymbol, newState: State) {
|
||||
getVariable(symbol)?.state = newState
|
||||
memory[symbol]?.state = newState
|
||||
}
|
||||
|
||||
fun getAll(): List<Variable> = memory
|
||||
fun getAll(): List<Pair<IrSymbol, Variable>> = memory.toList()
|
||||
}
|
||||
|
||||
private class DataStack {
|
||||
|
||||
+2
-15
@@ -1,23 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.stack
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
|
||||
// TODO maybe switch to typealias and use map instead of list
|
||||
internal data class Variable(val symbol: IrSymbol) {
|
||||
lateinit var state: State
|
||||
|
||||
constructor(symbol: IrSymbol, state: State) : this(symbol) {
|
||||
this.state = state
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Variable(symbol=${(symbol.owner as? IrDeclarationWithName)?.name}, state=$state)"
|
||||
}
|
||||
}
|
||||
internal data class Variable(var state: State?)
|
||||
@@ -13,17 +13,20 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.createCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.fqName
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal class Common private constructor(override val irClass: IrClass, override val fields: MutableList<Variable>) : Complex, StateWithClosure {
|
||||
override val upValues: MutableList<Variable> = mutableListOf()
|
||||
internal class Common private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableMap<IrSymbol, State>
|
||||
) : Complex, StateWithClosure {
|
||||
override val upValues: MutableMap<IrSymbol, Variable> = mutableMapOf()
|
||||
override var superWrapperClass: Wrapper? = null
|
||||
override var outerClass: Variable? = null
|
||||
override var outerClass: Pair<IrSymbol, State>? = null
|
||||
|
||||
constructor(irClass: IrClass) : this(irClass, mutableListOf())
|
||||
constructor(irClass: IrClass) : this(irClass, mutableMapOf())
|
||||
|
||||
// This method is used to get correct java method name
|
||||
private fun getKotlinName(declaringClassName: String, methodName: String): String {
|
||||
|
||||
+11
-8
@@ -5,18 +5,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.fqName
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.CallStack
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.util.overrides
|
||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
|
||||
internal interface Complex : State {
|
||||
var superWrapperClass: Wrapper?
|
||||
var outerClass: Variable?
|
||||
var outerClass: Pair<IrSymbol, State>?
|
||||
|
||||
fun irClassFqName() = irClass.fqName
|
||||
|
||||
@@ -53,12 +56,12 @@ internal interface Complex : State {
|
||||
return list
|
||||
}
|
||||
|
||||
generateSequence(outerClass) { (it.state as? Complex)?.outerClass }
|
||||
generateSequence(outerClass) { (it.second as? Complex)?.outerClass }
|
||||
.toList()
|
||||
.takeFromEndWhile { receiver == null || it.symbol != receiver } // only state's below receiver must be loaded on stack
|
||||
.forEach { variable ->
|
||||
callStack.addVariable(variable)
|
||||
(variable.state as? StateWithClosure)?.let { callStack.loadUpValues(it) }
|
||||
.takeFromEndWhile { receiver == null || it.first != receiver } // only state's below receiver must be loaded on stack
|
||||
.forEach { (symbol, state) ->
|
||||
callStack.addVariable(symbol, state)
|
||||
(state as? StateWithClosure)?.let { callStack.loadUpValues(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-14
@@ -8,15 +8,16 @@ 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.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
import kotlin.math.min
|
||||
|
||||
internal class ExceptionState private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>
|
||||
override val irClass: IrClass, override val fields: MutableMap<IrSymbol, State>, stackTrace: List<String>
|
||||
) : Complex, StateWithClosure, Throwable() {
|
||||
override val upValues: MutableList<Variable> = mutableListOf()
|
||||
override val upValues: MutableMap<IrSymbol, Variable> = mutableMapOf()
|
||||
override var superWrapperClass: Wrapper? = null
|
||||
override var outerClass: Variable? = null
|
||||
override var outerClass: Pair<IrSymbol, State>? = null
|
||||
|
||||
override val message: String?
|
||||
get() = getField(messageProperty.symbol)?.asStringOrNull()
|
||||
@@ -32,11 +33,11 @@ internal class ExceptionState private constructor(
|
||||
|
||||
init {
|
||||
if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName()
|
||||
if (fields.none { it.symbol == messageProperty.symbol }) setMessage(null)
|
||||
if (fields.none { it.symbol == causeProperty.symbol }) setCause(null)
|
||||
if (!fields.containsKey(messageProperty.symbol)) setMessage(null)
|
||||
if (!fields.containsKey(causeProperty.symbol)) setCause(null)
|
||||
}
|
||||
|
||||
constructor(irClass: IrClass, stackTrace: List<String>) : this(irClass, mutableListOf(), stackTrace)
|
||||
constructor(irClass: IrClass, stackTrace: List<String>) : this(irClass, mutableMapOf(), stackTrace)
|
||||
|
||||
constructor(
|
||||
exception: Throwable, irClass: IrClass, stackTrace: List<String>
|
||||
@@ -58,8 +59,8 @@ internal class ExceptionState private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun setField(newVar: Variable) {
|
||||
super.setField(newVar)
|
||||
override fun setField(symbol: IrSymbol, state: State) {
|
||||
super.setField(symbol, state)
|
||||
recalculateCauseAndMessage()
|
||||
}
|
||||
|
||||
@@ -78,11 +79,11 @@ internal class ExceptionState private constructor(
|
||||
}
|
||||
|
||||
private fun setMessage(messageValue: String?) {
|
||||
setField(Variable(messageProperty.symbol, Primitive(messageValue, messageProperty.getter!!.returnType)))
|
||||
setField(messageProperty.symbol, Primitive(messageValue, messageProperty.getter!!.returnType))
|
||||
}
|
||||
|
||||
private fun setCause(causeValue: State?) {
|
||||
setField(Variable(causeProperty.symbol, causeValue ?: Primitive.nullStateOfType(causeProperty.getter!!.returnType)))
|
||||
setField(causeProperty.symbol, causeValue ?: Primitive.nullStateOfType(causeProperty.getter!!.returnType))
|
||||
}
|
||||
|
||||
fun getFullDescription(): String {
|
||||
@@ -99,15 +100,15 @@ internal class ExceptionState private constructor(
|
||||
override fun toString(): String = message?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
|
||||
companion object {
|
||||
private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List<String>): MutableList<Variable> {
|
||||
private fun evaluateFields(exception: Throwable, irClass: IrClass, stackTrace: List<String>): MutableMap<IrSymbol, State> {
|
||||
val messageProperty = irClass.getOriginalPropertyByName("message")
|
||||
val causeProperty = irClass.getOriginalPropertyByName("cause")
|
||||
|
||||
val messageVar = Variable(messageProperty.symbol, Primitive(exception.message, messageProperty.getter!!.returnType))
|
||||
val messageVar = messageProperty.symbol to Primitive(exception.message, messageProperty.getter!!.returnType)
|
||||
val causeVar = exception.cause?.let {
|
||||
Variable(causeProperty.symbol, ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" }))
|
||||
causeProperty.symbol to ExceptionState(it, irClass, stackTrace + it.stackTrace.reversed().map { "at $it" })
|
||||
}
|
||||
return causeVar?.let { mutableListOf(messageVar, it) } ?: mutableListOf(messageVar)
|
||||
return causeVar?.let { mutableMapOf(messageVar, it) } ?: mutableMapOf(messageVar)
|
||||
}
|
||||
|
||||
private fun evaluateAdditionalStackTrace(e: Throwable): List<String> {
|
||||
|
||||
+1
-2
@@ -9,14 +9,13 @@ 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.getLastOverridden
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
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.defaultType
|
||||
|
||||
internal class Primitive<T>(val value: T, val type: IrType) : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
override val fields: MutableMap<IrSymbol, State> = mutableMapOf()
|
||||
override val irClass: IrClass = type.classOrNull!!.owner
|
||||
|
||||
override fun getField(symbol: IrSymbol): State? = null
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
|
||||
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
|
||||
import org.jetbrains.kotlin.ir.interpreter.isFunction
|
||||
import org.jetbrains.kotlin.ir.interpreter.isKFunction
|
||||
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
|
||||
@@ -22,18 +21,15 @@ import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal interface State {
|
||||
val fields: MutableList<Variable>
|
||||
val fields: MutableMap<IrSymbol, State>
|
||||
val irClass: IrClass
|
||||
|
||||
fun getField(symbol: IrSymbol): State? {
|
||||
return fields.firstOrNull { it.symbol == symbol }?.state
|
||||
return fields[symbol]
|
||||
}
|
||||
|
||||
fun setField(newVar: Variable) {
|
||||
when (val oldState = fields.firstOrNull { it.symbol == newVar.symbol }) {
|
||||
null -> fields.add(newVar) // newVar isn't present in value list
|
||||
else -> fields[fields.indexOf(oldState)].state = newVar.state // newVar already present
|
||||
}
|
||||
fun setField(symbol: IrSymbol, state: State) {
|
||||
fields[symbol] = state
|
||||
}
|
||||
|
||||
fun getIrFunctionByIrCall(expression: IrCall): IrFunction?
|
||||
@@ -103,9 +99,8 @@ internal fun State?.mustBeHandledAsReflection(call: IrCall): Boolean {
|
||||
|
||||
internal fun State.hasTheSameFieldsWith(other: State): Boolean {
|
||||
if (this.fields.size != other.fields.size) return false
|
||||
for (i in 0 until this.fields.size) {
|
||||
val firstState = this.fields[i].state
|
||||
val secondState = other.fields[i].state
|
||||
// TODO prove that this will always work or find better solution
|
||||
this.fields.values.zip(other.fields.values).forEach { (firstState, secondState) ->
|
||||
when {
|
||||
firstState is Primitive<*> && secondState is Primitive<*> -> if (firstState.value != secondState.value) return false
|
||||
else -> if (firstState !== secondState) return false
|
||||
|
||||
+2
-1
@@ -6,7 +6,8 @@
|
||||
package org.jetbrains.kotlin.ir.interpreter.state
|
||||
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
|
||||
internal interface StateWithClosure {
|
||||
val upValues: MutableList<Variable>
|
||||
val upValues: MutableMap<IrSymbol, Variable>
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.*
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
@@ -23,10 +23,10 @@ import kotlin.collections.HashMap
|
||||
import kotlin.collections.LinkedHashMap
|
||||
|
||||
internal class Wrapper(val value: Any, override val irClass: IrClass, environment: IrInterpreterEnvironment) : Complex {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
override val fields: MutableMap<IrSymbol, State> = mutableMapOf()
|
||||
|
||||
override var superWrapperClass: Wrapper? = null
|
||||
override var outerClass: Variable? = null
|
||||
override var outerClass: Pair<IrSymbol, State>? = null
|
||||
|
||||
private val receiverClass = irClass.defaultType.getClass(true)
|
||||
|
||||
|
||||
+11
-7
@@ -15,16 +15,18 @@ 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.State
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.StateWithClosure
|
||||
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.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import kotlin.reflect.KParameter
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.KTypeParameter
|
||||
@@ -33,9 +35,9 @@ internal class KFunctionState(
|
||||
val irFunction: IrFunction,
|
||||
override val irClass: IrClass,
|
||||
environment: IrInterpreterEnvironment,
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
override val fields: MutableMap<IrSymbol, State> = mutableMapOf()
|
||||
) : ReflectionState(), StateWithClosure {
|
||||
override val upValues: MutableList<Variable> = mutableListOf()
|
||||
override val upValues: MutableMap<IrSymbol, Variable> = mutableMapOf()
|
||||
|
||||
var funInterface: IrType? = null
|
||||
set(value) {
|
||||
@@ -123,16 +125,18 @@ internal class KFunctionState(
|
||||
constructor(
|
||||
functionReference: IrFunctionReference,
|
||||
environment: IrInterpreterEnvironment,
|
||||
dispatchReceiver: Variable?,
|
||||
extensionReceiver: Variable?
|
||||
dispatchReceiver: Pair<IrSymbol, State>?,
|
||||
extensionReceiver: Pair<IrSymbol, State>?
|
||||
) : this(
|
||||
functionReference.symbol.owner,
|
||||
functionReference.type.classOrNull!!.owner,
|
||||
environment,
|
||||
listOfNotNull(dispatchReceiver, extensionReceiver).toMutableList()
|
||||
listOfNotNull(dispatchReceiver, extensionReceiver).toMap().toMutableMap()
|
||||
) {
|
||||
dispatchReceiver?.let { (symbol, state) -> setField(symbol, state) }
|
||||
extensionReceiver?.let { (symbol, state) -> setField(symbol, state) }
|
||||
// receivers are used in comparison of two functions in KFunctionProxy
|
||||
upValues += fields
|
||||
upValues += fields.map { it.key to Variable(it.value) }
|
||||
}
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
|
||||
|
||||
+2
-7
@@ -5,25 +5,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.interpreter.state.reflection
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||
import org.jetbrains.kotlin.ir.interpreter.state.State
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
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.types.typeOrNull
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import kotlin.math.min
|
||||
|
||||
internal abstract class ReflectionState : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
override val fields: MutableMap<IrSymbol, State> = mutableMapOf()
|
||||
|
||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user