1 /*
   2  * Copyright (c) 2001, 2018, 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                 @SuppressWarnings("deprecation") // Class.newInstance
 396                 public MagicAccessorImpl run() {
 397                         try {
 398                         return (MagicAccessorImpl)
 399                         ClassDefiner.defineClass
 400                                 (generatedName,
 401                                  bytes,
 402                                  0,
 403                                  bytes.length,
 404                                  declaringClass.getClassLoader()).newInstance();
 405                         } catch (InstantiationException | IllegalAccessException e) {
 406                             throw new InternalError(e);
 407                         }
 408                     }
 409                 });
 410     }
 411 
 412     /** This emits the code for either invoke() or newInstance() */
 413     private void emitInvoke() {
 414         // NOTE that this code will only handle 65535 parameters since we
 415         // use the sipush instruction to get the array index on the
 416         // operand stack.
 417         if (parameterTypes.length > 65535) {
 418             throw new InternalError("Can't handle more than 65535 parameters");
 419         }
 420 
 421         // Generate code into fresh code buffer
 422         ClassFileAssembler cb = new ClassFileAssembler();
 423         if (isConstructor) {
 424             // 1 incoming argument
 425             cb.setMaxLocals(2);
 426         } else {
 427             // 2 incoming arguments
 428             cb.setMaxLocals(3);
 429         }
 430 
 431         short illegalArgStartPC = 0;
 432 
 433         if (isConstructor) {
 434             // Instantiate target class before continuing
 435             // new <target class type>
 436             // dup
 437             cb.opc_new(targetClass);
 438             cb.opc_dup();
 439         } else {
 440             // Get target object on operand stack if necessary.
 441 
 442             // We need to do an explicit null check here; we won't see
 443             // NullPointerExceptions from the invoke bytecode, since it's
 444             // covered by an exception handler.
 445             if (!isStatic()) {
 446                 // aload_1
 447                 // ifnonnull <checkcast label>
 448                 // new <NullPointerException>
 449                 // dup
 450                 // invokespecial <NullPointerException ctor>
 451                 // athrow
 452                 // <checkcast label:>
 453                 // aload_1
 454                 // checkcast <target class's type>
 455                 cb.opc_aload_1();
 456                 Label l = new Label();
 457                 cb.opc_ifnonnull(l);
 458                 cb.opc_new(nullPointerClass);
 459                 cb.opc_dup();
 460                 cb.opc_invokespecial(nullPointerCtorIdx, 0, 0);
 461                 cb.opc_athrow();
 462                 l.bind();
 463                 illegalArgStartPC = cb.getLength();
 464                 cb.opc_aload_1();
 465                 cb.opc_checkcast(targetClass);
 466             }
 467         }
 468 
 469         // Have to check length of incoming array and throw
 470         // IllegalArgumentException if not correct. A concession to the
 471         // JCK (isn't clearly specified in the spec): we allow null in the
 472         // case where the argument list is zero length.
 473         // if no-arg:
 474         //   aload_2 | aload_1 (Method | Constructor)
 475         //   ifnull <success label>
 476         // aload_2 | aload_1
 477         // arraylength
 478         // sipush <num parameter types>
 479         // if_icmpeq <success label>
 480         // new <IllegalArgumentException>
 481         // dup
 482         // invokespecial <IllegalArgumentException ctor>
 483         // athrow
 484         // <success label:>
 485         Label successLabel = new Label();
 486         if (parameterTypes.length == 0) {
 487             if (isConstructor) {
 488                 cb.opc_aload_1();
 489             } else {
 490                 cb.opc_aload_2();
 491             }
 492             cb.opc_ifnull(successLabel);
 493         }
 494         if (isConstructor) {
 495             cb.opc_aload_1();
 496         } else {
 497             cb.opc_aload_2();
 498         }
 499         cb.opc_arraylength();
 500         cb.opc_sipush((short) parameterTypes.length);
 501         cb.opc_if_icmpeq(successLabel);
 502         cb.opc_new(illegalArgumentClass);
 503         cb.opc_dup();
 504         cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
 505         cb.opc_athrow();
 506         successLabel.bind();
 507 
 508         // Iterate through incoming actual parameters, ensuring that each
 509         // is compatible with the formal parameter type, and pushing the
 510         // actual on the operand stack (unboxing and widening if necessary).
 511 
 512         short paramTypeCPIdx = nonPrimitiveParametersBaseIdx;
 513         Label nextParamLabel = null;
 514         byte count = 1; // both invokeinterface opcode's "count" as well as
 515         // num args of other invoke bytecodes
 516         for (int i = 0; i < parameterTypes.length; i++) {
 517             Class<?> paramType = parameterTypes[i];
 518             count += (byte) typeSizeInStackSlots(paramType);
 519             if (nextParamLabel != null) {
 520                 nextParamLabel.bind();
 521                 nextParamLabel = null;
 522             }
 523             // aload_2 | aload_1
 524             // sipush <index>
 525             // aaload
 526             if (isConstructor) {
 527                 cb.opc_aload_1();
 528             } else {
 529                 cb.opc_aload_2();
 530             }
 531             cb.opc_sipush((short) i);
 532             cb.opc_aaload();
 533             if (isPrimitive(paramType)) {
 534                 // Unboxing code.
 535                 // Put parameter into temporary local variable
 536                 // astore_3 | astore_2
 537                 if (isConstructor) {
 538                     cb.opc_astore_2();
 539                 } else {
 540                     cb.opc_astore_3();
 541                 }
 542 
 543                 // repeat for all possible widening conversions:
 544                 //   aload_3 | aload_2
 545                 //   instanceof <primitive boxing type>
 546                 //   ifeq <next unboxing label>
 547                 //   aload_3 | aload_2
 548                 //   checkcast <primitive boxing type> // Note: this is "redundant",
 549                 //                                     // but necessary for the verifier
 550                 //   invokevirtual <unboxing method>
 551                 //   <widening conversion bytecode, if necessary>
 552                 //   goto <next parameter label>
 553                 // <next unboxing label:> ...
 554                 // last unboxing label:
 555                 //   new <IllegalArgumentException>
 556                 //   dup
 557                 //   invokespecial <IllegalArgumentException ctor>
 558                 //   athrow
 559 
 560                 Label l = null; // unboxing label
 561                 nextParamLabel = new Label();
 562 
 563                 for (int j = 0; j < primitiveTypes.length; j++) {
 564                     Class<?> c = primitiveTypes[j];
 565                     if (canWidenTo(c, paramType)) {
 566                         if (l != null) {
 567                             l.bind();
 568                         }
 569                         // Emit checking and unboxing code for this type
 570                         if (isConstructor) {
 571                             cb.opc_aload_2();
 572                         } else {
 573                             cb.opc_aload_3();
 574                         }
 575                         cb.opc_instanceof(indexForPrimitiveType(c));
 576                         l = new Label();
 577                         cb.opc_ifeq(l);
 578                         if (isConstructor) {
 579                             cb.opc_aload_2();
 580                         } else {
 581                             cb.opc_aload_3();
 582                         }
 583                         cb.opc_checkcast(indexForPrimitiveType(c));
 584                         cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c),
 585                                              0,
 586                                              typeSizeInStackSlots(c));
 587                         emitWideningBytecodeForPrimitiveConversion(cb,
 588                                                                    c,
 589                                                                    paramType);
 590                         cb.opc_goto(nextParamLabel);
 591                     }
 592                 }
 593 
 594                 if (l == null) {
 595                     throw new InternalError
 596                         ("Must have found at least identity conversion");
 597                 }
 598 
 599                 // Fell through; given object is null or invalid. According to
 600                 // the spec, we can throw IllegalArgumentException for both of
 601                 // these cases.
 602 
 603                 l.bind();
 604                 cb.opc_new(illegalArgumentClass);
 605                 cb.opc_dup();
 606                 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
 607                 cb.opc_athrow();
 608             } else {
 609                 // Emit appropriate checkcast
 610                 cb.opc_checkcast(paramTypeCPIdx);
 611                 paramTypeCPIdx = add(paramTypeCPIdx, S2);
 612                 // Fall through to next argument
 613             }
 614         }
 615         // Bind last goto if present
 616         if (nextParamLabel != null) {
 617             nextParamLabel.bind();
 618         }
 619 
 620         short invokeStartPC = cb.getLength();
 621 
 622         // OK, ready to perform the invocation.
 623         if (isConstructor) {
 624             cb.opc_invokespecial(targetMethodRef, count, 0);
 625         } else {
 626             if (isStatic()) {
 627                 cb.opc_invokestatic(targetMethodRef,
 628                                     count,
 629                                     typeSizeInStackSlots(returnType));
 630             } else {
 631                 if (isInterface()) {
 632                     cb.opc_invokeinterface(targetMethodRef,
 633                                            count,
 634                                            count,
 635                                            typeSizeInStackSlots(returnType));
 636                 } else {
 637                     cb.opc_invokevirtual(targetMethodRef,
 638                                          count,
 639                                          typeSizeInStackSlots(returnType));
 640                 }
 641             }
 642         }
 643 
 644         short invokeEndPC = cb.getLength();
 645 
 646         if (!isConstructor) {
 647             // Box return value if necessary
 648             if (isPrimitive(returnType)) {
 649                 cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType),
 650                                     typeSizeInStackSlots(returnType),
 651                                     0);
 652             } else if (returnType == Void.TYPE) {
 653                 cb.opc_aconst_null();
 654             }
 655         }
 656         cb.opc_areturn();
 657 
 658         // We generate two exception handlers; one which is responsible
 659         // for catching ClassCastException and NullPointerException and
 660         // throwing IllegalArgumentException, and the other which catches
 661         // all java/lang/Throwable objects thrown from the target method
 662         // and wraps them in InvocationTargetExceptions.
 663 
 664         short classCastHandler = cb.getLength();
 665 
 666         // ClassCast, etc. exception handler
 667         cb.setStack(1);
 668         cb.opc_invokespecial(toStringIdx, 0, 1);
 669         cb.opc_new(illegalArgumentClass);
 670         cb.opc_dup_x1();
 671         cb.opc_swap();
 672         cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
 673         cb.opc_athrow();
 674 
 675         short invocationTargetHandler = cb.getLength();
 676 
 677         // InvocationTargetException exception handler
 678         cb.setStack(1);
 679         cb.opc_new(invocationTargetClass);
 680         cb.opc_dup_x1();
 681         cb.opc_swap();
 682         cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
 683         cb.opc_athrow();
 684 
 685         // Generate exception table. We cover the entire code sequence
 686         // with an exception handler which catches ClassCastException and
 687         // converts it into an IllegalArgumentException.
 688 
 689         ClassFileAssembler exc = new ClassFileAssembler();
 690 
 691         exc.emitShort(illegalArgStartPC);       // start PC
 692         exc.emitShort(invokeStartPC);           // end PC
 693         exc.emitShort(classCastHandler);        // handler PC
 694         exc.emitShort(classCastClass);          // catch type
 695 
 696         exc.emitShort(illegalArgStartPC);       // start PC
 697         exc.emitShort(invokeStartPC);           // end PC
 698         exc.emitShort(classCastHandler);        // handler PC
 699         exc.emitShort(nullPointerClass);        // catch type
 700 
 701         exc.emitShort(invokeStartPC);           // start PC
 702         exc.emitShort(invokeEndPC);             // end PC
 703         exc.emitShort(invocationTargetHandler); // handler PC
 704         exc.emitShort(throwableClass);          // catch type
 705 
 706         emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
 707                    new short[] { invocationTargetClass });
 708     }
 709 
 710     private boolean usesPrimitiveTypes() {
 711         // We need to emit boxing/unboxing constant pool information if
 712         // the method takes a primitive type for any of its parameters or
 713         // returns a primitive value (except void)
 714         if (returnType.isPrimitive()) {
 715             return true;
 716         }
 717         for (int i = 0; i < parameterTypes.length; i++) {
 718             if (parameterTypes[i].isPrimitive()) {
 719                 return true;
 720             }
 721         }
 722         return false;
 723     }
 724 
 725     private int numNonPrimitiveParameterTypes() {
 726         int num = 0;
 727         for (int i = 0; i < parameterTypes.length; i++) {
 728             if (!parameterTypes[i].isPrimitive()) {
 729                 ++num;
 730             }
 731         }
 732         return num;
 733     }
 734 
 735     private boolean isInterface() {
 736         return declaringClass.isInterface();
 737     }
 738 
 739     private String buildInternalSignature() {
 740         StringBuilder sb = new StringBuilder();
 741         sb.append("(");
 742         for (int i = 0; i < parameterTypes.length; i++) {
 743             sb.append(getClassName(parameterTypes[i], true));
 744         }
 745         sb.append(")");
 746         sb.append(getClassName(returnType, true));
 747         return sb.toString();
 748     }
 749 
 750     private static synchronized String generateName(boolean isConstructor,
 751                                                     boolean forSerialization)
 752     {
 753         if (isConstructor) {
 754             if (forSerialization) {
 755                 int num = ++serializationConstructorSymnum;
 756                 return "jdk/internal/reflect/GeneratedSerializationConstructorAccessor" + num;
 757             } else {
 758                 int num = ++constructorSymnum;
 759                 return "jdk/internal/reflect/GeneratedConstructorAccessor" + num;
 760             }
 761         } else {
 762             int num = ++methodSymnum;
 763             return "jdk/internal/reflect/GeneratedMethodAccessor" + num;
 764         }
 765     }
 766 }