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 jdk.internal.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] "jdk/internal/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                     ("jdk/internal/reflect/SerializationConstructorAccessorImpl");
 294             } else {
 295                 asm.emitConstantPoolUTF8("jdk/internal/reflect/ConstructorAccessorImpl");
 296             }
 297         } else {
 298             asm.emitConstantPoolUTF8("jdk/internal/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 "jdk/internal/reflect/GeneratedSerializationConstructorAccessor" + num;
 771             } else {
 772                 int num = ++constructorSymnum;
 773                 return "jdk/internal/reflect/GeneratedConstructorAccessor" + num;
 774             }
 775         } else {
 776             int num = ++methodSymnum;
 777             return "jdk/internal/reflect/GeneratedMethodAccessor" + num;
 778         }
 779     }
 780 }