mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
BytecodeAnalysis: ControlFlowBuilder deduplication
LiteControlFlowBuilder and ControlFlowBuilder are merged into single class (their body was actually identical); dependency from FramelessAnalyzer changed from inheritance to composition
This commit is contained in:
+11
-57
@@ -23,6 +23,9 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_ABSTRACT;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_NATIVE;
|
||||
|
||||
/**
|
||||
* @author lambdamix
|
||||
*/
|
||||
@@ -68,19 +71,21 @@ public final class ControlFlowGraph {
|
||||
}
|
||||
|
||||
public static ControlFlowGraph build(String className, MethodNode methodNode, boolean jsr) throws AnalyzerException {
|
||||
return jsr ? new ControlFlowBuilder(className, methodNode).buildCFG() : new LiteControlFlowBuilder(className, methodNode).buildCFG();
|
||||
return new ControlFlowBuilder(className, methodNode, jsr).buildCFG();
|
||||
}
|
||||
}
|
||||
|
||||
final class ControlFlowBuilder extends FramelessAnalyzer {
|
||||
final class ControlFlowBuilder implements FramelessAnalyzer.EdgeCreator {
|
||||
final String className;
|
||||
final MethodNode methodNode;
|
||||
final TIntArrayList[] transitions;
|
||||
final Set<ControlFlowGraph.Edge> errorTransitions;
|
||||
final FramelessAnalyzer myAnalyzer;
|
||||
private final boolean[] errors;
|
||||
private int edgeCount;
|
||||
|
||||
ControlFlowBuilder(String className, MethodNode methodNode) {
|
||||
ControlFlowBuilder(String className, MethodNode methodNode, boolean jsr) {
|
||||
myAnalyzer = jsr ? new FramelessAnalyzer(this) : new LiteFramelessAnalyzer(this);
|
||||
this.className = className;
|
||||
this.methodNode = methodNode;
|
||||
transitions = new TIntArrayList[methodNode.instructions.size()];
|
||||
@@ -93,7 +98,7 @@ final class ControlFlowBuilder extends FramelessAnalyzer {
|
||||
|
||||
final ControlFlowGraph buildCFG() throws AnalyzerException {
|
||||
if ((methodNode.access & (ACC_ABSTRACT | ACC_NATIVE)) == 0) {
|
||||
analyze(methodNode);
|
||||
myAnalyzer.analyze(methodNode);
|
||||
}
|
||||
int[][] resultTransitions = new int[transitions.length][];
|
||||
for (int i = 0; i < resultTransitions.length; i++) {
|
||||
@@ -103,7 +108,7 @@ final class ControlFlowBuilder extends FramelessAnalyzer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void newControlFlowEdge(int insn, int successor) {
|
||||
public final void newControlFlowEdge(int insn, int successor) {
|
||||
if (!transitions[insn].contains(successor)) {
|
||||
transitions[insn].add(successor);
|
||||
edgeCount++;
|
||||
@@ -111,7 +116,7 @@ final class ControlFlowBuilder extends FramelessAnalyzer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean newControlFlowExceptionEdge(int insn, int successor) {
|
||||
public final boolean newControlFlowExceptionEdge(int insn, int successor) {
|
||||
if (!transitions[insn].contains(successor)) {
|
||||
transitions[insn].add(successor);
|
||||
edgeCount++;
|
||||
@@ -121,54 +126,3 @@ final class ControlFlowBuilder extends FramelessAnalyzer {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
final class LiteControlFlowBuilder extends LiteFramelessAnalyzer {
|
||||
final String className;
|
||||
final MethodNode methodNode;
|
||||
final TIntArrayList[] transitions;
|
||||
final Set<ControlFlowGraph.Edge> errorTransitions;
|
||||
private final boolean[] errors;
|
||||
private int edgeCount;
|
||||
|
||||
LiteControlFlowBuilder(String className, MethodNode methodNode) {
|
||||
this.className = className;
|
||||
this.methodNode = methodNode;
|
||||
transitions = new TIntArrayList[methodNode.instructions.size()];
|
||||
errors = new boolean[methodNode.instructions.size()];
|
||||
for (int i = 0; i < transitions.length; i++) {
|
||||
transitions[i] = new TIntArrayList();
|
||||
}
|
||||
errorTransitions = new HashSet<>();
|
||||
}
|
||||
|
||||
final ControlFlowGraph buildCFG() throws AnalyzerException {
|
||||
if ((methodNode.access & (ACC_ABSTRACT | ACC_NATIVE)) == 0) {
|
||||
analyze(methodNode);
|
||||
}
|
||||
int[][] resultTransitions = new int[transitions.length][];
|
||||
for (int i = 0; i < resultTransitions.length; i++) {
|
||||
resultTransitions[i] = transitions[i].toNativeArray();
|
||||
}
|
||||
return new ControlFlowGraph(className, methodNode, resultTransitions, edgeCount, errors, errorTransitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void newControlFlowEdge(int insn, int successor) {
|
||||
if (!transitions[insn].contains(successor)) {
|
||||
transitions[insn].add(successor);
|
||||
edgeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean newControlFlowExceptionEdge(int insn, int successor) {
|
||||
if (!transitions[insn].contains(successor)) {
|
||||
transitions[insn].add(successor);
|
||||
edgeCount++;
|
||||
errorTransitions.add(new Edge(insn, successor));
|
||||
errors[successor] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-16
@@ -34,6 +34,9 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
protected boolean[] queued;
|
||||
protected int[] queue;
|
||||
protected int top;
|
||||
protected final EdgeCreator myEdgeCreator;
|
||||
|
||||
public FramelessAnalyzer(EdgeCreator creator) {myEdgeCreator = creator;}
|
||||
|
||||
public void analyze(final MethodNode m) throws AnalyzerException {
|
||||
n = m.instructions.size();
|
||||
@@ -101,7 +104,7 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
|
||||
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
||||
merge(insn + 1, subroutine);
|
||||
newControlFlowEdge(insn, insn + 1);
|
||||
myEdgeCreator.newControlFlowEdge(insn, insn + 1);
|
||||
} else {
|
||||
subroutine = subroutine == null ? null : subroutine.copy();
|
||||
|
||||
@@ -109,7 +112,7 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
JumpInsnNode j = (JumpInsnNode) insnNode;
|
||||
if (insnOpcode != GOTO && insnOpcode != JSR) {
|
||||
merge(insn + 1, subroutine);
|
||||
newControlFlowEdge(insn, insn + 1);
|
||||
myEdgeCreator.newControlFlowEdge(insn, insn + 1);
|
||||
}
|
||||
int jump = insns.indexOf(j.label);
|
||||
if (insnOpcode == JSR) {
|
||||
@@ -117,28 +120,28 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
} else {
|
||||
merge(jump, subroutine);
|
||||
}
|
||||
newControlFlowEdge(insn, jump);
|
||||
myEdgeCreator.newControlFlowEdge(insn, jump);
|
||||
} else if (insnNode instanceof LookupSwitchInsnNode) {
|
||||
LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
|
||||
int jump = insns.indexOf(lsi.dflt);
|
||||
merge(jump, subroutine);
|
||||
newControlFlowEdge(insn, jump);
|
||||
myEdgeCreator.newControlFlowEdge(insn, jump);
|
||||
for (int j = 0; j < lsi.labels.size(); ++j) {
|
||||
LabelNode label = lsi.labels.get(j);
|
||||
jump = insns.indexOf(label);
|
||||
merge(jump, subroutine);
|
||||
newControlFlowEdge(insn, jump);
|
||||
myEdgeCreator.newControlFlowEdge(insn, jump);
|
||||
}
|
||||
} else if (insnNode instanceof TableSwitchInsnNode) {
|
||||
TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
|
||||
int jump = insns.indexOf(tsi.dflt);
|
||||
merge(jump, subroutine);
|
||||
newControlFlowEdge(insn, jump);
|
||||
myEdgeCreator.newControlFlowEdge(insn, jump);
|
||||
for (int j = 0; j < tsi.labels.size(); ++j) {
|
||||
LabelNode label = tsi.labels.get(j);
|
||||
jump = insns.indexOf(label);
|
||||
merge(jump, subroutine);
|
||||
newControlFlowEdge(insn, jump);
|
||||
myEdgeCreator.newControlFlowEdge(insn, jump);
|
||||
}
|
||||
} else if (insnOpcode == RET) {
|
||||
if (subroutine == null) {
|
||||
@@ -149,7 +152,7 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
int call = insns.indexOf(caller);
|
||||
if (wasQueued[call]) {
|
||||
merge(call + 1, subroutines[call], subroutine.access);
|
||||
newControlFlowEdge(insn, call + 1);
|
||||
myEdgeCreator.newControlFlowEdge(insn, call + 1);
|
||||
}
|
||||
}
|
||||
} else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
|
||||
@@ -168,7 +171,7 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
}
|
||||
}
|
||||
merge(insn + 1, subroutine);
|
||||
newControlFlowEdge(insn, insn + 1);
|
||||
myEdgeCreator.newControlFlowEdge(insn, insn + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,14 +192,8 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
}
|
||||
}
|
||||
|
||||
protected void newControlFlowEdge(final int insn, final int successor) {}
|
||||
|
||||
protected boolean newControlFlowExceptionEdge(final int insn, final int successor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean newControlFlowExceptionEdge(final int insn, final TryCatchBlockNode tcb) {
|
||||
return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
|
||||
return myEdgeCreator.newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -243,4 +240,10 @@ public class FramelessAnalyzer extends SubroutineFinder {
|
||||
queue[top++] = insn;
|
||||
}
|
||||
}
|
||||
|
||||
interface EdgeCreator {
|
||||
void newControlFlowEdge(final int insn, final int successor);
|
||||
|
||||
boolean newControlFlowExceptionEdge(final int insn, final int successor);
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -28,6 +28,8 @@ import java.util.List;
|
||||
*/
|
||||
public class LiteFramelessAnalyzer extends FramelessAnalyzer {
|
||||
|
||||
public LiteFramelessAnalyzer(EdgeCreator creator) {super(creator);}
|
||||
|
||||
@Override
|
||||
protected void findSubroutine(int insn, Subroutine sub, List<AbstractInsnNode> calls) throws AnalyzerException {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user