Add simple handler for StackOverflowError in ir interpreter
This commit is contained in:
committed by
TeamCityServer
parent
f3d7dc5f22
commit
6a483a8464
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import java.lang.invoke.MethodHandle
|
import java.lang.invoke.MethodHandle
|
||||||
|
|
||||||
private const val MAX_COMMANDS = 500_000
|
private const val MAX_COMMANDS = 500_000
|
||||||
|
private const val MAX_STACK = 500
|
||||||
|
|
||||||
class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
|
class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
|
||||||
private val irExceptions = mutableListOf<IrClass>()
|
private val irExceptions = mutableListOf<IrClass>()
|
||||||
@@ -82,7 +83,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
}
|
}
|
||||||
else -> TODO("$returnLabel not supported as result of interpretation")
|
else -> TODO("$returnLabel not supported as result of interpretation")
|
||||||
}
|
}
|
||||||
} catch (e: InterpreterException) {
|
} catch (e: Throwable) {
|
||||||
// TODO don't handle, throw to lowering
|
// TODO don't handle, throw to lowering
|
||||||
IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + e.message)
|
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
|
// this method is used to get stack trace after exception
|
||||||
private fun interpretFunction(irFunction: IrSimpleFunction): ExecutionResult {
|
private fun interpretFunction(irFunction: IrSimpleFunction): ExecutionResult {
|
||||||
|
if (stack.getStackCount() >= MAX_STACK) StackOverflowError().throwAsUserException()
|
||||||
if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction)
|
if (irFunction.fileOrNull != null) stack.setCurrentFrameName(irFunction)
|
||||||
|
|
||||||
if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction)
|
if (irFunction.body is IrSyntheticBody) return handleIntrinsicMethods(irFunction)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ internal interface Stack {
|
|||||||
|
|
||||||
fun setCurrentFrameName(irFunction: IrFunction)
|
fun setCurrentFrameName(irFunction: IrFunction)
|
||||||
fun getStackTrace(): List<String>
|
fun getStackTrace(): List<String>
|
||||||
|
fun getStackCount(): Int
|
||||||
|
|
||||||
fun clean()
|
fun clean()
|
||||||
fun addVar(variable: Variable)
|
fun addVar(variable: Variable)
|
||||||
@@ -39,6 +40,7 @@ internal interface Stack {
|
|||||||
internal class StackImpl : 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 val frameList = mutableListOf(FrameContainer()) // first frame is default, it is easier to work when last() is not null
|
||||||
private fun getCurrentFrame() = frameList.last()
|
private fun getCurrentFrame() = frameList.last()
|
||||||
|
private var stackCount = 0
|
||||||
|
|
||||||
override fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
|
override fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
|
||||||
val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol }
|
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))
|
if (asSubFrame) getCurrentFrame().addSubFrame(newFrame) else frameList.add(FrameContainer(newFrame))
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
|
stackCount++
|
||||||
block()
|
block()
|
||||||
} finally {
|
} finally {
|
||||||
|
stackCount--
|
||||||
if (asSubFrame) getCurrentFrame().removeSubFrame() else removeLastFrame()
|
if (asSubFrame) getCurrentFrame().removeSubFrame() else removeLastFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +75,10 @@ internal class StackImpl : Stack {
|
|||||||
return frameList.mapNotNull { it.frameEntryPoint }
|
return frameList.mapNotNull { it.frameEntryPoint }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStackCount(): Int = stackCount
|
||||||
|
|
||||||
override fun clean() {
|
override fun clean() {
|
||||||
|
stackCount = 0
|
||||||
frameList.clear()
|
frameList.clear()
|
||||||
frameList.add(FrameContainer())
|
frameList.add(FrameContainer())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user