OSDN Git Service

fixed some typo
[stigmata/stigmata-plugins.git] / opcodes / src / main / java / jp / sourceforge / stigmata / birthmarks / OpcodeExtractMethodVisitor.java
1 package jp.sourceforge.stigmata.birthmarks;
2
3 /*
4  * $Id$
5  */
6
7 import java.util.ArrayList;
8 import java.util.List;
9
10 import org.objectweb.asm.Label;
11 import org.objectweb.asm.MethodAdapter;
12 import org.objectweb.asm.MethodVisitor;
13 import org.objectweb.asm.Opcodes;
14 import org.objectweb.asm.Type;
15
16 /**
17  *
18  * @author Haruaki TAMADA
19  * @version $Revision$
20  */
21 public class OpcodeExtractMethodVisitor extends MethodAdapter{
22     private List<Opcode> opcodes;
23     private OpcodeManager manager = OpcodeManager.getInstance();
24     private List<OpcodeExtractListener> listeners = new ArrayList<OpcodeExtractListener>();
25
26     public OpcodeExtractMethodVisitor(MethodVisitor visitor){
27         this(visitor, new ArrayList<Opcode>());
28     }
29
30     public OpcodeExtractMethodVisitor(MethodVisitor visitor, List<Opcode> opcodes){
31         super(visitor);
32         this.opcodes = opcodes;
33     }
34
35     public void addOpcodeExtractListener(OpcodeExtractListener listener){
36         listeners.add(listener);
37     }
38
39     public void removeOpcodeExtractListener(OpcodeExtractListener listener){
40         listeners.add(listener);
41     }
42
43     @Override
44     public void visitFieldInsn(int opcode, String owner, String name, String desc){
45         Opcode field = manager.getOpcode(opcode);
46         Opcode o = new Opcode(field);
47         int size = Type.getType(desc).getSize();
48         switch(opcode){
49         case Opcodes.PUTFIELD:
50             size = -1 - size;
51             break;
52         case Opcodes.PUTSTATIC:
53             size = 0 - size;
54             break;
55         case Opcodes.GETFIELD:
56             size = -1 + size;
57             break;
58         case Opcodes.GETSTATIC:
59             size = 0 + size;
60             break;
61         }
62         o.setAct(size);
63         opcodes.add(o);
64         super.visitFieldInsn(opcode, owner, name, desc);
65     }
66
67     @Override
68     public void visitIincInsn(int var, int increment){
69         opcodes.add(manager.getOpcode(Opcodes.IINC));
70         super.visitIincInsn(var, increment);
71     }
72
73     @Override
74     public void visitInsn(int opcode){
75         opcodes.add(manager.getOpcode(opcode));
76         super.visitInsn(opcode);
77     }
78
79     @Override
80     public void visitLabel(Label label){
81         opcodes.add(new LabelOpcode(label));
82     }
83
84     @Override
85     public void visitIntInsn(int opcode, int operand){
86         opcodes.add(manager.getOpcode(opcode));
87         super.visitIntInsn(opcode, operand);
88     }
89
90     @Override
91     public void visitJumpInsn(int opcode, Label label){
92         Opcode o = manager.getOpcode(opcode);
93         o.addLabel(label);
94         opcodes.add(o);
95         super.visitJumpInsn(opcode, label);
96     }
97
98     @Override
99     public void visitLdcInsn(Object value){
100         opcodes.add(manager.getOpcode(Opcodes.LDC));
101         super.visitLdcInsn(value);
102     }
103
104     @Override
105     public void visitTableSwitchInsn(int min, int max, Label defaultLabel, Label[] labels){
106         Opcode tableSwitch = new Opcode(manager.getOpcode(Opcodes.TABLESWITCH));
107         tableSwitch.setLabels(labels);
108         tableSwitch.addLabel(defaultLabel);
109
110         opcodes.add(tableSwitch);
111         super.visitTableSwitchInsn(min, max, defaultLabel, labels);
112     }
113
114     @Override
115     public void visitLookupSwitchInsn(Label defaultHandle, int[] keys, Label[] labels){
116         Opcode lookupSwitch = new Opcode(manager.getOpcode(Opcodes.LOOKUPSWITCH));
117         lookupSwitch.setLabels(labels);
118         lookupSwitch.addLabel(defaultHandle);
119
120         opcodes.add(lookupSwitch);
121         super.visitLookupSwitchInsn(defaultHandle, keys, labels);
122     }
123
124     @Override
125     public void visitMethodInsn(int opcode, String owner, String name, String desc){
126         Opcode methodOpcode = new Opcode(manager.getOpcode(opcode));
127         Type[] types = Type.getArgumentTypes(desc);
128         int argumentSize = 0;
129         for(Type type: types) argumentSize = type.getSize();
130         int size = Type.getReturnType(desc).getSize();
131         switch(opcode){
132         case Opcodes.INVOKESTATIC:
133             size = size - argumentSize;
134             break;
135         case Opcodes.INVOKEINTERFACE:
136         case Opcodes.INVOKESPECIAL:
137         case Opcodes.INVOKEVIRTUAL:
138             size = size - argumentSize - 1;
139             break;
140         }
141         methodOpcode.setAct(size);
142
143         opcodes.add(methodOpcode);
144         super.visitMethodInsn(opcode, owner, name, desc);
145     }
146
147     @Override
148     public void visitMultiANewArrayInsn(String desc, int dims){
149         opcodes.add(manager.getOpcode(Opcodes.MULTIANEWARRAY));
150         super.visitMultiANewArrayInsn(desc, dims);
151     }
152
153     @Override
154     public void visitTypeInsn(int opcode, String desc){
155         opcodes.add(manager.getOpcode(opcode));
156         super.visitTypeInsn(opcode, desc);
157     }
158
159     @Override
160     public void visitVarInsn(int opcode, int var){
161         opcodes.add(manager.getOpcode(opcode));
162         super.visitVarInsn(opcode, var);
163     }
164
165     @Override
166     public void visitEnd(){
167         for(OpcodeExtractListener listener: listeners){
168             listener.extractOpcodesFinished(opcodes);
169         }
170     }
171 }