OSDN Git Service

メンバをソートした.
[stigmata/stigmata-plugins.git] / cflib / 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 o = new Opcode(manager.getOpcode(opcode));
46         int size = Type.getType(desc).getSize();
47         switch(opcode){
48         case Opcodes.PUTFIELD:
49             size = -1 - size;
50             break;
51         case Opcodes.PUTSTATIC:
52             size = 0 - size;
53             break;
54         case Opcodes.GETFIELD:
55             size = -1 + size;
56             break;
57         case Opcodes.GETSTATIC:
58             size = 0 + size;
59             break;
60         }
61         o.setAct(size);
62         opcodes.add(o);
63         super.visitFieldInsn(opcode, owner, name, desc);
64     }
65
66     @Override
67     public void visitIincInsn(int var, int increment){
68         opcodes.add(manager.getOpcode(Opcodes.IINC));
69         super.visitIincInsn(var, increment);
70     }
71
72     @Override
73     public void visitInsn(int opcode){
74         opcodes.add(manager.getOpcode(opcode));
75         super.visitInsn(opcode);
76     }
77
78     @Override
79     public void visitLabel(Label label){
80         opcodes.add(new LabelOpcode(label));
81     }
82
83     @Override
84     public void visitIntInsn(int opcode, int operand){
85         opcodes.add(manager.getOpcode(opcode));
86         super.visitIntInsn(opcode, operand);
87     }
88
89     @Override
90     public void visitJumpInsn(int opcode, Label label){
91         Opcode o = new Opcode(manager.getOpcode(opcode));
92         o.addLabel(label);
93         opcodes.add(o);
94         super.visitJumpInsn(opcode, label);
95     }
96
97     @Override
98     public void visitLdcInsn(Object value){
99         opcodes.add(manager.getOpcode(Opcodes.LDC));
100         super.visitLdcInsn(value);
101     }
102
103     @Override
104     public void visitTableSwitchInsn(int min, int max, Label defaultLabel, Label[] labels){
105         Opcode tableSwitch = new Opcode(manager.getOpcode(Opcodes.TABLESWITCH));
106         tableSwitch.setLabels(labels);
107         tableSwitch.addLabel(defaultLabel);
108
109         opcodes.add(tableSwitch);
110         super.visitTableSwitchInsn(min, max, defaultLabel, labels);
111     }
112
113     @Override
114     public void visitLookupSwitchInsn(Label defaultHandle, int[] keys, Label[] labels){
115         Opcode lookupSwitch = new Opcode(manager.getOpcode(Opcodes.LOOKUPSWITCH));
116         lookupSwitch.setLabels(labels);
117         lookupSwitch.addLabel(defaultHandle);
118
119         opcodes.add(lookupSwitch);
120         super.visitLookupSwitchInsn(defaultHandle, keys, labels);
121     }
122
123     @Override
124     public void visitMethodInsn(int opcode, String owner, String name, String desc){
125         Opcode methodOpcode = new Opcode(manager.getOpcode(opcode));
126         Type[] types = Type.getArgumentTypes(desc);
127         int argumentSize = 0;
128         for(Type type: types) argumentSize = type.getSize();
129         int size = Type.getReturnType(desc).getSize();
130         switch(opcode){
131         case Opcodes.INVOKESTATIC:
132             size = size - argumentSize;
133             break;
134         case Opcodes.INVOKEINTERFACE:
135         case Opcodes.INVOKESPECIAL:
136         case Opcodes.INVOKEVIRTUAL:
137             size = size - argumentSize - 1;
138             break;
139         }
140         methodOpcode.setAct(size);
141
142         opcodes.add(methodOpcode);
143         super.visitMethodInsn(opcode, owner, name, desc);
144     }
145
146     @Override
147     public void visitMultiANewArrayInsn(String desc, int dims){
148         opcodes.add(manager.getOpcode(Opcodes.MULTIANEWARRAY));
149         super.visitMultiANewArrayInsn(desc, dims);
150     }
151
152     @Override
153     public void visitTypeInsn(int opcode, String desc){
154         opcodes.add(manager.getOpcode(opcode));
155         super.visitTypeInsn(opcode, desc);
156     }
157
158     @Override
159     public void visitVarInsn(int opcode, int var){
160         opcodes.add(manager.getOpcode(opcode));
161         super.visitVarInsn(opcode, var);
162     }
163
164     @Override
165     public void visitEnd(){
166         for(OpcodeExtractListener listener: listeners){
167             listener.extractOpcodesFinished(opcodes);
168         }
169     }
170 }