test/jdk/lib/testlibrary/bytecode/jdk/experimental/bytecode/CodeBuilder.java
changeset 48826 c4d9d1b08e2e
equal deleted inserted replaced
48825:ef8a98bc71f8 48826:c4d9d1b08e2e
       
     1 /*
       
     2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package jdk.experimental.bytecode;
       
    25 
       
    26 import jdk.experimental.bytecode.PoolHelper.StaticArgListBuilder;
       
    27 
       
    28 import java.lang.invoke.MethodHandle;
       
    29 import java.util.Iterator;
       
    30 import java.util.List;
       
    31 import java.util.function.BiFunction;
       
    32 import java.util.function.Consumer;
       
    33 import java.util.function.Function;
       
    34 import java.util.function.ToIntFunction;
       
    35 
       
    36 /**
       
    37  * Builder for class file code attributes. A code attribute is defined:
       
    38  * <pre>
       
    39  * {@code
       
    40  * Code_attribute {
       
    41  *    u2 attribute_name_index;
       
    42  *    u4 attribute_length;
       
    43  *    u2 max_stack;
       
    44  *    u2 max_locals;
       
    45  *    u4 code_length;
       
    46  *    u1 code[code_length];
       
    47  *    u2 exception_table_length;
       
    48  *    {   u2 start_pc;
       
    49  *        u2 end_pc;
       
    50  *        u2 handler_pc;
       
    51  *        u2 catch_type;
       
    52  *    } exception_table[exception_table_length];
       
    53  *    u2 attributes_count;
       
    54  *    attribute_info attributes[attributes_count];
       
    55  * } }
       
    56  * </pre>
       
    57  *
       
    58  * @param <S> the type of symbol representation
       
    59  * @param <T> the type of type descriptors representation
       
    60  * @param <E> the type of pool entries
       
    61  * @param <C> the type of this code builder
       
    62  */
       
    63 public class CodeBuilder<S, T, E, C extends CodeBuilder<S, T, E, C>> extends AttributeBuilder<S, T, E, C> {
       
    64 
       
    65     protected GrowableByteBuffer code = new GrowableByteBuffer();
       
    66     GrowableByteBuffer catchers = new GrowableByteBuffer();
       
    67     GrowableByteBuffer stackmaps = new GrowableByteBuffer();
       
    68     MethodBuilder<S, T, E> methodBuilder;
       
    69     int ncatchers;
       
    70     int stacksize = -1;
       
    71     int localsize = -1;
       
    72     int nstackmaps = 0;
       
    73 
       
    74     public enum JumpMode {
       
    75         NARROW,
       
    76         WIDE;
       
    77     }
       
    78 
       
    79     CodeBuilder(MethodBuilder<S, T, E> methodBuilder) {
       
    80         super(methodBuilder.poolHelper, methodBuilder.typeHelper);
       
    81         this.methodBuilder = methodBuilder;
       
    82     }
       
    83 
       
    84     public C getstatic(S owner, CharSequence name, T type) {
       
    85         emitOp(Opcode.GETSTATIC, type);
       
    86         code.writeChar(poolHelper.putFieldRef(owner, name, type));
       
    87         return thisBuilder();
       
    88     }
       
    89 
       
    90     public C putstatic(S owner, CharSequence name, T type) {
       
    91         emitOp(Opcode.PUTSTATIC, type);
       
    92         code.writeChar(poolHelper.putFieldRef(owner, name, type));
       
    93         return thisBuilder();
       
    94     }
       
    95 
       
    96     public C getfield(S owner, CharSequence name, T type) {
       
    97         emitOp(Opcode.GETFIELD, type);
       
    98         code.writeChar(poolHelper.putFieldRef(owner, name, type));
       
    99         return thisBuilder();
       
   100     }
       
   101 
       
   102     public C vgetfield(S owner, CharSequence name, T type) {
       
   103         emitOp(Opcode.VGETFIELD, type);
       
   104         code.writeChar(poolHelper.putFieldRef(owner, name, type));
       
   105         return thisBuilder();
       
   106     }
       
   107 
       
   108     public C putfield(S owner, CharSequence name, T type) {
       
   109         emitOp(Opcode.PUTFIELD, type);
       
   110         code.writeChar(poolHelper.putFieldRef(owner, name, type));
       
   111         return thisBuilder();
       
   112     }
       
   113 
       
   114     public C invokevirtual(S owner, CharSequence name, T type, boolean isInterface) {
       
   115         emitOp(Opcode.INVOKEVIRTUAL, type);
       
   116         code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface));
       
   117         return thisBuilder();
       
   118     }
       
   119 
       
   120     public C invokespecial(S owner, CharSequence name, T type, boolean isInterface) {
       
   121         emitOp(Opcode.INVOKESPECIAL, type);
       
   122         code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface));
       
   123         return thisBuilder();
       
   124     }
       
   125 
       
   126     public C invokestatic(S owner, CharSequence name, T type, boolean isInterface) {
       
   127         emitOp(Opcode.INVOKESTATIC, type);
       
   128         code.writeChar(poolHelper.putMethodRef(owner, name, type, isInterface));
       
   129         return thisBuilder();
       
   130     }
       
   131 
       
   132     public C invokeinterface(S owner, CharSequence name, T type) {
       
   133         emitOp(Opcode.INVOKEINTERFACE, type);
       
   134         code.writeChar(poolHelper.putMethodRef(owner, name, type, true));
       
   135         int nargs = 1;
       
   136         Iterator<T> it = typeHelper.parameterTypes(type);
       
   137         while (it.hasNext()) {
       
   138             nargs += typeHelper.tag(it.next()).width;
       
   139         }
       
   140         code.writeByte(nargs);
       
   141         code.writeByte(0);
       
   142         return thisBuilder();
       
   143     }
       
   144 
       
   145     public C invokedynamic(CharSequence invokedName, T invokedType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs) {
       
   146         emitOp(Opcode.INVOKEDYNAMIC, invokedType);
       
   147         code.writeChar(poolHelper.putInvokeDynamic(invokedName, invokedType, bsmClass, bsmName, bsmType, staticArgs));
       
   148         code.writeChar(0); //padding
       
   149         return thisBuilder();
       
   150     }
       
   151 
       
   152     public C new_(S clazz) {
       
   153         emitOp(Opcode.NEW, clazz);
       
   154         code.writeChar(poolHelper.putClass(clazz));
       
   155         return thisBuilder();
       
   156     }
       
   157 
       
   158     public C vnew_(S clazz, CharSequence name, T desc) {
       
   159         emitOp(Opcode.VNEW, clazz);
       
   160         code.writeChar(poolHelper.putMethodRef(clazz, name, desc, false));
       
   161         return thisBuilder();
       
   162     }
       
   163 
       
   164     public C vnewarray(S array) {
       
   165         emitOp(Opcode.VNEWARRAY, array);
       
   166         code.writeChar(poolHelper.putClass(array));
       
   167         return thisBuilder();
       
   168     }
       
   169 
       
   170     public C newarray(TypeTag tag) {
       
   171         emitOp(Opcode.NEWARRAY, tag);
       
   172         int newarraycode = tag.newarraycode;
       
   173         if (newarraycode == -1) {
       
   174             throw new IllegalStateException("Bad tag " + tag);
       
   175         }
       
   176         code.writeByte(newarraycode);
       
   177         return thisBuilder();
       
   178     }
       
   179 
       
   180     public C anewarray(S array) {
       
   181         emitOp(Opcode.ANEWARRAY, array);
       
   182         code.writeChar(poolHelper.putClass(array));
       
   183         return thisBuilder();
       
   184     }
       
   185 
       
   186     public C checkcast(S target) {
       
   187         emitOp(Opcode.CHECKCAST);
       
   188         code.writeChar(poolHelper.putClass(target));
       
   189         return thisBuilder();
       
   190     }
       
   191 
       
   192     public C instanceof_(S target) {
       
   193         emitOp(Opcode.INSTANCEOF);
       
   194         code.writeChar(poolHelper.putClass(target));
       
   195         return thisBuilder();
       
   196     }
       
   197 
       
   198     public C multianewarray(S array, byte dims) {
       
   199         emitOp(Opcode.MULTIANEWARRAY, new Object[]{array, dims});
       
   200         code.writeChar(poolHelper.putClass(array)).writeByte(dims);
       
   201         return thisBuilder();
       
   202     }
       
   203 
       
   204     public C multivnewarray(S array, byte dims) {
       
   205         emitOp(Opcode.MULTIVNEWARRAY, new Object[]{array, dims});
       
   206         code.writeChar(poolHelper.putClass(array)).writeByte(dims);
       
   207         return thisBuilder();
       
   208     }
       
   209 
       
   210     public C vbox(S target) {
       
   211         emitOp(Opcode.VBOX, target);
       
   212         code.writeChar(poolHelper.putClass(target));
       
   213         return thisBuilder();
       
   214     }
       
   215 
       
   216     public C vunbox(S target) {
       
   217         emitOp(Opcode.VUNBOX, target);
       
   218         code.writeChar(poolHelper.putClass(target));
       
   219         return thisBuilder();
       
   220     }
       
   221 
       
   222     public C ldc(int i) {
       
   223         return ldc(pool -> pool.putInt(i), false);
       
   224     }
       
   225 
       
   226     public C ldc(long l) {
       
   227         return ldc(pool -> pool.putLong(l), true);
       
   228     }
       
   229 
       
   230     public C ldc(float f) {
       
   231         return ldc(pool -> pool.putFloat(f), false);
       
   232     }
       
   233 
       
   234     public C ldc(double d) {
       
   235         return ldc(pool -> pool.putDouble(d), true);
       
   236     }
       
   237 
       
   238     public C ldc(String s) {
       
   239         return ldc(pool -> pool.putString(s), false);
       
   240     }
       
   241 
       
   242     public C ldc(CharSequence constName, T constType, S bsmClass, CharSequence bsmName, T bsmType, Consumer<StaticArgListBuilder<S, T, E>> staticArgs) {
       
   243         boolean fat = typeHelper.tag(constType).width() == 2;
       
   244         return ldc(pool -> pool.putDynamicConstant(constName, constType, bsmClass, bsmName, bsmType, staticArgs), fat);
       
   245     }
       
   246 
       
   247     public <Z> C ldc(Z z, BiFunction<PoolHelper<S, T, E>, Z, Integer> poolFunc) {
       
   248         return ldc(pool -> poolFunc.apply(pool, z), false);
       
   249     }
       
   250 
       
   251     protected C ldc(ToIntFunction<PoolHelper<S, T, E>> indexFunc, boolean fat) {
       
   252         // @@@ This should probably be abstract
       
   253         int index = indexFunc.applyAsInt(poolHelper);
       
   254         return ldc(index, null, fat);
       
   255     }
       
   256 
       
   257     protected final C ldc(int index, T type, boolean fat) {
       
   258         if (fat) {
       
   259             emitOp(Opcode.LDC2_W, type);
       
   260             code.writeChar(index);
       
   261         } else if (index > 63) {
       
   262             emitOp(Opcode.LDC_W, type);
       
   263             code.writeChar(index);
       
   264         } else {
       
   265             emitOp(Opcode.LDC, type);
       
   266             code.writeByte(index);
       
   267         }
       
   268         return thisBuilder();
       
   269     }
       
   270 
       
   271     //other non-CP dependent opcodes
       
   272     public C areturn() {
       
   273         return emitOp(Opcode.ARETURN);
       
   274     }
       
   275 
       
   276     public C ireturn() {
       
   277         return emitOp(Opcode.IRETURN);
       
   278     }
       
   279 
       
   280     public C freturn() {
       
   281         return emitOp(Opcode.FRETURN);
       
   282     }
       
   283 
       
   284     public C lreturn() {
       
   285         return emitOp(Opcode.LRETURN);
       
   286     }
       
   287 
       
   288     public C dreturn() {
       
   289         return emitOp(Opcode.DRETURN);
       
   290     }
       
   291 
       
   292     public C return_() {
       
   293         return emitOp(Opcode.RETURN);
       
   294     }
       
   295 
       
   296     public C vreturn() {
       
   297         return emitOp(Opcode.VRETURN);
       
   298     }
       
   299 
       
   300     protected C emitWideIfNeeded(Opcode opcode, int n) {
       
   301         boolean wide = n > Byte.MAX_VALUE;
       
   302         if (wide) {
       
   303             wide();
       
   304         }
       
   305         emitOp(opcode, n);
       
   306         if (wide) {
       
   307             code.writeChar(n);
       
   308         } else {
       
   309             code.writeByte(n);
       
   310         }
       
   311         return thisBuilder();
       
   312     }
       
   313 
       
   314     protected C emitWideIfNeeded(Opcode opcode, int n, int v) {
       
   315         boolean wide = n > Byte.MAX_VALUE || v > Byte.MAX_VALUE;
       
   316         if (wide) {
       
   317             wide();
       
   318         }
       
   319         emitOp(opcode, n);
       
   320         if (wide) {
       
   321             code.writeChar(n).writeChar(v);
       
   322         } else {
       
   323             code.writeByte(n).writeByte(v);
       
   324         }
       
   325         return thisBuilder();
       
   326     }
       
   327 
       
   328     public TypedBuilder typed(TypeTag typeTag) {
       
   329         return typed(typeTag, _unused -> new TypedBuilder());
       
   330     }
       
   331 
       
   332     protected <TB extends TypedBuilder> TB typed(TypeTag typeTag, Function<TypeTag, TB> typedBuilderFunc) {
       
   333         emitOp(Opcode.TYPED);
       
   334         code.writeChar(poolHelper.putType(typeHelper.fromTag(typeTag)));
       
   335         return typedBuilderFunc.apply(typeTag);
       
   336     }
       
   337 
       
   338     public class TypedBuilder {
       
   339         public C aload_0() {
       
   340             return CodeBuilder.this.aload_0();
       
   341         }
       
   342 
       
   343         public C aload_1() {
       
   344             return CodeBuilder.this.aload_1();
       
   345         }
       
   346 
       
   347         public C aload_2() {
       
   348             return CodeBuilder.this.aload_2();
       
   349         }
       
   350 
       
   351         public C aload_3() {
       
   352             return CodeBuilder.this.aload_3();
       
   353         }
       
   354 
       
   355         public C aload(int n) {
       
   356             return CodeBuilder.this.aload(n);
       
   357         }
       
   358 
       
   359         public C astore_0() {
       
   360             return CodeBuilder.this.astore_0();
       
   361         }
       
   362 
       
   363         public C astore_1() {
       
   364             return CodeBuilder.this.astore_1();
       
   365         }
       
   366 
       
   367         public C astore_2() {
       
   368             return CodeBuilder.this.astore_2();
       
   369         }
       
   370 
       
   371         public C astore_3() {
       
   372             return CodeBuilder.this.astore_3();
       
   373         }
       
   374 
       
   375         public C astore(int n) {
       
   376             return CodeBuilder.this.astore(n);
       
   377         }
       
   378 
       
   379         public C aaload() {
       
   380             return CodeBuilder.this.aaload();
       
   381         }
       
   382 
       
   383         public C aastore() {
       
   384             return CodeBuilder.this.aastore();
       
   385         }
       
   386 
       
   387         public C areturn() {
       
   388             return CodeBuilder.this.areturn();
       
   389         }
       
   390 
       
   391         public C anewarray(S s) {
       
   392             return CodeBuilder.this.anewarray(s);
       
   393         }
       
   394 
       
   395         public C aconst_null() {
       
   396             return CodeBuilder.this.aconst_null();
       
   397         }
       
   398 
       
   399         public C if_acmpeq(short target) {
       
   400             return CodeBuilder.this.if_acmpeq(target);
       
   401         }
       
   402 
       
   403         public C if_acmpne(short target) {
       
   404             return CodeBuilder.this.if_acmpeq(target);
       
   405         }
       
   406     }
       
   407 
       
   408     public C vload(int i) {
       
   409         return emitWideIfNeeded(Opcode.VLOAD, i);
       
   410     }
       
   411 
       
   412     public C aload(int i) {
       
   413         return emitWideIfNeeded(Opcode.ALOAD, i);
       
   414     }
       
   415 
       
   416     public C iload(int i) {
       
   417         return emitWideIfNeeded(Opcode.ILOAD, i);
       
   418     }
       
   419 
       
   420     public C fload(int i) {
       
   421         return emitWideIfNeeded(Opcode.FLOAD, i);
       
   422     }
       
   423 
       
   424     public C lload(int i) {
       
   425         return emitWideIfNeeded(Opcode.LLOAD, i);
       
   426     }
       
   427 
       
   428     public C dload(int i) {
       
   429         return emitWideIfNeeded(Opcode.DLOAD, i);
       
   430     }
       
   431 
       
   432     public C aload_0() {
       
   433         return emitOp(Opcode.ALOAD_0);
       
   434     }
       
   435 
       
   436     public C iload_0() {
       
   437         return emitOp(Opcode.ILOAD_0);
       
   438     }
       
   439 
       
   440     public C fload_0() {
       
   441         return emitOp(Opcode.FLOAD_0);
       
   442     }
       
   443 
       
   444     public C lload_0() {
       
   445         return emitOp(Opcode.LLOAD_0);
       
   446     }
       
   447 
       
   448     public C dload_0() {
       
   449         return emitOp(Opcode.DLOAD_0);
       
   450     }
       
   451 
       
   452     public C aload_1() {
       
   453         return emitOp(Opcode.ALOAD_1);
       
   454     }
       
   455 
       
   456     public C iload_1() {
       
   457         return emitOp(Opcode.ILOAD_1);
       
   458     }
       
   459 
       
   460     public C fload_1() {
       
   461         return emitOp(Opcode.FLOAD_1);
       
   462     }
       
   463 
       
   464     public C lload_1() {
       
   465         return emitOp(Opcode.LLOAD_1);
       
   466     }
       
   467 
       
   468     public C dload_1() {
       
   469         return emitOp(Opcode.DLOAD_1);
       
   470     }
       
   471 
       
   472     public C aload_2() {
       
   473         return emitOp(Opcode.ALOAD_2);
       
   474     }
       
   475 
       
   476     public C iload_2() {
       
   477         return emitOp(Opcode.ILOAD_2);
       
   478     }
       
   479 
       
   480     public C fload_2() {
       
   481         return emitOp(Opcode.FLOAD_2);
       
   482     }
       
   483 
       
   484     public C lload_2() {
       
   485         return emitOp(Opcode.LLOAD_2);
       
   486     }
       
   487 
       
   488     public C dload_2() {
       
   489         return emitOp(Opcode.DLOAD_2);
       
   490     }
       
   491 
       
   492     public C aload_3() {
       
   493         return emitOp(Opcode.ALOAD_3);
       
   494     }
       
   495 
       
   496     public C iload_3() {
       
   497         return emitOp(Opcode.ILOAD_3);
       
   498     }
       
   499 
       
   500     public C fload_3() {
       
   501         return emitOp(Opcode.FLOAD_3);
       
   502     }
       
   503 
       
   504     public C lload_3() {
       
   505         return emitOp(Opcode.LLOAD_3);
       
   506     }
       
   507 
       
   508     public C dload_3() {
       
   509         return emitOp(Opcode.DLOAD_3);
       
   510     }
       
   511 
       
   512     public C vstore(int i) {
       
   513         return emitWideIfNeeded(Opcode.VSTORE, i);
       
   514     }
       
   515 
       
   516     public C astore(int i) {
       
   517         return emitWideIfNeeded(Opcode.ASTORE, i);
       
   518     }
       
   519 
       
   520     public C istore(int i) {
       
   521         return emitWideIfNeeded(Opcode.ISTORE, i);
       
   522     }
       
   523 
       
   524     public C fstore(int i) {
       
   525         return emitWideIfNeeded(Opcode.FSTORE, i);
       
   526     }
       
   527 
       
   528     public C lstore(int i) {
       
   529         return emitWideIfNeeded(Opcode.LSTORE, i);
       
   530     }
       
   531 
       
   532     public C dstore(int i) {
       
   533         return emitWideIfNeeded(Opcode.DSTORE, i);
       
   534     }
       
   535 
       
   536     public C astore_0() {
       
   537         return emitOp(Opcode.ASTORE_0);
       
   538     }
       
   539 
       
   540     public C istore_0() {
       
   541         return emitOp(Opcode.ISTORE_0);
       
   542     }
       
   543 
       
   544     public C fstore_0() {
       
   545         return emitOp(Opcode.FSTORE_0);
       
   546     }
       
   547 
       
   548     public C lstore_0() {
       
   549         return emitOp(Opcode.LSTORE_0);
       
   550     }
       
   551 
       
   552     public C dstore_0() {
       
   553         return emitOp(Opcode.DSTORE_0);
       
   554     }
       
   555 
       
   556     public C astore_1() {
       
   557         return emitOp(Opcode.ASTORE_1);
       
   558     }
       
   559 
       
   560     public C istore_1() {
       
   561         return emitOp(Opcode.ISTORE_1);
       
   562     }
       
   563 
       
   564     public C fstore_1() {
       
   565         return emitOp(Opcode.FSTORE_1);
       
   566     }
       
   567 
       
   568     public C lstore_1() {
       
   569         return emitOp(Opcode.LSTORE_1);
       
   570     }
       
   571 
       
   572     public C dstore_1() {
       
   573         return emitOp(Opcode.DSTORE_1);
       
   574     }
       
   575 
       
   576     public C astore_2() {
       
   577         return emitOp(Opcode.ASTORE_2);
       
   578     }
       
   579 
       
   580     public C istore_2() {
       
   581         return emitOp(Opcode.ISTORE_2);
       
   582     }
       
   583 
       
   584     public C fstore_2() {
       
   585         return emitOp(Opcode.FSTORE_2);
       
   586     }
       
   587 
       
   588     public C lstore_2() {
       
   589         return emitOp(Opcode.LSTORE_2);
       
   590     }
       
   591 
       
   592     public C dstore_2() {
       
   593         return emitOp(Opcode.DSTORE_2);
       
   594     }
       
   595 
       
   596     public C astore_3() {
       
   597         return emitOp(Opcode.ASTORE_3);
       
   598     }
       
   599 
       
   600     public C istore_3() {
       
   601         return emitOp(Opcode.ISTORE_3);
       
   602     }
       
   603 
       
   604     public C fstore_3() {
       
   605         return emitOp(Opcode.FSTORE_3);
       
   606     }
       
   607 
       
   608     public C lstore_3() {
       
   609         return emitOp(Opcode.LSTORE_3);
       
   610     }
       
   611 
       
   612     public C dstore_3() {
       
   613         return emitOp(Opcode.DSTORE_3);
       
   614     }
       
   615 
       
   616     //...
       
   617 
       
   618     public C iaload() {
       
   619         return emitOp(Opcode.IALOAD);
       
   620     }
       
   621 
       
   622     public C laload() {
       
   623         return emitOp(Opcode.LALOAD);
       
   624     }
       
   625 
       
   626     public C faload() {
       
   627         return emitOp(Opcode.FALOAD);
       
   628     }
       
   629 
       
   630     public C daload() {
       
   631         return emitOp(Opcode.DALOAD);
       
   632     }
       
   633 
       
   634     public C vaload() {
       
   635         return emitOp(Opcode.VALOAD);
       
   636     }
       
   637 
       
   638     public C aaload() {
       
   639         return emitOp(Opcode.AALOAD);
       
   640     }
       
   641 
       
   642     public C baload() {
       
   643         return emitOp(Opcode.BALOAD);
       
   644     }
       
   645 
       
   646     public C caload() {
       
   647         return emitOp(Opcode.CALOAD);
       
   648     }
       
   649 
       
   650     public C saload() {
       
   651         return emitOp(Opcode.SALOAD);
       
   652     }
       
   653 
       
   654     public C iastore() {
       
   655         return emitOp(Opcode.IASTORE);
       
   656     }
       
   657 
       
   658     public C lastore() {
       
   659         return emitOp(Opcode.LASTORE);
       
   660     }
       
   661 
       
   662     public C fastore() {
       
   663         return emitOp(Opcode.FASTORE);
       
   664     }
       
   665 
       
   666     public C dastore() {
       
   667         return emitOp(Opcode.DASTORE);
       
   668     }
       
   669 
       
   670     public C vastore() {
       
   671         return emitOp(Opcode.VASTORE);
       
   672     }
       
   673 
       
   674     public C aastore() {
       
   675         return emitOp(Opcode.AASTORE);
       
   676     }
       
   677 
       
   678     public C bastore() {
       
   679         return emitOp(Opcode.BASTORE);
       
   680     }
       
   681 
       
   682     public C castore() {
       
   683         return emitOp(Opcode.CASTORE);
       
   684     }
       
   685 
       
   686     public C sastore() {
       
   687         return emitOp(Opcode.SASTORE);
       
   688     }
       
   689 
       
   690     public C nop() {
       
   691         return emitOp(Opcode.NOP);
       
   692     }
       
   693 
       
   694     public C aconst_null() {
       
   695         return emitOp(Opcode.ACONST_NULL);
       
   696     }
       
   697 
       
   698     public C iconst_0() {
       
   699         return emitOp(Opcode.ICONST_0);
       
   700     }
       
   701 
       
   702     public C iconst_1() {
       
   703         return emitOp(Opcode.ICONST_1);
       
   704     }
       
   705 
       
   706     public C iconst_2() {
       
   707         return emitOp(Opcode.ICONST_2);
       
   708     }
       
   709 
       
   710     public C iconst_3() {
       
   711         return emitOp(Opcode.ICONST_3);
       
   712     }
       
   713 
       
   714     public C iconst_4() {
       
   715         return emitOp(Opcode.ICONST_4);
       
   716     }
       
   717 
       
   718     public C iconst_5() {
       
   719         return emitOp(Opcode.ICONST_5);
       
   720     }
       
   721 
       
   722     public C iconst_m1() {
       
   723         return emitOp(Opcode.ICONST_M1);
       
   724     }
       
   725 
       
   726     public C lconst_0() {
       
   727         return emitOp(Opcode.LCONST_0);
       
   728     }
       
   729 
       
   730     public C lconst_1() {
       
   731         return emitOp(Opcode.LCONST_1);
       
   732     }
       
   733 
       
   734     public C fconst_0() {
       
   735         return emitOp(Opcode.FCONST_0);
       
   736     }
       
   737 
       
   738     public C fconst_1() {
       
   739         return emitOp(Opcode.FCONST_1);
       
   740     }
       
   741 
       
   742     public C fconst_2() {
       
   743         return emitOp(Opcode.FCONST_2);
       
   744     }
       
   745 
       
   746     public C dconst_0() {
       
   747         return emitOp(Opcode.DCONST_0);
       
   748     }
       
   749 
       
   750     public C dconst_1() {
       
   751         return emitOp(Opcode.DCONST_1);
       
   752     }
       
   753 
       
   754     public C sipush(int s) {
       
   755         emitOp(Opcode.SIPUSH);
       
   756         code.writeChar(s);
       
   757         return thisBuilder();
       
   758     }
       
   759 
       
   760     public C bipush(int b) {
       
   761         emitOp(Opcode.BIPUSH);
       
   762         code.writeByte(b);
       
   763         return thisBuilder();
       
   764     }
       
   765 
       
   766     public C pop() {
       
   767         return emitOp(Opcode.POP);
       
   768     }
       
   769 
       
   770     public C pop2() {
       
   771         return emitOp(Opcode.POP2);
       
   772     }
       
   773 
       
   774     public C dup() {
       
   775         return emitOp(Opcode.DUP);
       
   776     }
       
   777 
       
   778     public C dup_x1() {
       
   779         return emitOp(Opcode.DUP_X1);
       
   780     }
       
   781 
       
   782     public C dup_x2() {
       
   783         return emitOp(Opcode.DUP_X2);
       
   784     }
       
   785 
       
   786     public C dup2() {
       
   787         return emitOp(Opcode.DUP2);
       
   788     }
       
   789 
       
   790     public C dup2_x1() {
       
   791         return emitOp(Opcode.DUP2_X1);
       
   792     }
       
   793 
       
   794     public C dup2_x2() {
       
   795         return emitOp(Opcode.DUP2_X2);
       
   796     }
       
   797 
       
   798     public C swap() {
       
   799         return emitOp(Opcode.SWAP);
       
   800     }
       
   801 
       
   802     public C iadd() {
       
   803         return emitOp(Opcode.IADD);
       
   804     }
       
   805 
       
   806     public C ladd() {
       
   807         return emitOp(Opcode.LADD);
       
   808     }
       
   809 
       
   810     public C fadd() {
       
   811         return emitOp(Opcode.FADD);
       
   812     }
       
   813 
       
   814     public C dadd() {
       
   815         return emitOp(Opcode.DADD);
       
   816     }
       
   817 
       
   818     public C isub() {
       
   819         return emitOp(Opcode.ISUB);
       
   820     }
       
   821 
       
   822     public C lsub() {
       
   823         return emitOp(Opcode.LSUB);
       
   824     }
       
   825 
       
   826     public C fsub() {
       
   827         return emitOp(Opcode.FSUB);
       
   828     }
       
   829 
       
   830     public C dsub() {
       
   831         return emitOp(Opcode.DSUB);
       
   832     }
       
   833 
       
   834     public C imul() {
       
   835         return emitOp(Opcode.IMUL);
       
   836     }
       
   837 
       
   838     public C lmul() {
       
   839         return emitOp(Opcode.LMUL);
       
   840     }
       
   841 
       
   842     public C fmul() {
       
   843         return emitOp(Opcode.FMUL);
       
   844     }
       
   845 
       
   846     public C dmul() {
       
   847         return emitOp(Opcode.DMUL);
       
   848     }
       
   849 
       
   850     public C idiv() {
       
   851         return emitOp(Opcode.IDIV);
       
   852     }
       
   853 
       
   854     public C ldiv() {
       
   855         return emitOp(Opcode.LDIV);
       
   856     }
       
   857 
       
   858     public C fdiv() {
       
   859         return emitOp(Opcode.FDIV);
       
   860     }
       
   861 
       
   862     public C ddiv() {
       
   863         return emitOp(Opcode.DDIV);
       
   864     }
       
   865 
       
   866     public C irem() {
       
   867         return emitOp(Opcode.IREM);
       
   868     }
       
   869 
       
   870     public C lrem() {
       
   871         return emitOp(Opcode.LREM);
       
   872     }
       
   873 
       
   874     public C frem() {
       
   875         return emitOp(Opcode.FREM);
       
   876     }
       
   877 
       
   878     public C drem() {
       
   879         return emitOp(Opcode.DREM);
       
   880     }
       
   881 
       
   882     public C ineg() {
       
   883         return emitOp(Opcode.INEG);
       
   884     }
       
   885 
       
   886     public C lneg() {
       
   887         return emitOp(Opcode.LNEG);
       
   888     }
       
   889 
       
   890     public C fneg() {
       
   891         return emitOp(Opcode.FNEG);
       
   892     }
       
   893 
       
   894     public C dneg() {
       
   895         return emitOp(Opcode.DNEG);
       
   896     }
       
   897 
       
   898     public C ishl() {
       
   899         return emitOp(Opcode.ISHL);
       
   900     }
       
   901 
       
   902     public C lshl() {
       
   903         return emitOp(Opcode.LSHL);
       
   904     }
       
   905 
       
   906     public C ishr() {
       
   907         return emitOp(Opcode.ISHR);
       
   908     }
       
   909 
       
   910     public C lshr() {
       
   911         return emitOp(Opcode.LSHR);
       
   912     }
       
   913 
       
   914     public C iushr() {
       
   915         return emitOp(Opcode.IUSHR);
       
   916     }
       
   917 
       
   918     public C lushr() {
       
   919         return emitOp(Opcode.LUSHR);
       
   920     }
       
   921 
       
   922     public C iand() {
       
   923         return emitOp(Opcode.IAND);
       
   924     }
       
   925 
       
   926     public C land() {
       
   927         return emitOp(Opcode.LAND);
       
   928     }
       
   929 
       
   930     public C ior() {
       
   931         return emitOp(Opcode.IOR);
       
   932     }
       
   933 
       
   934     public C lor() {
       
   935         return emitOp(Opcode.LOR);
       
   936     }
       
   937 
       
   938     public C ixor() {
       
   939         return emitOp(Opcode.IXOR);
       
   940     }
       
   941 
       
   942     public C lxor() {
       
   943         return emitOp(Opcode.LXOR);
       
   944     }
       
   945 
       
   946     public C iinc(int index, int val) {
       
   947         return emitWideIfNeeded(Opcode.IINC, index, val);
       
   948     }
       
   949 
       
   950     public C i2l() {
       
   951         return emitOp(Opcode.I2L);
       
   952     }
       
   953 
       
   954     public C i2f() {
       
   955         return emitOp(Opcode.I2F);
       
   956     }
       
   957 
       
   958     public C i2d() {
       
   959         return emitOp(Opcode.I2D);
       
   960     }
       
   961 
       
   962     public C l2i() {
       
   963         return emitOp(Opcode.L2I);
       
   964     }
       
   965 
       
   966     public C l2f() {
       
   967         return emitOp(Opcode.L2F);
       
   968     }
       
   969 
       
   970     public C l2d() {
       
   971         return emitOp(Opcode.L2D);
       
   972     }
       
   973 
       
   974     public C f2i() {
       
   975         return emitOp(Opcode.F2I);
       
   976     }
       
   977 
       
   978     public C f2l() {
       
   979         return emitOp(Opcode.F2L);
       
   980     }
       
   981 
       
   982     public C f2d() {
       
   983         return emitOp(Opcode.F2D);
       
   984     }
       
   985 
       
   986     public C d2i() {
       
   987         return emitOp(Opcode.D2I);
       
   988     }
       
   989 
       
   990     public C d2l() {
       
   991         return emitOp(Opcode.D2L);
       
   992     }
       
   993 
       
   994     public C d2f() {
       
   995         return emitOp(Opcode.D2F);
       
   996     }
       
   997 
       
   998     public C i2b() {
       
   999         return emitOp(Opcode.I2B);
       
  1000     }
       
  1001 
       
  1002     public C i2c() {
       
  1003         return emitOp(Opcode.I2C);
       
  1004     }
       
  1005 
       
  1006     public C i2s() {
       
  1007         return emitOp(Opcode.I2S);
       
  1008     }
       
  1009 
       
  1010     public C lcmp() {
       
  1011         return emitOp(Opcode.LCMP);
       
  1012     }
       
  1013 
       
  1014     public C fcmpl() {
       
  1015         return emitOp(Opcode.FCMPL);
       
  1016     }
       
  1017 
       
  1018     public C fcmpg() {
       
  1019         return emitOp(Opcode.FCMPG);
       
  1020     }
       
  1021 
       
  1022     public C dcmpl() {
       
  1023         return emitOp(Opcode.DCMPL);
       
  1024     }
       
  1025 
       
  1026     public C dcmpg() {
       
  1027         return emitOp(Opcode.DCMPG);
       
  1028     }
       
  1029 
       
  1030     public C ifeq(short target) {
       
  1031         return emitNarrowJumpOp(Opcode.IFEQ, target);
       
  1032     }
       
  1033 
       
  1034     public C ifne(short target) {
       
  1035         return emitNarrowJumpOp(Opcode.IFNE, target);
       
  1036     }
       
  1037 
       
  1038     public C iflt(short target) {
       
  1039         return emitNarrowJumpOp(Opcode.IFLT, target);
       
  1040     }
       
  1041 
       
  1042     public C ifge(short target) {
       
  1043         return emitNarrowJumpOp(Opcode.IFGE, target);
       
  1044     }
       
  1045 
       
  1046     public C ifgt(short target) {
       
  1047         return emitNarrowJumpOp(Opcode.IFGT, target);
       
  1048     }
       
  1049 
       
  1050     public C ifle(short target) {
       
  1051         return emitNarrowJumpOp(Opcode.IFLE, target);
       
  1052     }
       
  1053 
       
  1054     public C if_icmpeq(short target) {
       
  1055         return emitNarrowJumpOp(Opcode.IF_ICMPEQ, target);
       
  1056     }
       
  1057 
       
  1058     public C if_icmpne(short target) {
       
  1059         return emitNarrowJumpOp(Opcode.IF_ICMPNE, target);
       
  1060     }
       
  1061 
       
  1062     public C if_icmplt(short target) {
       
  1063         return emitNarrowJumpOp(Opcode.IF_ICMPLT, target);
       
  1064     }
       
  1065 
       
  1066     public C if_icmpge(short target) {
       
  1067         return emitNarrowJumpOp(Opcode.IF_ICMPGE, target);
       
  1068     }
       
  1069 
       
  1070     public C if_icmpgt(short target) {
       
  1071         return emitNarrowJumpOp(Opcode.IF_ICMPGT, target);
       
  1072     }
       
  1073 
       
  1074     public C if_icmple(short target) {
       
  1075         return emitNarrowJumpOp(Opcode.IF_ICMPLE, target);
       
  1076     }
       
  1077 
       
  1078     public C if_acmpeq(short target) {
       
  1079         return emitNarrowJumpOp(Opcode.IF_ACMPEQ, target);
       
  1080     }
       
  1081 
       
  1082     public C if_acmpne(short target) {
       
  1083         return emitNarrowJumpOp(Opcode.IF_ACMPNE, target);
       
  1084     }
       
  1085 
       
  1086     public C goto_(short target) {
       
  1087         return emitNarrowJumpOp(Opcode.GOTO_, target);
       
  1088     }
       
  1089 
       
  1090     public C jsr(short target) {
       
  1091         return emitNarrowJumpOp(Opcode.JSR, target);
       
  1092     }
       
  1093 
       
  1094     public C ret(int index) {
       
  1095         return emitWideIfNeeded(Opcode.RET, index);
       
  1096     }
       
  1097 
       
  1098     public C tableswitch(int low, int high, int defaultTarget, int... targets) {
       
  1099         if (high - low + 1 != targets.length) throw new IllegalStateException("Bad targets length");
       
  1100         emitOp(Opcode.TABLESWITCH);
       
  1101         //padding
       
  1102         int start = code.offset;
       
  1103         if ((start % 4) != 0) {
       
  1104             //add padding
       
  1105             for (int i = 0; i < 4 - (start % 4); i++) {
       
  1106                 code.writeByte(0);
       
  1107             }
       
  1108         }
       
  1109         code.writeInt(defaultTarget)
       
  1110                 .writeInt(low)
       
  1111                 .writeInt(high);
       
  1112         for (int target : targets) {
       
  1113             code.writeInt(target);
       
  1114         }
       
  1115         return thisBuilder();
       
  1116     }
       
  1117 
       
  1118     public C lookupswitch(int defaultTarget, int... npairs) {
       
  1119         if (npairs.length % 2 != 0) throw new IllegalStateException("Bad npairs length");
       
  1120         emitOp(Opcode.LOOKUPSWITCH);
       
  1121         //padding
       
  1122         int start = code.offset;
       
  1123         for (int i = 0; i < (4 - (start % 4)); i++) {
       
  1124             code.writeByte(0);
       
  1125         }
       
  1126         code.writeInt(defaultTarget)
       
  1127                 .writeInt(npairs.length / 2);
       
  1128         for (int i = 0; i < npairs.length; i += 2) {
       
  1129             code.writeInt(npairs[i]);
       
  1130             code.writeInt(npairs[i + 1]);
       
  1131         }
       
  1132         return thisBuilder();
       
  1133     }
       
  1134 
       
  1135     public C arraylength() {
       
  1136         return emitOp(Opcode.ARRAYLENGTH);
       
  1137     }
       
  1138 
       
  1139     public C athrow() {
       
  1140         return emitOp(Opcode.ATHROW);
       
  1141     }
       
  1142 
       
  1143     public C monitorenter() {
       
  1144         return emitOp(Opcode.MONITORENTER);
       
  1145     }
       
  1146 
       
  1147     public C monitorexit() {
       
  1148         return emitOp(Opcode.MONITOREXIT);
       
  1149     }
       
  1150 
       
  1151     public C wide() {
       
  1152         return emitOp(Opcode.WIDE);
       
  1153     }
       
  1154 
       
  1155     public C if_null(short offset) {
       
  1156         return emitNarrowJumpOp(Opcode.IF_NULL, offset);
       
  1157     }
       
  1158 
       
  1159     public C if_nonnull(short offset) {
       
  1160         return emitNarrowJumpOp(Opcode.IF_NONNULL, offset);
       
  1161     }
       
  1162 
       
  1163     public C goto_w(int target) {
       
  1164         return emitWideJumpOp(Opcode.GOTO_W, target);
       
  1165     }
       
  1166 
       
  1167     public C jsr_w(int target) {
       
  1168         return emitWideJumpOp(Opcode.JSR_W, target);
       
  1169     }
       
  1170 
       
  1171     public C withCatch(S type, int start, int end, int offset) {
       
  1172         catchers.writeChar(start);
       
  1173         catchers.writeChar(end);
       
  1174         catchers.writeChar(offset);
       
  1175         catchers.writeChar(type != null ? poolHelper.putClass(type) : 0);
       
  1176         ncatchers++;
       
  1177         return thisBuilder();
       
  1178     }
       
  1179 
       
  1180     public C withLocalSize(int localsize) {
       
  1181         this.localsize = localsize;
       
  1182         return thisBuilder();
       
  1183     }
       
  1184 
       
  1185     public C withStackSize(int stacksize) {
       
  1186         this.stacksize = stacksize;
       
  1187         return thisBuilder();
       
  1188     }
       
  1189 
       
  1190     protected int localsize() {
       
  1191         return localsize;
       
  1192     }
       
  1193 
       
  1194     void build(GrowableByteBuffer buf) {
       
  1195         buf.writeChar(stacksize); //max stack size
       
  1196         buf.writeChar(localsize()); //max locals
       
  1197         buf.writeInt(code.offset);
       
  1198         buf.writeBytes(code);
       
  1199         buf.writeChar(ncatchers);
       
  1200         buf.writeBytes(catchers);
       
  1201         buf.writeChar(nattrs); //attributes
       
  1202         buf.writeBytes(attributes);
       
  1203     }
       
  1204 
       
  1205     byte[] build() {
       
  1206         GrowableByteBuffer buf = new GrowableByteBuffer();
       
  1207         build(buf);
       
  1208         return buf.bytes();
       
  1209     }
       
  1210 
       
  1211     protected C emitNarrowJumpOp(Opcode opcode, short target) {
       
  1212         emitOp(opcode);
       
  1213         emitOffset(code, JumpMode.NARROW, target);
       
  1214         return thisBuilder();
       
  1215     }
       
  1216 
       
  1217     protected C emitWideJumpOp(Opcode opcode, int target) {
       
  1218         emitOp(opcode);
       
  1219         emitOffset(code, JumpMode.WIDE, target);
       
  1220         return thisBuilder();
       
  1221     }
       
  1222 
       
  1223     protected C emitOp(Opcode opcode) {
       
  1224         return emitOp(opcode, null);
       
  1225     }
       
  1226 
       
  1227     protected C emitOp(Opcode opcode, Object optPoolValue) {
       
  1228         code.writeByte(opcode.code);
       
  1229         return thisBuilder();
       
  1230     }
       
  1231 
       
  1232     protected void emitOffset(GrowableByteBuffer buf, JumpMode jumpMode, int offset) {
       
  1233         if (jumpMode == JumpMode.NARROW) {
       
  1234             buf.writeChar((short) offset);
       
  1235         } else {
       
  1236             buf.writeInt(offset);
       
  1237         }
       
  1238     }
       
  1239 
       
  1240     int offset() {
       
  1241         return code.offset;
       
  1242     }
       
  1243 
       
  1244     /*** stackmap support ***/
       
  1245 
       
  1246     /**
       
  1247      * The tags and constants used in compressed stackmap.
       
  1248      */
       
  1249     static final int SAME_FRAME_SIZE = 64;
       
  1250     static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
       
  1251     static final int SAME_FRAME_EXTENDED = 251;
       
  1252     static final int FULL_FRAME = 255;
       
  1253     static final int MAX_LOCAL_LENGTH_DIFF = 4;
       
  1254 
       
  1255     @SuppressWarnings("unchecked")
       
  1256     private void writeStackMapType(T t) {
       
  1257         if (t == null) {
       
  1258             stackmaps.writeByte(0);
       
  1259         } else {
       
  1260             switch (typeHelper.tag(t)) {
       
  1261                 case B:
       
  1262                 case C:
       
  1263                 case S:
       
  1264                 case I:
       
  1265                 case Z:
       
  1266                     stackmaps.writeByte(1);
       
  1267                     break;
       
  1268                 case F:
       
  1269                     stackmaps.writeByte(2);
       
  1270                     break;
       
  1271                 case D:
       
  1272                     stackmaps.writeByte(3);
       
  1273                     break;
       
  1274                 case J:
       
  1275                     stackmaps.writeByte(4);
       
  1276                     break;
       
  1277                 case A:
       
  1278                     if (t == typeHelper.nullType()) {
       
  1279                         stackmaps.writeByte(5); //null
       
  1280                     } else {
       
  1281                         //TODO: uninit this, top?
       
  1282                         stackmaps.writeByte(7);
       
  1283                         stackmaps.writeChar(poolHelper.putClass(typeHelper.symbol(t)));
       
  1284                     }
       
  1285                     break;
       
  1286                 default:
       
  1287                     throw new IllegalStateException("Bad type");
       
  1288             }
       
  1289         }
       
  1290     }
       
  1291 
       
  1292     public void sameFrame(int offsetDelta) {
       
  1293         int frameType = (offsetDelta < SAME_FRAME_SIZE) ?
       
  1294                 offsetDelta : SAME_FRAME_EXTENDED;
       
  1295         stackmaps.writeByte(frameType);
       
  1296         if (frameType == SAME_FRAME_EXTENDED) {
       
  1297             stackmaps.writeChar(offsetDelta);
       
  1298         }
       
  1299     }
       
  1300 
       
  1301     public void sameLocals1StackItemFrame(int offsetDelta, T stackItem) {
       
  1302         int frameType = (offsetDelta < SAME_FRAME_SIZE) ?
       
  1303                 (SAME_FRAME_SIZE + offsetDelta) : SAME_LOCALS_1_STACK_ITEM_EXTENDED;
       
  1304         stackmaps.writeByte(frameType);
       
  1305         if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
       
  1306             stackmaps.writeChar(offsetDelta);
       
  1307         }
       
  1308         writeStackMapType(stackItem);
       
  1309     }
       
  1310 
       
  1311     public void appendFrame(int offsetDelta, int prevLocalsSize, List<T> locals) {
       
  1312         int frameType = SAME_FRAME_EXTENDED + (locals.size() - prevLocalsSize);
       
  1313         stackmaps.writeByte(frameType);
       
  1314         stackmaps.writeChar(offsetDelta);
       
  1315         for (int i = prevLocalsSize; i < locals.size(); i++) {
       
  1316             writeStackMapType(locals.get(i));
       
  1317         }
       
  1318     }
       
  1319 
       
  1320     public void chopFrame(int offsetDelta, int droppedVars) {
       
  1321         int frameType = SAME_FRAME_EXTENDED - droppedVars;
       
  1322         stackmaps.writeByte(frameType);
       
  1323         stackmaps.writeChar(offsetDelta);
       
  1324     }
       
  1325 
       
  1326     public void fullFrame(int offsetDelta, List<T> locals, List<T> stackItems) {
       
  1327         stackmaps.writeByte(FULL_FRAME);
       
  1328         stackmaps.writeChar(offsetDelta);
       
  1329         stackmaps.writeChar(locals.size());
       
  1330         for (T local : locals) {
       
  1331             writeStackMapType(local);
       
  1332         }
       
  1333 
       
  1334         stackmaps.writeChar(stackItems.size());
       
  1335         for (T stackType : stackItems) {
       
  1336             writeStackMapType(stackType);
       
  1337         }
       
  1338     }
       
  1339 }