From 6a483a8464bc53b38604aa9d260d9a74efea5267 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Fri, 7 Aug 2020 21:27:00 +0300 Subject: [PATCH] Add simple handler for StackOverflowError in ir interpreter --- .../org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt | 4 +++- .../src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) 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 e6e3667df65..050e7099d55 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 @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.Name import java.lang.invoke.MethodHandle private const val MAX_COMMANDS = 500_000 +private const val MAX_STACK = 500 class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map = emptyMap()) { private val irExceptions = mutableListOf() @@ -82,7 +83,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map } else -> TODO("$returnLabel not supported as result of interpretation") } - } catch (e: InterpreterException) { + } catch (e: Throwable) { // TODO don't handle, throw to lowering IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + e.message) } @@ -142,6 +143,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map // this method is used to get stack trace after exception private fun interpretFunction(irFunction: IrSimpleFunction): ExecutionResult { + if (stack.getStackCount() >= MAX_STACK) StackOverflowError().throwAsUserException() if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction) if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction) 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 e57aff1dc2a..190266dcb77 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 @@ -22,6 +22,7 @@ internal interface Stack { fun setCurrentFrameName(irFunction: IrFunction) fun getStackTrace(): List + fun getStackCount(): Int fun clean() fun addVar(variable: Variable) @@ -39,6 +40,7 @@ internal interface Stack { internal class StackImpl : Stack { private val frameList = mutableListOf(FrameContainer()) // first frame is default, it is easier to work when last() is not null private fun getCurrentFrame() = frameList.last() + private var stackCount = 0 override fun newFrame(asSubFrame: Boolean, initPool: List, block: () -> ExecutionResult): ExecutionResult { val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol } @@ -47,8 +49,10 @@ internal class StackImpl : Stack { if (asSubFrame) getCurrentFrame().addSubFrame(newFrame) else frameList.add(FrameContainer(newFrame)) return try { + stackCount++ block() } finally { + stackCount-- if (asSubFrame) getCurrentFrame().removeSubFrame() else removeLastFrame() } } @@ -71,7 +75,10 @@ internal class StackImpl : Stack { return frameList.mapNotNull { it.frameEntryPoint } } + override fun getStackCount(): Int = stackCount + override fun clean() { + stackCount = 0 frameList.clear() frameList.add(FrameContainer()) }