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