Merge generateBreakOrContinueExpression and doFinallyOnReturn

This commit is contained in:
pyos
2019-03-27 12:34:49 +01:00
committed by Mikhael Bogdanov
parent c0af91b6d1
commit fb55e34b8f
@@ -75,8 +75,6 @@ class BlockInfo private constructor(val parent: BlockInfo?) {
this@apply.infos.addAll(this@BlockInfo.infos) this@apply.infos.addAll(this@BlockInfo.infos)
} }
fun isEmpty(): Boolean = infos.isEmpty()
fun hasFinallyBlocks(): Boolean = infos.firstIsInstanceOrNull<TryInfo>() != null fun hasFinallyBlocks(): Boolean = infos.firstIsInstanceOrNull<TryInfo>() != null
inline fun <R> withBlock(info: ExpressionInfo, f: (ExpressionInfo) -> R): R { inline fun <R> withBlock(info: ExpressionInfo, f: (ExpressionInfo) -> R): R {
@@ -88,7 +86,10 @@ class BlockInfo private constructor(val parent: BlockInfo?) {
} }
} }
inline fun <R> handleBlock(f: (ExpressionInfo) -> R): R { inline fun <R> handleBlock(f: (ExpressionInfo) -> R): R? {
if (infos.isEmpty()) {
return null
}
val top = infos.pop() val top = infos.pop()
try { try {
return f(top) return f(top)
@@ -955,37 +956,24 @@ class ExpressionCodegen(
return StackValue.none() return StackValue.none()
} }
override fun visitBreakContinue(jump: IrBreakContinue, data: BlockInfo): StackValue { private fun unwindBlockStack(endLabel: Label, data: BlockInfo, loop: IrLoop? = null): LoopInfo? {
jump.markLineNumber(startOffset = true) return data.handleBlock {
generateBreakOrContinueExpression(jump, Label(), data) when {
return none() it is TryInfo -> genFinallyBlock(it, null, endLabel, data)
it is LoopInfo && it.loop == loop -> return it
}
unwindBlockStack(endLabel, data, loop)
}
} }
private fun generateBreakOrContinueExpression( override fun visitBreakContinue(jump: IrBreakContinue, data: BlockInfo): StackValue {
expression: IrBreakContinue, jump.markLineNumber(startOffset = true)
afterBreakContinueLabel: Label, val endLabel = Label()
data: BlockInfo val stackElement = unwindBlockStack(endLabel, data, jump.loop)
) { ?: throw AssertionError("Target label for break/continue not found")
if (data.isEmpty()) { mv.fixStackAndJump(if (jump is IrBreak) stackElement.breakLabel else stackElement.continueLabel)
throw UnsupportedOperationException("Target label for break/continue not found") mv.mark(endLabel)
} return none()
data.handleBlock { stackElement ->
when (stackElement) {
is TryInfo -> genFinallyBlock(stackElement, null, afterBreakContinueLabel, data)
is LoopInfo -> {
val loop = expression.loop
if (loop == stackElement.loop) {
val label = if (expression is IrBreak) stackElement.breakLabel else stackElement.continueLabel
mv.fixStackAndJump(label)
mv.mark(afterBreakContinueLabel)
return
}
}
else -> throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
}
generateBreakOrContinueExpression(expression, afterBreakContinueLabel, data)
}
} }
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): StackValue { override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: BlockInfo): StackValue {
@@ -1126,24 +1114,11 @@ class ExpressionCodegen(
val returnValIndex = frame.enterTemp(returnType) val returnValIndex = frame.enterTemp(returnType)
val localForReturnValue = StackValue.local(returnValIndex, returnType) val localForReturnValue = StackValue.local(returnValIndex, returnType)
localForReturnValue.store(StackValue.onStack(returnType), mv) localForReturnValue.store(StackValue.onStack(returnType), mv)
doFinallyOnReturn(afterReturnLabel, data) unwindBlockStack(afterReturnLabel, data, null)
localForReturnValue.put(returnType, mv) localForReturnValue.put(returnType, mv)
frame.leaveTemp(returnType) frame.leaveTemp(returnType)
} else { } else {
doFinallyOnReturn(afterReturnLabel, data) unwindBlockStack(afterReturnLabel, data, null)
}
}
}
private fun doFinallyOnReturn(afterReturnLabel: Label, data: BlockInfo) {
if (!data.isEmpty()) {
data.handleBlock { stackElement ->
when (stackElement) {
is TryInfo -> genFinallyBlock(stackElement, null, afterReturnLabel, data)
is LoopInfo -> {}
else -> throw UnsupportedOperationException("Wrong BlockStackElement in processing stack")
}
doFinallyOnReturn(afterReturnLabel, data)
} }
} }
} }