OSDN Git Service

Exceptionフローも解析可能に.
[stigmata/stigmata-plugins.git] / opcodes / src / main / java / jp / sourceforge / stigmata / birthmarks / BasicBlock.java
1 package jp.sourceforge.stigmata.birthmarks;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collections;\r
5 import java.util.HashSet;\r
6 import java.util.Iterator;\r
7 import java.util.List;\r
8 import java.util.Set;\r
9 \r
10 import org.objectweb.asm.Label;\r
11 import org.objectweb.asm.Opcodes;\r
12 import org.objectweb.asm.tree.AbstractInsnNode;\r
13 import org.objectweb.asm.tree.InsnNode;\r
14 \r
15 /**\r
16  * 基本ブロックを表すクラス.\r
17  * \r
18  * @author tamada\r
19  */\r
20 public class BasicBlock {\r
21     private Set<BasicBlock> nexts = new HashSet<BasicBlock>();\r
22     private List<Opcode> opcodes = new ArrayList<Opcode>();\r
23     private Set<BasicBlock> prevs = new HashSet<BasicBlock>();\r
24     Set<Label> exceptionFlows = new HashSet<Label>();\r
25 \r
26     BasicBlock(){\r
27     }\r
28 \r
29     public BasicBlock(InsnNode[] nodeArray){\r
30         for(InsnNode node: nodeArray){\r
31             addNode(node);\r
32         }\r
33     }\r
34 \r
35     void addNode(AbstractInsnNode node){\r
36         OpcodeManager manager = OpcodeManager.getInstance();\r
37         Opcode opcode = manager.getOpcode(node);\r
38         if(opcode != null){\r
39             addNode(opcode);\r
40         }\r
41     }\r
42 \r
43     void addNode(Opcode opcode){\r
44         opcodes.add(opcode);\r
45     }\r
46 \r
47     public Opcode getOpcode(int index){\r
48         return opcodes.get(index);\r
49     }\r
50 \r
51     public int getSize(){\r
52         return opcodes.size();\r
53     }\r
54 \r
55     public Label[] getTargets(){\r
56         Set<Label> targets = new HashSet<Label>();\r
57         for(Opcode opcode: opcodes){\r
58             if(opcode.getCategory() != Opcode.Category.TARGETER){\r
59                 Label[] labels = opcode.getLabels();\r
60                 for(Label label: labels){\r
61                     targets.add(label);\r
62                 }\r
63             }\r
64         }\r
65         for(Label label: exceptionFlows){\r
66             targets.add(label);\r
67         }\r
68 \r
69         return targets.toArray(new Label[targets.size()]);\r
70     }\r
71 \r
72     public boolean hasLabel(Label label){\r
73         boolean flag = false;\r
74         for(Opcode opcode: opcodes){\r
75             if(flag || opcode.hasLabel(label)){\r
76                 flag = true;\r
77             }\r
78         }\r
79         return flag;\r
80     }\r
81 \r
82     public boolean isEmpty(){\r
83         return opcodes.size() == 0;\r
84     }\r
85 \r
86     public Iterator<BasicBlock> nextIterator(){\r
87         return Collections.unmodifiableSet(nexts).iterator();\r
88     }\r
89 \r
90     public Iterator<BasicBlock> previousIterator(){\r
91         return Collections.unmodifiableSet(prevs).iterator();\r
92     }\r
93 \r
94     public void setNext(BasicBlock block){\r
95         block.prevs.add(this);\r
96         nexts.add(block);\r
97     }\r
98 \r
99     public void setPrev(BasicBlock block){\r
100         block.nexts.add(this);\r
101         prevs.add(block);\r
102     }\r
103 \r
104     public String toString(){\r
105         StringBuilder sb = new StringBuilder("---- block ----");\r
106         String ln = System.getProperty("line.separator");\r
107         for(Opcode opcode: opcodes){\r
108             sb.append(ln).append(opcode);\r
109         }\r
110         sb.append(ln).append("Targeter: ");\r
111         for(Label label: getTargets()){\r
112             sb.append(label).append(", ");\r
113         }\r
114         return new String(sb);\r
115     }\r
116 \r
117     public boolean isFlowNext(){\r
118         Opcode opcode = getOpcode(getSize() - 1);\r
119         int op = opcode.getOpcode();\r
120 \r
121         return op != Opcodes.GOTO && op != Opcodes.RETURN\r
122         && op != Opcodes.RET && op != Opcodes.ATHROW;\r
123     }\r
124 }\r