Commit 788d0111 authored by Lukas Rytz's avatar Lukas Rytz

Add hook methods to analysis.Frame for branch-sensitive analyses

Adds two hook methods to `analysis.Frame`, called by `Analyzer.analyze`.
These methods are called on the temporary `currentFrame` before it is
merged with the existing frame at the branch target.

Overriding these methods allows implementing branch-sensitive analyses,
for example for nullness.
parent 4fef4700
......@@ -190,10 +190,12 @@ public class Analyzer<V extends Value> implements Opcodes {
if (insnNode instanceof JumpInsnNode) {
JumpInsnNode jumpInsn = (JumpInsnNode) insnNode;
if (insnOpcode != GOTO && insnOpcode != JSR) {
currentFrame.initForJumpTarget(insnOpcode, false);
merge(insnIndex + 1, currentFrame, subroutine);
newControlFlowEdge(insnIndex, insnIndex + 1);
}
int jumpInsnIndex = insnList.indexOf(jumpInsn.label);
currentFrame.initForJumpTarget(insnOpcode, true);
if (insnOpcode == JSR) {
merge(
jumpInsnIndex,
......@@ -206,20 +208,26 @@ public class Analyzer<V extends Value> implements Opcodes {
} else if (insnNode instanceof LookupSwitchInsnNode) {
LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;
int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
currentFrame.initForSwitchTarget(insnOpcode, lookupSwitchInsn.dflt);
merge(targetInsnIndex, currentFrame, subroutine);
newControlFlowEdge(insnIndex, targetInsnIndex);
for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
targetInsnIndex = insnList.indexOf(lookupSwitchInsn.labels.get(i));
LabelNode label = lookupSwitchInsn.labels.get(i);
targetInsnIndex = insnList.indexOf(label);
currentFrame.initForSwitchTarget(insnOpcode, label);
merge(targetInsnIndex, currentFrame, subroutine);
newControlFlowEdge(insnIndex, targetInsnIndex);
}
} else if (insnNode instanceof TableSwitchInsnNode) {
TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode;
int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt);
currentFrame.initForSwitchTarget(insnOpcode, tableSwitchInsn.dflt);
merge(targetInsnIndex, currentFrame, subroutine);
newControlFlowEdge(insnIndex, targetInsnIndex);
for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
targetInsnIndex = insnList.indexOf(tableSwitchInsn.labels.get(i));
LabelNode label = tableSwitchInsn.labels.get(i);
currentFrame.initForSwitchTarget(insnOpcode, label);
targetInsnIndex = insnList.indexOf(label);
merge(targetInsnIndex, currentFrame, subroutine);
newControlFlowEdge(insnIndex, targetInsnIndex);
}
......
......@@ -34,6 +34,7 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
......@@ -689,6 +690,35 @@ public class Frame<V extends Value> {
return changed;
}
/**
* A hook method called by {@link Analyzer#analyze(String, org.objectweb.asm.tree.MethodNode)}
* after interpreting a {@link org.objectweb.asm.tree.JumpInsnNode}. This method is called once
* for each branch, before the frame is merged with the existing frame at the branch target.
*
* <p>Overriding this method and changing the frame values allows implementing branch-sensitive
* analyses.
*
* @param opcode the Opcode of the jump instruction.
* @param conditionTrue {@literal true} when this method is called for the target branch of the
* {@link org.objectweb.asm.tree.JumpInsnNode}, {@literal false} for the successor
* instruction.
*/
public void initForJumpTarget(final int opcode, final boolean conditionTrue) {}
/**
* A hook method called by {@link Analyzer#analyze(String, org.objectweb.asm.tree.MethodNode)}
* after interpreting a {@link org.objectweb.asm.tree.LookupSwitchInsnNode} or a {@link
* org.objectweb.asm.tree.TableSwitchInsnNode}. This method is called once for each possible
* branch target.
*
* <p>Overriding this method and changing the frame values allows implementing branch-sensitive
* analyses.
*
* @param opcode the Opcode of the switch instruction.
* @param target the target branch.
*/
public void initForSwitchTarget(final int opcode, final LabelNode target) {}
/**
* Returns a string representation of this frame.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment