import org.objectweb.asm.tree.TableSwitchInsnNode;\r
import org.objectweb.asm.tree.TryCatchBlockNode;\r
\r
+/**\r
+ * コントロールフローを表すクラス.\r
+ * @author tamada\r
+ *\r
+ */\r
public class ControlFlowGraph {\r
- private String name;\r
+ private BasicBlock[] blocks;\r
private boolean includeException;\r
private MethodNode method;\r
- private BasicBlock[] blocks;\r
+ private String name;\r
\r
public ControlFlowGraph(String name, MethodNode node){\r
this(name, node, false);\r
parse(method);\r
}\r
\r
- public int[][] getGraphMatrix(){\r
- int[][] matrix = new int[blocks.length][blocks.length];\r
+ private void buildExceptionFlow(AbstractInsnNode inst, Set<Label> exceptionFlows, TryCatchBlockNode[] tryCatches){\r
+ if(inst.getType() == AbstractInsnNode.LABEL){\r
+ Label label = ((LabelNode)inst).getLabel();\r
\r
- for(int i = 0; i < blocks.length; i++){\r
- for(int j = 0; j < blocks.length; j++){\r
- int nextValue = 0;\r
- for(Iterator<BasicBlock> iter = blocks[i].nextIterator(); iter.hasNext(); ){\r
- BasicBlock nextBlock = iter.next();\r
- if(nextBlock == blocks[j]){\r
- nextValue = 1;\r
- break;\r
- }\r
+ for(TryCatchBlockNode node: tryCatches){\r
+ if(node.start.getLabel() == label){\r
+ exceptionFlows.add(node.handler.getLabel());\r
+ }\r
+ else if(node.end.getLabel() == label){\r
+ exceptionFlows.remove(node.handler.getLabel());\r
}\r
- matrix[i][j] = nextValue;\r
}\r
}\r
-\r
- return matrix;\r
- }\r
-\r
- public String getName(){\r
- return name;\r
- }\r
-\r
- public int getBasicBlockSize(){\r
- return blocks.length;\r
- }\r
-\r
- public boolean isIncludingExceptionFlow(){\r
- return includeException;\r
}\r
\r
- public void setIncludingExceptionFlow(boolean includeException){\r
- boolean oldvalue = this.includeException;\r
- this.includeException = includeException;\r
- if(oldvalue != includeException){\r
- parse(method);\r
+ /**\r
+ * TryCatchブロックの一覧を返します.\r
+ * Try Catchブロックが含まれていない場合や,\r
+ * {@link isIncludingExceptionFlow}がfalseを返す場合は長さ0の配列を返します.\r
+ * @param node\r
+ * @return\r
+ */\r
+ private TryCatchBlockNode[] buildTryCatchBlockNode(MethodNode node){\r
+ TryCatchBlockNode[] nodes = new TryCatchBlockNode[0];\r
+ if(isIncludingExceptionFlow()){\r
+ nodes = new TryCatchBlockNode[node.tryCatchBlocks.size()];\r
+ for(int i = 0; i < nodes.length; i++){\r
+ nodes[i] = (TryCatchBlockNode)node.tryCatchBlocks.get(i);\r
+ }\r
}\r
+ return nodes;\r
}\r
\r
private Set<LabelNode> collectLabels(MethodNode node){\r
return jumpTarget;\r
}\r
\r
- /**\r
- * TryCatchブロックの一覧を返します.\r
- * Try Catchブロックが含まれていない場合や,\r
- * {@link isIncludingExceptionFlow}がfalseを返す場合は長さ0の配列を返します.\r
- * @param node\r
- * @return\r
- */\r
- private TryCatchBlockNode[] buildTryCatchBlockNode(MethodNode node){\r
- TryCatchBlockNode[] nodes = new TryCatchBlockNode[0];\r
- if(isIncludingExceptionFlow()){\r
- nodes = new TryCatchBlockNode[node.tryCatchBlocks.size()];\r
- for(int i = 0; i < nodes.length; i++){\r
- nodes[i] = (TryCatchBlockNode)node.tryCatchBlocks.get(i);\r
+ public int getBasicBlockSize(){\r
+ return blocks.length;\r
+ }\r
+\r
+ public int[][] getGraphMatrix(){\r
+ int[][] matrix = new int[blocks.length][blocks.length];\r
+\r
+ for(int i = 0; i < blocks.length; i++){\r
+ for(int j = 0; j < blocks.length; j++){\r
+ int nextValue = 0;\r
+ for(Iterator<BasicBlock> iter = blocks[i].nextIterator(); iter.hasNext(); ){\r
+ BasicBlock nextBlock = iter.next();\r
+ if(nextBlock == blocks[j]){\r
+ nextValue = 1;\r
+ break;\r
+ }\r
+ }\r
+ matrix[i][j] = nextValue;\r
}\r
}\r
- return nodes;\r
+\r
+ return matrix;\r
}\r
\r
- private void buildExceptionFlow(AbstractInsnNode inst, Set<Label> exceptionFlows, TryCatchBlockNode[] tryCatches){\r
- if(inst.getType() == AbstractInsnNode.LABEL){\r
- Label label = ((LabelNode)inst).getLabel();\r
+ public String getName(){\r
+ return name;\r
+ }\r
\r
- for(TryCatchBlockNode node: tryCatches){\r
- if(node.start.getLabel() == label){\r
- exceptionFlows.add(node.handler.getLabel());\r
- }\r
- else if(node.end.getLabel() == label){\r
- exceptionFlows.remove(node.handler.getLabel());\r
+ public boolean isIncludingExceptionFlow(){\r
+ return includeException;\r
+ }\r
+\r
+ private BasicBlock[] joinBasicBlocks(BasicBlock[] blocks){\r
+ for(int i = 0; i < blocks.length; i++){\r
+ Label[] labels = blocks[i].getTargets();\r
+ for(int j = 0; j < labels.length; j++){\r
+ for(int k = 0; k < blocks.length; k++){\r
+ if(i != k && blocks[k].hasLabel(labels[j])){\r
+ blocks[i].setNext(blocks[k]);\r
+ break;\r
+ }\r
}\r
}\r
+ if((i + 1) < blocks.length && blocks[i].isFlowNext()){\r
+ blocks[i].setNext(blocks[i + 1]);\r
+ }\r
}\r
+\r
+ return blocks;\r
+ }\r
+\r
+ private void parse(MethodNode node){\r
+ Set<LabelNode> jumpTarget = collectLabels(node);\r
+ BasicBlock[] blocks = separateBasicBlock(node, jumpTarget);\r
+ this.blocks = joinBasicBlocks(blocks);\r
}\r
\r
private BasicBlock[] separateBasicBlock(MethodNode node, Set<LabelNode> jumpTarget){\r
return blockList.toArray(new BasicBlock[blockList.size()]);\r
}\r
\r
- private BasicBlock[] joinBasicBlocks(BasicBlock[] blocks){\r
- for(int i = 0; i < blocks.length; i++){\r
- Label[] labels = blocks[i].getTargets();\r
- for(int j = 0; j < labels.length; j++){\r
- for(int k = 0; k < blocks.length; k++){\r
- if(i != k && blocks[k].hasLabel(labels[j])){\r
- blocks[i].setNext(blocks[k]);\r
- break;\r
- }\r
- }\r
- }\r
- if((i + 1) < blocks.length && blocks[i].isFlowNext()){\r
- blocks[i].setNext(blocks[i + 1]);\r
- }\r
+ public void setIncludingExceptionFlow(boolean includeException){\r
+ boolean oldvalue = this.includeException;\r
+ this.includeException = includeException;\r
+ if(oldvalue != includeException){\r
+ parse(method);\r
}\r
-\r
- return blocks;\r
- }\r
-\r
- private void parse(MethodNode node){\r
- Set<LabelNode> jumpTarget = collectLabels(node);\r
- BasicBlock[] blocks = separateBasicBlock(node, jumpTarget);\r
- this.blocks = joinBasicBlocks(blocks);\r
}\r
}\r