• 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 
29 package org.objectweb.asm.commons;
30 
31 import org.objectweb.asm.ConstantDynamic;
32 import org.objectweb.asm.Handle;
33 import org.objectweb.asm.Label;
34 import org.objectweb.asm.MethodVisitor;
35 import org.objectweb.asm.Opcodes;
36 import org.objectweb.asm.Type;
37 
38 /**
39  * A {@link MethodVisitor} providing a more detailed API to generate and transform instructions.
40  *
41  * @author Eric Bruneton
42  */
43 public class InstructionAdapter extends MethodVisitor {
44 
45   /** The type of the java.lang.Object class. */
46   public static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
47 
48   /**
49    * Constructs a new {@link InstructionAdapter}. <i>Subclasses must not use this constructor</i>.
50    * Instead, they must use the {@link #InstructionAdapter(int, MethodVisitor)} version.
51    *
52    * @param methodVisitor the method visitor to which this adapter delegates calls.
53    * @throws IllegalStateException If a subclass calls this constructor.
54    */
InstructionAdapter(final MethodVisitor methodVisitor)55   public InstructionAdapter(final MethodVisitor methodVisitor) {
56     this(/* latest api = */ Opcodes.ASM9, methodVisitor);
57     if (getClass() != InstructionAdapter.class) {
58       throw new IllegalStateException();
59     }
60   }
61 
62   /**
63    * Constructs a new {@link InstructionAdapter}.
64    *
65    * @param api the ASM API version implemented by this visitor. Must be one of the {@code
66    *     ASM}<i>x</i> values in {@link Opcodes}.
67    * @param methodVisitor the method visitor to which this adapter delegates calls.
68    */
InstructionAdapter(final int api, final MethodVisitor methodVisitor)69   protected InstructionAdapter(final int api, final MethodVisitor methodVisitor) {
70     super(api, methodVisitor);
71   }
72 
73   @Override
visitInsn(final int opcode)74   public void visitInsn(final int opcode) {
75     switch (opcode) {
76       case Opcodes.NOP:
77         nop();
78         break;
79       case Opcodes.ACONST_NULL:
80         aconst(null);
81         break;
82       case Opcodes.ICONST_M1:
83       case Opcodes.ICONST_0:
84       case Opcodes.ICONST_1:
85       case Opcodes.ICONST_2:
86       case Opcodes.ICONST_3:
87       case Opcodes.ICONST_4:
88       case Opcodes.ICONST_5:
89         iconst(opcode - Opcodes.ICONST_0);
90         break;
91       case Opcodes.LCONST_0:
92       case Opcodes.LCONST_1:
93         lconst((long) (opcode - Opcodes.LCONST_0));
94         break;
95       case Opcodes.FCONST_0:
96       case Opcodes.FCONST_1:
97       case Opcodes.FCONST_2:
98         fconst((float) (opcode - Opcodes.FCONST_0));
99         break;
100       case Opcodes.DCONST_0:
101       case Opcodes.DCONST_1:
102         dconst((double) (opcode - Opcodes.DCONST_0));
103         break;
104       case Opcodes.IALOAD:
105         aload(Type.INT_TYPE);
106         break;
107       case Opcodes.LALOAD:
108         aload(Type.LONG_TYPE);
109         break;
110       case Opcodes.FALOAD:
111         aload(Type.FLOAT_TYPE);
112         break;
113       case Opcodes.DALOAD:
114         aload(Type.DOUBLE_TYPE);
115         break;
116       case Opcodes.AALOAD:
117         aload(OBJECT_TYPE);
118         break;
119       case Opcodes.BALOAD:
120         aload(Type.BYTE_TYPE);
121         break;
122       case Opcodes.CALOAD:
123         aload(Type.CHAR_TYPE);
124         break;
125       case Opcodes.SALOAD:
126         aload(Type.SHORT_TYPE);
127         break;
128       case Opcodes.IASTORE:
129         astore(Type.INT_TYPE);
130         break;
131       case Opcodes.LASTORE:
132         astore(Type.LONG_TYPE);
133         break;
134       case Opcodes.FASTORE:
135         astore(Type.FLOAT_TYPE);
136         break;
137       case Opcodes.DASTORE:
138         astore(Type.DOUBLE_TYPE);
139         break;
140       case Opcodes.AASTORE:
141         astore(OBJECT_TYPE);
142         break;
143       case Opcodes.BASTORE:
144         astore(Type.BYTE_TYPE);
145         break;
146       case Opcodes.CASTORE:
147         astore(Type.CHAR_TYPE);
148         break;
149       case Opcodes.SASTORE:
150         astore(Type.SHORT_TYPE);
151         break;
152       case Opcodes.POP:
153         pop();
154         break;
155       case Opcodes.POP2:
156         pop2();
157         break;
158       case Opcodes.DUP:
159         dup();
160         break;
161       case Opcodes.DUP_X1:
162         dupX1();
163         break;
164       case Opcodes.DUP_X2:
165         dupX2();
166         break;
167       case Opcodes.DUP2:
168         dup2();
169         break;
170       case Opcodes.DUP2_X1:
171         dup2X1();
172         break;
173       case Opcodes.DUP2_X2:
174         dup2X2();
175         break;
176       case Opcodes.SWAP:
177         swap();
178         break;
179       case Opcodes.IADD:
180         add(Type.INT_TYPE);
181         break;
182       case Opcodes.LADD:
183         add(Type.LONG_TYPE);
184         break;
185       case Opcodes.FADD:
186         add(Type.FLOAT_TYPE);
187         break;
188       case Opcodes.DADD:
189         add(Type.DOUBLE_TYPE);
190         break;
191       case Opcodes.ISUB:
192         sub(Type.INT_TYPE);
193         break;
194       case Opcodes.LSUB:
195         sub(Type.LONG_TYPE);
196         break;
197       case Opcodes.FSUB:
198         sub(Type.FLOAT_TYPE);
199         break;
200       case Opcodes.DSUB:
201         sub(Type.DOUBLE_TYPE);
202         break;
203       case Opcodes.IMUL:
204         mul(Type.INT_TYPE);
205         break;
206       case Opcodes.LMUL:
207         mul(Type.LONG_TYPE);
208         break;
209       case Opcodes.FMUL:
210         mul(Type.FLOAT_TYPE);
211         break;
212       case Opcodes.DMUL:
213         mul(Type.DOUBLE_TYPE);
214         break;
215       case Opcodes.IDIV:
216         div(Type.INT_TYPE);
217         break;
218       case Opcodes.LDIV:
219         div(Type.LONG_TYPE);
220         break;
221       case Opcodes.FDIV:
222         div(Type.FLOAT_TYPE);
223         break;
224       case Opcodes.DDIV:
225         div(Type.DOUBLE_TYPE);
226         break;
227       case Opcodes.IREM:
228         rem(Type.INT_TYPE);
229         break;
230       case Opcodes.LREM:
231         rem(Type.LONG_TYPE);
232         break;
233       case Opcodes.FREM:
234         rem(Type.FLOAT_TYPE);
235         break;
236       case Opcodes.DREM:
237         rem(Type.DOUBLE_TYPE);
238         break;
239       case Opcodes.INEG:
240         neg(Type.INT_TYPE);
241         break;
242       case Opcodes.LNEG:
243         neg(Type.LONG_TYPE);
244         break;
245       case Opcodes.FNEG:
246         neg(Type.FLOAT_TYPE);
247         break;
248       case Opcodes.DNEG:
249         neg(Type.DOUBLE_TYPE);
250         break;
251       case Opcodes.ISHL:
252         shl(Type.INT_TYPE);
253         break;
254       case Opcodes.LSHL:
255         shl(Type.LONG_TYPE);
256         break;
257       case Opcodes.ISHR:
258         shr(Type.INT_TYPE);
259         break;
260       case Opcodes.LSHR:
261         shr(Type.LONG_TYPE);
262         break;
263       case Opcodes.IUSHR:
264         ushr(Type.INT_TYPE);
265         break;
266       case Opcodes.LUSHR:
267         ushr(Type.LONG_TYPE);
268         break;
269       case Opcodes.IAND:
270         and(Type.INT_TYPE);
271         break;
272       case Opcodes.LAND:
273         and(Type.LONG_TYPE);
274         break;
275       case Opcodes.IOR:
276         or(Type.INT_TYPE);
277         break;
278       case Opcodes.LOR:
279         or(Type.LONG_TYPE);
280         break;
281       case Opcodes.IXOR:
282         xor(Type.INT_TYPE);
283         break;
284       case Opcodes.LXOR:
285         xor(Type.LONG_TYPE);
286         break;
287       case Opcodes.I2L:
288         cast(Type.INT_TYPE, Type.LONG_TYPE);
289         break;
290       case Opcodes.I2F:
291         cast(Type.INT_TYPE, Type.FLOAT_TYPE);
292         break;
293       case Opcodes.I2D:
294         cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
295         break;
296       case Opcodes.L2I:
297         cast(Type.LONG_TYPE, Type.INT_TYPE);
298         break;
299       case Opcodes.L2F:
300         cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
301         break;
302       case Opcodes.L2D:
303         cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
304         break;
305       case Opcodes.F2I:
306         cast(Type.FLOAT_TYPE, Type.INT_TYPE);
307         break;
308       case Opcodes.F2L:
309         cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
310         break;
311       case Opcodes.F2D:
312         cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
313         break;
314       case Opcodes.D2I:
315         cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
316         break;
317       case Opcodes.D2L:
318         cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
319         break;
320       case Opcodes.D2F:
321         cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
322         break;
323       case Opcodes.I2B:
324         cast(Type.INT_TYPE, Type.BYTE_TYPE);
325         break;
326       case Opcodes.I2C:
327         cast(Type.INT_TYPE, Type.CHAR_TYPE);
328         break;
329       case Opcodes.I2S:
330         cast(Type.INT_TYPE, Type.SHORT_TYPE);
331         break;
332       case Opcodes.LCMP:
333         lcmp();
334         break;
335       case Opcodes.FCMPL:
336         cmpl(Type.FLOAT_TYPE);
337         break;
338       case Opcodes.FCMPG:
339         cmpg(Type.FLOAT_TYPE);
340         break;
341       case Opcodes.DCMPL:
342         cmpl(Type.DOUBLE_TYPE);
343         break;
344       case Opcodes.DCMPG:
345         cmpg(Type.DOUBLE_TYPE);
346         break;
347       case Opcodes.IRETURN:
348         areturn(Type.INT_TYPE);
349         break;
350       case Opcodes.LRETURN:
351         areturn(Type.LONG_TYPE);
352         break;
353       case Opcodes.FRETURN:
354         areturn(Type.FLOAT_TYPE);
355         break;
356       case Opcodes.DRETURN:
357         areturn(Type.DOUBLE_TYPE);
358         break;
359       case Opcodes.ARETURN:
360         areturn(OBJECT_TYPE);
361         break;
362       case Opcodes.RETURN:
363         areturn(Type.VOID_TYPE);
364         break;
365       case Opcodes.ARRAYLENGTH:
366         arraylength();
367         break;
368       case Opcodes.ATHROW:
369         athrow();
370         break;
371       case Opcodes.MONITORENTER:
372         monitorenter();
373         break;
374       case Opcodes.MONITOREXIT:
375         monitorexit();
376         break;
377       default:
378         throw new IllegalArgumentException();
379     }
380   }
381 
382   @Override
visitIntInsn(final int opcode, final int operand)383   public void visitIntInsn(final int opcode, final int operand) {
384     switch (opcode) {
385       case Opcodes.BIPUSH:
386         iconst(operand);
387         break;
388       case Opcodes.SIPUSH:
389         iconst(operand);
390         break;
391       case Opcodes.NEWARRAY:
392         switch (operand) {
393           case Opcodes.T_BOOLEAN:
394             newarray(Type.BOOLEAN_TYPE);
395             break;
396           case Opcodes.T_CHAR:
397             newarray(Type.CHAR_TYPE);
398             break;
399           case Opcodes.T_BYTE:
400             newarray(Type.BYTE_TYPE);
401             break;
402           case Opcodes.T_SHORT:
403             newarray(Type.SHORT_TYPE);
404             break;
405           case Opcodes.T_INT:
406             newarray(Type.INT_TYPE);
407             break;
408           case Opcodes.T_FLOAT:
409             newarray(Type.FLOAT_TYPE);
410             break;
411           case Opcodes.T_LONG:
412             newarray(Type.LONG_TYPE);
413             break;
414           case Opcodes.T_DOUBLE:
415             newarray(Type.DOUBLE_TYPE);
416             break;
417           default:
418             throw new IllegalArgumentException();
419         }
420         break;
421       default:
422         throw new IllegalArgumentException();
423     }
424   }
425 
426   @Override
visitVarInsn(final int opcode, final int varIndex)427   public void visitVarInsn(final int opcode, final int varIndex) {
428     switch (opcode) {
429       case Opcodes.ILOAD:
430         load(varIndex, Type.INT_TYPE);
431         break;
432       case Opcodes.LLOAD:
433         load(varIndex, Type.LONG_TYPE);
434         break;
435       case Opcodes.FLOAD:
436         load(varIndex, Type.FLOAT_TYPE);
437         break;
438       case Opcodes.DLOAD:
439         load(varIndex, Type.DOUBLE_TYPE);
440         break;
441       case Opcodes.ALOAD:
442         load(varIndex, OBJECT_TYPE);
443         break;
444       case Opcodes.ISTORE:
445         store(varIndex, Type.INT_TYPE);
446         break;
447       case Opcodes.LSTORE:
448         store(varIndex, Type.LONG_TYPE);
449         break;
450       case Opcodes.FSTORE:
451         store(varIndex, Type.FLOAT_TYPE);
452         break;
453       case Opcodes.DSTORE:
454         store(varIndex, Type.DOUBLE_TYPE);
455         break;
456       case Opcodes.ASTORE:
457         store(varIndex, OBJECT_TYPE);
458         break;
459       case Opcodes.RET:
460         ret(varIndex);
461         break;
462       default:
463         throw new IllegalArgumentException();
464     }
465   }
466 
467   @Override
visitTypeInsn(final int opcode, final String type)468   public void visitTypeInsn(final int opcode, final String type) {
469     Type objectType = Type.getObjectType(type);
470     switch (opcode) {
471       case Opcodes.NEW:
472         anew(objectType);
473         break;
474       case Opcodes.ANEWARRAY:
475         newarray(objectType);
476         break;
477       case Opcodes.CHECKCAST:
478         checkcast(objectType);
479         break;
480       case Opcodes.INSTANCEOF:
481         instanceOf(objectType);
482         break;
483       default:
484         throw new IllegalArgumentException();
485     }
486   }
487 
488   @Override
visitFieldInsn( final int opcode, final String owner, final String name, final String descriptor)489   public void visitFieldInsn(
490       final int opcode, final String owner, final String name, final String descriptor) {
491     switch (opcode) {
492       case Opcodes.GETSTATIC:
493         getstatic(owner, name, descriptor);
494         break;
495       case Opcodes.PUTSTATIC:
496         putstatic(owner, name, descriptor);
497         break;
498       case Opcodes.GETFIELD:
499         getfield(owner, name, descriptor);
500         break;
501       case Opcodes.PUTFIELD:
502         putfield(owner, name, descriptor);
503         break;
504       default:
505         throw new IllegalArgumentException();
506     }
507   }
508 
509   @Override
visitMethodInsn( final int opcodeAndSource, final String owner, final String name, final String descriptor, final boolean isInterface)510   public void visitMethodInsn(
511       final int opcodeAndSource,
512       final String owner,
513       final String name,
514       final String descriptor,
515       final boolean isInterface) {
516     if (api < Opcodes.ASM5 && (opcodeAndSource & Opcodes.SOURCE_DEPRECATED) == 0) {
517       // Redirect the call to the deprecated version of this method.
518       super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface);
519       return;
520     }
521     int opcode = opcodeAndSource & ~Opcodes.SOURCE_MASK;
522 
523     switch (opcode) {
524       case Opcodes.INVOKESPECIAL:
525         invokespecial(owner, name, descriptor, isInterface);
526         break;
527       case Opcodes.INVOKEVIRTUAL:
528         invokevirtual(owner, name, descriptor, isInterface);
529         break;
530       case Opcodes.INVOKESTATIC:
531         invokestatic(owner, name, descriptor, isInterface);
532         break;
533       case Opcodes.INVOKEINTERFACE:
534         invokeinterface(owner, name, descriptor);
535         break;
536       default:
537         throw new IllegalArgumentException();
538     }
539   }
540 
541   @Override
visitInvokeDynamicInsn( final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments)542   public void visitInvokeDynamicInsn(
543       final String name,
544       final String descriptor,
545       final Handle bootstrapMethodHandle,
546       final Object... bootstrapMethodArguments) {
547     invokedynamic(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
548   }
549 
550   @Override
visitJumpInsn(final int opcode, final Label label)551   public void visitJumpInsn(final int opcode, final Label label) {
552     switch (opcode) {
553       case Opcodes.IFEQ:
554         ifeq(label);
555         break;
556       case Opcodes.IFNE:
557         ifne(label);
558         break;
559       case Opcodes.IFLT:
560         iflt(label);
561         break;
562       case Opcodes.IFGE:
563         ifge(label);
564         break;
565       case Opcodes.IFGT:
566         ifgt(label);
567         break;
568       case Opcodes.IFLE:
569         ifle(label);
570         break;
571       case Opcodes.IF_ICMPEQ:
572         ificmpeq(label);
573         break;
574       case Opcodes.IF_ICMPNE:
575         ificmpne(label);
576         break;
577       case Opcodes.IF_ICMPLT:
578         ificmplt(label);
579         break;
580       case Opcodes.IF_ICMPGE:
581         ificmpge(label);
582         break;
583       case Opcodes.IF_ICMPGT:
584         ificmpgt(label);
585         break;
586       case Opcodes.IF_ICMPLE:
587         ificmple(label);
588         break;
589       case Opcodes.IF_ACMPEQ:
590         ifacmpeq(label);
591         break;
592       case Opcodes.IF_ACMPNE:
593         ifacmpne(label);
594         break;
595       case Opcodes.GOTO:
596         goTo(label);
597         break;
598       case Opcodes.JSR:
599         jsr(label);
600         break;
601       case Opcodes.IFNULL:
602         ifnull(label);
603         break;
604       case Opcodes.IFNONNULL:
605         ifnonnull(label);
606         break;
607       default:
608         throw new IllegalArgumentException();
609     }
610   }
611 
612   @Override
visitLabel(final Label label)613   public void visitLabel(final Label label) {
614     mark(label);
615   }
616 
617   @Override
visitLdcInsn(final Object value)618   public void visitLdcInsn(final Object value) {
619     if (api < Opcodes.ASM5
620         && (value instanceof Handle
621             || (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
622       throw new UnsupportedOperationException("This feature requires ASM5");
623     }
624     if (api < Opcodes.ASM7 && value instanceof ConstantDynamic) {
625       throw new UnsupportedOperationException("This feature requires ASM7");
626     }
627     if (value instanceof Integer) {
628       iconst((Integer) value);
629     } else if (value instanceof Byte) {
630       iconst(((Byte) value).intValue());
631     } else if (value instanceof Character) {
632       iconst(((Character) value).charValue());
633     } else if (value instanceof Short) {
634       iconst(((Short) value).intValue());
635     } else if (value instanceof Boolean) {
636       iconst(((Boolean) value).booleanValue() ? 1 : 0);
637     } else if (value instanceof Float) {
638       fconst((Float) value);
639     } else if (value instanceof Long) {
640       lconst((Long) value);
641     } else if (value instanceof Double) {
642       dconst((Double) value);
643     } else if (value instanceof String) {
644       aconst(value);
645     } else if (value instanceof Type) {
646       tconst((Type) value);
647     } else if (value instanceof Handle) {
648       hconst((Handle) value);
649     } else if (value instanceof ConstantDynamic) {
650       cconst((ConstantDynamic) value);
651     } else {
652       throw new IllegalArgumentException();
653     }
654   }
655 
656   @Override
visitIincInsn(final int varIndex, final int increment)657   public void visitIincInsn(final int varIndex, final int increment) {
658     iinc(varIndex, increment);
659   }
660 
661   @Override
visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label... labels)662   public void visitTableSwitchInsn(
663       final int min, final int max, final Label dflt, final Label... labels) {
664     tableswitch(min, max, dflt, labels);
665   }
666 
667   @Override
visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels)668   public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
669     lookupswitch(dflt, keys, labels);
670   }
671 
672   @Override
visitMultiANewArrayInsn(final String descriptor, final int numDimensions)673   public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
674     multianewarray(descriptor, numDimensions);
675   }
676 
677   // -----------------------------------------------------------------------------------------------
678 
679   /** Generates a nop instruction. */
nop()680   public void nop() {
681     mv.visitInsn(Opcodes.NOP);
682   }
683 
684   /**
685    * Generates the instruction to push the given value on the stack.
686    *
687    * @param value the constant to be pushed on the stack. This parameter must be an {@link Integer},
688    *     a {@link Float}, a {@link Long}, a {@link Double}, a {@link String}, a {@link Type} of
689    *     OBJECT or ARRAY sort for {@code .class} constants, for classes whose version is 49, a
690    *     {@link Type} of METHOD sort for MethodType, a {@link Handle} for MethodHandle constants,
691    *     for classes whose version is 51 or a {@link ConstantDynamic} for a constant dynamic for
692    *     classes whose version is 55.
693    */
aconst(final Object value)694   public void aconst(final Object value) {
695     if (value == null) {
696       mv.visitInsn(Opcodes.ACONST_NULL);
697     } else {
698       mv.visitLdcInsn(value);
699     }
700   }
701 
702   /**
703    * Generates the instruction to push the given value on the stack.
704    *
705    * @param intValue the constant to be pushed on the stack.
706    */
iconst(final int intValue)707   public void iconst(final int intValue) {
708     if (intValue >= -1 && intValue <= 5) {
709       mv.visitInsn(Opcodes.ICONST_0 + intValue);
710     } else if (intValue >= Byte.MIN_VALUE && intValue <= Byte.MAX_VALUE) {
711       mv.visitIntInsn(Opcodes.BIPUSH, intValue);
712     } else if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) {
713       mv.visitIntInsn(Opcodes.SIPUSH, intValue);
714     } else {
715       mv.visitLdcInsn(intValue);
716     }
717   }
718 
719   /**
720    * Generates the instruction to push the given value on the stack.
721    *
722    * @param longValue the constant to be pushed on the stack.
723    */
lconst(final long longValue)724   public void lconst(final long longValue) {
725     if (longValue == 0L || longValue == 1L) {
726       mv.visitInsn(Opcodes.LCONST_0 + (int) longValue);
727     } else {
728       mv.visitLdcInsn(longValue);
729     }
730   }
731 
732   /**
733    * Generates the instruction to push the given value on the stack.
734    *
735    * @param floatValue the constant to be pushed on the stack.
736    */
fconst(final float floatValue)737   public void fconst(final float floatValue) {
738     int bits = Float.floatToIntBits(floatValue);
739     if (bits == 0L || bits == 0x3F800000 || bits == 0x40000000) { // 0..2
740       mv.visitInsn(Opcodes.FCONST_0 + (int) floatValue);
741     } else {
742       mv.visitLdcInsn(floatValue);
743     }
744   }
745 
746   /**
747    * Generates the instruction to push the given value on the stack.
748    *
749    * @param doubleValue the constant to be pushed on the stack.
750    */
dconst(final double doubleValue)751   public void dconst(final double doubleValue) {
752     long bits = Double.doubleToLongBits(doubleValue);
753     if (bits == 0L || bits == 0x3FF0000000000000L) { // +0.0d and 1.0d
754       mv.visitInsn(Opcodes.DCONST_0 + (int) doubleValue);
755     } else {
756       mv.visitLdcInsn(doubleValue);
757     }
758   }
759 
760   /**
761    * Generates the instruction to push the given type on the stack.
762    *
763    * @param type the type to be pushed on the stack.
764    */
tconst(final Type type)765   public void tconst(final Type type) {
766     mv.visitLdcInsn(type);
767   }
768 
769   /**
770    * Generates the instruction to push the given handle on the stack.
771    *
772    * @param handle the handle to be pushed on the stack.
773    */
hconst(final Handle handle)774   public void hconst(final Handle handle) {
775     mv.visitLdcInsn(handle);
776   }
777 
778   /**
779    * Generates the instruction to push the given constant dynamic on the stack.
780    *
781    * @param constantDynamic the constant dynamic to be pushed on the stack.
782    */
cconst(final ConstantDynamic constantDynamic)783   public void cconst(final ConstantDynamic constantDynamic) {
784     mv.visitLdcInsn(constantDynamic);
785   }
786 
load(final int varIndex, final Type type)787   public void load(final int varIndex, final Type type) {
788     mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), varIndex);
789   }
790 
aload(final Type type)791   public void aload(final Type type) {
792     mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
793   }
794 
store(final int varIndex, final Type type)795   public void store(final int varIndex, final Type type) {
796     mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), varIndex);
797   }
798 
astore(final Type type)799   public void astore(final Type type) {
800     mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
801   }
802 
pop()803   public void pop() {
804     mv.visitInsn(Opcodes.POP);
805   }
806 
pop2()807   public void pop2() {
808     mv.visitInsn(Opcodes.POP2);
809   }
810 
dup()811   public void dup() {
812     mv.visitInsn(Opcodes.DUP);
813   }
814 
dup2()815   public void dup2() {
816     mv.visitInsn(Opcodes.DUP2);
817   }
818 
dupX1()819   public void dupX1() {
820     mv.visitInsn(Opcodes.DUP_X1);
821   }
822 
dupX2()823   public void dupX2() {
824     mv.visitInsn(Opcodes.DUP_X2);
825   }
826 
dup2X1()827   public void dup2X1() {
828     mv.visitInsn(Opcodes.DUP2_X1);
829   }
830 
dup2X2()831   public void dup2X2() {
832     mv.visitInsn(Opcodes.DUP2_X2);
833   }
834 
swap()835   public void swap() {
836     mv.visitInsn(Opcodes.SWAP);
837   }
838 
add(final Type type)839   public void add(final Type type) {
840     mv.visitInsn(type.getOpcode(Opcodes.IADD));
841   }
842 
sub(final Type type)843   public void sub(final Type type) {
844     mv.visitInsn(type.getOpcode(Opcodes.ISUB));
845   }
846 
mul(final Type type)847   public void mul(final Type type) {
848     mv.visitInsn(type.getOpcode(Opcodes.IMUL));
849   }
850 
div(final Type type)851   public void div(final Type type) {
852     mv.visitInsn(type.getOpcode(Opcodes.IDIV));
853   }
854 
rem(final Type type)855   public void rem(final Type type) {
856     mv.visitInsn(type.getOpcode(Opcodes.IREM));
857   }
858 
neg(final Type type)859   public void neg(final Type type) {
860     mv.visitInsn(type.getOpcode(Opcodes.INEG));
861   }
862 
shl(final Type type)863   public void shl(final Type type) {
864     mv.visitInsn(type.getOpcode(Opcodes.ISHL));
865   }
866 
shr(final Type type)867   public void shr(final Type type) {
868     mv.visitInsn(type.getOpcode(Opcodes.ISHR));
869   }
870 
ushr(final Type type)871   public void ushr(final Type type) {
872     mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
873   }
874 
and(final Type type)875   public void and(final Type type) {
876     mv.visitInsn(type.getOpcode(Opcodes.IAND));
877   }
878 
or(final Type type)879   public void or(final Type type) {
880     mv.visitInsn(type.getOpcode(Opcodes.IOR));
881   }
882 
xor(final Type type)883   public void xor(final Type type) {
884     mv.visitInsn(type.getOpcode(Opcodes.IXOR));
885   }
886 
iinc(final int varIndex, final int increment)887   public void iinc(final int varIndex, final int increment) {
888     mv.visitIincInsn(varIndex, increment);
889   }
890 
891   /**
892    * Generates the instruction to cast from the first given type to the other.
893    *
894    * @param from a Type.
895    * @param to a Type.
896    */
cast(final Type from, final Type to)897   public void cast(final Type from, final Type to) {
898     cast(mv, from, to);
899   }
900 
901   /**
902    * Generates the instruction to cast from the first given type to the other.
903    *
904    * @param methodVisitor the method visitor to use to generate the instruction.
905    * @param from a Type.
906    * @param to a Type.
907    */
cast(final MethodVisitor methodVisitor, final Type from, final Type to)908   static void cast(final MethodVisitor methodVisitor, final Type from, final Type to) {
909     if (from != to) {
910       if (from == Type.DOUBLE_TYPE) {
911         if (to == Type.FLOAT_TYPE) {
912           methodVisitor.visitInsn(Opcodes.D2F);
913         } else if (to == Type.LONG_TYPE) {
914           methodVisitor.visitInsn(Opcodes.D2L);
915         } else {
916           methodVisitor.visitInsn(Opcodes.D2I);
917           cast(methodVisitor, Type.INT_TYPE, to);
918         }
919       } else if (from == Type.FLOAT_TYPE) {
920         if (to == Type.DOUBLE_TYPE) {
921           methodVisitor.visitInsn(Opcodes.F2D);
922         } else if (to == Type.LONG_TYPE) {
923           methodVisitor.visitInsn(Opcodes.F2L);
924         } else {
925           methodVisitor.visitInsn(Opcodes.F2I);
926           cast(methodVisitor, Type.INT_TYPE, to);
927         }
928       } else if (from == Type.LONG_TYPE) {
929         if (to == Type.DOUBLE_TYPE) {
930           methodVisitor.visitInsn(Opcodes.L2D);
931         } else if (to == Type.FLOAT_TYPE) {
932           methodVisitor.visitInsn(Opcodes.L2F);
933         } else {
934           methodVisitor.visitInsn(Opcodes.L2I);
935           cast(methodVisitor, Type.INT_TYPE, to);
936         }
937       } else {
938         if (to == Type.BYTE_TYPE) {
939           methodVisitor.visitInsn(Opcodes.I2B);
940         } else if (to == Type.CHAR_TYPE) {
941           methodVisitor.visitInsn(Opcodes.I2C);
942         } else if (to == Type.DOUBLE_TYPE) {
943           methodVisitor.visitInsn(Opcodes.I2D);
944         } else if (to == Type.FLOAT_TYPE) {
945           methodVisitor.visitInsn(Opcodes.I2F);
946         } else if (to == Type.LONG_TYPE) {
947           methodVisitor.visitInsn(Opcodes.I2L);
948         } else if (to == Type.SHORT_TYPE) {
949           methodVisitor.visitInsn(Opcodes.I2S);
950         }
951       }
952     }
953   }
954 
lcmp()955   public void lcmp() {
956     mv.visitInsn(Opcodes.LCMP);
957   }
958 
cmpl(final Type type)959   public void cmpl(final Type type) {
960     mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
961   }
962 
cmpg(final Type type)963   public void cmpg(final Type type) {
964     mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
965   }
966 
ifeq(final Label label)967   public void ifeq(final Label label) {
968     mv.visitJumpInsn(Opcodes.IFEQ, label);
969   }
970 
ifne(final Label label)971   public void ifne(final Label label) {
972     mv.visitJumpInsn(Opcodes.IFNE, label);
973   }
974 
iflt(final Label label)975   public void iflt(final Label label) {
976     mv.visitJumpInsn(Opcodes.IFLT, label);
977   }
978 
ifge(final Label label)979   public void ifge(final Label label) {
980     mv.visitJumpInsn(Opcodes.IFGE, label);
981   }
982 
ifgt(final Label label)983   public void ifgt(final Label label) {
984     mv.visitJumpInsn(Opcodes.IFGT, label);
985   }
986 
ifle(final Label label)987   public void ifle(final Label label) {
988     mv.visitJumpInsn(Opcodes.IFLE, label);
989   }
990 
ificmpeq(final Label label)991   public void ificmpeq(final Label label) {
992     mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
993   }
994 
ificmpne(final Label label)995   public void ificmpne(final Label label) {
996     mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
997   }
998 
ificmplt(final Label label)999   public void ificmplt(final Label label) {
1000     mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
1001   }
1002 
ificmpge(final Label label)1003   public void ificmpge(final Label label) {
1004     mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
1005   }
1006 
ificmpgt(final Label label)1007   public void ificmpgt(final Label label) {
1008     mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
1009   }
1010 
ificmple(final Label label)1011   public void ificmple(final Label label) {
1012     mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
1013   }
1014 
ifacmpeq(final Label label)1015   public void ifacmpeq(final Label label) {
1016     mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
1017   }
1018 
ifacmpne(final Label label)1019   public void ifacmpne(final Label label) {
1020     mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
1021   }
1022 
goTo(final Label label)1023   public void goTo(final Label label) {
1024     mv.visitJumpInsn(Opcodes.GOTO, label);
1025   }
1026 
jsr(final Label label)1027   public void jsr(final Label label) {
1028     mv.visitJumpInsn(Opcodes.JSR, label);
1029   }
1030 
ret(final int varIndex)1031   public void ret(final int varIndex) {
1032     mv.visitVarInsn(Opcodes.RET, varIndex);
1033   }
1034 
tableswitch(final int min, final int max, final Label dflt, final Label... labels)1035   public void tableswitch(final int min, final int max, final Label dflt, final Label... labels) {
1036     mv.visitTableSwitchInsn(min, max, dflt, labels);
1037   }
1038 
lookupswitch(final Label dflt, final int[] keys, final Label[] labels)1039   public void lookupswitch(final Label dflt, final int[] keys, final Label[] labels) {
1040     mv.visitLookupSwitchInsn(dflt, keys, labels);
1041   }
1042 
areturn(final Type type)1043   public void areturn(final Type type) {
1044     mv.visitInsn(type.getOpcode(Opcodes.IRETURN));
1045   }
1046 
getstatic(final String owner, final String name, final String descriptor)1047   public void getstatic(final String owner, final String name, final String descriptor) {
1048     mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, descriptor);
1049   }
1050 
putstatic(final String owner, final String name, final String descriptor)1051   public void putstatic(final String owner, final String name, final String descriptor) {
1052     mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, descriptor);
1053   }
1054 
getfield(final String owner, final String name, final String descriptor)1055   public void getfield(final String owner, final String name, final String descriptor) {
1056     mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, descriptor);
1057   }
1058 
putfield(final String owner, final String name, final String descriptor)1059   public void putfield(final String owner, final String name, final String descriptor) {
1060     mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, descriptor);
1061   }
1062 
1063   /**
1064    * Deprecated.
1065    *
1066    * @param owner the internal name of the method's owner class (see {@link
1067    *     Type#getInternalName()}).
1068    * @param name the method's name.
1069    * @param descriptor the method's descriptor (see {@link Type}).
1070    * @deprecated use {@link #invokevirtual(String, String, String, boolean)} instead.
1071    */
1072   @Deprecated
invokevirtual(final String owner, final String name, final String descriptor)1073   public void invokevirtual(final String owner, final String name, final String descriptor) {
1074     if (api >= Opcodes.ASM5) {
1075       invokevirtual(owner, name, descriptor, false);
1076       return;
1077     }
1078     mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor);
1079   }
1080 
1081   /**
1082    * Generates the instruction to call the given virtual method.
1083    *
1084    * @param owner the internal name of the method's owner class (see {@link
1085    *     Type#getInternalName()}).
1086    * @param name the method's name.
1087    * @param descriptor the method's descriptor (see {@link Type}).
1088    * @param isInterface if the method's owner class is an interface.
1089    */
invokevirtual( final String owner, final String name, final String descriptor, final boolean isInterface)1090   public void invokevirtual(
1091       final String owner, final String name, final String descriptor, final boolean isInterface) {
1092     if (api < Opcodes.ASM5) {
1093       if (isInterface) {
1094         throw new UnsupportedOperationException("INVOKEVIRTUAL on interfaces require ASM 5");
1095       }
1096       invokevirtual(owner, name, descriptor);
1097       return;
1098     }
1099     mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
1100   }
1101 
1102   /**
1103    * Deprecated.
1104    *
1105    * @param owner the internal name of the method's owner class (see {@link
1106    *     Type#getInternalName()}).
1107    * @param name the method's name.
1108    * @param descriptor the method's descriptor (see {@link Type}).
1109    * @deprecated use {@link #invokespecial(String, String, String, boolean)} instead.
1110    */
1111   @Deprecated
invokespecial(final String owner, final String name, final String descriptor)1112   public void invokespecial(final String owner, final String name, final String descriptor) {
1113     if (api >= Opcodes.ASM5) {
1114       invokespecial(owner, name, descriptor, false);
1115       return;
1116     }
1117     mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, false);
1118   }
1119 
1120   /**
1121    * Generates the instruction to call the given special method.
1122    *
1123    * @param owner the internal name of the method's owner class (see {@link
1124    *     Type#getInternalName()}).
1125    * @param name the method's name.
1126    * @param descriptor the method's descriptor (see {@link Type}).
1127    * @param isInterface if the method's owner class is an interface.
1128    */
invokespecial( final String owner, final String name, final String descriptor, final boolean isInterface)1129   public void invokespecial(
1130       final String owner, final String name, final String descriptor, final boolean isInterface) {
1131     if (api < Opcodes.ASM5) {
1132       if (isInterface) {
1133         throw new UnsupportedOperationException("INVOKESPECIAL on interfaces require ASM 5");
1134       }
1135       invokespecial(owner, name, descriptor);
1136       return;
1137     }
1138     mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, descriptor, isInterface);
1139   }
1140 
1141   /**
1142    * Deprecated.
1143    *
1144    * @param owner the internal name of the method's owner class (see {@link
1145    *     Type#getInternalName()}).
1146    * @param name the method's name.
1147    * @param descriptor the method's descriptor (see {@link Type}).
1148    * @deprecated use {@link #invokestatic(String, String, String, boolean)} instead.
1149    */
1150   @Deprecated
invokestatic(final String owner, final String name, final String descriptor)1151   public void invokestatic(final String owner, final String name, final String descriptor) {
1152     if (api >= Opcodes.ASM5) {
1153       invokestatic(owner, name, descriptor, false);
1154       return;
1155     }
1156     mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, false);
1157   }
1158 
1159   /**
1160    * Generates the instruction to call the given static method.
1161    *
1162    * @param owner the internal name of the method's owner class (see {@link
1163    *     Type#getInternalName()}).
1164    * @param name the method's name.
1165    * @param descriptor the method's descriptor (see {@link Type}).
1166    * @param isInterface if the method's owner class is an interface.
1167    */
invokestatic( final String owner, final String name, final String descriptor, final boolean isInterface)1168   public void invokestatic(
1169       final String owner, final String name, final String descriptor, final boolean isInterface) {
1170     if (api < Opcodes.ASM5) {
1171       if (isInterface) {
1172         throw new UnsupportedOperationException("INVOKESTATIC on interfaces require ASM 5");
1173       }
1174       invokestatic(owner, name, descriptor);
1175       return;
1176     }
1177     mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, descriptor, isInterface);
1178   }
1179 
1180   /**
1181    * Generates the instruction to call the given interface method.
1182    *
1183    * @param owner the internal name of the method's owner class (see {@link
1184    *     Type#getInternalName()}).
1185    * @param name the method's name.
1186    * @param descriptor the method's descriptor (see {@link Type}).
1187    */
invokeinterface(final String owner, final String name, final String descriptor)1188   public void invokeinterface(final String owner, final String name, final String descriptor) {
1189     mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, descriptor, true);
1190   }
1191 
1192   /**
1193    * Generates the instruction to call the given dynamic method.
1194    *
1195    * @param name the method's name.
1196    * @param descriptor the method's descriptor (see {@link Type}).
1197    * @param bootstrapMethodHandle the bootstrap method.
1198    * @param bootstrapMethodArguments the bootstrap method constant arguments. Each argument must be
1199    *     an {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String}, {@link
1200    *     Type}, {@link Handle} or {@link ConstantDynamic} value. This method is allowed to modify
1201    *     the content of the array so a caller should expect that this array may change.
1202    */
invokedynamic( final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object[] bootstrapMethodArguments)1203   public void invokedynamic(
1204       final String name,
1205       final String descriptor,
1206       final Handle bootstrapMethodHandle,
1207       final Object[] bootstrapMethodArguments) {
1208     mv.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
1209   }
1210 
anew(final Type type)1211   public void anew(final Type type) {
1212     mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
1213   }
1214 
1215   /**
1216    * Generates the instruction to create and push on the stack an array of the given type.
1217    *
1218    * @param type an array Type.
1219    */
newarray(final Type type)1220   public void newarray(final Type type) {
1221     newarray(mv, type);
1222   }
1223 
1224   /**
1225    * Generates the instruction to create and push on the stack an array of the given type.
1226    *
1227    * @param methodVisitor the method visitor to use to generate the instruction.
1228    * @param type an array Type.
1229    */
newarray(final MethodVisitor methodVisitor, final Type type)1230   static void newarray(final MethodVisitor methodVisitor, final Type type) {
1231     int arrayType;
1232     switch (type.getSort()) {
1233       case Type.BOOLEAN:
1234         arrayType = Opcodes.T_BOOLEAN;
1235         break;
1236       case Type.CHAR:
1237         arrayType = Opcodes.T_CHAR;
1238         break;
1239       case Type.BYTE:
1240         arrayType = Opcodes.T_BYTE;
1241         break;
1242       case Type.SHORT:
1243         arrayType = Opcodes.T_SHORT;
1244         break;
1245       case Type.INT:
1246         arrayType = Opcodes.T_INT;
1247         break;
1248       case Type.FLOAT:
1249         arrayType = Opcodes.T_FLOAT;
1250         break;
1251       case Type.LONG:
1252         arrayType = Opcodes.T_LONG;
1253         break;
1254       case Type.DOUBLE:
1255         arrayType = Opcodes.T_DOUBLE;
1256         break;
1257       default:
1258         methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
1259         return;
1260     }
1261     methodVisitor.visitIntInsn(Opcodes.NEWARRAY, arrayType);
1262   }
1263 
arraylength()1264   public void arraylength() {
1265     mv.visitInsn(Opcodes.ARRAYLENGTH);
1266   }
1267 
athrow()1268   public void athrow() {
1269     mv.visitInsn(Opcodes.ATHROW);
1270   }
1271 
checkcast(final Type type)1272   public void checkcast(final Type type) {
1273     mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
1274   }
1275 
instanceOf(final Type type)1276   public void instanceOf(final Type type) {
1277     mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
1278   }
1279 
monitorenter()1280   public void monitorenter() {
1281     mv.visitInsn(Opcodes.MONITORENTER);
1282   }
1283 
monitorexit()1284   public void monitorexit() {
1285     mv.visitInsn(Opcodes.MONITOREXIT);
1286   }
1287 
multianewarray(final String descriptor, final int numDimensions)1288   public void multianewarray(final String descriptor, final int numDimensions) {
1289     mv.visitMultiANewArrayInsn(descriptor, numDimensions);
1290   }
1291 
ifnull(final Label label)1292   public void ifnull(final Label label) {
1293     mv.visitJumpInsn(Opcodes.IFNULL, label);
1294   }
1295 
ifnonnull(final Label label)1296   public void ifnonnull(final Label label) {
1297     mv.visitJumpInsn(Opcodes.IFNONNULL, label);
1298   }
1299 
mark(final Label label)1300   public void mark(final Label label) {
1301     mv.visitLabel(label);
1302   }
1303 }
1304