OSDN Git Service

メンバをソートした.
[stigmata/stigmata-plugins.git] / cflib / src / main / java / jp / sourceforge / stigmata / birthmarks / OpcodeManager.java
1 package jp.sourceforge.stigmata.birthmarks;
2
3 /*
4  * $Id$
5  */
6
7 import java.io.BufferedReader;
8 import java.io.InputStreamReader;
9 import java.net.URL;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.List;
13 import java.util.Map;
14
15 import jp.sourceforge.talisman.csvio.CsvLine;
16 import jp.sourceforge.talisman.csvio.CsvParser;
17
18 import org.objectweb.asm.Label;
19 import org.objectweb.asm.Opcodes;
20 import org.objectweb.asm.Type;
21 import org.objectweb.asm.tree.AbstractInsnNode;
22 import org.objectweb.asm.tree.FieldInsnNode;
23 import org.objectweb.asm.tree.JumpInsnNode;
24 import org.objectweb.asm.tree.LabelNode;
25 import org.objectweb.asm.tree.LookupSwitchInsnNode;
26 import org.objectweb.asm.tree.MethodInsnNode;
27 import org.objectweb.asm.tree.TableSwitchInsnNode;
28
29 /** 
30  * 
31  * @author Haruaki Tamada
32  * @version $Revision$
33  */
34 public class OpcodeManager{
35     private Map<Integer, Opcode> opcodeMap = new HashMap<Integer, Opcode>();
36     private static OpcodeManager manager = new OpcodeManager();
37
38     /**
39      * private constructor for singleton pattern.
40      */
41     private OpcodeManager(){
42         try{
43             URL location = OpcodeManager.class.getResource("/META-INF/bytecode.def");
44             BufferedReader in = new BufferedReader(new InputStreamReader(location.openStream()));
45             CsvParser parser = new CsvParser(in);
46             while(parser.hasNext()){
47                 CsvLine line = parser.next();
48                 String[] values = line.getValues();
49                 if(values.length == 5){
50                     Opcode def = new Opcode(
51                         Integer.parseInt(values[0]), values[1],
52                         Integer.parseInt(values[2]),
53                         Integer.parseInt(values[3]), values[4]
54                     );
55                     opcodeMap.put(def.getOpcode(), def);
56                 }
57             }
58         } catch(Exception e){
59             throw new InternalError(e.getMessage());
60         }
61     }
62
63     public static OpcodeManager getInstance(){
64         return manager;
65     }
66
67     public Opcode getOpcode(int opcode){
68         return opcodeMap.get(opcode);
69     }
70
71     private Map<LabelNode, LabelOpcode> labelMap = new HashMap<LabelNode, LabelOpcode>();
72
73     public Opcode getOpcode(AbstractInsnNode node){
74         Opcode opcode = getOpcode(node.getOpcode());
75         if(opcode == null && node instanceof LabelNode){
76             opcode = labelMap.get(node);
77             if(opcode == null){
78                 opcode = new LabelOpcode(((LabelNode)node).getLabel());
79                 labelMap.put((LabelNode)node, (LabelOpcode)opcode);
80             }
81         }
82         if(opcode != null){
83             switch(opcode.getCategory()){
84             case BRANCH:
85                 opcode = constructBranchOpcode(opcode, node);
86                 break;
87             case INVOKE:
88                 opcode = constructMethodOpcode(opcode, node);
89                 break;
90             case OBJECT:
91                 opcode = constructObjectOpcode(opcode, node);
92                 break;
93             case NORMAL:   // Not needs conversion.
94             case TARGETER: // Already convert above.
95             default:
96                 break;
97             }
98         }
99
100         return opcode;
101     }
102
103     private Opcode constructMethodOpcode(Opcode o, AbstractInsnNode node){
104         Opcode methodOpcode = new Opcode(o);
105         MethodInsnNode methodNode = (MethodInsnNode)node;
106         Type[] types = Type.getArgumentTypes(methodNode.desc);
107         int argumentSize = 0;
108         for(Type type: types) argumentSize = type.getSize();
109         int size = Type.getReturnType(methodNode.desc).getSize();
110         switch(o.getOpcode()){
111         case Opcodes.INVOKESTATIC:
112             size = size - argumentSize;
113             break;
114         case Opcodes.INVOKEINTERFACE:
115         case Opcodes.INVOKESPECIAL:
116         case Opcodes.INVOKEVIRTUAL:
117             size = size - argumentSize - 1;
118             break;
119         }
120         methodOpcode.setAct(size);
121
122         return methodOpcode;
123     }
124
125     private Opcode constructObjectOpcode(Opcode o, AbstractInsnNode node){
126         Opcode opcode = new Opcode(o);
127         FieldInsnNode field = (FieldInsnNode)node;
128         
129         int size = Type.getType(field.desc).getSize();
130         switch(opcode.getOpcode()){
131         case Opcodes.PUTFIELD:
132             size = -1 - size;
133             break;
134         case Opcodes.PUTSTATIC:
135             size = 0 - size;
136             break;
137         case Opcodes.GETFIELD:
138             size = -1 + size;
139             break;
140         case Opcodes.GETSTATIC:
141             size = 0 + size;
142             break;
143         }
144         opcode.setAct(size);
145         return opcode;
146     }
147
148     private Opcode constructBranchOpcode(Opcode defaultOpcode, AbstractInsnNode node){
149         Opcode opcode = new Opcode(defaultOpcode);
150         if(node instanceof TableSwitchInsnNode){
151             TableSwitchInsnNode table = (TableSwitchInsnNode)node;
152             List<Label> labels = new ArrayList<Label>();
153             labels.add(table.dflt.getLabel());
154             for(Object o: table.labels){
155                 labels.add(((LabelNode)o).getLabel());
156             }
157         }
158         else if(node instanceof LookupSwitchInsnNode){
159             LookupSwitchInsnNode lookup = (LookupSwitchInsnNode)node;
160             List<Label> labels = new ArrayList<Label>();
161             labels.add(lookup.dflt.getLabel());
162             for(Object o: lookup.labels){
163                 labels.add(((LabelNode)o).getLabel());
164             }
165         }
166         else{
167             opcode.addLabel(((JumpInsnNode)node).label.getLabel());
168         }
169         return opcode;
170     }
171 }