From 492b8acf93d69b8703c4eb99371fb506401208dc Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Tue, 10 Aug 2021 15:27:15 +0300 Subject: [PATCH] Rename some methods in interpreter's stack to make their purpose clearer --- .../kotlin/ir/interpreter/CallInterceptor.kt | 15 +- .../ir/interpreter/InstructionsUnfolder.kt | 150 +++++++++--------- .../kotlin/ir/interpreter/IrInterpreter.kt | 78 ++++----- .../jetbrains/kotlin/ir/interpreter/Utils.kt | 4 +- .../intrinsics/IntrinsicImplementations.kt | 42 ++--- .../ir/interpreter/proxy/CommonProxy.kt | 2 +- .../kotlin/ir/interpreter/stack/CallStack.kt | 83 ++++------ .../kotlin/ir/interpreter/stack/Frame.kt | 55 ++----- .../kotlin/ir/interpreter/state/Complex.kt | 2 +- 9 files changed, 190 insertions(+), 241 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt index 0cc17b9fe02..94ac16e5e90 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt @@ -19,7 +19,6 @@ 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.state.* -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.isArray @@ -51,7 +50,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : override fun interceptProxy(irFunction: IrFunction, valueArguments: List, expectedResultClass: Class<*>): Any? { val irCall = irFunction.createCall() return interpreter.withNewCallStack(irCall) { - this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall)) + this@withNewCallStack.environment.callStack.pushInstruction(SimpleInstruction(irCall)) valueArguments.forEach { this@withNewCallStack.environment.callStack.pushState(it) } }.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass) } @@ -73,7 +72,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : } override fun interceptConstructor(constructorCall: IrFunctionAccessExpression, args: List, defaultAction: () -> Unit) { - val receiver = callStack.getState(constructorCall.getThisReceiver()) + val receiver = callStack.loadState(constructorCall.getThisReceiver()) val irConstructor = constructorCall.symbol.owner val irClass = irConstructor.parentAsClass when { @@ -81,7 +80,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : Wrapper.getConstructorMethod(irConstructor).invokeMethod(irConstructor, args) when { irClass.isSubclassOfThrowable() -> (receiver as ExceptionState).copyFieldsFrom(callStack.popState() as Wrapper) - constructorCall is IrConstructorCall -> callStack.setState(constructorCall.getThisReceiver(), callStack.popState()) + constructorCall is IrConstructorCall -> callStack.rewriteState(constructorCall.getThisReceiver(), callStack.popState()) else -> (receiver as Complex).superWrapperClass = callStack.popState() as Wrapper } } @@ -140,7 +139,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : private fun handleIntrinsicMethods(irFunction: IrFunction): Boolean { val instructions = IntrinsicEvaluator.unwindInstructions(irFunction, environment) ?: return false - instructions.forEach { callStack.addInstruction(it) } + instructions.forEach { callStack.pushInstruction(it) } return true } @@ -185,7 +184,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : constructorCall.putValueArgument(index, primitive.value.toIrConst(constructorValueParameters[index].owner.type)) } - callStack.addInstruction(CompoundInstruction(constructorCall)) + callStack.pushInstruction(CompoundInstruction(constructorCall)) } private fun Any?.getType(defaultType: IrType): IrType { @@ -207,7 +206,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : private fun IrFunction.trySubstituteFunctionBody(): IrElement? { val signature = this.symbol.signature ?: return null this.body = bodyMap[signature] ?: return null - callStack.addInstruction(CompoundInstruction(this)) + callStack.pushInstruction(CompoundInstruction(this)) return body } @@ -215,6 +214,6 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : private fun IrFunction.tryCalculateLazyConst(): IrExpression? { if (this !is IrSimpleFunction) return null val expression = this.correspondingPropertySymbol?.owner?.backingField?.initializer?.expression - return expression?.apply { callStack.addInstruction(CompoundInstruction(this)) } + return expression?.apply { callStack.pushInstruction(CompoundInstruction(this)) } } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt index ca808758894..876a73299c9 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt @@ -25,8 +25,8 @@ internal fun IrExpression.handleAndDropResult(callStack: CallStack, dropOnlyUnit val dropResult = fun() { if (!dropOnlyUnit && !this.type.isUnit() || callStack.peekState().isUnit()) callStack.popState() } - callStack.addInstruction(CustomInstruction(dropResult)) - callStack.addInstruction(CompoundInstruction(this)) + callStack.pushInstruction(CustomInstruction(dropResult)) + callStack.pushInstruction(CompoundInstruction(this)) } internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEnvironment) { @@ -45,11 +45,11 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn is IrBlock -> unfoldBlock(element, callStack) is IrReturn -> unfoldReturn(element, callStack) is IrSetField -> unfoldSetField(element, callStack) - is IrGetField -> callStack.addInstruction(SimpleInstruction(element)) + is IrGetField -> callStack.pushInstruction(SimpleInstruction(element)) is IrGetValue -> unfoldGetValue(element, environment) is IrGetObjectValue -> unfoldGetObjectValue(element, environment) is IrGetEnumValue -> unfoldGetEnumValue(element, environment) - is IrConst<*> -> callStack.addInstruction(SimpleInstruction(element)) + is IrConst<*> -> callStack.pushInstruction(SimpleInstruction(element)) is IrVariable -> unfoldVariable(element, callStack) is IrSetValue -> unfoldSetValue(element, callStack) is IrTypeOperatorCall -> unfoldTypeOperatorCall(element, callStack) @@ -60,12 +60,12 @@ internal fun unfoldInstruction(element: IrElement?, environment: IrInterpreterEn is IrBreak -> unfoldBreak(element, callStack) is IrContinue -> unfoldContinue(element, callStack) is IrVararg -> unfoldVararg(element, callStack) - is IrSpreadElement -> callStack.addInstruction(CompoundInstruction(element.expression)) + is IrSpreadElement -> callStack.pushInstruction(CompoundInstruction(element.expression)) is IrTry -> unfoldTry(element, callStack) is IrCatch -> unfoldCatch(element, callStack) is IrThrow -> unfoldThrow(element, callStack) is IrStringConcatenation -> unfoldStringConcatenation(element, environment) - is IrFunctionExpression -> callStack.addInstruction(SimpleInstruction(element)) + is IrFunctionExpression -> callStack.pushInstruction(SimpleInstruction(element)) is IrFunctionReference -> unfoldFunctionReference(element, callStack) is IrPropertyReference -> unfoldPropertyReference(element, callStack) is IrClassReference -> unfoldClassReference(element, callStack) @@ -83,7 +83,7 @@ private fun unfoldFunction(function: IrSimpleFunction, environment: IrInterprete } // SimpleInstruction with function is added in IrCall // It will serve as endpoint for all possible calls, there we drop frame and copy result to new one - function.body?.let { environment.callStack.addInstruction(CompoundInstruction(it)) } + function.body?.let { environment.callStack.pushInstruction(CompoundInstruction(it)) } ?: throw InterpreterError("Ir function must be with body") } @@ -92,18 +92,18 @@ private fun unfoldConstructor(constructor: IrConstructor, callStack: CallStack) "kotlin.Enum.", "kotlin.Throwable." -> { val irClass = constructor.parentAsClass val receiverSymbol = irClass.thisReceiver!!.symbol - val receiverState = callStack.getState(receiverSymbol) + val receiverState = callStack.loadState(receiverSymbol) irClass.declarations.filterIsInstance().forEach { property -> 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.loadState(it.symbol) } ?: Primitive.nullStateOfType(property.getter!!.returnType) receiverState.setField(property.symbol, state) } } else -> { // SimpleInstruction with function is added in constructor call // It will serve as endpoint for all possible constructor calls, there we drop frame and return object - callStack.addInstruction(CompoundInstruction(constructor.body!!)) + callStack.pushInstruction(CompoundInstruction(constructor.body!!)) } } } @@ -114,7 +114,7 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, enviro if (hasDefaults) { environment.getCachedFunction(expression.symbol, fromDelegatingCall = expression is IrDelegatingConstructorCall)?.let { val callToDefault = it.owner.createCall().apply { environment.irBuiltIns.copyArgs(expression, this) } - callStack.addInstruction(CompoundInstruction(callToDefault)) + callStack.pushInstruction(CompoundInstruction(callToDefault)) return } @@ -140,7 +140,7 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, enviro actualParameters[index] = if (copiedParameter.defaultValue != null || copiedParameter.isVararg) { copiedParameter.type = copiedParameter.type.makeNullable() // make nullable type to keep consistency; parameter can be null if it is missing val irGetParameter = copiedParameter.createGetValue() - // if parameter is vararg and it is missing then create constructor call for empty array + // if parameter is vararg and it is missing, then create constructor call for empty array val defaultInitializer = originalParameter.getDefaultWithActualParameters(this@apply, actualParameters) ?: environment.irBuiltIns.emptyArrayConstructor(expression.getVarargType(index)!!.getTypeIfReified(callStack)) @@ -162,14 +162,14 @@ private fun unfoldValueParameters(expression: IrFunctionAccessExpression, enviro val callToDefault = environment.setCachedFunction( expression.symbol, fromDelegatingCall = expression is IrDelegatingConstructorCall, newFunction = defaultFun.symbol ).owner.createCall().apply { environment.irBuiltIns.copyArgs(expression, this) } - callStack.addInstruction(CompoundInstruction(callToDefault)) + callStack.pushInstruction(CompoundInstruction(callToDefault)) } else { val irFunction = expression.symbol.owner - callStack.addInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(SimpleInstruction(expression)) fun IrValueParameter.schedule(arg: IrExpression?) { - callStack.addInstruction(SimpleInstruction(this)) - callStack.addInstruction(CompoundInstruction(arg)) + callStack.pushInstruction(SimpleInstruction(this)) + callStack.pushInstruction(CompoundInstruction(arg)) } (expression.valueArgumentsCount - 1 downTo 0).forEach { irFunction.valueParameters[it].schedule(expression.getValueArgument(it)) } expression.extensionReceiver?.let { irFunction.extensionReceiverParameter!!.schedule(it) } @@ -183,25 +183,25 @@ private fun unfoldInstanceInitializerCall(instanceInitializerCall: IrInstanceIni toInitialize.reversed().forEach { when { - it is IrAnonymousInitializer -> callStack.addInstruction(CompoundInstruction(it.body)) - it is IrProperty && it.backingField?.initializer?.expression != null -> callStack.addInstruction(CompoundInstruction(it.backingField)) + it is IrAnonymousInitializer -> callStack.pushInstruction(CompoundInstruction(it.body)) + it is IrProperty && it.backingField?.initializer?.expression != null -> callStack.pushInstruction(CompoundInstruction(it.backingField)) } } } private fun unfoldField(field: IrField, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(field)) - callStack.addInstruction(CompoundInstruction(field.initializer?.expression)) + callStack.pushInstruction(SimpleInstruction(field)) + callStack.pushInstruction(CompoundInstruction(field.initializer?.expression)) } private fun unfoldBody(body: IrBody, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(body)) + callStack.pushInstruction(SimpleInstruction(body)) unfoldStatements(body.statements, callStack) } private fun unfoldBlock(block: IrBlock, callStack: CallStack) { callStack.newSubFrame(block) - callStack.addInstruction(SimpleInstruction(block)) + callStack.pushInstruction(SimpleInstruction(block)) unfoldStatements(block.statements, callStack) } @@ -214,24 +214,24 @@ private fun unfoldStatements(statements: List, callStack: CallStack is IrFunction -> if (!statement.isLocal) TODO("Only local functions are supported") is IrExpression -> when { - i.isLastIndex() -> callStack.addInstruction(CompoundInstruction(statement)) + i.isLastIndex() -> callStack.pushInstruction(CompoundInstruction(statement)) else -> statement.handleAndDropResult(callStack, dropOnlyUnit = true) } - else -> callStack.addInstruction(CompoundInstruction(statement)) + else -> callStack.pushInstruction(CompoundInstruction(statement)) } } } private fun unfoldReturn(expression: IrReturn, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(expression)) - callStack.addInstruction(CompoundInstruction(expression.value)) + callStack.pushInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(CompoundInstruction(expression.value)) } private fun unfoldSetField(expression: IrSetField, callStack: CallStack) { verify(!expression.accessesTopLevelOrObjectField()) { "Cannot interpret set method on top level properties" } - callStack.addInstruction(SimpleInstruction(expression)) - callStack.addInstruction(CompoundInstruction(expression.value)) + callStack.pushInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(CompoundInstruction(expression.value)) } private fun unfoldGetValue(expression: IrGetValue, environment: IrInterpreterEnvironment) { @@ -242,7 +242,7 @@ private fun unfoldGetValue(expression: IrGetValue, environment: IrInterpreterEnv val irGetObject = expectedClass.createGetObject() return unfoldGetObjectValue(irGetObject, environment) } - environment.callStack.pushState(environment.callStack.getState(expression.symbol)) + environment.callStack.pushState(environment.callStack.loadState(expression.symbol)) } private fun unfoldGetObjectValue(expression: IrGetObjectValue, environment: IrInterpreterEnvironment) { @@ -250,64 +250,64 @@ private fun unfoldGetObjectValue(expression: IrGetObjectValue, environment: IrIn val objectClass = expression.symbol.owner environment.mapOfObjects[objectClass.symbol]?.let { return callStack.pushState(it) } - callStack.addInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(SimpleInstruction(expression)) } private fun unfoldGetEnumValue(expression: IrGetEnumValue, environment: IrInterpreterEnvironment) { val callStack = environment.callStack environment.mapOfEnums[expression.symbol]?.let { return callStack.pushState(it) } - callStack.addInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(SimpleInstruction(expression)) val enumEntry = expression.symbol.owner val enumClass = enumEntry.symbol.owner.parentAsClass enumClass.declarations.filterIsInstance().forEach { - callStack.addInstruction(SimpleInstruction(it)) + callStack.pushInstruction(SimpleInstruction(it)) } } private fun unfoldVariable(variable: IrVariable, callStack: CallStack) { when (variable.initializer) { - null -> callStack.addVariable(variable.symbol, null) + null -> callStack.storeState(variable.symbol, null) else -> { - callStack.addInstruction(SimpleInstruction(variable)) - callStack.addInstruction(CompoundInstruction(variable.initializer!!)) + callStack.pushInstruction(SimpleInstruction(variable)) + callStack.pushInstruction(CompoundInstruction(variable.initializer!!)) } } } private fun unfoldSetValue(expression: IrSetValue, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(expression)) - callStack.addInstruction(CompoundInstruction(expression.value)) + callStack.pushInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(CompoundInstruction(expression.value)) } private fun unfoldTypeOperatorCall(element: IrTypeOperatorCall, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(element)) - callStack.addInstruction(CompoundInstruction(element.argument)) + callStack.pushInstruction(SimpleInstruction(element)) + callStack.pushInstruction(CompoundInstruction(element.argument)) } private fun unfoldBranch(branch: IrBranch, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(branch)) - callStack.addInstruction(CompoundInstruction(branch.condition)) + callStack.pushInstruction(SimpleInstruction(branch)) + callStack.pushInstruction(CompoundInstruction(branch.condition)) } private fun unfoldWhileLoop(loop: IrWhileLoop, callStack: CallStack) { callStack.newSubFrame(loop) - callStack.addInstruction(SimpleInstruction(loop)) - callStack.addInstruction(CompoundInstruction(loop.condition)) + callStack.pushInstruction(SimpleInstruction(loop)) + callStack.pushInstruction(CompoundInstruction(loop.condition)) } private fun unfoldDoWhileLoop(loop: IrDoWhileLoop, callStack: CallStack) { callStack.newSubFrame(loop) - callStack.addInstruction(SimpleInstruction(loop)) - callStack.addInstruction(CompoundInstruction(loop.condition)) - callStack.addInstruction(CompoundInstruction(loop.body)) + callStack.pushInstruction(SimpleInstruction(loop)) + callStack.pushInstruction(CompoundInstruction(loop.condition)) + callStack.pushInstruction(CompoundInstruction(loop.body)) } private fun unfoldWhen(element: IrWhen, callStack: CallStack) { // new sub frame to drop it after callStack.newSubFrame(element) - callStack.addInstruction(SimpleInstruction(element)) - element.branches.reversed().forEach { callStack.addInstruction(CompoundInstruction(it)) } + callStack.pushInstruction(SimpleInstruction(element)) + element.branches.reversed().forEach { callStack.pushInstruction(CompoundInstruction(it)) } } private fun unfoldContinue(element: IrContinue, callStack: CallStack) { @@ -319,14 +319,14 @@ private fun unfoldBreak(element: IrBreak, callStack: CallStack) { } private fun unfoldVararg(element: IrVararg, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(element)) - element.elements.reversed().forEach { callStack.addInstruction(CompoundInstruction(it)) } + callStack.pushInstruction(SimpleInstruction(element)) + element.elements.reversed().forEach { callStack.pushInstruction(CompoundInstruction(it)) } } private fun unfoldTry(element: IrTry, callStack: CallStack) { callStack.newSubFrame(element) - callStack.addInstruction(SimpleInstruction(element)) - callStack.addInstruction(CompoundInstruction(element.tryResult)) + callStack.pushInstruction(SimpleInstruction(element)) + callStack.pushInstruction(CompoundInstruction(element.tryResult)) } private fun unfoldCatch(element: IrCatch, callStack: CallStack) { @@ -336,20 +336,20 @@ 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(element.catchParameter.symbol, exceptionState) - callStack.addInstruction(SimpleInstruction(frameOwner)) - callStack.addInstruction(CompoundInstruction(element.result)) + callStack.storeState(element.catchParameter.symbol, exceptionState) + callStack.pushInstruction(SimpleInstruction(frameOwner)) + callStack.pushInstruction(CompoundInstruction(element.result)) } } private fun unfoldThrow(expression: IrThrow, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(expression)) - callStack.addInstruction(CompoundInstruction(expression.value)) + callStack.pushInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(CompoundInstruction(expression.value)) } private fun unfoldStringConcatenation(expression: IrStringConcatenation, environment: IrInterpreterEnvironment) { val callStack = environment.callStack - callStack.addInstruction(SimpleInstruction(expression)) + callStack.pushInstruction(SimpleInstruction(expression)) // this callback is used to check the need for an explicit toString call val explicitToStringCheck = fun() { @@ -368,52 +368,52 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ return callStack.pushState(environment.convertToState(result, environment.irBuiltIns.stringType)) } val toStringCall = state.createToStringIrCall() - callStack.addInstruction(SimpleInstruction(toStringCall)) + callStack.pushInstruction(SimpleInstruction(toStringCall)) callStack.pushState(state) } } } expression.arguments.reversed().forEach { - callStack.addInstruction(CustomInstruction(explicitToStringCheck)) - callStack.addInstruction(CompoundInstruction(it)) + callStack.pushInstruction(CustomInstruction(explicitToStringCheck)) + callStack.pushInstruction(CompoundInstruction(it)) } } private fun unfoldComposite(element: IrComposite, callStack: CallStack) { when (element.origin) { IrStatementOrigin.DESTRUCTURING_DECLARATION, IrStatementOrigin.DO_WHILE_LOOP, null -> // is null for body of do while loop - element.statements.reversed().forEach { callStack.addInstruction(CompoundInstruction(it)) } + element.statements.reversed().forEach { callStack.pushInstruction(CompoundInstruction(it)) } else -> TODO("${element.origin} not implemented") } } private fun unfoldFunctionReference(reference: IrFunctionReference, callStack: CallStack) { val function = reference.symbol.owner - callStack.addInstruction(SimpleInstruction(reference)) + callStack.pushInstruction(SimpleInstruction(reference)) - reference.dispatchReceiver?.let { callStack.addInstruction(SimpleInstruction(function.dispatchReceiverParameter!!)) } - reference.extensionReceiver?.let { callStack.addInstruction(SimpleInstruction(function.extensionReceiverParameter!!)) } + reference.dispatchReceiver?.let { callStack.pushInstruction(SimpleInstruction(function.dispatchReceiverParameter!!)) } + reference.extensionReceiver?.let { callStack.pushInstruction(SimpleInstruction(function.extensionReceiverParameter!!)) } - reference.extensionReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) } - reference.dispatchReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) } + reference.extensionReceiver?.let { callStack.pushInstruction(CompoundInstruction(it)) } + reference.dispatchReceiver?.let { callStack.pushInstruction(CompoundInstruction(it)) } } private fun unfoldPropertyReference(propertyReference: IrPropertyReference, callStack: CallStack) { val getter = propertyReference.getter!!.owner - callStack.addInstruction(SimpleInstruction(propertyReference)) + callStack.pushInstruction(SimpleInstruction(propertyReference)) - propertyReference.dispatchReceiver?.let { callStack.addInstruction(SimpleInstruction(getter.dispatchReceiverParameter!!)) } - propertyReference.extensionReceiver?.let { callStack.addInstruction(SimpleInstruction(getter.extensionReceiverParameter!!)) } + propertyReference.dispatchReceiver?.let { callStack.pushInstruction(SimpleInstruction(getter.dispatchReceiverParameter!!)) } + propertyReference.extensionReceiver?.let { callStack.pushInstruction(SimpleInstruction(getter.extensionReceiverParameter!!)) } - propertyReference.extensionReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) } - propertyReference.dispatchReceiver?.let { callStack.addInstruction(CompoundInstruction(it)) } + propertyReference.extensionReceiver?.let { callStack.pushInstruction(CompoundInstruction(it)) } + propertyReference.dispatchReceiver?.let { callStack.pushInstruction(CompoundInstruction(it)) } } private fun unfoldClassReference(classReference: IrClassReference, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(classReference)) + callStack.pushInstruction(SimpleInstruction(classReference)) } private fun unfoldGetClass(element: IrGetClass, callStack: CallStack) { - callStack.addInstruction(SimpleInstruction(element)) - callStack.addInstruction(CompoundInstruction(element.argument)) + callStack.pushInstruction(SimpleInstruction(element)) + callStack.pushInstruction(CompoundInstruction(element.argument)) } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index 08b1a043d91..5041e496dc3 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -65,7 +65,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal fun interpret(expression: IrExpression, file: IrFile? = null): IrExpression { commandCount = 0 callStack.newFrame(expression, file) - callStack.addInstruction(CompoundInstruction(expression)) + callStack.pushInstruction(CompoundInstruction(expression)) while (!callStack.hasNoInstructions()) { callStack.popInstruction().handle() @@ -106,8 +106,8 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal is IrGetEnumValue -> interpretGetEnumValue(element) is IrEnumEntry -> interpretEnumEntry(element) is IrConst<*> -> interpretConst(element) - is IrVariable -> callStack.addVariable(element.symbol, callStack.popState()) - is IrSetValue -> callStack.setState(element.symbol, callStack.popState()) + is IrVariable -> callStack.storeState(element.symbol, callStack.popState()) + is IrSetValue -> callStack.rewriteState(element.symbol, callStack.popState()) is IrTypeOperatorCall -> interpretTypeOperatorCall(element) is IrBranch -> interpretBranch(element) is IrWhileLoop -> interpretWhile(element) @@ -174,7 +174,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val reifiedTypeArguments = environment.loadReifiedTypeArguments(call) callStack.newFrame(irFunction) - callStack.addInstruction(SimpleInstruction(irFunction)) + callStack.pushInstruction(SimpleInstruction(irFunction)) // 4. load up values onto stack; do it at first to set low priority of these variables if (dispatchReceiver is StateWithClosure) callStack.loadUpValues(dispatchReceiver) @@ -182,27 +182,27 @@ 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(it, dispatchReceiver!!) } - irFunction.getExtensionReceiver()?.let { callStack.addVariable(it, extensionReceiver ?: callStack.getState(it)) } - irFunction.valueParameters.forEachIndexed { i, param -> callStack.addVariable(param.symbol, valueArguments[i]) } + irFunction.getDispatchReceiver()?.let { callStack.storeState(it, dispatchReceiver!!) } + irFunction.getExtensionReceiver()?.let { callStack.storeState(it, extensionReceiver ?: callStack.loadState(it)) } + irFunction.valueParameters.forEachIndexed { i, param -> callStack.storeState(param.symbol, valueArguments[i]) } // `call.type` is used in check cast and emptyArray - callStack.addVariable(irFunction.symbol, KTypeState(call.type, environment.kTypeClass.owner)) + callStack.storeState(irFunction.symbol, KTypeState(call.type, environment.kTypeClass.owner)) // 6. store reified type parameters - reifiedTypeArguments.forEach { callStack.addVariable(it.key, it.value) } + reifiedTypeArguments.forEach { callStack.storeState(it.key, it.value) } // 7. load outer class object if (dispatchReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) dispatchReceiver.loadOuterClassesInto(callStack) callInterceptor.interceptCall(call, irFunction, args) { - callStack.addInstruction(CompoundInstruction(irFunction)) + callStack.pushInstruction(CompoundInstruction(irFunction)) } } private fun interpretField(field: IrField) { val irClass = field.parentAsClass val receiver = irClass.thisReceiver!!.symbol - val receiverState = callStack.getState(receiver) + val receiverState = callStack.loadState(receiver) receiverState.setField(field.correspondingPropertySymbol!!, callStack.popState()) } @@ -219,7 +219,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal @Suppress("UNUSED_PARAMETER") private fun interpretConstructor(constructor: IrConstructor) { - callStack.pushState(callStack.getState(constructor.parentAsClass.thisReceiver!!.symbol)) + callStack.pushState(callStack.loadState(constructor.parentAsClass.thisReceiver!!.symbol)) callStack.dropFrameAndCopyResult() } @@ -231,7 +231,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal // this check is used to be sure that object will be created once val objectState = when (constructorCall) { - !is IrConstructorCall -> callStack.getState(constructorCall.getThisReceiver()) + !is IrConstructorCall -> callStack.loadState(constructorCall.getThisReceiver()) else -> (if (irClass.isSubclassOfThrowable()) ExceptionState(irClass, callStack.getStackTrace()) else Common(irClass)) .apply { // must set object's state here, before actual initialization, to avoid cyclic evaluation @@ -244,12 +244,12 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val returnType = constructorCall.type.getTypeIfReified(callStack) callStack.newFrame(constructor) - callStack.addInstruction(SimpleInstruction(constructor)) + callStack.pushInstruction(SimpleInstruction(constructor)) if (irClass.isLocal) callStack.loadUpValues(objectState as StateWithClosure) - 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)) + callStack.storeState(constructorCall.getThisReceiver(), objectState) + constructor.valueParameters.forEachIndexed { i, param -> callStack.storeState(param.symbol, valueArguments[i]) } + callStack.storeState(constructor.symbol, KTypeState(returnType, environment.kTypeClass.owner)) val superReceiver = when (val irStatement = constructor.body?.statements?.get(0)) { null -> null // for jvm @@ -258,7 +258,7 @@ 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(it, objectState) } + superReceiver?.let { callStack.storeState(it, objectState) } if (outerClass != null) { val outerClassSymbolToState = irClass.parentAsClass.thisReceiver!!.symbol to outerClass @@ -267,14 +267,14 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal // 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(receiverSymbol, outerClass) + callStack.storeState(receiverSymbol, outerClass) // used to get information from outer class objectState.loadOuterClassesInto(callStack, constructorCall.getThisReceiver()) } } callInterceptor.interceptConstructor(constructorCall, valueArguments) { - callStack.addInstruction(CompoundInstruction(constructor)) + callStack.pushInstruction(CompoundInstruction(constructor)) } } @@ -303,7 +303,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol) constructorCall.putValueArgument(0, expression.value.toIrConst(signedType)) - return callStack.addInstruction(CompoundInstruction(constructorCall)) + return callStack.pushInstruction(CompoundInstruction(constructorCall)) } callStack.pushState(expression.toPrimitive()) } @@ -317,9 +317,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal callStack.dropSubFrame() if (result) { callStack.newSubFrame(loop) - callStack.addInstruction(SimpleInstruction(loop)) - callStack.addInstruction(CompoundInstruction(loop.condition)) - callStack.addInstruction(CompoundInstruction(loop.body)) + callStack.pushInstruction(SimpleInstruction(loop)) + callStack.pushInstruction(CompoundInstruction(loop.condition)) + callStack.pushInstruction(CompoundInstruction(loop.body)) } } @@ -328,9 +328,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal callStack.dropSubFrame() if (result) { callStack.newSubFrame(loop) - callStack.addInstruction(SimpleInstruction(loop)) - callStack.addInstruction(CompoundInstruction(loop.condition)) - callStack.addInstruction(CompoundInstruction(loop.body)) + callStack.pushInstruction(SimpleInstruction(loop)) + callStack.pushInstruction(CompoundInstruction(loop.condition)) + callStack.pushInstruction(CompoundInstruction(loop.body)) } } @@ -338,14 +338,14 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val result = callStack.popState().asBoolean() if (result) { callStack.dropSubFrame() - callStack.addInstruction(CompoundInstruction(branch.result)) + callStack.pushInstruction(CompoundInstruction(branch.result)) } } private fun interpretSetField(expression: IrSetField) { val receiver = (expression.receiver as IrDeclarationReference).symbol val propertySymbol = expression.symbol.owner.correspondingPropertySymbol!! - callStack.getState(receiver).apply { this.setField(propertySymbol, callStack.popState()) } + callStack.loadState(receiver).apply { this.setField(propertySymbol, callStack.popState()) } } private fun interpretGetField(expression: IrGetField) { @@ -355,12 +355,12 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal field.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && field.isStatic -> { // for java static variables when (val initializerExpression = field.initializer?.expression) { - is IrConst<*> -> callStack.addInstruction(SimpleInstruction(initializerExpression)) + is IrConst<*> -> callStack.pushInstruction(SimpleInstruction(initializerExpression)) else -> callInterceptor.interceptJavaStaticField(expression) } } field.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD && field.correspondingPropertySymbol?.owner?.isConst == true -> { - callStack.addInstruction(CompoundInstruction(field.initializer?.expression)) + callStack.pushInstruction(CompoundInstruction(field.initializer?.expression)) } expression.accessesTopLevelOrObjectField() -> { val propertyOwner = field.correspondingPropertySymbol?.owner @@ -368,10 +368,10 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal propertyOwner?.backingField?.initializer?.expression is IrConst<*> || propertyOwner?.parentClassOrNull?.hasAnnotation(compileTimeAnnotation) == true // check if object is marked as compile time verify(isConst) { "Cannot interpret get method on top level non const properties" } - callStack.addInstruction(CompoundInstruction(field.initializer?.expression)) + callStack.pushInstruction(CompoundInstruction(field.initializer?.expression)) } else -> { - val result = callStack.getState(receiver!!).getField(field.correspondingPropertySymbol!!) + val result = callStack.loadState(receiver!!).getField(field.correspondingPropertySymbol!!) callStack.pushState(result!!) } } @@ -391,7 +391,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal val constructor = objectClass.constructors.first() val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol) - callStack.addInstruction(CompoundInstruction(constructorCall)) + callStack.pushInstruction(CompoundInstruction(constructorCall)) } } @@ -427,9 +427,9 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal environment.mapOfEnums[enumEntry.symbol] = enumClassObject callStack.newSubFrame(enumEntry) - callStack.addInstruction(CustomInstruction(cleanEnumSuperCall)) - callStack.addInstruction(CompoundInstruction(enumInitializer)) - callStack.addVariable(enumConstructorCall.getThisReceiver(), enumClassObject) + callStack.pushInstruction(CustomInstruction(cleanEnumSuperCall)) + callStack.pushInstruction(CompoundInstruction(enumInitializer)) + callStack.storeState(enumConstructorCall.getThisReceiver(), enumClassObject) } } @@ -563,7 +563,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal callStack.pushState(possibleException) callStack.dropFramesUntilTryCatch() } - callStack.addInstruction(CustomInstruction(checkUnhandledException)) + callStack.pushInstruction(CustomInstruction(checkUnhandledException)) } element.finallyExpression?.handleAndDropResult(callStack) } @@ -628,7 +628,7 @@ class IrInterpreter(internal val environment: IrInterpreterEnvironment, internal private fun interpretClassReference(classReference: IrClassReference) { when (classReference.symbol) { is IrTypeParameterSymbol -> { // reified - val kTypeState = callStack.getState(classReference.symbol) as KTypeState + val kTypeState = callStack.loadState(classReference.symbol) as KTypeState callStack.pushState(KClassState(kTypeState.irType.classOrNull!!.owner, classReference.type.classOrNull!!.owner)) } else -> callStack.pushState(KClassState(classReference)) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index 2ac39d39e20..c574804ac27 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt @@ -161,7 +161,7 @@ internal fun IrFunction?.checkCast(environment: IrInterpreterEnvironment): Boole if (actualType.classifierOrNull !is IrTypeParameterSymbol) return true // TODO expectedType can be missing for functions called as proxy - val expectedType = (environment.callStack.getState(this.symbol) as? KTypeState)?.irType ?: return true + val expectedType = (environment.callStack.loadState(this.symbol) as? KTypeState)?.irType ?: return true if (expectedType.classifierOrFail is IrTypeParameterSymbol) return true val actualState = environment.callStack.peekState() ?: return true @@ -242,7 +242,7 @@ internal fun IrValueParameter.getDefaultWithActualParameters( } internal fun IrType.getTypeIfReified(callStack: CallStack): IrType { - return this.getTypeIfReified { (callStack.getState(it) as KTypeState).irType } + return this.getTypeIfReified { (callStack.loadState(it) as KTypeState).irType } } internal fun IrType.getTypeIfReified(getType: (IrClassifierSymbol) -> IrType): IrType { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt index 3d78276872f..bb575dc641b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt @@ -43,7 +43,7 @@ internal object EmptyArray : IntrinsicBase() { } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { - val returnType = environment.callStack.getState(irFunction.symbol) as KTypeState + val returnType = environment.callStack.loadState(irFunction.symbol) as KTypeState environment.callStack.pushState(environment.convertToState(emptyArray(), returnType.irType)) } } @@ -58,7 +58,7 @@ internal object ArrayOf : IntrinsicBase() { override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { val elementsSymbol = irFunction.valueParameters.single().symbol - val varargVariable = environment.callStack.getState(elementsSymbol) + val varargVariable = environment.callStack.loadState(elementsSymbol) environment.callStack.pushState(varargVariable) } } @@ -69,9 +69,9 @@ internal object ArrayOfNulls : IntrinsicBase() { } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { - val size = environment.callStack.getState(irFunction.valueParameters.first().symbol).asInt() + val size = environment.callStack.loadState(irFunction.valueParameters.first().symbol).asInt() val array = arrayOfNulls(size) - val typeArgument = irFunction.typeParameters.map { environment.callStack.getState(it.symbol) }.single() as KTypeState + val typeArgument = irFunction.typeParameters.map { environment.callStack.loadState(it.symbol) }.single() as KTypeState val returnType = (irFunction.returnType as IrSimpleType).buildSimpleType { arguments = listOf(makeTypeProjection(typeArgument.irType, Variance.INVARIANT)) } @@ -88,7 +88,7 @@ internal object EnumValues : IntrinsicBase() { private fun getEnumClass(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrClass { return when (irFunction.fqName) { "kotlin.enumValues" -> { - val kType = environment.callStack.getState(irFunction.typeParameters.first().symbol) as KTypeState + val kType = environment.callStack.loadState(irFunction.typeParameters.first().symbol) as KTypeState kType.irType.classOrNull!!.owner } else -> irFunction.parent as IrClass @@ -118,7 +118,7 @@ internal object EnumValueOf : IntrinsicBase() { private fun getEnumClass(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrClass { return when (irFunction.fqName) { "kotlin.enumValueOf" -> { - val kType = environment.callStack.getState(irFunction.typeParameters.first().symbol) as KTypeState + val kType = environment.callStack.loadState(irFunction.typeParameters.first().symbol) as KTypeState kType.irType.classOrNull!!.owner } else -> irFunction.parent as IrClass @@ -127,7 +127,7 @@ internal object EnumValueOf : IntrinsicBase() { private fun getEnumEntryByName(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrEnumEntry? { val enumClass = getEnumClass(irFunction, environment) - val enumEntryName = environment.callStack.getState(irFunction.valueParameters.first().symbol).asString() + val enumEntryName = environment.callStack.loadState(irFunction.valueParameters.first().symbol).asString() val enumEntry = enumClass.declarations.filterIsInstance().singleOrNull { it.name.asString() == enumEntryName } if (enumEntry == null) { IllegalArgumentException("No enum constant ${enumClass.fqName}.$enumEntryName").handleUserException(environment) @@ -168,7 +168,7 @@ internal object EnumIntrinsics : IntrinsicBase() { override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { val callStack = environment.callStack - val enumEntry = callStack.getState(irFunction.dispatchReceiverParameter!!.symbol) + val enumEntry = callStack.loadState(irFunction.dispatchReceiverParameter!!.symbol) when (irFunction.name.asString()) { "", "" -> { val symbol = (irFunction as IrSimpleFunction).correspondingPropertySymbol!! @@ -176,13 +176,13 @@ internal object EnumIntrinsics : IntrinsicBase() { } "compareTo" -> { val ordinalSymbol = enumEntry.irClass.getOriginalPropertyByName("ordinal").symbol - val other = callStack.getState(irFunction.valueParameters.single().symbol) + val other = callStack.loadState(irFunction.valueParameters.single().symbol) val compareTo = enumEntry.getField(ordinalSymbol)!!.asInt().compareTo(other.getField(ordinalSymbol)!!.asInt()) callStack.pushState(environment.convertToState(compareTo, irFunction.returnType)) } // TODO "clone" -> throw exception "equals" -> { - val other = callStack.getState(irFunction.valueParameters.single().symbol) + val other = callStack.loadState(irFunction.valueParameters.single().symbol) callStack.pushState(environment.convertToState((enumEntry === other), irFunction.returnType)) } "hashCode" -> callStack.pushState(environment.convertToState(enumEntry.hashCode(), irFunction.returnType)) @@ -204,12 +204,12 @@ internal object JsPrimitives : IntrinsicBase() { override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { when (irFunction.fqName) { "kotlin.Long." -> { - val low = environment.callStack.getState(irFunction.valueParameters[0].symbol).asInt() - val high = environment.callStack.getState(irFunction.valueParameters[1].symbol).asInt() + val low = environment.callStack.loadState(irFunction.valueParameters[0].symbol).asInt() + val high = environment.callStack.loadState(irFunction.valueParameters[1].symbol).asInt() environment.callStack.pushState(environment.convertToState((high.toLong().shl(32) + low), irFunction.returnType)) } "kotlin.Char." -> { - val value = environment.callStack.getState(irFunction.valueParameters[0].symbol).asInt() + val value = environment.callStack.loadState(irFunction.valueParameters[0].symbol).asInt() environment.callStack.pushState(environment.convertToState(value.toChar(), irFunction.returnType)) } } @@ -231,14 +231,14 @@ internal object ArrayConstructor : IntrinsicBase() { val instructions = mutableListOf(customEvaluateInstruction(irFunction, environment)) val sizeSymbol = irFunction.valueParameters[0].symbol - val size = callStack.getState(sizeSymbol).asInt() + val size = callStack.loadState(sizeSymbol).asInt() val initSymbol = irFunction.valueParameters[1].symbol - val state = callStack.getState(initSymbol).let { + val state = callStack.loadState(initSymbol).let { (it as? KFunctionState) ?: (it as KPropertyState).convertGetterToKFunctionState(environment) } // if property was converted, then we must replace symbol in memory to get correct receiver later - callStack.setState(initSymbol, state) + callStack.rewriteState(initSymbol, state) for (i in size - 1 downTo 0) { val call = (state.invokeSymbol.owner as IrSimpleFunction).createCall() @@ -252,7 +252,7 @@ internal object ArrayConstructor : IntrinsicBase() { override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { val sizeDescriptor = irFunction.valueParameters[0].symbol - val size = environment.callStack.getState(sizeDescriptor).asInt() + val size = environment.callStack.loadState(sizeDescriptor).asInt() val arrayValue = MutableList(size) { when { irFunction.returnType.isCharArray() -> 0.toChar() @@ -274,7 +274,7 @@ internal object ArrayConstructor : IntrinsicBase() { } } - val type = (environment.callStack.getState(irFunction.symbol) as KTypeState).irType + val type = (environment.callStack.loadState(irFunction.symbol) as KTypeState).irType environment.callStack.pushState(arrayValue.toPrimitiveStateArray(type)) } } @@ -298,7 +298,7 @@ internal object AssertIntrinsic : IntrinsicBase() { if (irFunction.valueParameters.size == 1) return listOf(customEvaluateInstruction(irFunction, environment)) val lambdaParameter = irFunction.valueParameters.last() - val lambdaState = environment.callStack.getState(lambdaParameter.symbol) as KFunctionState + val lambdaState = environment.callStack.loadState(lambdaParameter.symbol) as KFunctionState val call = (lambdaState.invokeSymbol.owner as IrSimpleFunction).createCall() call.dispatchReceiver = lambdaParameter.createGetValue() @@ -306,7 +306,7 @@ internal object AssertIntrinsic : IntrinsicBase() { } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { - val value = environment.callStack.getState(irFunction.valueParameters.first().symbol).asBoolean() + val value = environment.callStack.loadState(irFunction.valueParameters.first().symbol).asBoolean() if (value) return when (irFunction.valueParameters.size) { 1 -> AssertionError("Assertion failed").handleUserException(environment) @@ -337,7 +337,7 @@ internal object DataClassArrayToString : IntrinsicBase() { } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { - val array = environment.callStack.getState(irFunction.valueParameters.single().symbol) as Primitive<*> + val array = environment.callStack.loadState(irFunction.valueParameters.single().symbol) as Primitive<*> environment.callStack.pushState(environment.convertToState(arrayToString(array.value), irFunction.returnType)) } } \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt index afa66036b9c..21513008ff0 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt @@ -25,7 +25,7 @@ internal class CommonProxy private constructor(override val state: Common, overr private fun IrFunction.wasAlreadyCalled(): Boolean { val anyParameter = this.getLastOverridden().dispatchReceiverParameter!!.symbol val callStack = callInterceptor.environment.callStack - if (callStack.containsVariable(anyParameter) && callStack.getState(anyParameter) === state) return true + if (callStack.containsStateInMemory(anyParameter) && callStack.loadState(anyParameter) === state) return true return this == callInterceptor.environment.callStack.currentFrameOwner } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/CallStack.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/CallStack.kt index e85e5941f66..870cdb1cda7 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/CallStack.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/CallStack.kt @@ -60,7 +60,7 @@ internal class CallStack { is IrTry -> { dropSubFrame() pushState(result) - addInstruction(SimpleInstruction(irReturn)) + pushInstruction(SimpleInstruction(irReturn)) frameOwner.finallyExpression?.handleAndDropResult(this) return } @@ -68,7 +68,7 @@ internal class CallStack { val tryBlock = currentFrame.dropInstructions()!!.element as IrTry// last instruction in `catch` block is `try` dropSubFrame() pushState(result) - addInstruction(SimpleInstruction(irReturn)) + pushInstruction(SimpleInstruction(irReturn)) tryBlock.finallyExpression?.handleAndDropResult(this) return } @@ -81,7 +81,7 @@ internal class CallStack { } currentFrame.dropInstructions() - addInstruction(SimpleInstruction(returnTarget)) + pushInstruction(SimpleInstruction(returnTarget)) if (returnTarget !is IrConstructor) pushState(result) } @@ -91,17 +91,17 @@ internal class CallStack { when (frameOwner) { is IrTry -> { currentFrame.removeSubFrameWithoutDataPropagation() - addInstruction(CompoundInstruction(breakOrContinue)) + pushInstruction(CompoundInstruction(breakOrContinue)) newSubFrame(frameOwner) // will be deleted when interpret 'try' - addInstruction(SimpleInstruction(frameOwner)) + pushInstruction(SimpleInstruction(frameOwner)) return } is IrCatch -> { val tryInstruction = currentFrame.dropInstructions()!! // last instruction in `catch` block is `try` currentFrame.removeSubFrameWithoutDataPropagation() - addInstruction(CompoundInstruction(breakOrContinue)) + pushInstruction(CompoundInstruction(breakOrContinue)) newSubFrame(tryInstruction.element!!) // will be deleted when interpret 'try' - addInstruction(tryInstruction) + pushInstruction(tryInstruction) return } else -> { @@ -114,10 +114,10 @@ internal class CallStack { when (breakOrContinue) { is IrBreak -> currentFrame.removeSubFrameWithoutDataPropagation() // drop loop else -> if (breakOrContinue.loop is IrDoWhileLoop) { - addInstruction(SimpleInstruction(breakOrContinue.loop)) - addInstruction(CompoundInstruction(breakOrContinue.loop.condition)) + pushInstruction(SimpleInstruction(breakOrContinue.loop)) + pushInstruction(CompoundInstruction(breakOrContinue.loop.condition)) } else { - addInstruction(CompoundInstruction(breakOrContinue.loop)) + pushInstruction(CompoundInstruction(breakOrContinue.loop)) } } } @@ -133,14 +133,14 @@ internal class CallStack { is IrTry -> { dropSubFrame() // drop all instructions that left newSubFrame(frameOwner) - addInstruction(SimpleInstruction(frameOwner)) // to evaluate finally at the end - frameOwner.catches.reversed().forEach { addInstruction(CompoundInstruction(it)) } + pushInstruction(SimpleInstruction(frameOwner)) // to evaluate finally at the end + frameOwner.catches.reversed().forEach { pushInstruction(CompoundInstruction(it)) } pushState(exception) return } is IrCatch -> { // in case of exception in catch, drop everything except of last `try` instruction - addInstruction(frame.dropInstructions()!!) + pushInstruction(frame.dropInstructions()!!) pushState(exception) return } @@ -155,54 +155,25 @@ internal class CallStack { } fun hasNoInstructions() = frames.isEmpty() || (frames.size == 1 && frames.first().hasNoInstructions()) + fun pushInstruction(instruction: Instruction) = currentFrame.pushInstruction(instruction) + fun popInstruction(): Instruction = currentFrame.popInstruction() - fun addInstruction(instruction: Instruction) { - currentFrame.addInstruction(instruction) - } - - fun popInstruction(): Instruction { - return currentFrame.popInstruction() - } - - fun pushState(state: State) { - currentFrame.pushState(state) - } - + fun pushState(state: State) = currentFrame.pushState(state) fun popState(): State = currentFrame.popState() fun peekState(): State? = currentFrame.peekState() - fun addVariable(symbol: IrSymbol, state: State?) { - currentFrame.addVariable(symbol, state) - } + fun storeState(symbol: IrSymbol, state: State?) = currentFrame.storeState(symbol, state) + private fun storeState(symbol: IrSymbol, variable: Variable) = currentFrame.storeState(symbol, variable) + fun containsStateInMemory(symbol: IrSymbol): Boolean = currentFrame.containsStateInMemory(symbol) + fun loadState(symbol: IrSymbol): State = currentFrame.loadState(symbol) + fun rewriteState(symbol: IrSymbol, newState: State) = currentFrame.rewriteState(symbol, newState) - private fun addVariable(symbol: IrSymbol, variable: Variable) { - currentFrame.addVariable(symbol, variable) - } - - fun getState(symbol: IrSymbol): State = currentFrame.getState(symbol) - fun setState(symbol: IrSymbol, newState: State) = currentFrame.setState(symbol, newState) - fun containsVariable(symbol: IrSymbol): Boolean = currentFrame.containsVariable(symbol) - - fun storeUpValues(state: StateWithClosure) { - // TODO save only necessary declarations - currentFrame.copyMemoryInto(state) - } - - fun loadUpValues(state: StateWithClosure) { - state.upValues.forEach { (symbol, variable) -> addVariable(symbol, variable) } - } - - fun copyUpValuesFromPreviousFrame() { - frames[frames.size - 2].copyMemoryInto(currentFrame) - } - - fun getStackTrace(): List { - return frames.map { it.toString() }.filter { it != Frame.NOT_DEFINED } - } - - fun getFileAndPositionInfo(): String { - return frames[frames.size - 2].getFileAndPositionInfo() - } + // TODO save only necessary declarations + fun storeUpValues(state: StateWithClosure) = currentFrame.copyMemoryInto(state) + fun loadUpValues(state: StateWithClosure) = state.upValues.forEach { (symbol, variable) -> storeState(symbol, variable) } + fun copyUpValuesFromPreviousFrame() = frames[frames.size - 2].copyMemoryInto(currentFrame) + fun getStackTrace(): List = frames.map { it.toString() }.filter { it != Frame.NOT_DEFINED } + fun getFileAndPositionInfo(): String = frames[frames.size - 2].getFileAndPositionInfo() fun getStackCount(): Int = frames.size } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt index 232a452217e..bc0fb75ddda 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Frame.kt @@ -43,31 +43,16 @@ internal class Frame(subFrameOwner: IrElement, val irFile: IrFile? = null) { fun hasNoSubFrames() = innerStack.isEmpty() fun hasNoInstructions() = hasNoSubFrames() || (innerStack.size == 1 && innerStack.first().isEmpty()) - - fun addInstruction(instruction: Instruction) { - currentFrame.pushInstruction(instruction) - } - - fun popInstruction(): Instruction { - return currentFrame.popInstruction().apply { currentInstruction = this } - } - + fun pushInstruction(instruction: Instruction) = currentFrame.pushInstruction(instruction) + fun popInstruction(): Instruction = currentFrame.popInstruction().apply { currentInstruction = this } fun dropInstructions() = currentFrame.dropInstructions() - fun pushState(state: State) { - currentFrame.pushState(state) - } - + fun pushState(state: State) = currentFrame.pushState(state) fun popState(): State = currentFrame.popState() fun peekState(): State? = currentFrame.peekState() - fun addVariable(symbol: IrSymbol, state: State?) { - currentFrame.addVariable(symbol, state) - } - - fun addVariable(symbol: IrSymbol, variable: Variable) { - currentFrame.addVariable(symbol, variable) - } + fun storeState(symbol: IrSymbol, state: State?) = currentFrame.storeState(symbol, state) + fun storeState(symbol: IrSymbol, variable: Variable) = currentFrame.storeState(symbol, variable) private inline fun forEachSubFrame(block: (SubFrame) -> Unit) { // TODO speed up reverse iteration or do it forward @@ -76,28 +61,22 @@ internal class Frame(subFrameOwner: IrElement, val irFile: IrFile? = null) { } } - fun getState(symbol: IrSymbol): State { - forEachSubFrame { - it.getState(symbol)?.let { state -> return state } - } + fun loadState(symbol: IrSymbol): State { + forEachSubFrame { it.loadState(symbol)?.let { state -> return state } } throw InterpreterError("$symbol not found") // TODO better message } - fun setState(symbol: IrSymbol, newState: State) { - forEachSubFrame { - if (it.containsVariable(symbol)) return it.setState(symbol, newState) - } + fun rewriteState(symbol: IrSymbol, newState: State) { + forEachSubFrame { if (it.containsStateInMemory(symbol)) return it.rewriteState(symbol, newState) } } - fun containsVariable(symbol: IrSymbol): Boolean { - forEachSubFrame { - if (it.containsVariable(symbol)) return true - } + fun containsStateInMemory(symbol: IrSymbol): Boolean { + forEachSubFrame { if (it.containsStateInMemory(symbol)) return true } return false } fun copyMemoryInto(newFrame: Frame) { - this.getAll().forEach { (symbol, variable) -> if (!newFrame.containsVariable(symbol)) newFrame.addVariable(symbol, variable) } + this.getAll().forEach { (symbol, variable) -> if (!newFrame.containsStateInMemory(symbol)) newFrame.storeState(symbol, variable) } } fun copyMemoryInto(closure: StateWithClosure) { @@ -149,17 +128,17 @@ private class SubFrame(val owner: IrElement) { fun peekState(): State? = dataStack.peek() // Methods to work with memory - fun addVariable(symbol: IrSymbol, variable: Variable) { + fun storeState(symbol: IrSymbol, variable: Variable) { memory[symbol] = variable } - fun addVariable(symbol: IrSymbol, state: State?) { + fun storeState(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) { + fun containsStateInMemory(symbol: IrSymbol): Boolean = memory[symbol] != null + fun loadState(symbol: IrSymbol): State? = memory[symbol]?.state + fun rewriteState(symbol: IrSymbol, newState: State) { memory[symbol]?.state = newState } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt index c2965ebd30c..c06daf4c2e9 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Complex.kt @@ -60,7 +60,7 @@ internal interface Complex : State { .toList() .takeFromEndWhile { receiver == null || it.first != receiver } // only state's below receiver must be loaded on stack .forEach { (symbol, state) -> - callStack.addVariable(symbol, state) + callStack.storeState(symbol, state) (state as? StateWithClosure)?.let { callStack.loadUpValues(it) } } }