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                                          Class<?>[] checkedExceptions,
 76                                          int modifiers)
 77     {
 78         return (MethodAccessor) generate(declaringClass,
 79                                          name,
 80                                          parameterTypes,
 81                                          returnType,
 82                                          checkedExceptions,
 83                                          modifiers,
 84                                          false,
 85                                          false,
 86                                          false,
 87                                          null);
 88     }
 89 
 90     /** This routine is not thread-safe */
 91     public ConstructorAccessor generateConstructor(Class<?> declaringClass,
 92                                                    Class<?>[] parameterTypes,
 93                                                    Class<?>[] checkedExceptions,
 94                                                    int modifiers)
 95     {
 96         boolean isStaticFactory = declaringClass.isValue();
 97         return (ConstructorAccessor) generate(declaringClass,
 98                                               "<init>",
 99                                               parameterTypes,
100                                               isStaticFactory ? PrimitiveClass.asValueType(declaringClass) : Void.TYPE,
101                                               checkedExceptions,
102                                               modifiers,
103                                               true,
104                                               isStaticFactory,
105                                               false,
106                                               null);
107     }
108 
109     /** This routine is not thread-safe */
110     public SerializationConstructorAccessorImpl
111     generateSerializationConstructor(Class<?> declaringClass,
112                                      Class<?>[] parameterTypes,
113                                      Class<?>[] checkedExceptions,
114                                      int modifiers,
115                                      Class<?> targetConstructorClass)
116     {
117         return (SerializationConstructorAccessorImpl)
118             generate(declaringClass,
119                      "<init>",
120                      parameterTypes,
121                      Void.TYPE,
122                      checkedExceptions,
123                      modifiers,
124                      true,
125                      false,
126                      true,
127                      targetConstructorClass);
128     }
129 
130     /** This routine is not thread-safe */
131     @SuppressWarnings("removal")
132     private MagicAccessorImpl generate(final Class<?> declaringClass,
133                                        String name,
134                                        Class<?>[] parameterTypes,
135                                        Class<?>   returnType,
136                                        Class<?>[] checkedExceptions,
137                                        int modifiers,
138                                        boolean isConstructor,
139                                        boolean isStaticFactory,
140                                        boolean forSerialization,
141                                        Class<?> serializationTargetClass)
142     {
143         ByteVector vec = ByteVectorFactory.create();
144         asm = new ClassFileAssembler(vec);
145         this.declaringClass = declaringClass;
146         this.parameterTypes = parameterTypes;
147         this.returnType = returnType;
148         this.modifiers = modifiers;
149         this.isConstructor = isConstructor;
150         this.isStaticFactory = isStaticFactory;
151         this.forSerialization = forSerialization;
152 
153         asm.emitMagicAndVersion();
154 
155         // Constant pool entries:
156         // ( * = Boxing information: optional)
157         // (+  = Shared entries provided by AccessorGenerator)
158         // (^  = Only present if generating SerializationConstructorAccessor)
159         //     [UTF-8] [This class's name]
160         //     [CONSTANT_Class_info] for above
161         //     [UTF-8] "jdk/internal/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
162         //     [CONSTANT_Class_info] for above
163         //     [UTF-8] [Target class's name]
164         //     [CONSTANT_Class_info] for above
165         // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
166         // ^   [CONSTANT_Class_info] for above
167         //     [UTF-8] target method or constructor name
168         //     [UTF-8] target method or constructor signature
169         //     [CONSTANT_NameAndType_info] for above
170         //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
171         //     [UTF-8] "invoke" or "newInstance"
172         //     [UTF-8] invoke or newInstance descriptor
173         //     [UTF-8] descriptor for type of non-primitive parameter 1
174         //     [CONSTANT_Class_info] for type of non-primitive parameter 1
175         //     ...
176         //     [UTF-8] descriptor for type of non-primitive parameter n
177         //     [CONSTANT_Class_info] for type of non-primitive parameter n
178         // +   [UTF-8] "java/lang/Exception"
179         // +   [CONSTANT_Class_info] for above
180         // +   [UTF-8] "java/lang/ClassCastException"
181         // +   [CONSTANT_Class_info] for above
182         // +   [UTF-8] "java/lang/NullPointerException"
183         // +   [CONSTANT_Class_info] for above
184         // +   [UTF-8] "java/lang/IllegalArgumentException"
185         // +   [CONSTANT_Class_info] for above
186         // +   [UTF-8] "java/lang/InvocationTargetException"
187         // +   [CONSTANT_Class_info] for above
188         // +   [UTF-8] "<init>"
189         // +   [UTF-8] "()V"
190         // +   [CONSTANT_NameAndType_info] for above
191         // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
192         // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
193         // +   [UTF-8] "(Ljava/lang/String;)V"
194         // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
195         // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
196         // +   [UTF-8] "(Ljava/lang/Throwable;)V"
197         // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
198         // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
199         // +   [CONSTANT_Methodref_info] for "super()"
200         // +   [UTF-8] "java/lang/Object"
201         // +   [CONSTANT_Class_info] for above
202         // +   [UTF-8] "toString"
203         // +   [UTF-8] "()Ljava/lang/String;"
204         // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
205         // +   [CONSTANT_Methodref_info] for Object's toString method
206         // +   [UTF-8] "Code"
207         // +   [UTF-8] "Exceptions"
208         //  *  [UTF-8] "java/lang/Boolean"
209         //  *  [CONSTANT_Class_info] for above
210         //  *  [UTF-8] "(Z)V"
211         //  *  [CONSTANT_NameAndType_info] for above
212         //  *  [CONSTANT_Methodref_info] for above
213         //  *  [UTF-8] "booleanValue"
214         //  *  [UTF-8] "()Z"
215         //  *  [CONSTANT_NameAndType_info] for above
216         //  *  [CONSTANT_Methodref_info] for above
217         //  *  [UTF-8] "java/lang/Byte"
218         //  *  [CONSTANT_Class_info] for above
219         //  *  [UTF-8] "(B)V"
220         //  *  [CONSTANT_NameAndType_info] for above
221         //  *  [CONSTANT_Methodref_info] for above
222         //  *  [UTF-8] "byteValue"
223         //  *  [UTF-8] "()B"
224         //  *  [CONSTANT_NameAndType_info] for above
225         //  *  [CONSTANT_Methodref_info] for above
226         //  *  [UTF-8] "java/lang/Character"
227         //  *  [CONSTANT_Class_info] for above
228         //  *  [UTF-8] "(C)V"
229         //  *  [CONSTANT_NameAndType_info] for above
230         //  *  [CONSTANT_Methodref_info] for above
231         //  *  [UTF-8] "charValue"
232         //  *  [UTF-8] "()C"
233         //  *  [CONSTANT_NameAndType_info] for above
234         //  *  [CONSTANT_Methodref_info] for above
235         //  *  [UTF-8] "java/lang/Double"
236         //  *  [CONSTANT_Class_info] for above
237         //  *  [UTF-8] "(D)V"
238         //  *  [CONSTANT_NameAndType_info] for above
239         //  *  [CONSTANT_Methodref_info] for above
240         //  *  [UTF-8] "doubleValue"
241         //  *  [UTF-8] "()D"
242         //  *  [CONSTANT_NameAndType_info] for above
243         //  *  [CONSTANT_Methodref_info] for above
244         //  *  [UTF-8] "java/lang/Float"
245         //  *  [CONSTANT_Class_info] for above
246         //  *  [UTF-8] "(F)V"
247         //  *  [CONSTANT_NameAndType_info] for above
248         //  *  [CONSTANT_Methodref_info] for above
249         //  *  [UTF-8] "floatValue"
250         //  *  [UTF-8] "()F"
251         //  *  [CONSTANT_NameAndType_info] for above
252         //  *  [CONSTANT_Methodref_info] for above
253         //  *  [UTF-8] "java/lang/Integer"
254         //  *  [CONSTANT_Class_info] for above
255         //  *  [UTF-8] "(I)V"
256         //  *  [CONSTANT_NameAndType_info] for above
257         //  *  [CONSTANT_Methodref_info] for above
258         //  *  [UTF-8] "intValue"
259         //  *  [UTF-8] "()I"
260         //  *  [CONSTANT_NameAndType_info] for above
261         //  *  [CONSTANT_Methodref_info] for above
262         //  *  [UTF-8] "java/lang/Long"
263         //  *  [CONSTANT_Class_info] for above
264         //  *  [UTF-8] "(J)V"
265         //  *  [CONSTANT_NameAndType_info] for above
266         //  *  [CONSTANT_Methodref_info] for above
267         //  *  [UTF-8] "longValue"
268         //  *  [UTF-8] "()J"
269         //  *  [CONSTANT_NameAndType_info] for above
270         //  *  [CONSTANT_Methodref_info] for above
271         //  *  [UTF-8] "java/lang/Short"
272         //  *  [CONSTANT_Class_info] for above
273         //  *  [UTF-8] "(S)V"
274         //  *  [CONSTANT_NameAndType_info] for above
275         //  *  [CONSTANT_Methodref_info] for above
276         //  *  [UTF-8] "shortValue"
277         //  *  [UTF-8] "()S"
278         //  *  [CONSTANT_NameAndType_info] for above
279         //  *  [CONSTANT_Methodref_info] for above
280 
281         short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES;
282         boolean usesPrimitives = usesPrimitiveTypes();
283         if (usesPrimitives) {
284             numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
285         }
286         if (forSerialization) {
287             numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
288         }
289 
290         // Add in variable-length number of entries to be able to describe
291         // non-primitive parameter types and checked exceptions.
292         numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());
293 
294         asm.emitShort(add(numCPEntries, S1));
295 
296         final String generatedName = generateName(isConstructor, forSerialization);
297         asm.emitConstantPoolUTF8(generatedName);
298         asm.emitConstantPoolClass(asm.cpi());
299         thisClass = asm.cpi();
300         if (isConstructor) {
301             if (forSerialization) {
302                 asm.emitConstantPoolUTF8
303                     ("jdk/internal/reflect/SerializationConstructorAccessorImpl");
304             } else {
305                 asm.emitConstantPoolUTF8("jdk/internal/reflect/ConstructorAccessorImpl");
306             }
307         } else {
308             asm.emitConstantPoolUTF8("jdk/internal/reflect/MethodAccessorImpl");
309         }
310         asm.emitConstantPoolClass(asm.cpi());
311         superClass = asm.cpi();
312         asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
313         asm.emitConstantPoolClass(asm.cpi());
314         targetClass = asm.cpi();
315         short serializationTargetClassIdx = (short) 0;
316         if (forSerialization) {
317             asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false));
318             asm.emitConstantPoolClass(asm.cpi());
319             serializationTargetClassIdx = asm.cpi();
320         }
321         asm.emitConstantPoolUTF8(name);
322         asm.emitConstantPoolUTF8(buildInternalSignature());
323         asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
324         if (isInterface()) {
325             asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi());
326         } else {
327             if (forSerialization) {
328                 asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi());
329             } else {
330                 asm.emitConstantPoolMethodref(targetClass, asm.cpi());
331             }
332         }
333         targetMethodRef = asm.cpi();
334         if (isConstructor) {
335             asm.emitConstantPoolUTF8("newInstance");
336         } else {
337             asm.emitConstantPoolUTF8("invoke");
338         }
339         invokeIdx = asm.cpi();
340         if (isConstructor) {
341             asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
342         } else {
343             asm.emitConstantPoolUTF8
344                 ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
345         }
346         invokeDescriptorIdx = asm.cpi();
347 
348         // Output class information for non-primitive parameter types
349         nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
350         for (int i = 0; i < parameterTypes.length; i++) {
351             Class<?> c = parameterTypes[i];
352             if (!isPrimitive(c)) {
353                 asm.emitConstantPoolUTF8(getClassName(c, true));
354                 asm.emitConstantPoolClass(asm.cpi());
355             }
356         }
357 
358         // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
359         emitCommonConstantPoolEntries();
360 
361         // Boxing entries
362         if (usesPrimitives) {
363             emitBoxingContantPoolEntries();
364         }
365 
366         if (asm.cpi() != numCPEntries) {
367             throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
368                                     ", numCPEntries = " + numCPEntries + ")");
369         }
370 
371         // Access flags
372         asm.emitShort(ACC_PUBLIC);
373 
374         // This class
375         asm.emitShort(thisClass);
376 
377         // Superclass
378         asm.emitShort(superClass);
379 
380         // Interfaces count and interfaces
381         asm.emitShort(S0);
382 
383         // Fields count and fields
384         asm.emitShort(S0);
385 
386         // Methods count and methods
387         asm.emitShort(NUM_METHODS);
388 
389         emitConstructor();
390         emitInvoke();
391 
392         // Additional attributes (none)
393         asm.emitShort(S0);
394 
395         // Load class
396         vec.trim();
397         final byte[] bytes = vec.getData();
398         // Note: the class loader is the only thing that really matters
399         // here -- it's important to get the generated code into the
400         // same namespace as the target class. Since the generated code
401         // is privileged anyway, the protection domain probably doesn't
402         // matter.
403         return AccessController.doPrivileged(
404             new PrivilegedAction<MagicAccessorImpl>() {
405                 @SuppressWarnings("deprecation") // Class.newInstance
406                 public MagicAccessorImpl run() {
407                         try {
408                         return (MagicAccessorImpl)
409                         ClassDefiner.defineClass
410                                 (generatedName,
411                                  bytes,
412                                  0,
413                                  bytes.length,
414                                  declaringClass.getClassLoader()).newInstance();
415                         } catch (InstantiationException | IllegalAccessException e) {
416                             throw new InternalError(e);
417                         }
418                     }
419                 });
420     }
421 
422     /** This emits the code for either invoke() or newInstance() */
423     private void emitInvoke() {
424         // NOTE that this code will only handle 65535 parameters since we
425         // use the sipush instruction to get the array index on the
426         // operand stack.
427         if (parameterTypes.length > 65535) {
428             throw new InternalError("Can't handle more than 65535 parameters");
429         }
430 
431         // Generate code into fresh code buffer
432         ClassFileAssembler cb = new ClassFileAssembler();
433         if (isConstructor) {
434             // 1 incoming argument
435             cb.setMaxLocals(2);
436         } else {
437             // 2 incoming arguments
438             cb.setMaxLocals(3);
439         }
440 
441         short illegalArgStartPC = 0;
442 
443         if (isConstructor && !isStaticFactory) {
444             // Instantiate target class before continuing
445             // new <target class type>
446             // dup
447             cb.opc_new(targetClass);
448             cb.opc_dup();
449         } else {
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 && !isStaticFactory) {
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                     cb.opc_invokeinterface(targetMethodRef,
643                                            count,
644                                            count,
645                                            typeSizeInStackSlots(returnType));
646                 } else {
647                     cb.opc_invokevirtual(targetMethodRef,
648                                          count,
649                                          typeSizeInStackSlots(returnType));
650                 }
651             }
652         }
653 
654         short invokeEndPC = cb.getLength();
655 
656         if (!isConstructor) {
657             // Box return value if necessary
658             if (isPrimitive(returnType)) {
659                 cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType),
660                                     typeSizeInStackSlots(returnType),
661                                     0);
662             } else if (returnType == Void.TYPE) {
663                 cb.opc_aconst_null();
664             }
665         }
666         cb.opc_areturn();
667 
668         // We generate two exception handlers; one which is responsible
669         // for catching ClassCastException and NullPointerException and
670         // throwing IllegalArgumentException, and the other which catches
671         // all java/lang/Throwable objects thrown from the target method
672         // and wraps them in InvocationTargetExceptions.
673 
674         short classCastHandler = cb.getLength();
675 
676         // ClassCast, etc. exception handler
677         cb.setStack(1);
678         cb.opc_invokespecial(toStringIdx, 0, 1);
679         cb.opc_new(illegalArgumentClass);
680         cb.opc_dup_x1();
681         cb.opc_swap();
682         cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
683         cb.opc_athrow();
684 
685         short invocationTargetHandler = cb.getLength();
686 
687         // InvocationTargetException exception handler
688         cb.setStack(1);
689         cb.opc_new(invocationTargetClass);
690         cb.opc_dup_x1();
691         cb.opc_swap();
692         cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
693         cb.opc_athrow();
694 
695         // Generate exception table. We cover the entire code sequence
696         // with an exception handler which catches ClassCastException and
697         // converts it into an IllegalArgumentException.
698 
699         ClassFileAssembler exc = new ClassFileAssembler();
700 
701         exc.emitShort(illegalArgStartPC);       // start PC
702         exc.emitShort(invokeStartPC);           // end PC
703         exc.emitShort(classCastHandler);        // handler PC
704         exc.emitShort(classCastClass);          // catch type
705 
706         exc.emitShort(illegalArgStartPC);       // start PC
707         exc.emitShort(invokeStartPC);           // end PC
708         exc.emitShort(classCastHandler);        // handler PC
709         exc.emitShort(nullPointerClass);        // catch type
710 
711         exc.emitShort(invokeStartPC);           // start PC
712         exc.emitShort(invokeEndPC);             // end PC
713         exc.emitShort(invocationTargetHandler); // handler PC
714         exc.emitShort(throwableClass);          // catch type
715 
716         emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
717                    new short[] { invocationTargetClass });
718     }
719 
720     private boolean usesPrimitiveTypes() {
721         // We need to emit boxing/unboxing constant pool information if
722         // the method takes a primitive type for any of its parameters or
723         // returns a primitive value (except void)
724         if (returnType.isPrimitive()) {
725             return true;
726         }
727         for (int i = 0; i < parameterTypes.length; i++) {
728             if (parameterTypes[i].isPrimitive()) {
729                 return true;
730             }
731         }
732         return false;
733     }
734 
735     private int numNonPrimitiveParameterTypes() {
736         int num = 0;
737         for (int i = 0; i < parameterTypes.length; i++) {
738             if (!parameterTypes[i].isPrimitive()) {
739                 ++num;
740             }
741         }
742         return num;
743     }
744 
745     private boolean isInterface() {
746         return declaringClass.isInterface();
747     }
748 
749     private String buildInternalSignature() {
750         StringBuilder sb = new StringBuilder();
751         sb.append("(");
752         for (int i = 0; i < parameterTypes.length; i++) {
753             sb.append(getClassName(parameterTypes[i], true));
754         }
755         sb.append(")");
756         sb.append(getClassName(returnType, true));
757         return sb.toString();
758     }
759 
760     private static synchronized String generateName(boolean isConstructor,
761                                                     boolean forSerialization)
762     {
763         if (isConstructor) {
764             if (forSerialization) {
765                 int num = ++serializationConstructorSymnum;
766                 return "jdk/internal/reflect/GeneratedSerializationConstructorAccessor" + num;
767             } else {
768                 int num = ++constructorSymnum;
769                 return "jdk/internal/reflect/GeneratedConstructorAccessor" + num;
770             }
771         } else {
772             int num = ++methodSymnum;
773             return "jdk/internal/reflect/GeneratedMethodAccessor" + num;
774         }
775     }
776 }