[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
|
queued[insn] = false
|
||||||
|
|
||||||
val insnNode = method.instructions[insn]
|
val insnNode = method.instructions[insn]
|
||||||
try {
|
val insnOpcode = insnNode.opcode
|
||||||
val insnOpcode = insnNode.opcode
|
|
||||||
val insnType = insnNode.type
|
val insnType = insnNode.type
|
||||||
|
|
||||||
if (insnType == AbstractInsnNode.LABEL ||
|
try {
|
||||||
insnType == AbstractInsnNode.LINE ||
|
analyzeInstruction(insnType, insnOpcode, insn, f, current, insnNode, isTcbStart, handler)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: AnalyzerException) {
|
} catch (e: AnalyzerException) {
|
||||||
throw AnalyzerException(
|
throw AnalyzerException(
|
||||||
e.node,
|
e.node,
|
||||||
@@ -132,12 +102,53 @@ open class FastMethodAnalyzer<V : Value>
|
|||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames
|
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>) {
|
private fun initLocals(current: Frame<V>) {
|
||||||
current.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)))
|
current.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)))
|
||||||
val args = Type.getArgumentTypes(method.desc)
|
val args = Type.getArgumentTypes(method.desc)
|
||||||
|
|||||||
+33
-23
@@ -88,39 +88,49 @@ internal open class FastStackAnalyzer<V : Value>(
|
|||||||
val insnType = insnNode.type
|
val insnType = insnNode.type
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
analyzeInstruction(insnType, insnNode, f, insn, current, insnOpcode, handler)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: AnalyzerException) {
|
} catch (e: AnalyzerException) {
|
||||||
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
|
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
|
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames
|
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>? =
|
fun getFrame(insn: AbstractInsnNode): Frame<V>? =
|
||||||
frames[insn.indexOf()]
|
frames[insn.indexOf()]
|
||||||
|
|
||||||
|
|||||||
+26
-15
@@ -131,33 +131,44 @@ class FastStoreLoadAnalyzer<V : StoreLoadValue>(
|
|||||||
queued[insn] = false
|
queued[insn] = false
|
||||||
|
|
||||||
val insnNode = method.instructions[insn]
|
val insnNode = method.instructions[insn]
|
||||||
try {
|
val insnOpcode = insnNode.opcode
|
||||||
val insnOpcode = insnNode.opcode
|
|
||||||
val insnType = insnNode.type
|
val insnType = insnNode.type
|
||||||
|
|
||||||
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
try {
|
||||||
mergeControlFlowEdge(insn + 1, f)
|
analyzeInstruction(insnType, insn, f, current, insnNode, insnOpcode, handler)
|
||||||
} 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)
|
|
||||||
}
|
|
||||||
} catch (e: AnalyzerException) {
|
} catch (e: AnalyzerException) {
|
||||||
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText(method.instructions)}: ${e.message}", e)
|
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText(method.instructions)}: ${e.message}", e)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText(method.instructions)}: ${e.message}", e)
|
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText(method.instructions)}: ${e.message}", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames
|
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) =
|
private fun newFrame(maxLocals: Int) =
|
||||||
StoreLoadFrame<V>(maxLocals)
|
StoreLoadFrame<V>(maxLocals)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user