KT-16713 Insufficient maximum stack size
1. Analyze method node with fake jumps for loops to make sure that all instructions reachable only through break/continue jumps are processed. 2. Fix stack for break/continue jumps. 3. Drop fake jumps for loops, analyze method node again. 4. Fix stack for try/catch and beforeInline.
This commit is contained in:
committed by
Mikhael Bogdanov
parent
80063b6f91
commit
11caa03427
+1
-8
@@ -58,16 +58,9 @@ internal class FixStackAnalyzer(
|
||||
for (marker in context.fakeAlwaysFalseIfeqMarkers) {
|
||||
val next = marker.next
|
||||
if (next is JumpInsnNode) {
|
||||
val nop = InsnNode(Opcodes.NOP)
|
||||
expectedStackNode[next.label] = nop
|
||||
method.instructions.insert(next, nop)
|
||||
method.instructions.remove(marker)
|
||||
method.instructions.remove(next)
|
||||
context.nodesToRemoveOnCleanup.add(nop)
|
||||
expectedStackNode[next.label] = marker
|
||||
}
|
||||
}
|
||||
|
||||
context.fakeAlwaysFalseIfeqMarkers.clear()
|
||||
}
|
||||
|
||||
private val analyzer = InternalAnalyzer(owner, method, context)
|
||||
|
||||
-2
@@ -39,8 +39,6 @@ internal class FixStackContext(val methodNode: MethodNode) {
|
||||
val openingInlineMethodMarker = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
|
||||
var consistentInlineMarkers: Boolean = true; private set
|
||||
|
||||
val nodesToRemoveOnCleanup = arrayListOf<AbstractInsnNode>()
|
||||
|
||||
init {
|
||||
saveStackMarkerForRestoreMarker = insertTryCatchBlocksMarkers(methodNode)
|
||||
isThereAnyTryCatch = saveStackMarkerForRestoreMarker.isNotEmpty()
|
||||
|
||||
+37
-17
@@ -39,31 +39,51 @@ class FixStackMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
if (context.isAnalysisRequired()) {
|
||||
val analyzer = FixStackAnalyzer(internalClassName, methodNode, context)
|
||||
analyzer.analyze()
|
||||
|
||||
methodNode.maxStack = methodNode.maxStack + analyzer.maxExtraStackSize
|
||||
|
||||
val actions = arrayListOf<() -> Unit>()
|
||||
|
||||
transformBreakContinueGotos(methodNode, context, actions, analyzer)
|
||||
|
||||
transformSaveRestoreStackMarkers(methodNode, context, actions, analyzer)
|
||||
|
||||
actions.forEach { it() }
|
||||
analyzeAndTransformBreakContinueGotos(context, internalClassName, methodNode)
|
||||
removeAlwaysFalseIfeqMarkers(context, methodNode)
|
||||
analyzeAndTransformSaveRestoreStack(context, internalClassName, methodNode)
|
||||
}
|
||||
|
||||
context.fakeAlwaysTrueIfeqMarkers.forEach { marker ->
|
||||
replaceAlwaysTrueIfeqWithGoto(methodNode, marker)
|
||||
}
|
||||
removeAlwaysTrueIfeqMarkers(context, methodNode)
|
||||
removeAlwaysFalseIfeqMarkers(context, methodNode)
|
||||
}
|
||||
|
||||
private fun analyzeAndTransformBreakContinueGotos(context: FixStackContext, internalClassName: String, methodNode: MethodNode) {
|
||||
val analyzer = FixStackAnalyzer(internalClassName, methodNode, context)
|
||||
analyzer.analyze()
|
||||
|
||||
methodNode.maxStack = methodNode.maxStack + analyzer.maxExtraStackSize
|
||||
|
||||
val actions = arrayListOf<() -> Unit>()
|
||||
|
||||
transformBreakContinueGotos(methodNode, context, actions, analyzer)
|
||||
|
||||
actions.forEach { it() }
|
||||
}
|
||||
|
||||
private fun analyzeAndTransformSaveRestoreStack(context: FixStackContext, internalClassName: String, methodNode: MethodNode) {
|
||||
val analyzer = FixStackAnalyzer(internalClassName, methodNode, context)
|
||||
analyzer.analyze()
|
||||
|
||||
val actions = arrayListOf<() -> Unit>()
|
||||
|
||||
transformSaveRestoreStackMarkers(methodNode, context, actions, analyzer)
|
||||
|
||||
actions.forEach { it() }
|
||||
}
|
||||
|
||||
private fun removeAlwaysFalseIfeqMarkers(context: FixStackContext, methodNode: MethodNode) {
|
||||
context.fakeAlwaysFalseIfeqMarkers.forEach { marker ->
|
||||
removeAlwaysFalseIfeq(methodNode, marker)
|
||||
}
|
||||
context.fakeAlwaysFalseIfeqMarkers.clear()
|
||||
}
|
||||
|
||||
context.nodesToRemoveOnCleanup.forEach {
|
||||
methodNode.instructions.remove(it)
|
||||
private fun removeAlwaysTrueIfeqMarkers(context: FixStackContext, methodNode: MethodNode) {
|
||||
context.fakeAlwaysTrueIfeqMarkers.forEach { marker ->
|
||||
replaceAlwaysTrueIfeqWithGoto(methodNode, marker)
|
||||
}
|
||||
context.fakeAlwaysTrueIfeqMarkers.clear()
|
||||
}
|
||||
|
||||
private fun transformBreakContinueGotos(
|
||||
|
||||
Reference in New Issue
Block a user