• 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.ConstantDynamic;
32 import org.objectweb.asm.Handle;
33 import org.objectweb.asm.Opcodes;
34 import org.objectweb.asm.Type;
35 import org.objectweb.asm.tree.AbstractInsnNode;
36 import org.objectweb.asm.tree.FieldInsnNode;
37 import org.objectweb.asm.tree.IntInsnNode;
38 import org.objectweb.asm.tree.InvokeDynamicInsnNode;
39 import org.objectweb.asm.tree.LdcInsnNode;
40 import org.objectweb.asm.tree.MethodInsnNode;
41 import org.objectweb.asm.tree.MultiANewArrayInsnNode;
42 import org.objectweb.asm.tree.TypeInsnNode;
43 
44 /**
45  * An {@link Interpreter} for {@link BasicValue} values.
46  *
47  * @author Eric Bruneton
48  * @author Bing Ran
49  */
50 public class BasicInterpreter extends Interpreter<BasicValue> implements Opcodes {
51 
52   /**
53    * Special type used for the {@literal null} literal. This is an object reference type with
54    * descriptor 'Lnull;'.
55    */
56   public static final Type NULL_TYPE = Type.getObjectType("null");
57 
58   /**
59    * Constructs a new {@link BasicInterpreter} for the latest ASM API version. <i>Subclasses must
60    * not use this constructor</i>. Instead, they must use the {@link #BasicInterpreter(int)}
61    * version.
62    */
BasicInterpreter()63   public BasicInterpreter() {
64     super(/* latest api = */ ASM9);
65     if (getClass() != BasicInterpreter.class) {
66       throw new IllegalStateException();
67     }
68   }
69 
70   /**
71    * Constructs a new {@link BasicInterpreter}.
72    *
73    * @param api the ASM API version supported by this interpreter. Must be one of the {@code
74    *     ASM}<i>x</i> values in {@link Opcodes}.
75    */
BasicInterpreter(final int api)76   protected BasicInterpreter(final int api) {
77     super(api);
78   }
79 
80   @Override
newValue(final Type type)81   public BasicValue newValue(final Type type) {
82     if (type == null) {
83       return BasicValue.UNINITIALIZED_VALUE;
84     }
85     switch (type.getSort()) {
86       case Type.VOID:
87         return null;
88       case Type.BOOLEAN:
89       case Type.CHAR:
90       case Type.BYTE:
91       case Type.SHORT:
92       case Type.INT:
93         return BasicValue.INT_VALUE;
94       case Type.FLOAT:
95         return BasicValue.FLOAT_VALUE;
96       case Type.LONG:
97         return BasicValue.LONG_VALUE;
98       case Type.DOUBLE:
99         return BasicValue.DOUBLE_VALUE;
100       case Type.ARRAY:
101       case Type.OBJECT:
102         return BasicValue.REFERENCE_VALUE;
103       default:
104         throw new AssertionError();
105     }
106   }
107 
108   @Override
newOperation(final AbstractInsnNode insn)109   public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
110     switch (insn.getOpcode()) {
111       case ACONST_NULL:
112         return newValue(NULL_TYPE);
113       case ICONST_M1:
114       case ICONST_0:
115       case ICONST_1:
116       case ICONST_2:
117       case ICONST_3:
118       case ICONST_4:
119       case ICONST_5:
120         return BasicValue.INT_VALUE;
121       case LCONST_0:
122       case LCONST_1:
123         return BasicValue.LONG_VALUE;
124       case FCONST_0:
125       case FCONST_1:
126       case FCONST_2:
127         return BasicValue.FLOAT_VALUE;
128       case DCONST_0:
129       case DCONST_1:
130         return BasicValue.DOUBLE_VALUE;
131       case BIPUSH:
132       case SIPUSH:
133         return BasicValue.INT_VALUE;
134       case LDC:
135         Object value = ((LdcInsnNode) insn).cst;
136         if (value instanceof Integer) {
137           return BasicValue.INT_VALUE;
138         } else if (value instanceof Float) {
139           return BasicValue.FLOAT_VALUE;
140         } else if (value instanceof Long) {
141           return BasicValue.LONG_VALUE;
142         } else if (value instanceof Double) {
143           return BasicValue.DOUBLE_VALUE;
144         } else if (value instanceof String) {
145           return newValue(Type.getObjectType("java/lang/String"));
146         } else if (value instanceof Type) {
147           int sort = ((Type) value).getSort();
148           if (sort == Type.OBJECT || sort == Type.ARRAY) {
149             return newValue(Type.getObjectType("java/lang/Class"));
150           } else if (sort == Type.METHOD) {
151             return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
152           } else {
153             throw new AnalyzerException(insn, "Illegal LDC value " + value);
154           }
155         } else if (value instanceof Handle) {
156           return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
157         } else if (value instanceof ConstantDynamic) {
158           return newValue(Type.getType(((ConstantDynamic) value).getDescriptor()));
159         } else {
160           throw new AnalyzerException(insn, "Illegal LDC value " + value);
161         }
162       case JSR:
163         return BasicValue.RETURNADDRESS_VALUE;
164       case GETSTATIC:
165         return newValue(Type.getType(((FieldInsnNode) insn).desc));
166       case NEW:
167         return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
168       default:
169         throw new AssertionError();
170     }
171   }
172 
173   @Override
copyOperation(final AbstractInsnNode insn, final BasicValue value)174   public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value)
175       throws AnalyzerException {
176     return value;
177   }
178 
179   @Override
unaryOperation(final AbstractInsnNode insn, final BasicValue value)180   public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
181       throws AnalyzerException {
182     switch (insn.getOpcode()) {
183       case INEG:
184       case IINC:
185       case L2I:
186       case F2I:
187       case D2I:
188       case I2B:
189       case I2C:
190       case I2S:
191         return BasicValue.INT_VALUE;
192       case FNEG:
193       case I2F:
194       case L2F:
195       case D2F:
196         return BasicValue.FLOAT_VALUE;
197       case LNEG:
198       case I2L:
199       case F2L:
200       case D2L:
201         return BasicValue.LONG_VALUE;
202       case DNEG:
203       case I2D:
204       case L2D:
205       case F2D:
206         return BasicValue.DOUBLE_VALUE;
207       case IFEQ:
208       case IFNE:
209       case IFLT:
210       case IFGE:
211       case IFGT:
212       case IFLE:
213       case TABLESWITCH:
214       case LOOKUPSWITCH:
215       case IRETURN:
216       case LRETURN:
217       case FRETURN:
218       case DRETURN:
219       case ARETURN:
220       case PUTSTATIC:
221         return null;
222       case GETFIELD:
223         return newValue(Type.getType(((FieldInsnNode) insn).desc));
224       case NEWARRAY:
225         switch (((IntInsnNode) insn).operand) {
226           case T_BOOLEAN:
227             return newValue(Type.getType("[Z"));
228           case T_CHAR:
229             return newValue(Type.getType("[C"));
230           case T_BYTE:
231             return newValue(Type.getType("[B"));
232           case T_SHORT:
233             return newValue(Type.getType("[S"));
234           case T_INT:
235             return newValue(Type.getType("[I"));
236           case T_FLOAT:
237             return newValue(Type.getType("[F"));
238           case T_DOUBLE:
239             return newValue(Type.getType("[D"));
240           case T_LONG:
241             return newValue(Type.getType("[J"));
242           default:
243             break;
244         }
245         throw new AnalyzerException(insn, "Invalid array type");
246       case ANEWARRAY:
247         return newValue(Type.getType("[" + Type.getObjectType(((TypeInsnNode) insn).desc)));
248       case ARRAYLENGTH:
249         return BasicValue.INT_VALUE;
250       case ATHROW:
251         return null;
252       case CHECKCAST:
253         return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
254       case INSTANCEOF:
255         return BasicValue.INT_VALUE;
256       case MONITORENTER:
257       case MONITOREXIT:
258       case IFNULL:
259       case IFNONNULL:
260         return null;
261       default:
262         throw new AssertionError();
263     }
264   }
265 
266   @Override
binaryOperation( final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2)267   public BasicValue binaryOperation(
268       final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2)
269       throws AnalyzerException {
270     switch (insn.getOpcode()) {
271       case IALOAD:
272       case BALOAD:
273       case CALOAD:
274       case SALOAD:
275       case IADD:
276       case ISUB:
277       case IMUL:
278       case IDIV:
279       case IREM:
280       case ISHL:
281       case ISHR:
282       case IUSHR:
283       case IAND:
284       case IOR:
285       case IXOR:
286         return BasicValue.INT_VALUE;
287       case FALOAD:
288       case FADD:
289       case FSUB:
290       case FMUL:
291       case FDIV:
292       case FREM:
293         return BasicValue.FLOAT_VALUE;
294       case LALOAD:
295       case LADD:
296       case LSUB:
297       case LMUL:
298       case LDIV:
299       case LREM:
300       case LSHL:
301       case LSHR:
302       case LUSHR:
303       case LAND:
304       case LOR:
305       case LXOR:
306         return BasicValue.LONG_VALUE;
307       case DALOAD:
308       case DADD:
309       case DSUB:
310       case DMUL:
311       case DDIV:
312       case DREM:
313         return BasicValue.DOUBLE_VALUE;
314       case AALOAD:
315         return BasicValue.REFERENCE_VALUE;
316       case LCMP:
317       case FCMPL:
318       case FCMPG:
319       case DCMPL:
320       case DCMPG:
321         return BasicValue.INT_VALUE;
322       case IF_ICMPEQ:
323       case IF_ICMPNE:
324       case IF_ICMPLT:
325       case IF_ICMPGE:
326       case IF_ICMPGT:
327       case IF_ICMPLE:
328       case IF_ACMPEQ:
329       case IF_ACMPNE:
330       case PUTFIELD:
331         return null;
332       default:
333         throw new AssertionError();
334     }
335   }
336 
337   @Override
ternaryOperation( final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2, final BasicValue value3)338   public BasicValue ternaryOperation(
339       final AbstractInsnNode insn,
340       final BasicValue value1,
341       final BasicValue value2,
342       final BasicValue value3)
343       throws AnalyzerException {
344     return null;
345   }
346 
347   @Override
naryOperation( final AbstractInsnNode insn, final List<? extends BasicValue> values)348   public BasicValue naryOperation(
349       final AbstractInsnNode insn, final List<? extends BasicValue> values)
350       throws AnalyzerException {
351     int opcode = insn.getOpcode();
352     if (opcode == MULTIANEWARRAY) {
353       return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
354     } else if (opcode == INVOKEDYNAMIC) {
355       return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
356     } else {
357       return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
358     }
359   }
360 
361   @Override
returnOperation( final AbstractInsnNode insn, final BasicValue value, final BasicValue expected)362   public void returnOperation(
363       final AbstractInsnNode insn, final BasicValue value, final BasicValue expected)
364       throws AnalyzerException {
365     // Nothing to do.
366   }
367 
368   @Override
merge(final BasicValue value1, final BasicValue value2)369   public BasicValue merge(final BasicValue value1, final BasicValue value2) {
370     if (!value1.equals(value2)) {
371       return BasicValue.UNINITIALIZED_VALUE;
372     }
373     return value1;
374   }
375 }
376