rlm@10
|
1 /***
|
rlm@10
|
2 * ASM: a very small and fast Java bytecode manipulation framework
|
rlm@10
|
3 * Copyright (c) 2000-2005 INRIA, France Telecom
|
rlm@10
|
4 * All rights reserved.
|
rlm@10
|
5 *
|
rlm@10
|
6 * Redistribution and use in source and binary forms, with or without
|
rlm@10
|
7 * modification, are permitted provided that the following conditions
|
rlm@10
|
8 * are met:
|
rlm@10
|
9 * 1. Redistributions of source code must retain the above copyright
|
rlm@10
|
10 * notice, this list of conditions and the following disclaimer.
|
rlm@10
|
11 * 2. Redistributions in binary form must reproduce the above copyright
|
rlm@10
|
12 * notice, this list of conditions and the following disclaimer in the
|
rlm@10
|
13 * documentation and/or other materials provided with the distribution.
|
rlm@10
|
14 * 3. Neither the name of the copyright holders nor the names of its
|
rlm@10
|
15 * contributors may be used to endorse or promote products derived from
|
rlm@10
|
16 * this software without specific prior written permission.
|
rlm@10
|
17 *
|
rlm@10
|
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
rlm@10
|
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
rlm@10
|
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
rlm@10
|
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
rlm@10
|
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
rlm@10
|
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
rlm@10
|
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
rlm@10
|
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
rlm@10
|
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
rlm@10
|
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
rlm@10
|
28 * THE POSSIBILITY OF SUCH DAMAGE.
|
rlm@10
|
29 */
|
rlm@10
|
30 package clojure.asm.commons;
|
rlm@10
|
31
|
rlm@10
|
32 import clojure.asm.Label;
|
rlm@10
|
33 import clojure.asm.MethodAdapter;
|
rlm@10
|
34 import clojure.asm.MethodVisitor;
|
rlm@10
|
35 import clojure.asm.Opcodes;
|
rlm@10
|
36
|
rlm@10
|
37 /**
|
rlm@10
|
38 * A {@link MethodAdapter} that can be used to approximate method size.
|
rlm@10
|
39 *
|
rlm@10
|
40 * @author Eugene Kuleshov
|
rlm@10
|
41 */
|
rlm@10
|
42 public class CodeSizeEvaluator extends MethodAdapter implements Opcodes{
|
rlm@10
|
43
|
rlm@10
|
44 private int minSize;
|
rlm@10
|
45
|
rlm@10
|
46 private int maxSize;
|
rlm@10
|
47
|
rlm@10
|
48 public CodeSizeEvaluator(final MethodVisitor mv){
|
rlm@10
|
49 super(mv);
|
rlm@10
|
50 }
|
rlm@10
|
51
|
rlm@10
|
52 public int getMinSize(){
|
rlm@10
|
53 return this.minSize;
|
rlm@10
|
54 }
|
rlm@10
|
55
|
rlm@10
|
56 public int getMaxSize(){
|
rlm@10
|
57 return this.maxSize;
|
rlm@10
|
58 }
|
rlm@10
|
59
|
rlm@10
|
60 public void visitInsn(final int opcode){
|
rlm@10
|
61 minSize += 1;
|
rlm@10
|
62 maxSize += 1;
|
rlm@10
|
63 if(mv != null)
|
rlm@10
|
64 {
|
rlm@10
|
65 mv.visitInsn(opcode);
|
rlm@10
|
66 }
|
rlm@10
|
67 }
|
rlm@10
|
68
|
rlm@10
|
69 public void visitIntInsn(final int opcode, final int operand){
|
rlm@10
|
70 if(opcode == SIPUSH)
|
rlm@10
|
71 {
|
rlm@10
|
72 minSize += 3;
|
rlm@10
|
73 maxSize += 3;
|
rlm@10
|
74 }
|
rlm@10
|
75 else
|
rlm@10
|
76 {
|
rlm@10
|
77 minSize += 2;
|
rlm@10
|
78 maxSize += 2;
|
rlm@10
|
79 }
|
rlm@10
|
80 if(mv != null)
|
rlm@10
|
81 {
|
rlm@10
|
82 mv.visitIntInsn(opcode, operand);
|
rlm@10
|
83 }
|
rlm@10
|
84 }
|
rlm@10
|
85
|
rlm@10
|
86 public void visitVarInsn(final int opcode, final int var){
|
rlm@10
|
87 if(var < 4 && opcode != Opcodes.RET)
|
rlm@10
|
88 {
|
rlm@10
|
89 minSize += 1;
|
rlm@10
|
90 maxSize += 1;
|
rlm@10
|
91 }
|
rlm@10
|
92 else if(var >= 256)
|
rlm@10
|
93 {
|
rlm@10
|
94 minSize += 4;
|
rlm@10
|
95 maxSize += 4;
|
rlm@10
|
96 }
|
rlm@10
|
97 else
|
rlm@10
|
98 {
|
rlm@10
|
99 minSize += 2;
|
rlm@10
|
100 maxSize += 2;
|
rlm@10
|
101 }
|
rlm@10
|
102 if(mv != null)
|
rlm@10
|
103 {
|
rlm@10
|
104 mv.visitVarInsn(opcode, var);
|
rlm@10
|
105 }
|
rlm@10
|
106 }
|
rlm@10
|
107
|
rlm@10
|
108 public void visitTypeInsn(final int opcode, final String desc){
|
rlm@10
|
109 minSize += 3;
|
rlm@10
|
110 maxSize += 3;
|
rlm@10
|
111 if(mv != null)
|
rlm@10
|
112 {
|
rlm@10
|
113 mv.visitTypeInsn(opcode, desc);
|
rlm@10
|
114 }
|
rlm@10
|
115 }
|
rlm@10
|
116
|
rlm@10
|
117 public void visitFieldInsn(
|
rlm@10
|
118 final int opcode,
|
rlm@10
|
119 final String owner,
|
rlm@10
|
120 final String name,
|
rlm@10
|
121 final String desc){
|
rlm@10
|
122 minSize += 3;
|
rlm@10
|
123 maxSize += 3;
|
rlm@10
|
124 if(mv != null)
|
rlm@10
|
125 {
|
rlm@10
|
126 mv.visitFieldInsn(opcode, owner, name, desc);
|
rlm@10
|
127 }
|
rlm@10
|
128 }
|
rlm@10
|
129
|
rlm@10
|
130 public void visitMethodInsn(
|
rlm@10
|
131 final int opcode,
|
rlm@10
|
132 final String owner,
|
rlm@10
|
133 final String name,
|
rlm@10
|
134 final String desc){
|
rlm@10
|
135 if(opcode == INVOKEINTERFACE)
|
rlm@10
|
136 {
|
rlm@10
|
137 minSize += 5;
|
rlm@10
|
138 maxSize += 5;
|
rlm@10
|
139 }
|
rlm@10
|
140 else
|
rlm@10
|
141 {
|
rlm@10
|
142 minSize += 3;
|
rlm@10
|
143 maxSize += 3;
|
rlm@10
|
144 }
|
rlm@10
|
145 if(mv != null)
|
rlm@10
|
146 {
|
rlm@10
|
147 mv.visitMethodInsn(opcode, owner, name, desc);
|
rlm@10
|
148 }
|
rlm@10
|
149 }
|
rlm@10
|
150
|
rlm@10
|
151 public void visitJumpInsn(final int opcode, final Label label){
|
rlm@10
|
152 minSize += 3;
|
rlm@10
|
153 if(opcode == GOTO || opcode == JSR)
|
rlm@10
|
154 {
|
rlm@10
|
155 maxSize += 5;
|
rlm@10
|
156 }
|
rlm@10
|
157 else
|
rlm@10
|
158 {
|
rlm@10
|
159 maxSize += 8;
|
rlm@10
|
160 }
|
rlm@10
|
161 if(mv != null)
|
rlm@10
|
162 {
|
rlm@10
|
163 mv.visitJumpInsn(opcode, label);
|
rlm@10
|
164 }
|
rlm@10
|
165 }
|
rlm@10
|
166
|
rlm@10
|
167 public void visitLdcInsn(final Object cst){
|
rlm@10
|
168 if(cst instanceof Long || cst instanceof Double)
|
rlm@10
|
169 {
|
rlm@10
|
170 minSize += 3;
|
rlm@10
|
171 maxSize += 3;
|
rlm@10
|
172 }
|
rlm@10
|
173 else
|
rlm@10
|
174 {
|
rlm@10
|
175 minSize += 2;
|
rlm@10
|
176 maxSize += 3;
|
rlm@10
|
177 }
|
rlm@10
|
178 if(mv != null)
|
rlm@10
|
179 {
|
rlm@10
|
180 mv.visitLdcInsn(cst);
|
rlm@10
|
181 }
|
rlm@10
|
182 }
|
rlm@10
|
183
|
rlm@10
|
184 public void visitIincInsn(final int var, final int increment){
|
rlm@10
|
185 if(var > 255 || increment > 127 || increment < -128)
|
rlm@10
|
186 {
|
rlm@10
|
187 minSize += 6;
|
rlm@10
|
188 maxSize += 6;
|
rlm@10
|
189 }
|
rlm@10
|
190 else
|
rlm@10
|
191 {
|
rlm@10
|
192 minSize += 3;
|
rlm@10
|
193 maxSize += 3;
|
rlm@10
|
194 }
|
rlm@10
|
195 if(mv != null)
|
rlm@10
|
196 {
|
rlm@10
|
197 mv.visitIincInsn(var, increment);
|
rlm@10
|
198 }
|
rlm@10
|
199 }
|
rlm@10
|
200
|
rlm@10
|
201 public void visitTableSwitchInsn(
|
rlm@10
|
202 final int min,
|
rlm@10
|
203 final int max,
|
rlm@10
|
204 final Label dflt,
|
rlm@10
|
205 final Label[] labels){
|
rlm@10
|
206 minSize += 13 + labels.length * 4;
|
rlm@10
|
207 maxSize += 16 + labels.length * 4;
|
rlm@10
|
208 if(mv != null)
|
rlm@10
|
209 {
|
rlm@10
|
210 mv.visitTableSwitchInsn(min, max, dflt, labels);
|
rlm@10
|
211 }
|
rlm@10
|
212 }
|
rlm@10
|
213
|
rlm@10
|
214 public void visitLookupSwitchInsn(
|
rlm@10
|
215 final Label dflt,
|
rlm@10
|
216 final int[] keys,
|
rlm@10
|
217 final Label[] labels){
|
rlm@10
|
218 minSize += 9 + keys.length * 8;
|
rlm@10
|
219 maxSize += 12 + keys.length * 8;
|
rlm@10
|
220 if(mv != null)
|
rlm@10
|
221 {
|
rlm@10
|
222 mv.visitLookupSwitchInsn(dflt, keys, labels);
|
rlm@10
|
223 }
|
rlm@10
|
224 }
|
rlm@10
|
225
|
rlm@10
|
226 public void visitMultiANewArrayInsn(final String desc, final int dims){
|
rlm@10
|
227 minSize += 4;
|
rlm@10
|
228 maxSize += 4;
|
rlm@10
|
229 if(mv != null)
|
rlm@10
|
230 {
|
rlm@10
|
231 mv.visitMultiANewArrayInsn(desc, dims);
|
rlm@10
|
232 }
|
rlm@10
|
233 }
|
rlm@10
|
234 }
|