From f3d7dc5f22949cafe620ec56ede32a4da4aad15d Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 7 Aug 2020 15:02:34 +0300 Subject: [PATCH] Rewrite exceptions handler in ir interpreter For now there are 2 types of exceptions: 1. UserExceptions - express user and jvm like exceptions 2. InterpreterError - thrown only if something is wrong with interpreter --- .../kotlin/ir/interpreter/IrInterpreter.kt | 68 +++++++++---------- .../jetbrains/kotlin/ir/interpreter/Label.kt | 3 +- .../jetbrains/kotlin/ir/interpreter/Utils.kt | 14 ++-- .../exceptions/InterpreterError.kt | 14 ++++ .../exceptions/InterpreterException.kt | 3 +- .../InterpreterMethodNotFoundException.kt | 9 --- .../exceptions/InterpreterTimeOutException.kt | 10 --- .../interpreter/exceptions/UserException.kt | 19 ++++++ .../intrinsics/IntrinsicEvaluator.kt | 4 +- .../intrinsics/IntrinsicImplementations.kt | 3 +- .../kotlin/ir/interpreter/stack/Frame.kt | 5 +- .../kotlin/ir/interpreter/stack/Stack.kt | 4 +- .../kotlin/ir/interpreter/state/State.kt | 5 +- .../kotlin/ir/interpreter/state/Wrapper.kt | 2 +- 14 files changed, 93 insertions(+), 70 deletions(-) create mode 100644 compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterError.kt delete mode 100644 compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterMethodNotFoundException.kt delete mode 100644 compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterTimeOutException.kt create mode 100644 compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/UserException.kt 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 954d143d5fd..e6e3667df65 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 @@ -14,9 +14,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.interpreter.builtins.* -import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterException -import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundException -import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterTimeOutException +import org.jetbrains.kotlin.ir.interpreter.exceptions.* import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator import org.jetbrains.kotlin.ir.interpreter.stack.StackImpl import org.jetbrains.kotlin.ir.interpreter.stack.Variable @@ -70,7 +68,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map private fun incrementAndCheckCommands() { commandCount++ - if (commandCount >= MAX_COMMANDS) throw InterpreterTimeOutException() + if (commandCount >= MAX_COMMANDS) throw InterpreterTimeOutError() } fun interpret(expression: IrExpression): IrExpression { @@ -133,13 +131,11 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map } return executionResult.getNextLabel(this) { this@getNextLabel.interpret() } - } catch (e: InterpreterException) { - throw e - } catch (e: Throwable) { - // catch exception from JVM such as: ArithmeticException, StackOverflowError and others - val exceptionName = e::class.java.simpleName + } catch (e: UserException) { + // can handle only user exceptions, all others must be rethrown + val exceptionName = e.exception::class.java.simpleName val irExceptionClass = irExceptions.firstOrNull { it.name.asString() == exceptionName } ?: irBuiltIns.throwableClass.owner - stack.pushReturnValue(ExceptionState(e, irExceptionClass, stack.getStackTrace())) + stack.pushReturnValue(ExceptionState(e.exception, irExceptionClass, stack.getStackTrace())) return Exception } } @@ -149,12 +145,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction) if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction) - return irFunction.body?.interpret() ?: throw InterpreterException("Ir function must be with body") + return irFunction.body?.interpret() ?: throw InterpreterError("Ir function must be with body") } private fun MethodHandle?.invokeMethod(irFunction: IrFunction): ExecutionResult { this ?: return handleIntrinsicMethods(irFunction) - val result = this.invokeWithArguments(irFunction.getArgsForMethodInvocation(stack.getAll())) + val result = withExceptionHandler { this.invokeWithArguments(irFunction.getArgsForMethodInvocation(stack.getAll())) } stack.pushReturnValue(result.toState(result.getType(irFunction.returnType))) return Next @@ -197,26 +193,28 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map val signature = CompileTimeFunction(methodName, argsType.map { it.getOnlyName() }) // TODO replace unary, binary, ternary functions with vararg - val result = when (argsType.size) { - 1 -> { - val function = unaryFunctions[signature] - ?: throw InterpreterMethodNotFoundException("For given function $signature there is no entry in unary map") - function.invoke(argsValues.first()) - } - 2 -> { - val function = binaryFunctions[signature] - ?: throw InterpreterMethodNotFoundException("For given function $signature there is no entry in binary map") - when (methodName) { - "rangeTo" -> return calculateRangeTo(irFunction.returnType) - else -> function.invoke(argsValues[0], argsValues[1]) + val result = withExceptionHandler { + when (argsType.size) { + 1 -> { + val function = unaryFunctions[signature] + ?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in unary map") + function.invoke(argsValues.first()) } + 2 -> { + val function = binaryFunctions[signature] + ?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in binary map") + when (methodName) { + "rangeTo" -> return calculateRangeTo(irFunction.returnType) + else -> function.invoke(argsValues[0], argsValues[1]) + } + } + 3 -> { + val function = ternaryFunctions[signature] + ?: throw InterpreterMethodNotFoundError("For given function $signature there is no entry in ternary map") + function.invoke(argsValues[0], argsValues[1], argsValues[2]) + } + else -> throw InterpreterError("Unsupported number of arguments for invocation as builtin functions") } - 3 -> { - val function = ternaryFunctions[signature] - ?: throw InterpreterMethodNotFoundException("For given function $signature there is no entry in ternary map") - function.invoke(argsValues[0], argsValues[1], argsValues[2]) - } - else -> throw InterpreterException("Unsupported number of arguments") } stack.pushReturnValue(result.toState(result.getType(irFunction.returnType))) @@ -259,7 +257,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map stack.peekReturnValue().checkNullability(valueParametersSymbols[i].owner.type) { val method = irFunction.getCapitalizedFileName() + "." + irFunction.fqNameWhenAvailable val parameter = valueParametersSymbols[i].owner.name - throw IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter") + IllegalArgumentException("Parameter specified as non-null is null: method $method, parameter $parameter").throwAsUserException() } with(Variable(valueParametersSymbols[i], stack.popReturnValue())) { @@ -637,7 +635,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map val executionResult = enumEntry.initializerExpression?.interpret()?.check { return it } enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null - return executionResult ?: throw InterpreterException("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null") + return executionResult ?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null") } private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult { @@ -653,7 +651,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST -> { if (!isErased && !stack.peekReturnValue().isSubtypeOf(typeOperand)) { val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable - throw ClassCastException("$convertibleClassName cannot be cast to ${typeOperand.render()}") + ClassCastException("$convertibleClassName cannot be cast to ${typeOperand.render()}").throwAsUserException() } } IrTypeOperator.SAFE_CAST -> { @@ -750,7 +748,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map is Common -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace())) is Wrapper -> stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace())) is ExceptionState -> stack.pushReturnValue(exception) - else -> throw InterpreterException("${exception::class} cannot be used as exception state") + else -> throw InterpreterError("${exception::class} cannot be used as exception state") } return Exception } @@ -778,7 +776,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map } } is Lambda -> state.toString() - else -> throw InterpreterException("${state::class.java} cannot be used in StringConcatenation expression") + else -> throw InterpreterError("${state::class.java} cannot be used in StringConcatenation expression") } stack.pushReturnValue(result.toState(irBuiltIns.stringType)) return Next diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt index 27382fa8ada..f11895fb0fa 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.expressions.IrWhen import org.jetbrains.kotlin.ir.expressions.IrWhileLoop +import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrFail @@ -72,7 +73,7 @@ internal fun ExecutionResult.implicitCastIfNeeded(expectedType: IrType, actualTy if (!actualState.isSubtypeOf(expectedType)) { val convertibleClassName = stack.popReturnValue().irClass.fqNameWhenAvailable - throw ClassCastException("$convertibleClassName cannot be cast to ${expectedType.render()}") + ClassCastException("$convertibleClassName cannot be cast to ${expectedType.render()}").throwAsUserException() } return this } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Utils.kt index 9a0a78f69fc..9cac5c6675f 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 @@ -14,12 +14,10 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.interpreter.builtins.evaluateIntrinsicAnnotation +import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.interpreter.state.* -import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.FqName @@ -240,3 +238,11 @@ fun IrClass.internalName(): String { } return internalName.toString() } + +inline fun withExceptionHandler(block: () -> Any?): Any? { + try { + return block() + } catch (e: Throwable) { + e.throwAsUserException() + } +} \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterError.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterError.kt new file mode 100644 index 00000000000..5dda318acea --- /dev/null +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterError.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.interpreter.exceptions + +open class InterpreterError(override val message: String) : InterpreterException() + +class InterpreterMethodNotFoundError(override val message: String) : InterpreterError(message) + +class InterpreterTimeOutError : InterpreterError("Exceeded execution limit of constexpr expression") + +class InterpreterEmptyReturnStackError : InterpreterError("Return values stack is empty") \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterException.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterException.kt index 4ac53b8ae15..563e299e4b8 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterException.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterException.kt @@ -5,5 +5,4 @@ package org.jetbrains.kotlin.ir.interpreter.exceptions -open class InterpreterException(override val message: String) : Exception(message) { -} \ No newline at end of file +abstract class InterpreterException : Exception() \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterMethodNotFoundException.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterMethodNotFoundException.kt deleted file mode 100644 index 8cf6941dd62..00000000000 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterMethodNotFoundException.kt +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.ir.interpreter.exceptions - -class InterpreterMethodNotFoundException(override val message: String) : InterpreterException(message) { -} \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterTimeOutException.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterTimeOutException.kt deleted file mode 100644 index 9bf7c522f5e..00000000000 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/InterpreterTimeOutException.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.ir.interpreter.exceptions - -class InterpreterTimeOutException : InterpreterException("Exceeded execution limit of constexpr expression") { - -} \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/UserException.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/UserException.kt new file mode 100644 index 00000000000..b359c240c5b --- /dev/null +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/exceptions/UserException.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.interpreter.exceptions + +/** + * This class used to wrap 2 types of exceptions: + * 1. exceptions from JVM such as: ArithmeticException, StackOverflowError and others + * 2. exceptions defined by user + */ +class UserException(val exception: Throwable) : InterpreterException() { + override fun fillInStackTrace(): Throwable = this +} + +fun Throwable.throwAsUserException(): Nothing { + throw UserException(this) +} \ No newline at end of file diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt index 7254b8c718e..a8933526e44 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.ir.interpreter.intrinsics import org.jetbrains.kotlin.ir.interpreter.ExecutionResult -import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundException +import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundError import org.jetbrains.kotlin.ir.interpreter.stack.Stack import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFunction @@ -23,7 +23,7 @@ internal class IntrinsicEvaluator { EnumHashCode.equalTo(irFunction) -> EnumHashCode.evaluate(irFunction, stack, interpret) JsPrimitives.equalTo(irFunction) -> JsPrimitives.evaluate(irFunction, stack, interpret) ArrayConstructor.equalTo(irFunction) -> ArrayConstructor.evaluate(irFunction, stack, interpret) - else -> throw InterpreterMethodNotFoundException("Method ${irFunction.name} hasn't implemented") + else -> throw InterpreterMethodNotFoundError("Method ${irFunction.name} hasn't implemented") } } } \ No newline at end of file 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 ff37fac91da..99723bae138 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 @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrEnumEntry import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.* @@ -96,7 +97,7 @@ internal object EnumValueOf : IntrinsicBase() { val enumEntryName = stack.getVariable(irFunction.valueParameters.first().symbol).state.asString() val enumEntry = enumClass.declarations.filterIsInstance().singleOrNull { it.name.asString() == enumEntryName } enumEntry?.interpret()?.check { return it } - ?: throw IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName") + ?: IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName").throwAsUserException() return Next } 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 51a131e02e3..351379933ef 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.interpreter.stack +import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterEmptyReturnStackError import org.jetbrains.kotlin.ir.interpreter.state.State import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol @@ -65,7 +66,7 @@ internal class InterpreterFrame( if (returnStack.isNotEmpty()) { return returnStack.last() } - throw NoSuchElementException("Return values stack is empty") + throw InterpreterEmptyReturnStackError() } override fun popReturnValue(): State { @@ -74,6 +75,6 @@ internal class InterpreterFrame( returnStack.removeAt(returnStack.size - 1) return item } - throw NoSuchElementException("Return values stack is empty") + throw InterpreterEmptyReturnStackError() } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt index 254763b5612..e57aff1dc2a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt @@ -6,11 +6,11 @@ package org.jetbrains.kotlin.ir.interpreter.stack import org.jetbrains.kotlin.ir.interpreter.ExecutionResult -import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterException import org.jetbrains.kotlin.ir.interpreter.getCapitalizedFileName import org.jetbrains.kotlin.ir.interpreter.state.State import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.name +import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterError import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.util.file @@ -132,7 +132,7 @@ private class FrameContainer(current: Frame = InterpreterFrame()) { fun getAll() = innerStack.flatMap { it.getAll() } fun getVariable(symbol: IrSymbol): Variable { return innerStack.firstNotNullOfOrNull { it.getVariable(symbol) } - ?: throw InterpreterException("$symbol not found") // TODO better message + ?: throw InterpreterError("$symbol not found") // TODO better message } fun contains(symbol: IrSymbol) = innerStack.any { it.contains(symbol) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt index 4b4cc3ec2d2..df01641628c 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/State.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.interpreter.stack.Variable import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.interpreter.exceptions.throwAsUserException import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType @@ -60,7 +61,9 @@ internal fun State.isSubtypeOf(other: IrType): Boolean { /** * This method used to check if for not null parameter there was passed null argument. */ -internal fun State.checkNullability(irType: IrType?, throwException: () -> Nothing = { throw NullPointerException() }): State { +internal fun State.checkNullability( + irType: IrType?, throwException: () -> Nothing = { NullPointerException().throwAsUserException() } +): State { if (irType !is IrSimpleType) return this if (this.isNull() && !irType.isNullable()) { throwException() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt index e3b47b499c8..64d60cb528c 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt @@ -56,7 +56,7 @@ internal class Wrapper(val value: Any, override val irClass: IrClass) : Complex( fun getCompanionObject(irClass: IrClass): Wrapper { val objectName = irClass.getEvaluateIntrinsicValue()!! - val objectValue = companionObjectValue[objectName] ?: throw AssertionError("Companion object $objectName cannot be interpreted") + val objectValue = companionObjectValue[objectName] ?: throw InternalError("Companion object $objectName cannot be interpreted") return Wrapper(objectValue, irClass) }