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