[JVM] Extract unique code in Fast...Analyzer into analyzeInstruction
This commit is contained in:
+45
-34
@@ -84,41 +84,11 @@ open class FastMethodAnalyzer<V : Value>
|
||||
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<V : Value>
|
||||
e
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return frames
|
||||
}
|
||||
|
||||
private fun analyzeInstruction(
|
||||
insnType: Int,
|
||||
insnOpcode: Int,
|
||||
insn: Int,
|
||||
f: Frame<V>,
|
||||
current: Frame<V>,
|
||||
insnNode: AbstractInsnNode,
|
||||
isTcbStart: BooleanArray,
|
||||
handler: Frame<V>,
|
||||
) {
|
||||
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<V>) {
|
||||
current.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)))
|
||||
val args = Type.getArgumentTypes(method.desc)
|
||||
|
||||
+33
-23
@@ -88,39 +88,49 @@ internal open class FastStackAnalyzer<V : Value>(
|
||||
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<V>,
|
||||
insn: Int,
|
||||
current: Frame<V>,
|
||||
insnOpcode: Int,
|
||||
handler: Frame<V>,
|
||||
) {
|
||||
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<V>? =
|
||||
frames[insn.indexOf()]
|
||||
|
||||
|
||||
+26
-15
@@ -131,33 +131,44 @@ class FastStoreLoadAnalyzer<V : StoreLoadValue>(
|
||||
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<V>,
|
||||
current: StoreLoadFrame<V>,
|
||||
insnNode: AbstractInsnNode,
|
||||
insnOpcode: Int,
|
||||
handler: StoreLoadFrame<V>,
|
||||
) {
|
||||
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<V>(maxLocals)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user