jdk/src/share/classes/sun/reflect/ClassFileAssembler.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2001-2004 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.reflect;
       
    27 
       
    28 class ClassFileAssembler implements ClassFileConstants {
       
    29     private ByteVector vec;
       
    30     private short cpIdx = 0;
       
    31 
       
    32     public ClassFileAssembler() {
       
    33         this(ByteVectorFactory.create());
       
    34     }
       
    35 
       
    36     public ClassFileAssembler(ByteVector vec) {
       
    37         this.vec = vec;
       
    38     }
       
    39 
       
    40     public ByteVector getData() {
       
    41         return vec;
       
    42     }
       
    43 
       
    44     /** Length in bytes */
       
    45     public short getLength() {
       
    46         return (short) vec.getLength();
       
    47     }
       
    48 
       
    49     public void emitMagicAndVersion() {
       
    50         emitInt(0xCAFEBABE);
       
    51         emitShort((short) 0);
       
    52         emitShort((short) 49);
       
    53     }
       
    54 
       
    55     public void emitInt(int val) {
       
    56         emitByte((byte) (val >> 24));
       
    57         emitByte((byte) ((val >> 16) & 0xFF));
       
    58         emitByte((byte) ((val >> 8) & 0xFF));
       
    59         emitByte((byte) (val & 0xFF));
       
    60     }
       
    61 
       
    62     public void emitShort(short val) {
       
    63         emitByte((byte) ((val >> 8) & 0xFF));
       
    64         emitByte((byte) (val & 0xFF));
       
    65     }
       
    66 
       
    67     // Support for labels; package-private
       
    68     void emitShort(short bci, short val) {
       
    69         vec.put(bci,     (byte) ((val >> 8) & 0xFF));
       
    70         vec.put(bci + 1, (byte) (val & 0xFF));
       
    71     }
       
    72 
       
    73     public void emitByte(byte val) {
       
    74         vec.add(val);
       
    75     }
       
    76 
       
    77     public void append(ClassFileAssembler asm) {
       
    78         append(asm.vec);
       
    79     }
       
    80 
       
    81     public void append(ByteVector vec) {
       
    82         for (int i = 0; i < vec.getLength(); i++) {
       
    83             emitByte(vec.get(i));
       
    84         }
       
    85     }
       
    86 
       
    87     /** Keeps track of the current (one-based) constant pool index;
       
    88         incremented after emitting one of the following constant pool
       
    89         entries. Can fetch the current constant pool index for use in
       
    90         later entries.  Index points at the last valid constant pool
       
    91         entry; initially invalid. It is illegal to fetch the constant
       
    92         pool index before emitting at least one constant pool entry. */
       
    93     public short cpi() {
       
    94         if (cpIdx == 0) {
       
    95             throw new RuntimeException("Illegal use of ClassFileAssembler");
       
    96         }
       
    97         return cpIdx;
       
    98     }
       
    99 
       
   100     public void emitConstantPoolUTF8(String str) {
       
   101         // NOTE: can not use str.getBytes("UTF-8") here because of
       
   102         // bootstrapping issues with the character set converters.
       
   103         byte[] bytes = UTF8.encode(str);
       
   104         emitByte(CONSTANT_Utf8);
       
   105         emitShort((short) bytes.length);
       
   106         for (int i = 0; i < bytes.length; i++) {
       
   107             emitByte(bytes[i]);
       
   108         }
       
   109         cpIdx++;
       
   110     }
       
   111 
       
   112     public void emitConstantPoolClass(short index) {
       
   113         emitByte(CONSTANT_Class);
       
   114         emitShort(index);
       
   115         cpIdx++;
       
   116     }
       
   117 
       
   118     public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) {
       
   119         emitByte(CONSTANT_NameAndType);
       
   120         emitShort(nameIndex);
       
   121         emitShort(typeIndex);
       
   122         cpIdx++;
       
   123     }
       
   124 
       
   125     public void emitConstantPoolFieldref
       
   126         (short classIndex, short nameAndTypeIndex)
       
   127     {
       
   128         emitByte(CONSTANT_Fieldref);
       
   129         emitShort(classIndex);
       
   130         emitShort(nameAndTypeIndex);
       
   131         cpIdx++;
       
   132     }
       
   133 
       
   134     public void emitConstantPoolMethodref
       
   135         (short classIndex, short nameAndTypeIndex)
       
   136     {
       
   137         emitByte(CONSTANT_Methodref);
       
   138         emitShort(classIndex);
       
   139         emitShort(nameAndTypeIndex);
       
   140         cpIdx++;
       
   141     }
       
   142 
       
   143     public void emitConstantPoolInterfaceMethodref
       
   144         (short classIndex, short nameAndTypeIndex)
       
   145     {
       
   146         emitByte(CONSTANT_InterfaceMethodref);
       
   147         emitShort(classIndex);
       
   148         emitShort(nameAndTypeIndex);
       
   149         cpIdx++;
       
   150     }
       
   151 
       
   152     public void emitConstantPoolString(short utf8Index) {
       
   153         emitByte(CONSTANT_String);
       
   154         emitShort(utf8Index);
       
   155         cpIdx++;
       
   156     }
       
   157 
       
   158     //----------------------------------------------------------------------
       
   159     // Opcodes. Keeps track of maximum stack and locals. Make a new
       
   160     // assembler for each piece of assembled code, then append the
       
   161     // result to the previous assembler's class file.
       
   162     //
       
   163 
       
   164     private int stack     = 0;
       
   165     private int maxStack  = 0;
       
   166     private int maxLocals = 0;
       
   167 
       
   168     private void incStack() {
       
   169         setStack(stack + 1);
       
   170     }
       
   171 
       
   172     private void decStack() {
       
   173         --stack;
       
   174     }
       
   175 
       
   176     public short getMaxStack() {
       
   177         return (short) maxStack;
       
   178     }
       
   179 
       
   180     public short getMaxLocals() {
       
   181         return (short) maxLocals;
       
   182     }
       
   183 
       
   184     /** It's necessary to be able to specify the number of arguments at
       
   185         the beginning of the method (which translates to the initial
       
   186         value of max locals) */
       
   187     public void setMaxLocals(int maxLocals) {
       
   188         this.maxLocals = maxLocals;
       
   189     }
       
   190 
       
   191     /** Needed to do flow control. Returns current stack depth. */
       
   192     public int getStack() {
       
   193         return stack;
       
   194     }
       
   195 
       
   196     /** Needed to do flow control. */
       
   197     public void setStack(int value) {
       
   198         stack = value;
       
   199         if (stack > maxStack) {
       
   200             maxStack = stack;
       
   201         }
       
   202     }
       
   203 
       
   204     ///////////////
       
   205     // Constants //
       
   206     ///////////////
       
   207 
       
   208     public void opc_aconst_null() {
       
   209         emitByte(opc_aconst_null);
       
   210         incStack();
       
   211     }
       
   212 
       
   213     public void opc_sipush(short constant) {
       
   214         emitByte(opc_sipush);
       
   215         emitShort(constant);
       
   216         incStack();
       
   217     }
       
   218 
       
   219     public void opc_ldc(byte cpIdx) {
       
   220         emitByte(opc_ldc);
       
   221         emitByte(cpIdx);
       
   222         incStack();
       
   223     }
       
   224 
       
   225     /////////////////////////////////////
       
   226     // Local variable loads and stores //
       
   227     /////////////////////////////////////
       
   228 
       
   229     public void opc_iload_0() {
       
   230         emitByte(opc_iload_0);
       
   231         if (maxLocals < 1) maxLocals = 1;
       
   232         incStack();
       
   233     }
       
   234 
       
   235     public void opc_iload_1() {
       
   236         emitByte(opc_iload_1);
       
   237         if (maxLocals < 2) maxLocals = 2;
       
   238         incStack();
       
   239     }
       
   240 
       
   241     public void opc_iload_2() {
       
   242         emitByte(opc_iload_2);
       
   243         if (maxLocals < 3) maxLocals = 3;
       
   244         incStack();
       
   245     }
       
   246 
       
   247     public void opc_iload_3() {
       
   248         emitByte(opc_iload_3);
       
   249         if (maxLocals < 4) maxLocals = 4;
       
   250         incStack();
       
   251     }
       
   252 
       
   253     public void opc_lload_0() {
       
   254         emitByte(opc_lload_0);
       
   255         if (maxLocals < 2) maxLocals = 2;
       
   256         incStack();
       
   257         incStack();
       
   258     }
       
   259 
       
   260     public void opc_lload_1() {
       
   261         emitByte(opc_lload_1);
       
   262         if (maxLocals < 3) maxLocals = 3;
       
   263         incStack();
       
   264         incStack();
       
   265     }
       
   266 
       
   267     public void opc_lload_2() {
       
   268         emitByte(opc_lload_2);
       
   269         if (maxLocals < 4) maxLocals = 4;
       
   270         incStack();
       
   271         incStack();
       
   272     }
       
   273 
       
   274     public void opc_lload_3() {
       
   275         emitByte(opc_lload_3);
       
   276         if (maxLocals < 5) maxLocals = 5;
       
   277         incStack();
       
   278         incStack();
       
   279     }
       
   280 
       
   281     public void opc_fload_0() {
       
   282         emitByte(opc_fload_0);
       
   283         if (maxLocals < 1) maxLocals = 1;
       
   284         incStack();
       
   285     }
       
   286 
       
   287     public void opc_fload_1() {
       
   288         emitByte(opc_fload_1);
       
   289         if (maxLocals < 2) maxLocals = 2;
       
   290         incStack();
       
   291     }
       
   292 
       
   293     public void opc_fload_2() {
       
   294         emitByte(opc_fload_2);
       
   295         if (maxLocals < 3) maxLocals = 3;
       
   296         incStack();
       
   297     }
       
   298 
       
   299     public void opc_fload_3() {
       
   300         emitByte(opc_fload_3);
       
   301         if (maxLocals < 4) maxLocals = 4;
       
   302         incStack();
       
   303     }
       
   304 
       
   305     public void opc_dload_0() {
       
   306         emitByte(opc_dload_0);
       
   307         if (maxLocals < 2) maxLocals = 2;
       
   308         incStack();
       
   309         incStack();
       
   310     }
       
   311 
       
   312     public void opc_dload_1() {
       
   313         emitByte(opc_dload_1);
       
   314         if (maxLocals < 3) maxLocals = 3;
       
   315         incStack();
       
   316         incStack();
       
   317     }
       
   318 
       
   319     public void opc_dload_2() {
       
   320         emitByte(opc_dload_2);
       
   321         if (maxLocals < 4) maxLocals = 4;
       
   322         incStack();
       
   323         incStack();
       
   324     }
       
   325 
       
   326     public void opc_dload_3() {
       
   327         emitByte(opc_dload_3);
       
   328         if (maxLocals < 5) maxLocals = 5;
       
   329         incStack();
       
   330         incStack();
       
   331     }
       
   332 
       
   333     public void opc_aload_0() {
       
   334         emitByte(opc_aload_0);
       
   335         if (maxLocals < 1) maxLocals = 1;
       
   336         incStack();
       
   337     }
       
   338 
       
   339     public void opc_aload_1() {
       
   340         emitByte(opc_aload_1);
       
   341         if (maxLocals < 2) maxLocals = 2;
       
   342         incStack();
       
   343     }
       
   344 
       
   345     public void opc_aload_2() {
       
   346         emitByte(opc_aload_2);
       
   347         if (maxLocals < 3) maxLocals = 3;
       
   348         incStack();
       
   349     }
       
   350 
       
   351     public void opc_aload_3() {
       
   352         emitByte(opc_aload_3);
       
   353         if (maxLocals < 4) maxLocals = 4;
       
   354         incStack();
       
   355     }
       
   356 
       
   357     public void opc_aaload() {
       
   358         emitByte(opc_aaload);
       
   359         decStack();
       
   360     }
       
   361 
       
   362     public void opc_astore_0() {
       
   363         emitByte(opc_astore_0);
       
   364         if (maxLocals < 1) maxLocals = 1;
       
   365         decStack();
       
   366     }
       
   367 
       
   368     public void opc_astore_1() {
       
   369         emitByte(opc_astore_1);
       
   370         if (maxLocals < 2) maxLocals = 2;
       
   371         decStack();
       
   372     }
       
   373 
       
   374     public void opc_astore_2() {
       
   375         emitByte(opc_astore_2);
       
   376         if (maxLocals < 3) maxLocals = 3;
       
   377         decStack();
       
   378     }
       
   379 
       
   380     public void opc_astore_3() {
       
   381         emitByte(opc_astore_3);
       
   382         if (maxLocals < 4) maxLocals = 4;
       
   383         decStack();
       
   384     }
       
   385 
       
   386     ////////////////////////
       
   387     // Stack manipulation //
       
   388     ////////////////////////
       
   389 
       
   390     public void opc_pop() {
       
   391         emitByte(opc_pop);
       
   392         decStack();
       
   393     }
       
   394 
       
   395     public void opc_dup() {
       
   396         emitByte(opc_dup);
       
   397         incStack();
       
   398     }
       
   399 
       
   400     public void opc_dup_x1() {
       
   401         emitByte(opc_dup_x1);
       
   402         incStack();
       
   403     }
       
   404 
       
   405     public void opc_swap() {
       
   406         emitByte(opc_swap);
       
   407     }
       
   408 
       
   409     ///////////////////////////////
       
   410     // Widening conversions only //
       
   411     ///////////////////////////////
       
   412 
       
   413     public void opc_i2l() {
       
   414         emitByte(opc_i2l);
       
   415     }
       
   416 
       
   417     public void opc_i2f() {
       
   418         emitByte(opc_i2f);
       
   419     }
       
   420 
       
   421     public void opc_i2d() {
       
   422         emitByte(opc_i2d);
       
   423     }
       
   424 
       
   425     public void opc_l2f() {
       
   426         emitByte(opc_l2f);
       
   427     }
       
   428 
       
   429     public void opc_l2d() {
       
   430         emitByte(opc_l2d);
       
   431     }
       
   432 
       
   433     public void opc_f2d() {
       
   434         emitByte(opc_f2d);
       
   435     }
       
   436 
       
   437     //////////////////
       
   438     // Control flow //
       
   439     //////////////////
       
   440 
       
   441     public void opc_ifeq(short bciOffset) {
       
   442         emitByte(opc_ifeq);
       
   443         emitShort(bciOffset);
       
   444         decStack();
       
   445     }
       
   446 
       
   447     /** Control flow with forward-reference BCI. Stack assumes
       
   448         straight-through control flow. */
       
   449     public void opc_ifeq(Label l) {
       
   450         short instrBCI = getLength();
       
   451         emitByte(opc_ifeq);
       
   452         l.add(this, instrBCI, getLength(), getStack() - 1);
       
   453         emitShort((short) -1); // Must be patched later
       
   454     }
       
   455 
       
   456     public void opc_if_icmpeq(short bciOffset) {
       
   457         emitByte(opc_if_icmpeq);
       
   458         emitShort(bciOffset);
       
   459         setStack(getStack() - 2);
       
   460     }
       
   461 
       
   462     /** Control flow with forward-reference BCI. Stack assumes straight
       
   463         control flow. */
       
   464     public void opc_if_icmpeq(Label l) {
       
   465         short instrBCI = getLength();
       
   466         emitByte(opc_if_icmpeq);
       
   467         l.add(this, instrBCI, getLength(), getStack() - 2);
       
   468         emitShort((short) -1); // Must be patched later
       
   469     }
       
   470 
       
   471     public void opc_goto(short bciOffset) {
       
   472         emitByte(opc_goto);
       
   473         emitShort(bciOffset);
       
   474     }
       
   475 
       
   476     /** Control flow with forward-reference BCI. Stack assumes straight
       
   477         control flow. */
       
   478     public void opc_goto(Label l) {
       
   479         short instrBCI = getLength();
       
   480         emitByte(opc_goto);
       
   481         l.add(this, instrBCI, getLength(), getStack());
       
   482         emitShort((short) -1); // Must be patched later
       
   483     }
       
   484 
       
   485     public void opc_ifnull(short bciOffset) {
       
   486         emitByte(opc_ifnull);
       
   487         emitShort(bciOffset);
       
   488         decStack();
       
   489     }
       
   490 
       
   491     /** Control flow with forward-reference BCI. Stack assumes straight
       
   492         control flow. */
       
   493     public void opc_ifnull(Label l) {
       
   494         short instrBCI = getLength();
       
   495         emitByte(opc_ifnull);
       
   496         l.add(this, instrBCI, getLength(), getStack() - 1);
       
   497         emitShort((short) -1); // Must be patched later
       
   498         decStack();
       
   499     }
       
   500 
       
   501     public void opc_ifnonnull(short bciOffset) {
       
   502         emitByte(opc_ifnonnull);
       
   503         emitShort(bciOffset);
       
   504         decStack();
       
   505     }
       
   506 
       
   507     /** Control flow with forward-reference BCI. Stack assumes straight
       
   508         control flow. */
       
   509     public void opc_ifnonnull(Label l) {
       
   510         short instrBCI = getLength();
       
   511         emitByte(opc_ifnonnull);
       
   512         l.add(this, instrBCI, getLength(), getStack() - 1);
       
   513         emitShort((short) -1); // Must be patched later
       
   514         decStack();
       
   515     }
       
   516 
       
   517     /////////////////////////
       
   518     // Return instructions //
       
   519     /////////////////////////
       
   520 
       
   521     public void opc_ireturn() {
       
   522         emitByte(opc_ireturn);
       
   523         setStack(0);
       
   524     }
       
   525 
       
   526     public void opc_lreturn() {
       
   527         emitByte(opc_lreturn);
       
   528         setStack(0);
       
   529     }
       
   530 
       
   531     public void opc_freturn() {
       
   532         emitByte(opc_freturn);
       
   533         setStack(0);
       
   534     }
       
   535 
       
   536     public void opc_dreturn() {
       
   537         emitByte(opc_dreturn);
       
   538         setStack(0);
       
   539     }
       
   540 
       
   541     public void opc_areturn() {
       
   542         emitByte(opc_areturn);
       
   543         setStack(0);
       
   544     }
       
   545 
       
   546     public void opc_return() {
       
   547         emitByte(opc_return);
       
   548         setStack(0);
       
   549     }
       
   550 
       
   551     //////////////////////
       
   552     // Field operations //
       
   553     //////////////////////
       
   554 
       
   555     public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) {
       
   556         emitByte(opc_getstatic);
       
   557         emitShort(fieldIndex);
       
   558         setStack(getStack() + fieldSizeInStackSlots);
       
   559     }
       
   560 
       
   561     public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) {
       
   562         emitByte(opc_putstatic);
       
   563         emitShort(fieldIndex);
       
   564         setStack(getStack() - fieldSizeInStackSlots);
       
   565     }
       
   566 
       
   567     public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {
       
   568         emitByte(opc_getfield);
       
   569         emitShort(fieldIndex);
       
   570         setStack(getStack() + fieldSizeInStackSlots - 1);
       
   571     }
       
   572 
       
   573     public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) {
       
   574         emitByte(opc_putfield);
       
   575         emitShort(fieldIndex);
       
   576         setStack(getStack() - fieldSizeInStackSlots - 1);
       
   577     }
       
   578 
       
   579     ////////////////////////
       
   580     // Method invocations //
       
   581     ////////////////////////
       
   582 
       
   583     /** Long and double arguments and return types count as 2 arguments;
       
   584         other values count as 1. */
       
   585     public void opc_invokevirtual(short methodIndex,
       
   586                                   int numArgs,
       
   587                                   int numReturnValues)
       
   588     {
       
   589         emitByte(opc_invokevirtual);
       
   590         emitShort(methodIndex);
       
   591         setStack(getStack() - numArgs - 1 + numReturnValues);
       
   592     }
       
   593 
       
   594     /** Long and double arguments and return types count as 2 arguments;
       
   595         other values count as 1. */
       
   596     public void opc_invokespecial(short methodIndex,
       
   597                                   int numArgs,
       
   598                                   int numReturnValues)
       
   599     {
       
   600         emitByte(opc_invokespecial);
       
   601         emitShort(methodIndex);
       
   602         setStack(getStack() - numArgs - 1 + numReturnValues);
       
   603     }
       
   604 
       
   605     /** Long and double arguments and return types count as 2 arguments;
       
   606         other values count as 1. */
       
   607     public void opc_invokestatic(short methodIndex,
       
   608                                  int numArgs,
       
   609                                  int numReturnValues)
       
   610     {
       
   611         emitByte(opc_invokestatic);
       
   612         emitShort(methodIndex);
       
   613         setStack(getStack() - numArgs + numReturnValues);
       
   614     }
       
   615 
       
   616     /** Long and double arguments and return types count as 2 arguments;
       
   617         other values count as 1. */
       
   618     public void opc_invokeinterface(short methodIndex,
       
   619                                     int numArgs,
       
   620                                     byte count,
       
   621                                     int numReturnValues)
       
   622     {
       
   623         emitByte(opc_invokeinterface);
       
   624         emitShort(methodIndex);
       
   625         emitByte(count);
       
   626         emitByte((byte) 0);
       
   627         setStack(getStack() - numArgs - 1 + numReturnValues);
       
   628     }
       
   629 
       
   630     //////////////////
       
   631     // Array length //
       
   632     //////////////////
       
   633 
       
   634     public void opc_arraylength() {
       
   635         emitByte(opc_arraylength);
       
   636     }
       
   637 
       
   638     /////////
       
   639     // New //
       
   640     /////////
       
   641 
       
   642     public void opc_new(short classIndex) {
       
   643         emitByte(opc_new);
       
   644         emitShort(classIndex);
       
   645         incStack();
       
   646     }
       
   647 
       
   648     ////////////
       
   649     // Athrow //
       
   650     ////////////
       
   651 
       
   652     public void opc_athrow() {
       
   653         emitByte(opc_athrow);
       
   654         setStack(1);
       
   655     }
       
   656 
       
   657     //////////////////////////////
       
   658     // Checkcast and instanceof //
       
   659     //////////////////////////////
       
   660 
       
   661     /** Assumes the checkcast succeeds */
       
   662     public void opc_checkcast(short classIndex) {
       
   663         emitByte(opc_checkcast);
       
   664         emitShort(classIndex);
       
   665     }
       
   666 
       
   667     public void opc_instanceof(short classIndex) {
       
   668         emitByte(opc_instanceof);
       
   669         emitShort(classIndex);
       
   670     }
       
   671 }