History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/reflect/MethodAccessorGenerator.java (1 of 18352 files). Show all

Unified · Split

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