jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java
changeset 37377 bd3b98a11a14
parent 37376 5daa5fbad3ce
parent 37374 ee1b8619eddb
child 37380 55c2549714af
equal deleted inserted replaced
37376:5daa5fbad3ce 37377:bd3b98a11a14
     1 /*
       
     2  * Copyright (c) 2001, 2013, 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.reflect;
       
    27 
       
    28 import java.security.AccessController;
       
    29 import java.security.PrivilegedAction;
       
    30 
       
    31 /** Generator for sun.reflect.MethodAccessor and
       
    32     sun.reflect.ConstructorAccessor objects using bytecodes to
       
    33     implement reflection. A java.lang.reflect.Method or
       
    34     java.lang.reflect.Constructor object can delegate its invoke or
       
    35     newInstance method to an accessor using native code or to one
       
    36     generated by this class. (Methods and Constructors were merged
       
    37     together in this class to ensure maximum code sharing.) */
       
    38 
       
    39 class MethodAccessorGenerator extends AccessorGenerator {
       
    40 
       
    41     private static final short NUM_BASE_CPOOL_ENTRIES   = (short) 12;
       
    42     // One for invoke() plus one for constructor
       
    43     private static final short NUM_METHODS              = (short) 2;
       
    44     // Only used if forSerialization is true
       
    45     private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
       
    46 
       
    47     private static volatile int methodSymnum;
       
    48     private static volatile int constructorSymnum;
       
    49     private static volatile int serializationConstructorSymnum;
       
    50 
       
    51     private Class<?>   declaringClass;
       
    52     private Class<?>[] parameterTypes;
       
    53     private Class<?>   returnType;
       
    54     private boolean    isConstructor;
       
    55     private boolean    forSerialization;
       
    56 
       
    57     private short targetMethodRef;
       
    58     private short invokeIdx;
       
    59     private short invokeDescriptorIdx;
       
    60     // Constant pool index of CONSTANT_Class_info for first
       
    61     // non-primitive parameter type. Should be incremented by 2.
       
    62     private short nonPrimitiveParametersBaseIdx;
       
    63 
       
    64     MethodAccessorGenerator() {
       
    65     }
       
    66 
       
    67     /** This routine is not thread-safe */
       
    68     public MethodAccessor generateMethod(Class<?> declaringClass,
       
    69                                          String   name,
       
    70                                          Class<?>[] parameterTypes,
       
    71                                          Class<?>   returnType,
       
    72                                          Class<?>[] checkedExceptions,
       
    73                                          int modifiers)
       
    74     {
       
    75         return (MethodAccessor) generate(declaringClass,
       
    76                                          name,
       
    77                                          parameterTypes,
       
    78                                          returnType,
       
    79                                          checkedExceptions,
       
    80                                          modifiers,
       
    81                                          false,
       
    82                                          false,
       
    83                                          null);
       
    84     }
       
    85 
       
    86     /** This routine is not thread-safe */
       
    87     public ConstructorAccessor generateConstructor(Class<?> declaringClass,
       
    88                                                    Class<?>[] parameterTypes,
       
    89                                                    Class<?>[] checkedExceptions,
       
    90                                                    int modifiers)
       
    91     {
       
    92         return (ConstructorAccessor) generate(declaringClass,
       
    93                                               "<init>",
       
    94                                               parameterTypes,
       
    95                                               Void.TYPE,
       
    96                                               checkedExceptions,
       
    97                                               modifiers,
       
    98                                               true,
       
    99                                               false,
       
   100                                               null);
       
   101     }
       
   102 
       
   103     /** This routine is not thread-safe */
       
   104     public SerializationConstructorAccessorImpl
       
   105     generateSerializationConstructor(Class<?> declaringClass,
       
   106                                      Class<?>[] parameterTypes,
       
   107                                      Class<?>[] checkedExceptions,
       
   108                                      int modifiers,
       
   109                                      Class<?> targetConstructorClass)
       
   110     {
       
   111         return (SerializationConstructorAccessorImpl)
       
   112             generate(declaringClass,
       
   113                      "<init>",
       
   114                      parameterTypes,
       
   115                      Void.TYPE,
       
   116                      checkedExceptions,
       
   117                      modifiers,
       
   118                      true,
       
   119                      true,
       
   120                      targetConstructorClass);
       
   121     }
       
   122 
       
   123     /** This routine is not thread-safe */
       
   124     private MagicAccessorImpl generate(final Class<?> declaringClass,
       
   125                                        String name,
       
   126                                        Class<?>[] parameterTypes,
       
   127                                        Class<?>   returnType,
       
   128                                        Class<?>[] checkedExceptions,
       
   129                                        int modifiers,
       
   130                                        boolean isConstructor,
       
   131                                        boolean forSerialization,
       
   132                                        Class<?> serializationTargetClass)
       
   133     {
       
   134         ByteVector vec = ByteVectorFactory.create();
       
   135         asm = new ClassFileAssembler(vec);
       
   136         this.declaringClass = declaringClass;
       
   137         this.parameterTypes = parameterTypes;
       
   138         this.returnType = returnType;
       
   139         this.modifiers = modifiers;
       
   140         this.isConstructor = isConstructor;
       
   141         this.forSerialization = forSerialization;
       
   142 
       
   143         asm.emitMagicAndVersion();
       
   144 
       
   145         // Constant pool entries:
       
   146         // ( * = Boxing information: optional)
       
   147         // (+  = Shared entries provided by AccessorGenerator)
       
   148         // (^  = Only present if generating SerializationConstructorAccessor)
       
   149         //     [UTF-8] [This class's name]
       
   150         //     [CONSTANT_Class_info] for above
       
   151         //     [UTF-8] "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
       
   152         //     [CONSTANT_Class_info] for above
       
   153         //     [UTF-8] [Target class's name]
       
   154         //     [CONSTANT_Class_info] for above
       
   155         // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
       
   156         // ^   [CONSTANT_Class_info] for above
       
   157         //     [UTF-8] target method or constructor name
       
   158         //     [UTF-8] target method or constructor signature
       
   159         //     [CONSTANT_NameAndType_info] for above
       
   160         //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
       
   161         //     [UTF-8] "invoke" or "newInstance"
       
   162         //     [UTF-8] invoke or newInstance descriptor
       
   163         //     [UTF-8] descriptor for type of non-primitive parameter 1
       
   164         //     [CONSTANT_Class_info] for type of non-primitive parameter 1
       
   165         //     ...
       
   166         //     [UTF-8] descriptor for type of non-primitive parameter n
       
   167         //     [CONSTANT_Class_info] for type of non-primitive parameter n
       
   168         // +   [UTF-8] "java/lang/Exception"
       
   169         // +   [CONSTANT_Class_info] for above
       
   170         // +   [UTF-8] "java/lang/ClassCastException"
       
   171         // +   [CONSTANT_Class_info] for above
       
   172         // +   [UTF-8] "java/lang/NullPointerException"
       
   173         // +   [CONSTANT_Class_info] for above
       
   174         // +   [UTF-8] "java/lang/IllegalArgumentException"
       
   175         // +   [CONSTANT_Class_info] for above
       
   176         // +   [UTF-8] "java/lang/InvocationTargetException"
       
   177         // +   [CONSTANT_Class_info] for above
       
   178         // +   [UTF-8] "<init>"
       
   179         // +   [UTF-8] "()V"
       
   180         // +   [CONSTANT_NameAndType_info] for above
       
   181         // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
       
   182         // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
       
   183         // +   [UTF-8] "(Ljava/lang/String;)V"
       
   184         // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
       
   185         // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
       
   186         // +   [UTF-8] "(Ljava/lang/Throwable;)V"
       
   187         // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
       
   188         // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
       
   189         // +   [CONSTANT_Methodref_info] for "super()"
       
   190         // +   [UTF-8] "java/lang/Object"
       
   191         // +   [CONSTANT_Class_info] for above
       
   192         // +   [UTF-8] "toString"
       
   193         // +   [UTF-8] "()Ljava/lang/String;"
       
   194         // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
       
   195         // +   [CONSTANT_Methodref_info] for Object's toString method
       
   196         // +   [UTF-8] "Code"
       
   197         // +   [UTF-8] "Exceptions"
       
   198         //  *  [UTF-8] "java/lang/Boolean"
       
   199         //  *  [CONSTANT_Class_info] for above
       
   200         //  *  [UTF-8] "(Z)V"
       
   201         //  *  [CONSTANT_NameAndType_info] for above
       
   202         //  *  [CONSTANT_Methodref_info] for above
       
   203         //  *  [UTF-8] "booleanValue"
       
   204         //  *  [UTF-8] "()Z"
       
   205         //  *  [CONSTANT_NameAndType_info] for above
       
   206         //  *  [CONSTANT_Methodref_info] for above
       
   207         //  *  [UTF-8] "java/lang/Byte"
       
   208         //  *  [CONSTANT_Class_info] for above
       
   209         //  *  [UTF-8] "(B)V"
       
   210         //  *  [CONSTANT_NameAndType_info] for above
       
   211         //  *  [CONSTANT_Methodref_info] for above
       
   212         //  *  [UTF-8] "byteValue"
       
   213         //  *  [UTF-8] "()B"
       
   214         //  *  [CONSTANT_NameAndType_info] for above
       
   215         //  *  [CONSTANT_Methodref_info] for above
       
   216         //  *  [UTF-8] "java/lang/Character"
       
   217         //  *  [CONSTANT_Class_info] for above
       
   218         //  *  [UTF-8] "(C)V"
       
   219         //  *  [CONSTANT_NameAndType_info] for above
       
   220         //  *  [CONSTANT_Methodref_info] for above
       
   221         //  *  [UTF-8] "charValue"
       
   222         //  *  [UTF-8] "()C"
       
   223         //  *  [CONSTANT_NameAndType_info] for above
       
   224         //  *  [CONSTANT_Methodref_info] for above
       
   225         //  *  [UTF-8] "java/lang/Double"
       
   226         //  *  [CONSTANT_Class_info] for above
       
   227         //  *  [UTF-8] "(D)V"
       
   228         //  *  [CONSTANT_NameAndType_info] for above
       
   229         //  *  [CONSTANT_Methodref_info] for above
       
   230         //  *  [UTF-8] "doubleValue"
       
   231         //  *  [UTF-8] "()D"
       
   232         //  *  [CONSTANT_NameAndType_info] for above
       
   233         //  *  [CONSTANT_Methodref_info] for above
       
   234         //  *  [UTF-8] "java/lang/Float"
       
   235         //  *  [CONSTANT_Class_info] for above
       
   236         //  *  [UTF-8] "(F)V"
       
   237         //  *  [CONSTANT_NameAndType_info] for above
       
   238         //  *  [CONSTANT_Methodref_info] for above
       
   239         //  *  [UTF-8] "floatValue"
       
   240         //  *  [UTF-8] "()F"
       
   241         //  *  [CONSTANT_NameAndType_info] for above
       
   242         //  *  [CONSTANT_Methodref_info] for above
       
   243         //  *  [UTF-8] "java/lang/Integer"
       
   244         //  *  [CONSTANT_Class_info] for above
       
   245         //  *  [UTF-8] "(I)V"
       
   246         //  *  [CONSTANT_NameAndType_info] for above
       
   247         //  *  [CONSTANT_Methodref_info] for above
       
   248         //  *  [UTF-8] "intValue"
       
   249         //  *  [UTF-8] "()I"
       
   250         //  *  [CONSTANT_NameAndType_info] for above
       
   251         //  *  [CONSTANT_Methodref_info] for above
       
   252         //  *  [UTF-8] "java/lang/Long"
       
   253         //  *  [CONSTANT_Class_info] for above
       
   254         //  *  [UTF-8] "(J)V"
       
   255         //  *  [CONSTANT_NameAndType_info] for above
       
   256         //  *  [CONSTANT_Methodref_info] for above
       
   257         //  *  [UTF-8] "longValue"
       
   258         //  *  [UTF-8] "()J"
       
   259         //  *  [CONSTANT_NameAndType_info] for above
       
   260         //  *  [CONSTANT_Methodref_info] for above
       
   261         //  *  [UTF-8] "java/lang/Short"
       
   262         //  *  [CONSTANT_Class_info] for above
       
   263         //  *  [UTF-8] "(S)V"
       
   264         //  *  [CONSTANT_NameAndType_info] for above
       
   265         //  *  [CONSTANT_Methodref_info] for above
       
   266         //  *  [UTF-8] "shortValue"
       
   267         //  *  [UTF-8] "()S"
       
   268         //  *  [CONSTANT_NameAndType_info] for above
       
   269         //  *  [CONSTANT_Methodref_info] for above
       
   270 
       
   271         short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES;
       
   272         boolean usesPrimitives = usesPrimitiveTypes();
       
   273         if (usesPrimitives) {
       
   274             numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
       
   275         }
       
   276         if (forSerialization) {
       
   277             numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
       
   278         }
       
   279 
       
   280         // Add in variable-length number of entries to be able to describe
       
   281         // non-primitive parameter types and checked exceptions.
       
   282         numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());
       
   283 
       
   284         asm.emitShort(add(numCPEntries, S1));
       
   285 
       
   286         final String generatedName = generateName(isConstructor, forSerialization);
       
   287         asm.emitConstantPoolUTF8(generatedName);
       
   288         asm.emitConstantPoolClass(asm.cpi());
       
   289         thisClass = asm.cpi();
       
   290         if (isConstructor) {
       
   291             if (forSerialization) {
       
   292                 asm.emitConstantPoolUTF8
       
   293                     ("sun/reflect/SerializationConstructorAccessorImpl");
       
   294             } else {
       
   295                 asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl");
       
   296             }
       
   297         } else {
       
   298             asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl");
       
   299         }
       
   300         asm.emitConstantPoolClass(asm.cpi());
       
   301         superClass = asm.cpi();
       
   302         asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
       
   303         asm.emitConstantPoolClass(asm.cpi());
       
   304         targetClass = asm.cpi();
       
   305         short serializationTargetClassIdx = (short) 0;
       
   306         if (forSerialization) {
       
   307             asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false));
       
   308             asm.emitConstantPoolClass(asm.cpi());
       
   309             serializationTargetClassIdx = asm.cpi();
       
   310         }
       
   311         asm.emitConstantPoolUTF8(name);
       
   312         asm.emitConstantPoolUTF8(buildInternalSignature());
       
   313         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
       
   314         if (isInterface()) {
       
   315             asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi());
       
   316         } else {
       
   317             if (forSerialization) {
       
   318                 asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi());
       
   319             } else {
       
   320                 asm.emitConstantPoolMethodref(targetClass, asm.cpi());
       
   321             }
       
   322         }
       
   323         targetMethodRef = asm.cpi();
       
   324         if (isConstructor) {
       
   325             asm.emitConstantPoolUTF8("newInstance");
       
   326         } else {
       
   327             asm.emitConstantPoolUTF8("invoke");
       
   328         }
       
   329         invokeIdx = asm.cpi();
       
   330         if (isConstructor) {
       
   331             asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
       
   332         } else {
       
   333             asm.emitConstantPoolUTF8
       
   334                 ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
       
   335         }
       
   336         invokeDescriptorIdx = asm.cpi();
       
   337 
       
   338         // Output class information for non-primitive parameter types
       
   339         nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
       
   340         for (int i = 0; i < parameterTypes.length; i++) {
       
   341             Class<?> c = parameterTypes[i];
       
   342             if (!isPrimitive(c)) {
       
   343                 asm.emitConstantPoolUTF8(getClassName(c, false));
       
   344                 asm.emitConstantPoolClass(asm.cpi());
       
   345             }
       
   346         }
       
   347 
       
   348         // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
       
   349         emitCommonConstantPoolEntries();
       
   350 
       
   351         // Boxing entries
       
   352         if (usesPrimitives) {
       
   353             emitBoxingContantPoolEntries();
       
   354         }
       
   355 
       
   356         if (asm.cpi() != numCPEntries) {
       
   357             throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
       
   358                                     ", numCPEntries = " + numCPEntries + ")");
       
   359         }
       
   360 
       
   361         // Access flags
       
   362         asm.emitShort(ACC_PUBLIC);
       
   363 
       
   364         // This class
       
   365         asm.emitShort(thisClass);
       
   366 
       
   367         // Superclass
       
   368         asm.emitShort(superClass);
       
   369 
       
   370         // Interfaces count and interfaces
       
   371         asm.emitShort(S0);
       
   372 
       
   373         // Fields count and fields
       
   374         asm.emitShort(S0);
       
   375 
       
   376         // Methods count and methods
       
   377         asm.emitShort(NUM_METHODS);
       
   378 
       
   379         emitConstructor();
       
   380         emitInvoke();
       
   381 
       
   382         // Additional attributes (none)
       
   383         asm.emitShort(S0);
       
   384 
       
   385         // Load class
       
   386         vec.trim();
       
   387         final byte[] bytes = vec.getData();
       
   388         // Note: the class loader is the only thing that really matters
       
   389         // here -- it's important to get the generated code into the
       
   390         // same namespace as the target class. Since the generated code
       
   391         // is privileged anyway, the protection domain probably doesn't
       
   392         // matter.
       
   393         return AccessController.doPrivileged(
       
   394             new PrivilegedAction<MagicAccessorImpl>() {
       
   395                 public MagicAccessorImpl run() {
       
   396                         try {
       
   397                         return (MagicAccessorImpl)
       
   398                         ClassDefiner.defineClass
       
   399                                 (generatedName,
       
   400                                  bytes,
       
   401                                  0,
       
   402                                  bytes.length,
       
   403                                  declaringClass.getClassLoader()).newInstance();
       
   404                         } catch (InstantiationException | IllegalAccessException e) {
       
   405                             throw new InternalError(e);
       
   406                         }
       
   407                     }
       
   408                 });
       
   409     }
       
   410 
       
   411     /** This emits the code for either invoke() or newInstance() */
       
   412     private void emitInvoke() {
       
   413         // NOTE that this code will only handle 65535 parameters since we
       
   414         // use the sipush instruction to get the array index on the
       
   415         // operand stack.
       
   416         if (parameterTypes.length > 65535) {
       
   417             throw new InternalError("Can't handle more than 65535 parameters");
       
   418         }
       
   419 
       
   420         // Generate code into fresh code buffer
       
   421         ClassFileAssembler cb = new ClassFileAssembler();
       
   422         if (isConstructor) {
       
   423             // 1 incoming argument
       
   424             cb.setMaxLocals(2);
       
   425         } else {
       
   426             // 2 incoming arguments
       
   427             cb.setMaxLocals(3);
       
   428         }
       
   429 
       
   430         short illegalArgStartPC = 0;
       
   431 
       
   432         if (isConstructor) {
       
   433             // Instantiate target class before continuing
       
   434             // new <target class type>
       
   435             // dup
       
   436             cb.opc_new(targetClass);
       
   437             cb.opc_dup();
       
   438         } else {
       
   439             // Setup before iterating down argument list
       
   440             if (isPrimitive(returnType)) {
       
   441                 // new <boxing type for primitive type>
       
   442                 // dup
       
   443                 // ... (see below:)
       
   444                 // invokespecial <constructor for boxing type for primitive type>
       
   445                 // areturn
       
   446                 cb.opc_new(indexForPrimitiveType(returnType));
       
   447                 cb.opc_dup();
       
   448             }
       
   449 
       
   450             // Get target object on operand stack if necessary.
       
   451 
       
   452             // We need to do an explicit null check here; we won't see
       
   453             // NullPointerExceptions from the invoke bytecode, since it's
       
   454             // covered by an exception handler.
       
   455             if (!isStatic()) {
       
   456                 // aload_1
       
   457                 // ifnonnull <checkcast label>
       
   458                 // new <NullPointerException>
       
   459                 // dup
       
   460                 // invokespecial <NullPointerException ctor>
       
   461                 // athrow
       
   462                 // <checkcast label:>
       
   463                 // aload_1
       
   464                 // checkcast <target class's type>
       
   465                 cb.opc_aload_1();
       
   466                 Label l = new Label();
       
   467                 cb.opc_ifnonnull(l);
       
   468                 cb.opc_new(nullPointerClass);
       
   469                 cb.opc_dup();
       
   470                 cb.opc_invokespecial(nullPointerCtorIdx, 0, 0);
       
   471                 cb.opc_athrow();
       
   472                 l.bind();
       
   473                 illegalArgStartPC = cb.getLength();
       
   474                 cb.opc_aload_1();
       
   475                 cb.opc_checkcast(targetClass);
       
   476             }
       
   477         }
       
   478 
       
   479         // Have to check length of incoming array and throw
       
   480         // IllegalArgumentException if not correct. A concession to the
       
   481         // JCK (isn't clearly specified in the spec): we allow null in the
       
   482         // case where the argument list is zero length.
       
   483         // if no-arg:
       
   484         //   aload_2 | aload_1 (Method | Constructor)
       
   485         //   ifnull <success label>
       
   486         // aload_2 | aload_1
       
   487         // arraylength
       
   488         // sipush <num parameter types>
       
   489         // if_icmpeq <success label>
       
   490         // new <IllegalArgumentException>
       
   491         // dup
       
   492         // invokespecial <IllegalArgumentException ctor>
       
   493         // athrow
       
   494         // <success label:>
       
   495         Label successLabel = new Label();
       
   496         if (parameterTypes.length == 0) {
       
   497             if (isConstructor) {
       
   498                 cb.opc_aload_1();
       
   499             } else {
       
   500                 cb.opc_aload_2();
       
   501             }
       
   502             cb.opc_ifnull(successLabel);
       
   503         }
       
   504         if (isConstructor) {
       
   505             cb.opc_aload_1();
       
   506         } else {
       
   507             cb.opc_aload_2();
       
   508         }
       
   509         cb.opc_arraylength();
       
   510         cb.opc_sipush((short) parameterTypes.length);
       
   511         cb.opc_if_icmpeq(successLabel);
       
   512         cb.opc_new(illegalArgumentClass);
       
   513         cb.opc_dup();
       
   514         cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
       
   515         cb.opc_athrow();
       
   516         successLabel.bind();
       
   517 
       
   518         // Iterate through incoming actual parameters, ensuring that each
       
   519         // is compatible with the formal parameter type, and pushing the
       
   520         // actual on the operand stack (unboxing and widening if necessary).
       
   521 
       
   522         short paramTypeCPIdx = nonPrimitiveParametersBaseIdx;
       
   523         Label nextParamLabel = null;
       
   524         byte count = 1; // both invokeinterface opcode's "count" as well as
       
   525         // num args of other invoke bytecodes
       
   526         for (int i = 0; i < parameterTypes.length; i++) {
       
   527             Class<?> paramType = parameterTypes[i];
       
   528             count += (byte) typeSizeInStackSlots(paramType);
       
   529             if (nextParamLabel != null) {
       
   530                 nextParamLabel.bind();
       
   531                 nextParamLabel = null;
       
   532             }
       
   533             // aload_2 | aload_1
       
   534             // sipush <index>
       
   535             // aaload
       
   536             if (isConstructor) {
       
   537                 cb.opc_aload_1();
       
   538             } else {
       
   539                 cb.opc_aload_2();
       
   540             }
       
   541             cb.opc_sipush((short) i);
       
   542             cb.opc_aaload();
       
   543             if (isPrimitive(paramType)) {
       
   544                 // Unboxing code.
       
   545                 // Put parameter into temporary local variable
       
   546                 // astore_3 | astore_2
       
   547                 if (isConstructor) {
       
   548                     cb.opc_astore_2();
       
   549                 } else {
       
   550                     cb.opc_astore_3();
       
   551                 }
       
   552 
       
   553                 // repeat for all possible widening conversions:
       
   554                 //   aload_3 | aload_2
       
   555                 //   instanceof <primitive boxing type>
       
   556                 //   ifeq <next unboxing label>
       
   557                 //   aload_3 | aload_2
       
   558                 //   checkcast <primitive boxing type> // Note: this is "redundant",
       
   559                 //                                     // but necessary for the verifier
       
   560                 //   invokevirtual <unboxing method>
       
   561                 //   <widening conversion bytecode, if necessary>
       
   562                 //   goto <next parameter label>
       
   563                 // <next unboxing label:> ...
       
   564                 // last unboxing label:
       
   565                 //   new <IllegalArgumentException>
       
   566                 //   dup
       
   567                 //   invokespecial <IllegalArgumentException ctor>
       
   568                 //   athrow
       
   569 
       
   570                 Label l = null; // unboxing label
       
   571                 nextParamLabel = new Label();
       
   572 
       
   573                 for (int j = 0; j < primitiveTypes.length; j++) {
       
   574                     Class<?> c = primitiveTypes[j];
       
   575                     if (canWidenTo(c, paramType)) {
       
   576                         if (l != null) {
       
   577                             l.bind();
       
   578                         }
       
   579                         // Emit checking and unboxing code for this type
       
   580                         if (isConstructor) {
       
   581                             cb.opc_aload_2();
       
   582                         } else {
       
   583                             cb.opc_aload_3();
       
   584                         }
       
   585                         cb.opc_instanceof(indexForPrimitiveType(c));
       
   586                         l = new Label();
       
   587                         cb.opc_ifeq(l);
       
   588                         if (isConstructor) {
       
   589                             cb.opc_aload_2();
       
   590                         } else {
       
   591                             cb.opc_aload_3();
       
   592                         }
       
   593                         cb.opc_checkcast(indexForPrimitiveType(c));
       
   594                         cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c),
       
   595                                              0,
       
   596                                              typeSizeInStackSlots(c));
       
   597                         emitWideningBytecodeForPrimitiveConversion(cb,
       
   598                                                                    c,
       
   599                                                                    paramType);
       
   600                         cb.opc_goto(nextParamLabel);
       
   601                     }
       
   602                 }
       
   603 
       
   604                 if (l == null) {
       
   605                     throw new InternalError
       
   606                         ("Must have found at least identity conversion");
       
   607                 }
       
   608 
       
   609                 // Fell through; given object is null or invalid. According to
       
   610                 // the spec, we can throw IllegalArgumentException for both of
       
   611                 // these cases.
       
   612 
       
   613                 l.bind();
       
   614                 cb.opc_new(illegalArgumentClass);
       
   615                 cb.opc_dup();
       
   616                 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
       
   617                 cb.opc_athrow();
       
   618             } else {
       
   619                 // Emit appropriate checkcast
       
   620                 cb.opc_checkcast(paramTypeCPIdx);
       
   621                 paramTypeCPIdx = add(paramTypeCPIdx, S2);
       
   622                 // Fall through to next argument
       
   623             }
       
   624         }
       
   625         // Bind last goto if present
       
   626         if (nextParamLabel != null) {
       
   627             nextParamLabel.bind();
       
   628         }
       
   629 
       
   630         short invokeStartPC = cb.getLength();
       
   631 
       
   632         // OK, ready to perform the invocation.
       
   633         if (isConstructor) {
       
   634             cb.opc_invokespecial(targetMethodRef, count, 0);
       
   635         } else {
       
   636             if (isStatic()) {
       
   637                 cb.opc_invokestatic(targetMethodRef,
       
   638                                     count,
       
   639                                     typeSizeInStackSlots(returnType));
       
   640             } else {
       
   641                 if (isInterface()) {
       
   642                     if (isPrivate()) {
       
   643                         cb.opc_invokespecial(targetMethodRef, count, 0);
       
   644                     } else {
       
   645                         cb.opc_invokeinterface(targetMethodRef,
       
   646                                                count,
       
   647                                                count,
       
   648                                                typeSizeInStackSlots(returnType));
       
   649                     }
       
   650                 } else {
       
   651                     cb.opc_invokevirtual(targetMethodRef,
       
   652                                          count,
       
   653                                          typeSizeInStackSlots(returnType));
       
   654                 }
       
   655             }
       
   656         }
       
   657 
       
   658         short invokeEndPC = cb.getLength();
       
   659 
       
   660         if (!isConstructor) {
       
   661             // Box return value if necessary
       
   662             if (isPrimitive(returnType)) {
       
   663                 cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType),
       
   664                                     typeSizeInStackSlots(returnType),
       
   665                                     0);
       
   666             } else if (returnType == Void.TYPE) {
       
   667                 cb.opc_aconst_null();
       
   668             }
       
   669         }
       
   670         cb.opc_areturn();
       
   671 
       
   672         // We generate two exception handlers; one which is responsible
       
   673         // for catching ClassCastException and NullPointerException and
       
   674         // throwing IllegalArgumentException, and the other which catches
       
   675         // all java/lang/Throwable objects thrown from the target method
       
   676         // and wraps them in InvocationTargetExceptions.
       
   677 
       
   678         short classCastHandler = cb.getLength();
       
   679 
       
   680         // ClassCast, etc. exception handler
       
   681         cb.setStack(1);
       
   682         cb.opc_invokespecial(toStringIdx, 0, 1);
       
   683         cb.opc_new(illegalArgumentClass);
       
   684         cb.opc_dup_x1();
       
   685         cb.opc_swap();
       
   686         cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
       
   687         cb.opc_athrow();
       
   688 
       
   689         short invocationTargetHandler = cb.getLength();
       
   690 
       
   691         // InvocationTargetException exception handler
       
   692         cb.setStack(1);
       
   693         cb.opc_new(invocationTargetClass);
       
   694         cb.opc_dup_x1();
       
   695         cb.opc_swap();
       
   696         cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
       
   697         cb.opc_athrow();
       
   698 
       
   699         // Generate exception table. We cover the entire code sequence
       
   700         // with an exception handler which catches ClassCastException and
       
   701         // converts it into an IllegalArgumentException.
       
   702 
       
   703         ClassFileAssembler exc = new ClassFileAssembler();
       
   704 
       
   705         exc.emitShort(illegalArgStartPC);       // start PC
       
   706         exc.emitShort(invokeStartPC);           // end PC
       
   707         exc.emitShort(classCastHandler);        // handler PC
       
   708         exc.emitShort(classCastClass);          // catch type
       
   709 
       
   710         exc.emitShort(illegalArgStartPC);       // start PC
       
   711         exc.emitShort(invokeStartPC);           // end PC
       
   712         exc.emitShort(classCastHandler);        // handler PC
       
   713         exc.emitShort(nullPointerClass);        // catch type
       
   714 
       
   715         exc.emitShort(invokeStartPC);           // start PC
       
   716         exc.emitShort(invokeEndPC);             // end PC
       
   717         exc.emitShort(invocationTargetHandler); // handler PC
       
   718         exc.emitShort(throwableClass);          // catch type
       
   719 
       
   720         emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
       
   721                    new short[] { invocationTargetClass });
       
   722     }
       
   723 
       
   724     private boolean usesPrimitiveTypes() {
       
   725         // We need to emit boxing/unboxing constant pool information if
       
   726         // the method takes a primitive type for any of its parameters or
       
   727         // returns a primitive value (except void)
       
   728         if (returnType.isPrimitive()) {
       
   729             return true;
       
   730         }
       
   731         for (int i = 0; i < parameterTypes.length; i++) {
       
   732             if (parameterTypes[i].isPrimitive()) {
       
   733                 return true;
       
   734             }
       
   735         }
       
   736         return false;
       
   737     }
       
   738 
       
   739     private int numNonPrimitiveParameterTypes() {
       
   740         int num = 0;
       
   741         for (int i = 0; i < parameterTypes.length; i++) {
       
   742             if (!parameterTypes[i].isPrimitive()) {
       
   743                 ++num;
       
   744             }
       
   745         }
       
   746         return num;
       
   747     }
       
   748 
       
   749     private boolean isInterface() {
       
   750         return declaringClass.isInterface();
       
   751     }
       
   752 
       
   753     private String buildInternalSignature() {
       
   754         StringBuilder sb = new StringBuilder();
       
   755         sb.append("(");
       
   756         for (int i = 0; i < parameterTypes.length; i++) {
       
   757             sb.append(getClassName(parameterTypes[i], true));
       
   758         }
       
   759         sb.append(")");
       
   760         sb.append(getClassName(returnType, true));
       
   761         return sb.toString();
       
   762     }
       
   763 
       
   764     private static synchronized String generateName(boolean isConstructor,
       
   765                                                     boolean forSerialization)
       
   766     {
       
   767         if (isConstructor) {
       
   768             if (forSerialization) {
       
   769                 int num = ++serializationConstructorSymnum;
       
   770                 return "sun/reflect/GeneratedSerializationConstructorAccessor" + num;
       
   771             } else {
       
   772                 int num = ++constructorSymnum;
       
   773                 return "sun/reflect/GeneratedConstructorAccessor" + num;
       
   774             }
       
   775         } else {
       
   776             int num = ++methodSymnum;
       
   777             return "sun/reflect/GeneratedMethodAccessor" + num;
       
   778         }
       
   779     }
       
   780 }