001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.reflect;
027:
028: import java.lang.reflect.*;
029: import sun.misc.Unsafe;
030:
031: /** Shared functionality for all accessor generators */
032:
033: class AccessorGenerator implements ClassFileConstants {
034: static final Unsafe unsafe = Unsafe.getUnsafe();
035:
036: // Constants because there's no way to say "short integer constant",
037: // i.e., "1S"
038: protected static final short S0 = (short) 0;
039: protected static final short S1 = (short) 1;
040: protected static final short S2 = (short) 2;
041: protected static final short S3 = (short) 3;
042: protected static final short S4 = (short) 4;
043: protected static final short S5 = (short) 5;
044: protected static final short S6 = (short) 6;
045:
046: // Instance variables for shared functionality between
047: // FieldAccessorGenerator and MethodAccessorGenerator
048: protected ClassFileAssembler asm;
049: protected int modifiers;
050: protected short this Class;
051: protected short super Class;
052: protected short targetClass;
053: // Common constant pool entries to FieldAccessor and MethodAccessor
054: protected short throwableClass;
055: protected short classCastClass;
056: protected short nullPointerClass;
057: protected short illegalArgumentClass;
058: protected short invocationTargetClass;
059: protected short initIdx;
060: protected short initNameAndTypeIdx;
061: protected short initStringNameAndTypeIdx;
062: protected short nullPointerCtorIdx;
063: protected short illegalArgumentCtorIdx;
064: protected short illegalArgumentStringCtorIdx;
065: protected short invocationTargetCtorIdx;
066: protected short super CtorIdx;
067: protected short objectClass;
068: protected short toStringIdx;
069: protected short codeIdx;
070: protected short exceptionsIdx;
071: // Boxing
072: protected short booleanIdx;
073: protected short booleanCtorIdx;
074: protected short booleanUnboxIdx;
075: protected short byteIdx;
076: protected short byteCtorIdx;
077: protected short byteUnboxIdx;
078: protected short characterIdx;
079: protected short characterCtorIdx;
080: protected short characterUnboxIdx;
081: protected short doubleIdx;
082: protected short doubleCtorIdx;
083: protected short doubleUnboxIdx;
084: protected short floatIdx;
085: protected short floatCtorIdx;
086: protected short floatUnboxIdx;
087: protected short integerIdx;
088: protected short integerCtorIdx;
089: protected short integerUnboxIdx;
090: protected short longIdx;
091: protected short longCtorIdx;
092: protected short longUnboxIdx;
093: protected short shortIdx;
094: protected short shortCtorIdx;
095: protected short shortUnboxIdx;
096:
097: protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30;
098: protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 72;
099:
100: // Requires that superClass has been set up
101: protected void emitCommonConstantPoolEntries() {
102: // + [UTF-8] "java/lang/Throwable"
103: // + [CONSTANT_Class_info] for above
104: // + [UTF-8] "java/lang/ClassCastException"
105: // + [CONSTANT_Class_info] for above
106: // + [UTF-8] "java/lang/NullPointerException"
107: // + [CONSTANT_Class_info] for above
108: // + [UTF-8] "java/lang/IllegalArgumentException"
109: // + [CONSTANT_Class_info] for above
110: // + [UTF-8] "java/lang/InvocationTargetException"
111: // + [CONSTANT_Class_info] for above
112: // + [UTF-8] "<init>"
113: // + [UTF-8] "()V"
114: // + [CONSTANT_NameAndType_info] for above
115: // + [CONSTANT_Methodref_info] for NullPointerException's constructor
116: // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
117: // + [UTF-8] "(Ljava/lang/String;)V"
118: // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
119: // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
120: // + [UTF-8] "(Ljava/lang/Throwable;)V"
121: // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
122: // + [CONSTANT_Methodref_info] for InvocationTargetException's constructor
123: // + [CONSTANT_Methodref_info] for "super()"
124: // + [UTF-8] "java/lang/Object"
125: // + [CONSTANT_Class_info] for above
126: // + [UTF-8] "toString"
127: // + [UTF-8] "()Ljava/lang/String;"
128: // + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
129: // + [CONSTANT_Methodref_info] for Object's toString method
130: // + [UTF-8] "Code"
131: // + [UTF-8] "Exceptions"
132: asm.emitConstantPoolUTF8("java/lang/Throwable");
133: asm.emitConstantPoolClass(asm.cpi());
134: throwableClass = asm.cpi();
135: asm.emitConstantPoolUTF8("java/lang/ClassCastException");
136: asm.emitConstantPoolClass(asm.cpi());
137: classCastClass = asm.cpi();
138: asm.emitConstantPoolUTF8("java/lang/NullPointerException");
139: asm.emitConstantPoolClass(asm.cpi());
140: nullPointerClass = asm.cpi();
141: asm.emitConstantPoolUTF8("java/lang/IllegalArgumentException");
142: asm.emitConstantPoolClass(asm.cpi());
143: illegalArgumentClass = asm.cpi();
144: asm
145: .emitConstantPoolUTF8("java/lang/reflect/InvocationTargetException");
146: asm.emitConstantPoolClass(asm.cpi());
147: invocationTargetClass = asm.cpi();
148: asm.emitConstantPoolUTF8("<init>");
149: initIdx = asm.cpi();
150: asm.emitConstantPoolUTF8("()V");
151: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
152: initNameAndTypeIdx = asm.cpi();
153: asm.emitConstantPoolMethodref(nullPointerClass,
154: initNameAndTypeIdx);
155: nullPointerCtorIdx = asm.cpi();
156: asm.emitConstantPoolMethodref(illegalArgumentClass,
157: initNameAndTypeIdx);
158: illegalArgumentCtorIdx = asm.cpi();
159: asm.emitConstantPoolUTF8("(Ljava/lang/String;)V");
160: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
161: initStringNameAndTypeIdx = asm.cpi();
162: asm.emitConstantPoolMethodref(illegalArgumentClass,
163: initStringNameAndTypeIdx);
164: illegalArgumentStringCtorIdx = asm.cpi();
165: asm.emitConstantPoolUTF8("(Ljava/lang/Throwable;)V");
166: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
167: asm.emitConstantPoolMethodref(invocationTargetClass, asm.cpi());
168: invocationTargetCtorIdx = asm.cpi();
169: asm.emitConstantPoolMethodref(super Class, initNameAndTypeIdx);
170: super CtorIdx = asm.cpi();
171: asm.emitConstantPoolUTF8("java/lang/Object");
172: asm.emitConstantPoolClass(asm.cpi());
173: objectClass = asm.cpi();
174: asm.emitConstantPoolUTF8("toString");
175: asm.emitConstantPoolUTF8("()Ljava/lang/String;");
176: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
177: asm.emitConstantPoolMethodref(objectClass, asm.cpi());
178: toStringIdx = asm.cpi();
179: asm.emitConstantPoolUTF8("Code");
180: codeIdx = asm.cpi();
181: asm.emitConstantPoolUTF8("Exceptions");
182: exceptionsIdx = asm.cpi();
183: }
184:
185: /** Constant pool entries required to be able to box/unbox primitive
186: types. Note that we don't emit these if we don't need them. */
187: protected void emitBoxingContantPoolEntries() {
188: // * [UTF-8] "java/lang/Boolean"
189: // * [CONSTANT_Class_info] for above
190: // * [UTF-8] "(Z)V"
191: // * [CONSTANT_NameAndType_info] for above
192: // * [CONSTANT_Methodref_info] for above
193: // * [UTF-8] "booleanValue"
194: // * [UTF-8] "()Z"
195: // * [CONSTANT_NameAndType_info] for above
196: // * [CONSTANT_Methodref_info] for above
197: // * [UTF-8] "java/lang/Byte"
198: // * [CONSTANT_Class_info] for above
199: // * [UTF-8] "(B)V"
200: // * [CONSTANT_NameAndType_info] for above
201: // * [CONSTANT_Methodref_info] for above
202: // * [UTF-8] "byteValue"
203: // * [UTF-8] "()B"
204: // * [CONSTANT_NameAndType_info] for above
205: // * [CONSTANT_Methodref_info] for above
206: // * [UTF-8] "java/lang/Character"
207: // * [CONSTANT_Class_info] for above
208: // * [UTF-8] "(C)V"
209: // * [CONSTANT_NameAndType_info] for above
210: // * [CONSTANT_Methodref_info] for above
211: // * [UTF-8] "charValue"
212: // * [UTF-8] "()C"
213: // * [CONSTANT_NameAndType_info] for above
214: // * [CONSTANT_Methodref_info] for above
215: // * [UTF-8] "java/lang/Double"
216: // * [CONSTANT_Class_info] for above
217: // * [UTF-8] "(D)V"
218: // * [CONSTANT_NameAndType_info] for above
219: // * [CONSTANT_Methodref_info] for above
220: // * [UTF-8] "doubleValue"
221: // * [UTF-8] "()D"
222: // * [CONSTANT_NameAndType_info] for above
223: // * [CONSTANT_Methodref_info] for above
224: // * [UTF-8] "java/lang/Float"
225: // * [CONSTANT_Class_info] for above
226: // * [UTF-8] "(F)V"
227: // * [CONSTANT_NameAndType_info] for above
228: // * [CONSTANT_Methodref_info] for above
229: // * [UTF-8] "floatValue"
230: // * [UTF-8] "()F"
231: // * [CONSTANT_NameAndType_info] for above
232: // * [CONSTANT_Methodref_info] for above
233: // * [UTF-8] "java/lang/Integer"
234: // * [CONSTANT_Class_info] for above
235: // * [UTF-8] "(I)V"
236: // * [CONSTANT_NameAndType_info] for above
237: // * [CONSTANT_Methodref_info] for above
238: // * [UTF-8] "intValue"
239: // * [UTF-8] "()I"
240: // * [CONSTANT_NameAndType_info] for above
241: // * [CONSTANT_Methodref_info] for above
242: // * [UTF-8] "java/lang/Long"
243: // * [CONSTANT_Class_info] for above
244: // * [UTF-8] "(J)V"
245: // * [CONSTANT_NameAndType_info] for above
246: // * [CONSTANT_Methodref_info] for above
247: // * [UTF-8] "longValue"
248: // * [UTF-8] "()J"
249: // * [CONSTANT_NameAndType_info] for above
250: // * [CONSTANT_Methodref_info] for above
251: // * [UTF-8] "java/lang/Short"
252: // * [CONSTANT_Class_info] for above
253: // * [UTF-8] "(S)V"
254: // * [CONSTANT_NameAndType_info] for above
255: // * [CONSTANT_Methodref_info] for above
256: // * [UTF-8] "shortValue"
257: // * [UTF-8] "()S"
258: // * [CONSTANT_NameAndType_info] for above
259: // * [CONSTANT_Methodref_info] for above
260: // Boolean
261: asm.emitConstantPoolUTF8("java/lang/Boolean");
262: asm.emitConstantPoolClass(asm.cpi());
263: booleanIdx = asm.cpi();
264: asm.emitConstantPoolUTF8("(Z)V");
265: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
266: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
267: booleanCtorIdx = asm.cpi();
268: asm.emitConstantPoolUTF8("booleanValue");
269: asm.emitConstantPoolUTF8("()Z");
270: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
271: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
272: booleanUnboxIdx = asm.cpi();
273:
274: // Byte
275: asm.emitConstantPoolUTF8("java/lang/Byte");
276: asm.emitConstantPoolClass(asm.cpi());
277: byteIdx = asm.cpi();
278: asm.emitConstantPoolUTF8("(B)V");
279: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
280: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
281: byteCtorIdx = asm.cpi();
282: asm.emitConstantPoolUTF8("byteValue");
283: asm.emitConstantPoolUTF8("()B");
284: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
285: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
286: byteUnboxIdx = asm.cpi();
287:
288: // Character
289: asm.emitConstantPoolUTF8("java/lang/Character");
290: asm.emitConstantPoolClass(asm.cpi());
291: characterIdx = asm.cpi();
292: asm.emitConstantPoolUTF8("(C)V");
293: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
294: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
295: characterCtorIdx = asm.cpi();
296: asm.emitConstantPoolUTF8("charValue");
297: asm.emitConstantPoolUTF8("()C");
298: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
299: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
300: characterUnboxIdx = asm.cpi();
301:
302: // Double
303: asm.emitConstantPoolUTF8("java/lang/Double");
304: asm.emitConstantPoolClass(asm.cpi());
305: doubleIdx = asm.cpi();
306: asm.emitConstantPoolUTF8("(D)V");
307: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
308: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
309: doubleCtorIdx = asm.cpi();
310: asm.emitConstantPoolUTF8("doubleValue");
311: asm.emitConstantPoolUTF8("()D");
312: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
313: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
314: doubleUnboxIdx = asm.cpi();
315:
316: // Float
317: asm.emitConstantPoolUTF8("java/lang/Float");
318: asm.emitConstantPoolClass(asm.cpi());
319: floatIdx = asm.cpi();
320: asm.emitConstantPoolUTF8("(F)V");
321: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
322: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
323: floatCtorIdx = asm.cpi();
324: asm.emitConstantPoolUTF8("floatValue");
325: asm.emitConstantPoolUTF8("()F");
326: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
327: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
328: floatUnboxIdx = asm.cpi();
329:
330: // Integer
331: asm.emitConstantPoolUTF8("java/lang/Integer");
332: asm.emitConstantPoolClass(asm.cpi());
333: integerIdx = asm.cpi();
334: asm.emitConstantPoolUTF8("(I)V");
335: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
336: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
337: integerCtorIdx = asm.cpi();
338: asm.emitConstantPoolUTF8("intValue");
339: asm.emitConstantPoolUTF8("()I");
340: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
341: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
342: integerUnboxIdx = asm.cpi();
343:
344: // Long
345: asm.emitConstantPoolUTF8("java/lang/Long");
346: asm.emitConstantPoolClass(asm.cpi());
347: longIdx = asm.cpi();
348: asm.emitConstantPoolUTF8("(J)V");
349: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
350: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
351: longCtorIdx = asm.cpi();
352: asm.emitConstantPoolUTF8("longValue");
353: asm.emitConstantPoolUTF8("()J");
354: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
355: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
356: longUnboxIdx = asm.cpi();
357:
358: // Short
359: asm.emitConstantPoolUTF8("java/lang/Short");
360: asm.emitConstantPoolClass(asm.cpi());
361: shortIdx = asm.cpi();
362: asm.emitConstantPoolUTF8("(S)V");
363: asm.emitConstantPoolNameAndType(initIdx, asm.cpi());
364: asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi());
365: shortCtorIdx = asm.cpi();
366: asm.emitConstantPoolUTF8("shortValue");
367: asm.emitConstantPoolUTF8("()S");
368: asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
369: asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi());
370: shortUnboxIdx = asm.cpi();
371: }
372:
373: // Necessary because of Java's annoying promotion rules
374: protected static short add(short s1, short s2) {
375: return (short) (s1 + s2);
376: }
377:
378: protected static short sub(short s1, short s2) {
379: return (short) (s1 - s2);
380: }
381:
382: protected boolean isStatic() {
383: return Modifier.isStatic(modifiers);
384: }
385:
386: /** Returns class name in "internal" form (i.e., '/' separators
387: instead of '.') */
388: protected static String getClassName(Class c,
389: boolean addPrefixAndSuffixForNonPrimitiveTypes) {
390: if (c.isPrimitive()) {
391: if (c == Boolean.TYPE) {
392: return "Z";
393: } else if (c == Byte.TYPE) {
394: return "B";
395: } else if (c == Character.TYPE) {
396: return "C";
397: } else if (c == Double.TYPE) {
398: return "D";
399: } else if (c == Float.TYPE) {
400: return "F";
401: } else if (c == Integer.TYPE) {
402: return "I";
403: } else if (c == Long.TYPE) {
404: return "J";
405: } else if (c == Short.TYPE) {
406: return "S";
407: } else if (c == Void.TYPE) {
408: return "V";
409: }
410: throw new InternalError("Should have found primitive type");
411: } else if (c.isArray()) {
412: return "[" + getClassName(c.getComponentType(), true);
413: } else {
414: if (addPrefixAndSuffixForNonPrimitiveTypes) {
415: return internalize("L" + c.getName() + ";");
416: } else {
417: return internalize(c.getName());
418: }
419: }
420: }
421:
422: private static String internalize(String className) {
423: return className.replace('.', '/');
424: }
425:
426: protected void emitConstructor() {
427: // Generate code into fresh code buffer
428: ClassFileAssembler cb = new ClassFileAssembler();
429: // 0 incoming arguments
430: cb.setMaxLocals(1);
431: cb.opc_aload_0();
432: cb.opc_invokespecial(super CtorIdx, 0, 0);
433: cb.opc_return();
434:
435: // Emit method
436: emitMethod(initIdx, cb.getMaxLocals(), cb, null, null);
437: }
438:
439: // The descriptor's index in the constant pool must be (1 +
440: // nameIdx). "numArgs" must indicate ALL arguments, including the
441: // implicit "this" argument; double and long arguments each count
442: // as 2 in this count. The code buffer must NOT contain the code
443: // length. The exception table may be null, but if non-null must
444: // NOT contain the exception table's length. The checked exception
445: // indices may be null.
446: protected void emitMethod(short nameIdx, int numArgs,
447: ClassFileAssembler code, ClassFileAssembler exceptionTable,
448: short[] checkedExceptionIndices) {
449: int codeLen = code.getLength();
450: int excLen = 0;
451: if (exceptionTable != null) {
452: excLen = exceptionTable.getLength();
453: if ((excLen % 8) != 0) {
454: throw new IllegalArgumentException(
455: "Illegal exception table");
456: }
457: }
458: int attrLen = 12 + codeLen + excLen;
459: excLen = excLen / 8; // No-op if no exception table
460:
461: asm.emitShort(ACC_PUBLIC);
462: asm.emitShort(nameIdx);
463: asm.emitShort(add(nameIdx, S1));
464: if (checkedExceptionIndices == null) {
465: // Code attribute only
466: asm.emitShort(S1);
467: } else {
468: // Code and Exceptions attributes
469: asm.emitShort(S2);
470: }
471: // Code attribute
472: asm.emitShort(codeIdx);
473: asm.emitInt(attrLen);
474: asm.emitShort(code.getMaxStack());
475: asm.emitShort((short) Math.max(numArgs, code.getMaxLocals()));
476: asm.emitInt(codeLen);
477: asm.append(code);
478: asm.emitShort((short) excLen);
479: if (exceptionTable != null) {
480: asm.append(exceptionTable);
481: }
482: asm.emitShort(S0); // No additional attributes for Code attribute
483: if (checkedExceptionIndices != null) {
484: // Exceptions attribute
485: asm.emitShort(exceptionsIdx);
486: asm.emitInt(2 + 2 * checkedExceptionIndices.length);
487: asm.emitShort((short) checkedExceptionIndices.length);
488: for (int i = 0; i < checkedExceptionIndices.length; i++) {
489: asm.emitShort(checkedExceptionIndices[i]);
490: }
491: }
492: }
493:
494: protected short indexForPrimitiveType(Class type) {
495: if (type == Boolean.TYPE) {
496: return booleanIdx;
497: } else if (type == Byte.TYPE) {
498: return byteIdx;
499: } else if (type == Character.TYPE) {
500: return characterIdx;
501: } else if (type == Double.TYPE) {
502: return doubleIdx;
503: } else if (type == Float.TYPE) {
504: return floatIdx;
505: } else if (type == Integer.TYPE) {
506: return integerIdx;
507: } else if (type == Long.TYPE) {
508: return longIdx;
509: } else if (type == Short.TYPE) {
510: return shortIdx;
511: }
512: throw new InternalError("Should have found primitive type");
513: }
514:
515: protected short ctorIndexForPrimitiveType(Class type) {
516: if (type == Boolean.TYPE) {
517: return booleanCtorIdx;
518: } else if (type == Byte.TYPE) {
519: return byteCtorIdx;
520: } else if (type == Character.TYPE) {
521: return characterCtorIdx;
522: } else if (type == Double.TYPE) {
523: return doubleCtorIdx;
524: } else if (type == Float.TYPE) {
525: return floatCtorIdx;
526: } else if (type == Integer.TYPE) {
527: return integerCtorIdx;
528: } else if (type == Long.TYPE) {
529: return longCtorIdx;
530: } else if (type == Short.TYPE) {
531: return shortCtorIdx;
532: }
533: throw new InternalError("Should have found primitive type");
534: }
535:
536: /** Returns true for widening or identity conversions for primitive
537: types only */
538: protected static boolean canWidenTo(Class type, Class otherType) {
539: if (!type.isPrimitive()) {
540: return false;
541: }
542:
543: // Widening conversions (from JVM spec):
544: // byte to short, int, long, float, or double
545: // short to int, long, float, or double
546: // char to int, long, float, or double
547: // int to long, float, or double
548: // long to float or double
549: // float to double
550:
551: if (type == Boolean.TYPE) {
552: if (otherType == Boolean.TYPE) {
553: return true;
554: }
555: } else if (type == Byte.TYPE) {
556: if (otherType == Byte.TYPE || otherType == Short.TYPE
557: || otherType == Integer.TYPE
558: || otherType == Long.TYPE
559: || otherType == Float.TYPE
560: || otherType == Double.TYPE) {
561: return true;
562: }
563: } else if (type == Short.TYPE) {
564: if (otherType == Short.TYPE || otherType == Integer.TYPE
565: || otherType == Long.TYPE
566: || otherType == Float.TYPE
567: || otherType == Double.TYPE) {
568: return true;
569: }
570: } else if (type == Character.TYPE) {
571: if (otherType == Character.TYPE
572: || otherType == Integer.TYPE
573: || otherType == Long.TYPE
574: || otherType == Float.TYPE
575: || otherType == Double.TYPE) {
576: return true;
577: }
578: } else if (type == Integer.TYPE) {
579: if (otherType == Integer.TYPE || otherType == Long.TYPE
580: || otherType == Float.TYPE
581: || otherType == Double.TYPE) {
582: return true;
583: }
584: } else if (type == Long.TYPE) {
585: if (otherType == Long.TYPE || otherType == Float.TYPE
586: || otherType == Double.TYPE) {
587: return true;
588: }
589: } else if (type == Float.TYPE) {
590: if (otherType == Float.TYPE || otherType == Double.TYPE) {
591: return true;
592: }
593: } else if (type == Double.TYPE) {
594: if (otherType == Double.TYPE) {
595: return true;
596: }
597: }
598:
599: return false;
600: }
601:
602: /** Emits the widening bytecode for the given primitive conversion
603: (or none if the identity conversion). Requires that a primitive
604: conversion exists; i.e., canWidenTo must have already been
605: called and returned true. */
606: protected static void emitWideningBytecodeForPrimitiveConversion(
607: ClassFileAssembler cb, Class fromType, Class toType) {
608: // Note that widening conversions for integral types (i.e., "b2s",
609: // "s2i") are no-ops since values on the Java stack are
610: // sign-extended.
611:
612: // Widening conversions (from JVM spec):
613: // byte to short, int, long, float, or double
614: // short to int, long, float, or double
615: // char to int, long, float, or double
616: // int to long, float, or double
617: // long to float or double
618: // float to double
619:
620: if (fromType == Byte.TYPE || fromType == Short.TYPE
621: || fromType == Character.TYPE
622: || fromType == Integer.TYPE) {
623: if (toType == Long.TYPE) {
624: cb.opc_i2l();
625: } else if (toType == Float.TYPE) {
626: cb.opc_i2f();
627: } else if (toType == Double.TYPE) {
628: cb.opc_i2d();
629: }
630: } else if (fromType == Long.TYPE) {
631: if (toType == Float.TYPE) {
632: cb.opc_l2f();
633: } else if (toType == Double.TYPE) {
634: cb.opc_l2d();
635: }
636: } else if (fromType == Float.TYPE) {
637: if (toType == Double.TYPE) {
638: cb.opc_f2d();
639: }
640: }
641:
642: // Otherwise, was identity or no-op conversion. Fall through.
643: }
644:
645: protected short unboxingMethodForPrimitiveType(Class primType) {
646: if (primType == Boolean.TYPE) {
647: return booleanUnboxIdx;
648: } else if (primType == Byte.TYPE) {
649: return byteUnboxIdx;
650: } else if (primType == Character.TYPE) {
651: return characterUnboxIdx;
652: } else if (primType == Short.TYPE) {
653: return shortUnboxIdx;
654: } else if (primType == Integer.TYPE) {
655: return integerUnboxIdx;
656: } else if (primType == Long.TYPE) {
657: return longUnboxIdx;
658: } else if (primType == Float.TYPE) {
659: return floatUnboxIdx;
660: } else if (primType == Double.TYPE) {
661: return doubleUnboxIdx;
662: }
663: throw new InternalError("Illegal primitive type "
664: + primType.getName());
665: }
666:
667: protected static final Class[] primitiveTypes = new Class[] {
668: Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE,
669: Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE };
670:
671: /** We don't consider "Void" to be a primitive type */
672: protected static boolean isPrimitive(Class c) {
673: return (c.isPrimitive() && c != Void.TYPE);
674: }
675:
676: protected int typeSizeInStackSlots(Class c) {
677: if (c == Void.TYPE) {
678: return 0;
679: }
680: if (c == Long.TYPE || c == Double.TYPE) {
681: return 2;
682: }
683: return 1;
684: }
685:
686: private ClassFileAssembler illegalArgumentCodeBuffer;
687:
688: protected ClassFileAssembler illegalArgumentCodeBuffer() {
689: if (illegalArgumentCodeBuffer == null) {
690: illegalArgumentCodeBuffer = new ClassFileAssembler();
691: illegalArgumentCodeBuffer.opc_new(illegalArgumentClass);
692: illegalArgumentCodeBuffer.opc_dup();
693: illegalArgumentCodeBuffer.opc_invokespecial(
694: illegalArgumentCtorIdx, 0, 0);
695: illegalArgumentCodeBuffer.opc_athrow();
696: }
697:
698: return illegalArgumentCodeBuffer;
699: }
700: }
|