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