From e0dd3a33c0af1dda400d00e37bf7c890da72c195 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Wed, 23 Aug 2023 20:08:11 +0200 Subject: [PATCH] [JVM] Extract unique code in `Fast...Analyzer` into `analyzeInstruction` --- .../optimization/common/FastMethodAnalyzer.kt | 79 +++++++++++-------- .../fixStack/FastStackAnalyzer.kt | 56 +++++++------ .../temporaryVals/FastStoreLoadAnalyzer.kt | 41 ++++++---- 3 files changed, 104 insertions(+), 72 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt index a8a73d7fcf4..2065974e7b2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/FastMethodAnalyzer.kt @@ -84,41 +84,11 @@ open class FastMethodAnalyzer queued[insn] = false val insnNode = method.instructions[insn] - try { - val insnOpcode = insnNode.opcode + val insnOpcode = insnNode.opcode val insnType = insnNode.type - if (insnType == AbstractInsnNode.LABEL || - insnType == AbstractInsnNode.LINE || - insnType == AbstractInsnNode.FRAME || - insnOpcode == Opcodes.NOP - ) { - mergeControlFlowEdge(insn + 1, f, canReuse = true) - } else { - current.init(f).execute(insnNode, interpreter) - visitMeaningfulInstruction(insnNode, insnType, insnOpcode, current, insn) - } - - // Jump by an exception edge clears the stack, putting exception on top. - // So, unless we have a store operation, anything we change on stack would be lost, - // and there's no need to analyze exception handler again. - // Add an exception edge from TCB start to make sure handler itself is still visited. - if (!pruneExceptionEdges || - insnOpcode in Opcodes.ISTORE..Opcodes.ASTORE || - insnOpcode == Opcodes.IINC || - isTcbStart[insn] - ) { - handlers[insn]?.forEach { tcb -> - val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable") - val jump = tcb.handler.indexOf() - - handler.init(f) - handler.clearStack() - handler.push(interpreter.newExceptionValue(tcb, handler, exnType)) - mergeControlFlowEdge(jump, handler) - } - } - + try { + analyzeInstruction(insnType, insnOpcode, insn, f, current, insnNode, isTcbStart, handler) } catch (e: AnalyzerException) { throw AnalyzerException( e.node, @@ -132,12 +102,53 @@ open class FastMethodAnalyzer e ) } - } return frames } + private fun analyzeInstruction( + insnType: Int, + insnOpcode: Int, + insn: Int, + f: Frame, + current: Frame, + insnNode: AbstractInsnNode, + isTcbStart: BooleanArray, + handler: Frame, + ) { + if (insnType == AbstractInsnNode.LABEL || + insnType == AbstractInsnNode.LINE || + insnType == AbstractInsnNode.FRAME || + insnOpcode == Opcodes.NOP + ) { + mergeControlFlowEdge(insn + 1, f, canReuse = true) + } else { + current.init(f).execute(insnNode, interpreter) + visitMeaningfulInstruction(insnNode, insnType, insnOpcode, current, insn) + } + + // Jump by an exception edge clears the stack, putting exception on top. + // So, unless we have a store operation, anything we change on stack would be lost, + // and there's no need to analyze exception handler again. + // Add an exception edge from TCB start to make sure handler itself is still visited. + if (!pruneExceptionEdges || + insnOpcode in Opcodes.ISTORE..Opcodes.ASTORE || + insnOpcode == Opcodes.IINC || + isTcbStart[insn] + ) { + handlers[insn]?.forEach { tcb -> + val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable") + val jump = tcb.handler.indexOf() + + handler.init(f) + handler.clearStack() + handler.push(interpreter.newExceptionValue(tcb, handler, exnType)) + mergeControlFlowEdge(jump, handler) + } + } + } + private fun initLocals(current: Frame) { current.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc))) val args = Type.getArgumentTypes(method.desc) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt index 6785b8189ba..f3bac484a35 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/fixStack/FastStackAnalyzer.kt @@ -88,39 +88,49 @@ internal open class FastStackAnalyzer( val insnType = insnNode.type try { - if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) { - visitNopInsn(insnNode, f, insn) - } else { - current.init(f) - if (insnOpcode != Opcodes.RETURN) { - // Don't care about possibly incompatible return type - current.execute(insnNode, interpreter) - } - visitMeaningfulInstruction(insnNode, insnType, insnOpcode, current, insn) - } - - handlers[insn]?.forEach { tcb -> - val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable") - val jump = tcb.handler.indexOf() - if (visitControlFlowExceptionEdge(insn, tcb.handler.indexOf())) { - handler.init(f) - handler.clearStack() - handler.push(interpreter.newValue(exnType)) - mergeControlFlowEdge(jump, handler) - } - } - + analyzeInstruction(insnType, insnNode, f, insn, current, insnOpcode, handler) } catch (e: AnalyzerException) { throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e) } catch (e: Exception) { throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e) } - } return frames } + private fun analyzeInstruction( + insnType: Int, + insnNode: AbstractInsnNode, + f: Frame, + insn: Int, + current: Frame, + insnOpcode: Int, + handler: Frame, + ) { + if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) { + visitNopInsn(insnNode, f, insn) + } else { + current.init(f) + if (insnOpcode != Opcodes.RETURN) { + // Don't care about possibly incompatible return type + current.execute(insnNode, interpreter) + } + visitMeaningfulInstruction(insnNode, insnType, insnOpcode, current, insn) + } + + handlers[insn]?.forEach { tcb -> + val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable") + val jump = tcb.handler.indexOf() + if (visitControlFlowExceptionEdge(insn, tcb.handler.indexOf())) { + handler.init(f) + handler.clearStack() + handler.push(interpreter.newValue(exnType)) + mergeControlFlowEdge(jump, handler) + } + } + } + fun getFrame(insn: AbstractInsnNode): Frame? = frames[insn.indexOf()] diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt index 1c81edb1c35..c9d8cc71119 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt @@ -131,33 +131,44 @@ class FastStoreLoadAnalyzer( queued[insn] = false val insnNode = method.instructions[insn] - try { - val insnOpcode = insnNode.opcode + val insnOpcode = insnNode.opcode val insnType = insnNode.type - if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) { - mergeControlFlowEdge(insn + 1, f) - } else { - current.init(f).execute(insnNode, interpreter) - visitMeaningfulInstruction(insnNode, insnType, insnOpcode, current, insn) - } - - handlers[insn]?.forEach { tcb -> - val jump = tcb.handler.indexOf() - handler.init(f) - mergeControlFlowEdge(jump, handler) - } + try { + analyzeInstruction(insnType, insn, f, current, insnNode, insnOpcode, handler) } catch (e: AnalyzerException) { throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText(method.instructions)}: ${e.message}", e) } catch (e: Exception) { throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText(method.instructions)}: ${e.message}", e) } - } return frames } + private fun analyzeInstruction( + insnType: Int, + insn: Int, + f: StoreLoadFrame, + current: StoreLoadFrame, + insnNode: AbstractInsnNode, + insnOpcode: Int, + handler: StoreLoadFrame, + ) { + if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) { + mergeControlFlowEdge(insn + 1, f) + } else { + current.init(f).execute(insnNode, interpreter) + visitMeaningfulInstruction(insnNode, insnType, insnOpcode, current, insn) + } + + handlers[insn]?.forEach { tcb -> + val jump = tcb.handler.indexOf() + handler.init(f) + mergeControlFlowEdge(jump, handler) + } + } + private fun newFrame(maxLocals: Int) = StoreLoadFrame(maxLocals)