1 package jp.sourceforge.stigmata.birthmarks;
7 import java.io.BufferedReader;
8 import java.io.InputStreamReader;
10 import java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.List;
15 import jp.sourceforge.talisman.csvio.CsvLine;
16 import jp.sourceforge.talisman.csvio.CsvParser;
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;
31 * @author Haruaki Tamada
34 public class OpcodeManager{
35 private Map<Integer, Opcode> opcodeMap = new HashMap<Integer, Opcode>();
36 private static OpcodeManager manager = new OpcodeManager();
39 * private constructor for singleton pattern.
41 private OpcodeManager(){
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]
55 opcodeMap.put(def.getOpcode(), def);
59 throw new InternalError(e.getMessage());
63 public static OpcodeManager getInstance(){
67 public Opcode getOpcode(int opcode){
68 return opcodeMap.get(opcode);
71 private Map<LabelNode, LabelOpcode> labelMap = new HashMap<LabelNode, LabelOpcode>();
73 public Opcode getOpcode(AbstractInsnNode node){
74 Opcode opcode = getOpcode(node.getOpcode());
75 if(opcode == null && node instanceof LabelNode){
76 opcode = labelMap.get(node);
78 opcode = new LabelOpcode(((LabelNode)node).getLabel());
79 labelMap.put((LabelNode)node, (LabelOpcode)opcode);
83 switch(opcode.getCategory()){
85 opcode = constructBranchOpcode(opcode, node);
88 opcode = constructMethodOpcode(opcode, node);
91 opcode = constructObjectOpcode(opcode, node);
93 case NORMAL: // Not needs conversion.
94 case TARGETER: // Already convert above.
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;
114 case Opcodes.INVOKEINTERFACE:
115 case Opcodes.INVOKESPECIAL:
116 case Opcodes.INVOKEVIRTUAL:
117 size = size - argumentSize - 1;
120 methodOpcode.setAct(size);
125 private Opcode constructObjectOpcode(Opcode o, AbstractInsnNode node){
126 Opcode opcode = new Opcode(o);
127 FieldInsnNode field = (FieldInsnNode)node;
129 int size = Type.getType(field.desc).getSize();
130 switch(opcode.getOpcode()){
131 case Opcodes.PUTFIELD:
134 case Opcodes.PUTSTATIC:
137 case Opcodes.GETFIELD:
140 case Opcodes.GETSTATIC:
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());
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());
167 opcode.addLabel(((JumpInsnNode)node).label.getLabel());