jdk/src/share/classes/sun/reflect/AccessorGenerator.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2001 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 import java.lang.reflect.*;
       
    29 import sun.misc.Unsafe;
       
    30 
       
    31 /** Shared functionality for all accessor generators */
       
    32 
       
    33 class AccessorGenerator implements ClassFileConstants {
       
    34     static final Unsafe unsafe = Unsafe.getUnsafe();
       
    35 
       
    36     // Constants because there's no way to say "short integer constant",
       
    37     // i.e., "1S"
       
    38     protected static final short S0 = (short) 0;
       
    39     protected static final short S1 = (short) 1;
       
    40     protected static final short S2 = (short) 2;
       
    41     protected static final short S3 = (short) 3;
       
    42     protected static final short S4 = (short) 4;
       
    43     protected static final short S5 = (short) 5;
       
    44     protected static final short S6 = (short) 6;
       
    45 
       
    46     // Instance variables for shared functionality between
       
    47     // FieldAccessorGenerator and MethodAccessorGenerator
       
    48     protected ClassFileAssembler asm;
       
    49     protected int   modifiers;
       
    50     protected short thisClass;
       
    51     protected short superClass;
       
    52     protected short targetClass;
       
    53     // Common constant pool entries to FieldAccessor and MethodAccessor
       
    54     protected short throwableClass;
       
    55     protected short classCastClass;
       
    56     protected short nullPointerClass;
       
    57     protected short illegalArgumentClass;
       
    58     protected short invocationTargetClass;
       
    59     protected short initIdx;
       
    60     protected short initNameAndTypeIdx;
       
    61     protected short initStringNameAndTypeIdx;
       
    62     protected short nullPointerCtorIdx;
       
    63     protected short illegalArgumentCtorIdx;
       
    64     protected short illegalArgumentStringCtorIdx;
       
    65     protected short invocationTargetCtorIdx;
       
    66     protected short superCtorIdx;
       
    67     protected short objectClass;
       
    68     protected short toStringIdx;
       
    69     protected short codeIdx;
       
    70     protected short exceptionsIdx;
       
    71     // Boxing
       
    72     protected short booleanIdx;
       
    73     protected short booleanCtorIdx;
       
    74     protected short booleanUnboxIdx;
       
    75     protected short byteIdx;
       
    76     protected short byteCtorIdx;
       
    77     protected short byteUnboxIdx;
       
    78     protected short characterIdx;
       
    79     protected short characterCtorIdx;
       
    80     protected short characterUnboxIdx;
       
    81     protected short doubleIdx;
       
    82     protected short doubleCtorIdx;
       
    83     protected short doubleUnboxIdx;
       
    84     protected short floatIdx;
       
    85     protected short floatCtorIdx;
       
    86     protected short floatUnboxIdx;
       
    87     protected short integerIdx;
       
    88     protected short integerCtorIdx;
       
    89     protected short integerUnboxIdx;
       
    90     protected short longIdx;
       
    91     protected short longCtorIdx;
       
    92     protected short longUnboxIdx;
       
    93     protected short shortIdx;
       
    94     protected short shortCtorIdx;
       
    95     protected short shortUnboxIdx;
       
    96 
       
    97     protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30;
       
    98     protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 72;
       
    99 
       
   100     // Requires that superClass has been set up
       
   101     protected void emitCommonConstantPoolEntries() {
       
   102         // +   [UTF-8] "java/lang/Throwable"
       
   103         // +   [CONSTANT_Class_info] for above
       
   104         // +   [UTF-8] "java/lang/ClassCastException"
       
   105         // +   [CONSTANT_Class_info] for above
       
   106         // +   [UTF-8] "java/lang/NullPointerException"
       
   107         // +   [CONSTANT_Class_info] for above
       
   108         // +   [UTF-8] "java/lang/IllegalArgumentException"
       
   109         // +   [CONSTANT_Class_info] for above
       
   110         // +   [UTF-8] "java/lang/InvocationTargetException"
       
   111         // +   [CONSTANT_Class_info] for above
       
   112         // +   [UTF-8] "<init>"
       
   113         // +   [UTF-8] "()V"
       
   114         // +   [CONSTANT_NameAndType_info] for above
       
   115         // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
       
   116         // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
       
   117         // +   [UTF-8] "(Ljava/lang/String;)V"
       
   118         // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
       
   119         // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
       
   120         // +   [UTF-8] "(Ljava/lang/Throwable;)V"
       
   121         // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
       
   122         // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
       
   123         // +   [CONSTANT_Methodref_info] for "super()"
       
   124         // +   [UTF-8] "java/lang/Object"
       
   125         // +   [CONSTANT_Class_info] for above
       
   126         // +   [UTF-8] "toString"
       
   127         // +   [UTF-8] "()Ljava/lang/String;"
       
   128         // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
       
   129         // +   [CONSTANT_Methodref_info] for Object's toString method
       
   130         // +   [UTF-8] "Code"
       
   131         // +   [UTF-8] "Exceptions"
       
   132         asm.emitConstantPoolUTF8("java/lang/Throwable");
       
   133         asm.emitConstantPoolClass(asm.cpi());
       
   134         throwableClass = asm.cpi();
       
   135         asm.emitConstantPoolUTF8("java/lang/ClassCastException");
       
   136         asm.emitConstantPoolClass(asm.cpi());
       
   137         classCastClass = asm.cpi();
       
   138         asm.emitConstantPoolUTF8("java/lang/NullPointerException");
       
   139         asm.emitConstantPoolClass(asm.cpi());
       
   140         nullPointerClass = asm.cpi();
       
   141         asm.emitConstantPoolUTF8("java/lang/IllegalArgumentException");
       
   142         asm.emitConstantPoolClass(asm.cpi());
       
   143         illegalArgumentClass = asm.cpi();
       
   144         asm.emitConstantPoolUTF8("java/lang/reflect/InvocationTargetException");
       
   145         asm.emitConstantPoolClass(asm.cpi());
       
   146         invocationTargetClass = asm.cpi();
       
   147         asm.emitConstantPoolUTF8("<init>");
       
   148         initIdx = asm.cpi();
       
   149         asm.emitConstantPoolUTF8("()V");
       
   150         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   151         initNameAndTypeIdx = asm.cpi();
       
   152         asm.emitConstantPoolMethodref(nullPointerClass, initNameAndTypeIdx);
       
   153         nullPointerCtorIdx = asm.cpi();
       
   154         asm.emitConstantPoolMethodref(illegalArgumentClass, initNameAndTypeIdx);
       
   155         illegalArgumentCtorIdx = asm.cpi();
       
   156         asm.emitConstantPoolUTF8("(Ljava/lang/String;)V");
       
   157         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   158         initStringNameAndTypeIdx = asm.cpi();
       
   159         asm.emitConstantPoolMethodref(illegalArgumentClass, initStringNameAndTypeIdx);
       
   160         illegalArgumentStringCtorIdx = asm.cpi();
       
   161         asm.emitConstantPoolUTF8("(Ljava/lang/Throwable;)V");
       
   162         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   163         asm.emitConstantPoolMethodref(invocationTargetClass, asm.cpi());
       
   164         invocationTargetCtorIdx = asm.cpi();
       
   165         asm.emitConstantPoolMethodref(superClass, initNameAndTypeIdx);
       
   166         superCtorIdx = asm.cpi();
       
   167         asm.emitConstantPoolUTF8("java/lang/Object");
       
   168         asm.emitConstantPoolClass(asm.cpi());
       
   169         objectClass = asm.cpi();
       
   170         asm.emitConstantPoolUTF8("toString");
       
   171         asm.emitConstantPoolUTF8("()Ljava/lang/String;");
       
   172         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   173         asm.emitConstantPoolMethodref(objectClass, asm.cpi());
       
   174         toStringIdx = asm.cpi();
       
   175         asm.emitConstantPoolUTF8("Code");
       
   176         codeIdx = asm.cpi();
       
   177         asm.emitConstantPoolUTF8("Exceptions");
       
   178         exceptionsIdx = asm.cpi();
       
   179     }
       
   180 
       
   181     /** Constant pool entries required to be able to box/unbox primitive
       
   182         types. Note that we don't emit these if we don't need them. */
       
   183     protected void emitBoxingContantPoolEntries() {
       
   184         //  *  [UTF-8] "java/lang/Boolean"
       
   185         //  *  [CONSTANT_Class_info] for above
       
   186         //  *  [UTF-8] "(Z)V"
       
   187         //  *  [CONSTANT_NameAndType_info] for above
       
   188         //  *  [CONSTANT_Methodref_info] for above
       
   189         //  *  [UTF-8] "booleanValue"
       
   190         //  *  [UTF-8] "()Z"
       
   191         //  *  [CONSTANT_NameAndType_info] for above
       
   192         //  *  [CONSTANT_Methodref_info] for above
       
   193         //  *  [UTF-8] "java/lang/Byte"
       
   194         //  *  [CONSTANT_Class_info] for above
       
   195         //  *  [UTF-8] "(B)V"
       
   196         //  *  [CONSTANT_NameAndType_info] for above
       
   197         //  *  [CONSTANT_Methodref_info] for above
       
   198         //  *  [UTF-8] "byteValue"
       
   199         //  *  [UTF-8] "()B"
       
   200         //  *  [CONSTANT_NameAndType_info] for above
       
   201         //  *  [CONSTANT_Methodref_info] for above
       
   202         //  *  [UTF-8] "java/lang/Character"
       
   203         //  *  [CONSTANT_Class_info] for above
       
   204         //  *  [UTF-8] "(C)V"
       
   205         //  *  [CONSTANT_NameAndType_info] for above
       
   206         //  *  [CONSTANT_Methodref_info] for above
       
   207         //  *  [UTF-8] "charValue"
       
   208         //  *  [UTF-8] "()C"
       
   209         //  *  [CONSTANT_NameAndType_info] for above
       
   210         //  *  [CONSTANT_Methodref_info] for above
       
   211         //  *  [UTF-8] "java/lang/Double"
       
   212         //  *  [CONSTANT_Class_info] for above
       
   213         //  *  [UTF-8] "(D)V"
       
   214         //  *  [CONSTANT_NameAndType_info] for above
       
   215         //  *  [CONSTANT_Methodref_info] for above
       
   216         //  *  [UTF-8] "doubleValue"
       
   217         //  *  [UTF-8] "()D"
       
   218         //  *  [CONSTANT_NameAndType_info] for above
       
   219         //  *  [CONSTANT_Methodref_info] for above
       
   220         //  *  [UTF-8] "java/lang/Float"
       
   221         //  *  [CONSTANT_Class_info] for above
       
   222         //  *  [UTF-8] "(F)V"
       
   223         //  *  [CONSTANT_NameAndType_info] for above
       
   224         //  *  [CONSTANT_Methodref_info] for above
       
   225         //  *  [UTF-8] "floatValue"
       
   226         //  *  [UTF-8] "()F"
       
   227         //  *  [CONSTANT_NameAndType_info] for above
       
   228         //  *  [CONSTANT_Methodref_info] for above
       
   229         //  *  [UTF-8] "java/lang/Integer"
       
   230         //  *  [CONSTANT_Class_info] for above
       
   231         //  *  [UTF-8] "(I)V"
       
   232         //  *  [CONSTANT_NameAndType_info] for above
       
   233         //  *  [CONSTANT_Methodref_info] for above
       
   234         //  *  [UTF-8] "intValue"
       
   235         //  *  [UTF-8] "()I"
       
   236         //  *  [CONSTANT_NameAndType_info] for above
       
   237         //  *  [CONSTANT_Methodref_info] for above
       
   238         //  *  [UTF-8] "java/lang/Long"
       
   239         //  *  [CONSTANT_Class_info] for above
       
   240         //  *  [UTF-8] "(J)V"
       
   241         //  *  [CONSTANT_NameAndType_info] for above
       
   242         //  *  [CONSTANT_Methodref_info] for above
       
   243         //  *  [UTF-8] "longValue"
       
   244         //  *  [UTF-8] "()J"
       
   245         //  *  [CONSTANT_NameAndType_info] for above
       
   246         //  *  [CONSTANT_Methodref_info] for above
       
   247         //  *  [UTF-8] "java/lang/Short"
       
   248         //  *  [CONSTANT_Class_info] for above
       
   249         //  *  [UTF-8] "(S)V"
       
   250         //  *  [CONSTANT_NameAndType_info] for above
       
   251         //  *  [CONSTANT_Methodref_info] for above
       
   252         //  *  [UTF-8] "shortValue"
       
   253         //  *  [UTF-8] "()S"
       
   254         //  *  [CONSTANT_NameAndType_info] for above
       
   255         //  *  [CONSTANT_Methodref_info] for above
       
   256         // Boolean
       
   257         asm.emitConstantPoolUTF8("java/lang/Boolean");
       
   258         asm.emitConstantPoolClass(asm.cpi());
       
   259         booleanIdx = asm.cpi();
       
   260         asm.emitConstantPoolUTF8("(Z)V");
       
   261         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   262         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   263         booleanCtorIdx = asm.cpi();
       
   264         asm.emitConstantPoolUTF8("booleanValue");
       
   265         asm.emitConstantPoolUTF8("()Z");
       
   266         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   267         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   268         booleanUnboxIdx = asm.cpi();
       
   269 
       
   270         // Byte
       
   271         asm.emitConstantPoolUTF8("java/lang/Byte");
       
   272         asm.emitConstantPoolClass(asm.cpi());
       
   273         byteIdx = asm.cpi();
       
   274         asm.emitConstantPoolUTF8("(B)V");
       
   275         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   276         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   277         byteCtorIdx = asm.cpi();
       
   278         asm.emitConstantPoolUTF8("byteValue");
       
   279         asm.emitConstantPoolUTF8("()B");
       
   280         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   281         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   282         byteUnboxIdx = asm.cpi();
       
   283 
       
   284         // Character
       
   285         asm.emitConstantPoolUTF8("java/lang/Character");
       
   286         asm.emitConstantPoolClass(asm.cpi());
       
   287         characterIdx = asm.cpi();
       
   288         asm.emitConstantPoolUTF8("(C)V");
       
   289         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   290         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   291         characterCtorIdx = asm.cpi();
       
   292         asm.emitConstantPoolUTF8("charValue");
       
   293         asm.emitConstantPoolUTF8("()C");
       
   294         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   295         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   296         characterUnboxIdx = asm.cpi();
       
   297 
       
   298         // Double
       
   299         asm.emitConstantPoolUTF8("java/lang/Double");
       
   300         asm.emitConstantPoolClass(asm.cpi());
       
   301         doubleIdx = asm.cpi();
       
   302         asm.emitConstantPoolUTF8("(D)V");
       
   303         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   304         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   305         doubleCtorIdx = asm.cpi();
       
   306         asm.emitConstantPoolUTF8("doubleValue");
       
   307         asm.emitConstantPoolUTF8("()D");
       
   308         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   309         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   310         doubleUnboxIdx = asm.cpi();
       
   311 
       
   312         // Float
       
   313         asm.emitConstantPoolUTF8("java/lang/Float");
       
   314         asm.emitConstantPoolClass(asm.cpi());
       
   315         floatIdx = asm.cpi();
       
   316         asm.emitConstantPoolUTF8("(F)V");
       
   317         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   318         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   319         floatCtorIdx = asm.cpi();
       
   320         asm.emitConstantPoolUTF8("floatValue");
       
   321         asm.emitConstantPoolUTF8("()F");
       
   322         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   323         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   324         floatUnboxIdx = asm.cpi();
       
   325 
       
   326         // Integer
       
   327         asm.emitConstantPoolUTF8("java/lang/Integer");
       
   328         asm.emitConstantPoolClass(asm.cpi());
       
   329         integerIdx = asm.cpi();
       
   330         asm.emitConstantPoolUTF8("(I)V");
       
   331         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   332         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   333         integerCtorIdx = asm.cpi();
       
   334         asm.emitConstantPoolUTF8("intValue");
       
   335         asm.emitConstantPoolUTF8("()I");
       
   336         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   337         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   338         integerUnboxIdx = asm.cpi();
       
   339 
       
   340         // Long
       
   341         asm.emitConstantPoolUTF8("java/lang/Long");
       
   342         asm.emitConstantPoolClass(asm.cpi());
       
   343         longIdx = asm.cpi();
       
   344         asm.emitConstantPoolUTF8("(J)V");
       
   345         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   346         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   347         longCtorIdx = asm.cpi();
       
   348         asm.emitConstantPoolUTF8("longValue");
       
   349         asm.emitConstantPoolUTF8("()J");
       
   350         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   351         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   352         longUnboxIdx = asm.cpi();
       
   353 
       
   354         // Short
       
   355         asm.emitConstantPoolUTF8("java/lang/Short");
       
   356         asm.emitConstantPoolClass(asm.cpi());
       
   357         shortIdx = asm.cpi();
       
   358         asm.emitConstantPoolUTF8("(S)V");
       
   359         asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
       
   360         asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
       
   361         shortCtorIdx = asm.cpi();
       
   362         asm.emitConstantPoolUTF8("shortValue");
       
   363         asm.emitConstantPoolUTF8("()S");
       
   364         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   365         asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
       
   366         shortUnboxIdx = asm.cpi();
       
   367     }
       
   368 
       
   369     // Necessary because of Java's annoying promotion rules
       
   370     protected static short add(short s1, short s2) {
       
   371         return (short) (s1 + s2);
       
   372     }
       
   373 
       
   374     protected static short sub(short s1, short s2) {
       
   375         return (short) (s1 - s2);
       
   376     }
       
   377 
       
   378     protected boolean isStatic() {
       
   379         return Modifier.isStatic(modifiers);
       
   380     }
       
   381 
       
   382     /** Returns class name in "internal" form (i.e., '/' separators
       
   383         instead of '.') */
       
   384     protected static String getClassName
       
   385         (Class c, boolean addPrefixAndSuffixForNonPrimitiveTypes)
       
   386     {
       
   387         if (c.isPrimitive()) {
       
   388             if (c == Boolean.TYPE) {
       
   389                 return "Z";
       
   390             } else if (c == Byte.TYPE) {
       
   391                 return "B";
       
   392             } else if (c == Character.TYPE) {
       
   393                 return "C";
       
   394             } else if (c == Double.TYPE) {
       
   395                 return "D";
       
   396             } else if (c == Float.TYPE) {
       
   397                 return "F";
       
   398             } else if (c == Integer.TYPE) {
       
   399                 return "I";
       
   400             } else if (c == Long.TYPE) {
       
   401                 return "J";
       
   402             } else if (c == Short.TYPE) {
       
   403                 return "S";
       
   404             } else if (c == Void.TYPE) {
       
   405                 return "V";
       
   406             }
       
   407             throw new InternalError("Should have found primitive type");
       
   408         } else if (c.isArray()) {
       
   409             return "[" + getClassName(c.getComponentType(), true);
       
   410         } else {
       
   411             if (addPrefixAndSuffixForNonPrimitiveTypes) {
       
   412                 return internalize("L" + c.getName() + ";");
       
   413             } else {
       
   414                 return internalize(c.getName());
       
   415             }
       
   416         }
       
   417     }
       
   418 
       
   419     private static String internalize(String className) {
       
   420         return className.replace('.', '/');
       
   421     }
       
   422 
       
   423     protected void emitConstructor() {
       
   424         // Generate code into fresh code buffer
       
   425         ClassFileAssembler cb = new ClassFileAssembler();
       
   426         // 0 incoming arguments
       
   427         cb.setMaxLocals(1);
       
   428         cb.opc_aload_0();
       
   429         cb.opc_invokespecial(superCtorIdx, 0, 0);
       
   430         cb.opc_return();
       
   431 
       
   432         // Emit method
       
   433         emitMethod(initIdx, cb.getMaxLocals(), cb, null, null);
       
   434     }
       
   435 
       
   436     // The descriptor's index in the constant pool must be (1 +
       
   437     // nameIdx). "numArgs" must indicate ALL arguments, including the
       
   438     // implicit "this" argument; double and long arguments each count
       
   439     // as 2 in this count. The code buffer must NOT contain the code
       
   440     // length. The exception table may be null, but if non-null must
       
   441     // NOT contain the exception table's length. The checked exception
       
   442     // indices may be null.
       
   443     protected void emitMethod(short nameIdx,
       
   444                               int numArgs,
       
   445                               ClassFileAssembler code,
       
   446                               ClassFileAssembler exceptionTable,
       
   447                               short[] checkedExceptionIndices)
       
   448     {
       
   449         int codeLen = code.getLength();
       
   450         int excLen  = 0;
       
   451         if (exceptionTable != null) {
       
   452             excLen = exceptionTable.getLength();
       
   453             if ((excLen % 8) != 0) {
       
   454                 throw new IllegalArgumentException("Illegal exception table");
       
   455             }
       
   456         }
       
   457         int attrLen = 12 + codeLen + excLen;
       
   458         excLen = excLen / 8; // No-op if no exception table
       
   459 
       
   460         asm.emitShort(ACC_PUBLIC);
       
   461         asm.emitShort(nameIdx);
       
   462         asm.emitShort(add(nameIdx, S1));
       
   463         if (checkedExceptionIndices == null) {
       
   464             // Code attribute only
       
   465             asm.emitShort(S1);
       
   466         } else {
       
   467             // Code and Exceptions attributes
       
   468             asm.emitShort(S2);
       
   469         }
       
   470         // Code attribute
       
   471         asm.emitShort(codeIdx);
       
   472         asm.emitInt(attrLen);
       
   473         asm.emitShort(code.getMaxStack());
       
   474         asm.emitShort((short) Math.max(numArgs, code.getMaxLocals()));
       
   475         asm.emitInt(codeLen);
       
   476         asm.append(code);
       
   477         asm.emitShort((short) excLen);
       
   478         if (exceptionTable != null) {
       
   479             asm.append(exceptionTable);
       
   480         }
       
   481         asm.emitShort(S0); // No additional attributes for Code attribute
       
   482         if (checkedExceptionIndices != null) {
       
   483             // Exceptions attribute
       
   484             asm.emitShort(exceptionsIdx);
       
   485             asm.emitInt(2 + 2 * checkedExceptionIndices.length);
       
   486             asm.emitShort((short) checkedExceptionIndices.length);
       
   487             for (int i = 0; i < checkedExceptionIndices.length; i++) {
       
   488                 asm.emitShort(checkedExceptionIndices[i]);
       
   489             }
       
   490         }
       
   491     }
       
   492 
       
   493     protected short indexForPrimitiveType(Class type) {
       
   494         if (type == Boolean.TYPE) {
       
   495             return booleanIdx;
       
   496         } else if (type == Byte.TYPE) {
       
   497             return byteIdx;
       
   498         } else if (type == Character.TYPE) {
       
   499             return characterIdx;
       
   500         } else if (type == Double.TYPE) {
       
   501             return doubleIdx;
       
   502         } else if (type == Float.TYPE) {
       
   503             return floatIdx;
       
   504         } else if (type == Integer.TYPE) {
       
   505             return integerIdx;
       
   506         } else if (type == Long.TYPE) {
       
   507             return longIdx;
       
   508         } else if (type == Short.TYPE) {
       
   509             return shortIdx;
       
   510         }
       
   511         throw new InternalError("Should have found primitive type");
       
   512     }
       
   513 
       
   514     protected short ctorIndexForPrimitiveType(Class type) {
       
   515         if (type == Boolean.TYPE) {
       
   516             return booleanCtorIdx;
       
   517         } else if (type == Byte.TYPE) {
       
   518             return byteCtorIdx;
       
   519         } else if (type == Character.TYPE) {
       
   520             return characterCtorIdx;
       
   521         } else if (type == Double.TYPE) {
       
   522             return doubleCtorIdx;
       
   523         } else if (type == Float.TYPE) {
       
   524             return floatCtorIdx;
       
   525         } else if (type == Integer.TYPE) {
       
   526             return integerCtorIdx;
       
   527         } else if (type == Long.TYPE) {
       
   528             return longCtorIdx;
       
   529         } else if (type == Short.TYPE) {
       
   530             return shortCtorIdx;
       
   531         }
       
   532         throw new InternalError("Should have found primitive type");
       
   533     }
       
   534 
       
   535     /** Returns true for widening or identity conversions for primitive
       
   536         types only */
       
   537     protected static boolean canWidenTo(Class type, Class otherType) {
       
   538         if (!type.isPrimitive()) {
       
   539             return false;
       
   540         }
       
   541 
       
   542         // Widening conversions (from JVM spec):
       
   543         //  byte to short, int, long, float, or double
       
   544         //  short to int, long, float, or double
       
   545         //  char to int, long, float, or double
       
   546         //  int to long, float, or double
       
   547         //  long to float or double
       
   548         //  float to double
       
   549 
       
   550         if (type == Boolean.TYPE) {
       
   551             if (otherType == Boolean.TYPE) {
       
   552                 return true;
       
   553             }
       
   554         } else if (type == Byte.TYPE) {
       
   555             if (   otherType == Byte.TYPE
       
   556                    || otherType == Short.TYPE
       
   557                    || otherType == Integer.TYPE
       
   558                    || otherType == Long.TYPE
       
   559                    || otherType == Float.TYPE
       
   560                    || otherType == Double.TYPE) {
       
   561                 return true;
       
   562             }
       
   563         } else if (type == Short.TYPE) {
       
   564             if (   otherType == Short.TYPE
       
   565                    || otherType == Integer.TYPE
       
   566                    || otherType == Long.TYPE
       
   567                    || otherType == Float.TYPE
       
   568                    || otherType == Double.TYPE) {
       
   569                 return true;
       
   570             }
       
   571         } else if (type == Character.TYPE) {
       
   572             if (   otherType == Character.TYPE
       
   573                    || otherType == Integer.TYPE
       
   574                    || otherType == Long.TYPE
       
   575                    || otherType == Float.TYPE
       
   576                    || otherType == Double.TYPE) {
       
   577                 return true;
       
   578             }
       
   579         } else if (type == Integer.TYPE) {
       
   580             if (   otherType == Integer.TYPE
       
   581                    || otherType == Long.TYPE
       
   582                    || otherType == Float.TYPE
       
   583                    || otherType == Double.TYPE) {
       
   584                 return true;
       
   585             }
       
   586         } else if (type == Long.TYPE) {
       
   587             if (   otherType == Long.TYPE
       
   588                    || otherType == Float.TYPE
       
   589                    || otherType == Double.TYPE) {
       
   590                 return true;
       
   591             }
       
   592         } else if (type == Float.TYPE) {
       
   593             if (   otherType == Float.TYPE
       
   594                    || otherType == Double.TYPE) {
       
   595                 return true;
       
   596             }
       
   597         } else if (type == Double.TYPE) {
       
   598             if (otherType == Double.TYPE) {
       
   599                 return true;
       
   600             }
       
   601         }
       
   602 
       
   603         return false;
       
   604     }
       
   605 
       
   606     /** Emits the widening bytecode for the given primitive conversion
       
   607         (or none if the identity conversion). Requires that a primitive
       
   608         conversion exists; i.e., canWidenTo must have already been
       
   609         called and returned true. */
       
   610     protected static void emitWideningBytecodeForPrimitiveConversion
       
   611         (ClassFileAssembler cb,
       
   612          Class fromType,
       
   613          Class toType)
       
   614     {
       
   615         // Note that widening conversions for integral types (i.e., "b2s",
       
   616         // "s2i") are no-ops since values on the Java stack are
       
   617         // sign-extended.
       
   618 
       
   619         // Widening conversions (from JVM spec):
       
   620         //  byte to short, int, long, float, or double
       
   621         //  short to int, long, float, or double
       
   622         //  char to int, long, float, or double
       
   623         //  int to long, float, or double
       
   624         //  long to float or double
       
   625         //  float to double
       
   626 
       
   627         if (   fromType == Byte.TYPE
       
   628                || fromType == Short.TYPE
       
   629                || fromType == Character.TYPE
       
   630                || fromType == Integer.TYPE) {
       
   631             if (toType == Long.TYPE) {
       
   632                 cb.opc_i2l();
       
   633             } else if (toType == Float.TYPE) {
       
   634                 cb.opc_i2f();
       
   635             } else if (toType == Double.TYPE) {
       
   636                 cb.opc_i2d();
       
   637             }
       
   638         } else if (fromType == Long.TYPE) {
       
   639             if (toType == Float.TYPE) {
       
   640                 cb.opc_l2f();
       
   641             } else if (toType == Double.TYPE) {
       
   642                 cb.opc_l2d();
       
   643             }
       
   644         } else if (fromType == Float.TYPE) {
       
   645             if (toType == Double.TYPE) {
       
   646                 cb.opc_f2d();
       
   647             }
       
   648         }
       
   649 
       
   650         // Otherwise, was identity or no-op conversion. Fall through.
       
   651     }
       
   652 
       
   653     protected short unboxingMethodForPrimitiveType(Class primType) {
       
   654         if (primType == Boolean.TYPE) {
       
   655             return booleanUnboxIdx;
       
   656         } else if (primType == Byte.TYPE) {
       
   657             return byteUnboxIdx;
       
   658         } else if (primType == Character.TYPE) {
       
   659             return characterUnboxIdx;
       
   660         } else if (primType == Short.TYPE) {
       
   661             return shortUnboxIdx;
       
   662         } else if (primType == Integer.TYPE) {
       
   663             return integerUnboxIdx;
       
   664         } else if (primType == Long.TYPE) {
       
   665             return longUnboxIdx;
       
   666         } else if (primType == Float.TYPE) {
       
   667             return floatUnboxIdx;
       
   668         } else if (primType == Double.TYPE) {
       
   669             return doubleUnboxIdx;
       
   670         }
       
   671         throw new InternalError("Illegal primitive type " + primType.getName());
       
   672     }
       
   673 
       
   674     protected static final Class[] primitiveTypes = new Class[] {
       
   675         Boolean.TYPE,
       
   676         Byte.TYPE,
       
   677         Character.TYPE,
       
   678         Short.TYPE,
       
   679         Integer.TYPE,
       
   680         Long.TYPE,
       
   681         Float.TYPE,
       
   682         Double.TYPE
       
   683     };
       
   684 
       
   685     /** We don't consider "Void" to be a primitive type */
       
   686     protected static boolean isPrimitive(Class c) {
       
   687         return (c.isPrimitive() && c != Void.TYPE);
       
   688     }
       
   689 
       
   690     protected int typeSizeInStackSlots(Class c) {
       
   691         if (c == Void.TYPE) {
       
   692             return 0;
       
   693         }
       
   694         if (c == Long.TYPE || c == Double.TYPE) {
       
   695             return 2;
       
   696         }
       
   697         return 1;
       
   698     }
       
   699 
       
   700     private ClassFileAssembler illegalArgumentCodeBuffer;
       
   701     protected ClassFileAssembler illegalArgumentCodeBuffer() {
       
   702         if (illegalArgumentCodeBuffer == null) {
       
   703             illegalArgumentCodeBuffer = new ClassFileAssembler();
       
   704             illegalArgumentCodeBuffer.opc_new(illegalArgumentClass);
       
   705             illegalArgumentCodeBuffer.opc_dup();
       
   706             illegalArgumentCodeBuffer.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
       
   707             illegalArgumentCodeBuffer.opc_athrow();
       
   708         }
       
   709 
       
   710         return illegalArgumentCodeBuffer;
       
   711     }
       
   712 }