• 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.tree.analysis;
29 
30 import java.util.List;
31 import org.objectweb.asm.Opcodes;
32 import org.objectweb.asm.Type;
33 import org.objectweb.asm.tree.AbstractInsnNode;
34 import org.objectweb.asm.tree.TryCatchBlockNode;
35 
36 /**
37  * A semantic bytecode interpreter. More precisely, this interpreter only manages the computation of
38  * values from other values: it does not manage the transfer of values to or from the stack, and to
39  * or from the local variables. This separation allows a generic bytecode {@link Analyzer} to work
40  * with various semantic interpreters, without needing to duplicate the code to simulate the
41  * transfer of values.
42  *
43  * @param <V> type of the Value used for the analysis.
44  * @author Eric Bruneton
45  */
46 public abstract class Interpreter<V extends Value> {
47 
48   /**
49    * The ASM API version supported by this interpreter. The value of this field must be one of the
50    * {@code ASM}<i>x</i> values in {@link Opcodes}.
51    */
52   protected final int api;
53 
54   /**
55    * Constructs a new {@link Interpreter}.
56    *
57    * @param api the ASM API version supported by this interpreter. Must be one of the {@code
58    *     ASM}<i>x</i> values in {@link Opcodes}.
59    */
Interpreter(final int api)60   protected Interpreter(final int api) {
61     this.api = api;
62   }
63 
64   /**
65    * Creates a new value that represents the given type.
66    *
67    * <p>Called for method parameters (including <code>this</code>), exception handler variable and
68    * with <code>null</code> type for variables reserved by long and double types.
69    *
70    * <p>An interpreter may choose to implement one or more of {@link
71    * Interpreter#newReturnTypeValue(Type)}, {@link Interpreter#newParameterValue(boolean, int,
72    * Type)}, {@link Interpreter#newEmptyValue(int)}, {@link
73    * Interpreter#newExceptionValue(TryCatchBlockNode, Frame, Type)} to distinguish different types
74    * of new value.
75    *
76    * @param type a primitive or reference type, or {@literal null} to represent an uninitialized
77    *     value.
78    * @return a value that represents the given type. The size of the returned value must be equal to
79    *     the size of the given type.
80    */
newValue(Type type)81   public abstract V newValue(Type type);
82 
83   /**
84    * Creates a new value that represents the given parameter type. This method is called to
85    * initialize the value of a local corresponding to a method parameter in a frame.
86    *
87    * <p>By default, calls <code>newValue(type)</code>.
88    *
89    * @param isInstanceMethod {@literal true} if the method is non-static.
90    * @param local the local variable index.
91    * @param type a primitive or reference type.
92    * @return a value that represents the given type. The size of the returned value must be equal to
93    *     the size of the given type.
94    */
newParameterValue(final boolean isInstanceMethod, final int local, final Type type)95   public V newParameterValue(final boolean isInstanceMethod, final int local, final Type type) {
96     return newValue(type);
97   }
98 
99   /**
100    * Creates a new value that represents the given return type. This method is called to initialize
101    * the return type value of a frame.
102    *
103    * <p>By default, calls <code>newValue(type)</code>.
104    *
105    * @param type a primitive or reference type.
106    * @return a value that represents the given type. The size of the returned value must be equal to
107    *     the size of the given type.
108    */
newReturnTypeValue(final Type type)109   public V newReturnTypeValue(final Type type) {
110     return newValue(type);
111   }
112 
113   /**
114    * Creates a new uninitialized value for a local variable. This method is called to initialize the
115    * value of a local that does not correspond to a method parameter, and to reset one half of a
116    * size-2 value when the other half is assigned a size-1 value.
117    *
118    * <p>By default, calls <code>newValue(null)</code>.
119    *
120    * @param local the local variable index.
121    * @return a value representing an uninitialized value. The size of the returned value must be
122    *     equal to 1.
123    */
newEmptyValue(final int local)124   public V newEmptyValue(final int local) {
125     return newValue(null);
126   }
127 
128   /**
129    * Creates a new value that represents the given exception type. This method is called to
130    * initialize the exception value on the call stack at the entry of an exception handler.
131    *
132    * <p>By default, calls <code>newValue(exceptionType)</code>.
133    *
134    * @param tryCatchBlockNode the exception handler.
135    * @param handlerFrame the exception handler frame.
136    * @param exceptionType the exception type handled by this handler.
137    * @return a value that represents the given {@code exceptionType}. The size of the returned value
138    *     must be equal to 1.
139    */
newExceptionValue( final TryCatchBlockNode tryCatchBlockNode, final Frame<V> handlerFrame, final Type exceptionType)140   public V newExceptionValue(
141       final TryCatchBlockNode tryCatchBlockNode,
142       final Frame<V> handlerFrame,
143       final Type exceptionType) {
144     return newValue(exceptionType);
145   }
146 
147   /**
148    * Interprets a bytecode instruction without arguments. This method is called for the following
149    * opcodes:
150    *
151    * <p>ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5,
152    * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, BIPUSH, SIPUSH, LDC, JSR,
153    * GETSTATIC, NEW
154    *
155    * @param insn the bytecode instruction to be interpreted.
156    * @return the result of the interpretation of the given instruction.
157    * @throws AnalyzerException if an error occurred during the interpretation.
158    */
newOperation(AbstractInsnNode insn)159   public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException;
160 
161   /**
162    * Interprets a bytecode instruction that moves a value on the stack or to or from local
163    * variables. This method is called for the following opcodes:
164    *
165    * <p>ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE, DUP, DUP_X1,
166    * DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
167    *
168    * @param insn the bytecode instruction to be interpreted.
169    * @param value the value that must be moved by the instruction.
170    * @return the result of the interpretation of the given instruction. The returned value must be
171    *     {@code equal} to the given value.
172    * @throws AnalyzerException if an error occurred during the interpretation.
173    */
copyOperation(AbstractInsnNode insn, V value)174   public abstract V copyOperation(AbstractInsnNode insn, V value) throws AnalyzerException;
175 
176   /**
177    * Interprets a bytecode instruction with a single argument. This method is called for the
178    * following opcodes:
179    *
180    * <p>INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
181    * I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN,
182    * FRETURN, DRETURN, ARETURN, PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW,
183    * CHECKCAST, INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
184    *
185    * @param insn the bytecode instruction to be interpreted.
186    * @param value the argument of the instruction to be interpreted.
187    * @return the result of the interpretation of the given instruction.
188    * @throws AnalyzerException if an error occurred during the interpretation.
189    */
unaryOperation(AbstractInsnNode insn, V value)190   public abstract V unaryOperation(AbstractInsnNode insn, V value) throws AnalyzerException;
191 
192   /**
193    * Interprets a bytecode instruction with two arguments. This method is called for the following
194    * opcodes:
195    *
196    * <p>IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD, LADD, FADD, DADD,
197    * ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM,
198    * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG,
199    * DCMPL, DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
200    * IF_ACMPNE, PUTFIELD
201    *
202    * @param insn the bytecode instruction to be interpreted.
203    * @param value1 the first argument of the instruction to be interpreted.
204    * @param value2 the second argument of the instruction to be interpreted.
205    * @return the result of the interpretation of the given instruction.
206    * @throws AnalyzerException if an error occurred during the interpretation.
207    */
binaryOperation(AbstractInsnNode insn, V value1, V value2)208   public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
209       throws AnalyzerException;
210 
211   /**
212    * Interprets a bytecode instruction with three arguments. This method is called for the following
213    * opcodes:
214    *
215    * <p>IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
216    *
217    * @param insn the bytecode instruction to be interpreted.
218    * @param value1 the first argument of the instruction to be interpreted.
219    * @param value2 the second argument of the instruction to be interpreted.
220    * @param value3 the third argument of the instruction to be interpreted.
221    * @return the result of the interpretation of the given instruction.
222    * @throws AnalyzerException if an error occurred during the interpretation.
223    */
ternaryOperation(AbstractInsnNode insn, V value1, V value2, V value3)224   public abstract V ternaryOperation(AbstractInsnNode insn, V value1, V value2, V value3)
225       throws AnalyzerException;
226 
227   /**
228    * Interprets a bytecode instruction with a variable number of arguments. This method is called
229    * for the following opcodes:
230    *
231    * <p>INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, MULTIANEWARRAY and
232    * INVOKEDYNAMIC
233    *
234    * @param insn the bytecode instruction to be interpreted.
235    * @param values the arguments of the instruction to be interpreted.
236    * @return the result of the interpretation of the given instruction.
237    * @throws AnalyzerException if an error occurred during the interpretation.
238    */
naryOperation(AbstractInsnNode insn, List<? extends V> values)239   public abstract V naryOperation(AbstractInsnNode insn, List<? extends V> values)
240       throws AnalyzerException;
241 
242   /**
243    * Interprets a bytecode return instruction. This method is called for the following opcodes:
244    *
245    * <p>IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
246    *
247    * @param insn the bytecode instruction to be interpreted.
248    * @param value the argument of the instruction to be interpreted.
249    * @param expected the expected return type of the analyzed method.
250    * @throws AnalyzerException if an error occurred during the interpretation.
251    */
returnOperation(AbstractInsnNode insn, V value, V expected)252   public abstract void returnOperation(AbstractInsnNode insn, V value, V expected)
253       throws AnalyzerException;
254 
255   /**
256    * Merges two values. The merge operation must return a value that represents both values (for
257    * instance, if the two values are two types, the merged value must be a common super type of the
258    * two types. If the two values are integer intervals, the merged value must be an interval that
259    * contains the previous ones. Likewise for other types of values).
260    *
261    * @param value1 a value.
262    * @param value2 another value.
263    * @return the merged value. If the merged value is equal to {@code value1}, this method
264    *     <i>must</i> return {@code value1}.
265    */
merge(V value1, V value2)266   public abstract V merge(V value1, V value2);
267 }
268