rev 47452 : imported patch jdk-new-asmv6.patch
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * ASM: a very small and fast Java bytecode manipulation framework
32 * Copyright (c) 2000-2011 INRIA, France Telecom
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the copyright holders nor the names of its
44 * contributors may be used to endorse or promote products derived from
45 * this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59 package jdk.internal.org.objectweb.asm;
60
61 import java.lang.reflect.Constructor;
62 import java.lang.reflect.Method;
63
64 /**
65 * A Java field or method type. This class can be used to make it easier to
66 * manipulate type and method descriptors.
67 *
68 * @author Eric Bruneton
69 * @author Chris Nokleberg
70 */
71 public class Type {
72
73 /**
74 * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
75 */
76 public static final int VOID = 0;
77
78 /**
79 * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
80 */
81 public static final int BOOLEAN = 1;
82
83 /**
84 * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
85 */
86 public static final int CHAR = 2;
87
88 /**
89 * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
90 */
91 public static final int BYTE = 3;
92
93 /**
94 * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
95 */
96 public static final int SHORT = 4;
97
98 /**
99 * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
100 */
101 public static final int INT = 5;
102
103 /**
104 * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
105 */
106 public static final int FLOAT = 6;
107
108 /**
109 * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
110 */
111 public static final int LONG = 7;
112
113 /**
114 * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
115 */
116 public static final int DOUBLE = 8;
117
118 /**
119 * The sort of array reference types. See {@link #getSort getSort}.
120 */
121 public static final int ARRAY = 9;
122
123 /**
124 * The sort of object reference types. See {@link #getSort getSort}.
125 */
126 public static final int OBJECT = 10;
127
128 /**
129 * The sort of method types. See {@link #getSort getSort}.
130 */
131 public static final int METHOD = 11;
132
133 /**
134 * The <tt>void</tt> type.
135 */
136 public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
137 | (5 << 16) | (0 << 8) | 0, 1);
138
139 /**
140 * The <tt>boolean</tt> type.
141 */
142 public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)
143 | (0 << 16) | (5 << 8) | 1, 1);
144
145 /**
146 * The <tt>char</tt> type.
147 */
148 public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)
149 | (0 << 16) | (6 << 8) | 1, 1);
150
151 /**
152 * The <tt>byte</tt> type.
153 */
154 public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)
155 | (0 << 16) | (5 << 8) | 1, 1);
156
157 /**
158 * The <tt>short</tt> type.
159 */
160 public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)
161 | (0 << 16) | (7 << 8) | 1, 1);
162
163 /**
164 * The <tt>int</tt> type.
165 */
166 public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)
167 | (0 << 16) | (0 << 8) | 1, 1);
168
169 /**
170 * The <tt>float</tt> type.
171 */
172 public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)
173 | (2 << 16) | (2 << 8) | 1, 1);
174
175 /**
176 * The <tt>long</tt> type.
177 */
178 public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)
179 | (1 << 16) | (1 << 8) | 2, 1);
180
181 /**
182 * The <tt>double</tt> type.
183 */
184 public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)
185 | (3 << 16) | (3 << 8) | 2, 1);
186
187 // ------------------------------------------------------------------------
188 // Fields
189 // ------------------------------------------------------------------------
190
191 /**
192 * The sort of this Java type.
193 */
194 private final int sort;
195
196 /**
197 * A buffer containing the internal name of this Java type. This field is
198 * only used for reference types.
199 */
200 private final char[] buf;
201
202 /**
203 * The offset of the internal name of this Java type in {@link #buf buf} or,
204 * for primitive types, the size, descriptor and getOpcode offsets for this
205 * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset
206 * for IALOAD or IASTORE, byte 3 the offset for all other instructions).
207 */
208 private final int off;
209
210 /**
211 * The length of the internal name of this Java type.
212 */
213 private final int len;
214
215 // ------------------------------------------------------------------------
216 // Constructors
217 // ------------------------------------------------------------------------
218
219 /**
220 * Constructs a reference type.
221 *
222 * @param sort
223 * the sort of the reference type to be constructed.
224 * @param buf
225 * a buffer containing the descriptor of the previous type.
226 * @param off
227 * the offset of this descriptor in the previous buffer.
228 * @param len
229 * the length of this descriptor.
230 */
231 private Type(final int sort, final char[] buf, final int off, final int len) {
232 this.sort = sort;
233 this.buf = buf;
234 this.off = off;
235 this.len = len;
236 }
237
238 /**
239 * Returns the Java type corresponding to the given type descriptor.
240 *
241 * @param typeDescriptor
242 * a field or method type descriptor.
243 * @return the Java type corresponding to the given type descriptor.
244 */
245 public static Type getType(final String typeDescriptor) {
246 return getType(typeDescriptor.toCharArray(), 0);
247 }
248
249 /**
250 * Returns the Java type corresponding to the given internal name.
251 *
252 * @param internalName
253 * an internal name.
254 * @return the Java type corresponding to the given internal name.
255 */
256 public static Type getObjectType(final String internalName) {
257 char[] buf = internalName.toCharArray();
258 return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
259 }
260
261 /**
262 * Returns the Java type corresponding to the given method descriptor.
263 * Equivalent to <code>Type.getType(methodDescriptor)</code>.
264 *
265 * @param methodDescriptor
266 * a method descriptor.
267 * @return the Java type corresponding to the given method descriptor.
268 */
269 public static Type getMethodType(final String methodDescriptor) {
270 return getType(methodDescriptor.toCharArray(), 0);
271 }
272
273 /**
274 * Returns the Java method type corresponding to the given argument and
275 * return types.
276 *
277 * @param returnType
278 * the return type of the method.
279 * @param argumentTypes
280 * the argument types of the method.
281 * @return the Java type corresponding to the given argument and return
282 * types.
283 */
284 public static Type getMethodType(final Type returnType,
285 final Type... argumentTypes) {
286 return getType(getMethodDescriptor(returnType, argumentTypes));
287 }
288
289 /**
290 * Returns the Java type corresponding to the given class.
291 *
292 * @param c
293 * a class.
294 * @return the Java type corresponding to the given class.
295 */
296 public static Type getType(final Class<?> c) {
297 if (c.isPrimitive()) {
298 if (c == Integer.TYPE) {
299 return INT_TYPE;
300 } else if (c == Void.TYPE) {
301 return VOID_TYPE;
302 } else if (c == Boolean.TYPE) {
303 return BOOLEAN_TYPE;
304 } else if (c == Byte.TYPE) {
305 return BYTE_TYPE;
306 } else if (c == Character.TYPE) {
307 return CHAR_TYPE;
308 } else if (c == Short.TYPE) {
309 return SHORT_TYPE;
310 } else if (c == Double.TYPE) {
311 return DOUBLE_TYPE;
312 } else if (c == Float.TYPE) {
313 return FLOAT_TYPE;
314 } else /* if (c == Long.TYPE) */{
315 return LONG_TYPE;
316 }
317 } else {
318 return getType(getDescriptor(c));
319 }
320 }
321
322 /**
323 * Returns the Java method type corresponding to the given constructor.
324 *
325 * @param c
326 * a {@link Constructor Constructor} object.
327 * @return the Java method type corresponding to the given constructor.
328 */
329 public static Type getType(final Constructor<?> c) {
330 return getType(getConstructorDescriptor(c));
331 }
332
333 /**
334 * Returns the Java method type corresponding to the given method.
335 *
336 * @param m
337 * a {@link Method Method} object.
338 * @return the Java method type corresponding to the given method.
339 */
340 public static Type getType(final Method m) {
341 return getType(getMethodDescriptor(m));
342 }
343
344 /**
345 * Returns the Java types corresponding to the argument types of the given
346 * method descriptor.
347 *
348 * @param methodDescriptor
349 * a method descriptor.
350 * @return the Java types corresponding to the argument types of the given
351 * method descriptor.
352 */
353 public static Type[] getArgumentTypes(final String methodDescriptor) {
354 char[] buf = methodDescriptor.toCharArray();
355 int off = 1;
356 int size = 0;
357 while (true) {
358 char car = buf[off++];
359 if (car == ')') {
360 break;
361 } else if (car == 'L') {
362 while (buf[off++] != ';') {
363 }
364 ++size;
365 } else if (car != '[') {
366 ++size;
367 }
368 }
369 Type[] args = new Type[size];
370 off = 1;
371 size = 0;
372 while (buf[off] != ')') {
373 args[size] = getType(buf, off);
374 off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
375 size += 1;
376 }
377 return args;
378 }
379
380 /**
381 * Returns the Java types corresponding to the argument types of the given
382 * method.
383 *
384 * @param method
385 * a method.
386 * @return the Java types corresponding to the argument types of the given
387 * method.
388 */
389 public static Type[] getArgumentTypes(final Method method) {
390 Class<?>[] classes = method.getParameterTypes();
391 Type[] types = new Type[classes.length];
392 for (int i = classes.length - 1; i >= 0; --i) {
393 types[i] = getType(classes[i]);
394 }
395 return types;
396 }
397
398 /**
399 * Returns the Java type corresponding to the return type of the given
400 * method descriptor.
401 *
402 * @param methodDescriptor
403 * a method descriptor.
404 * @return the Java type corresponding to the return type of the given
405 * method descriptor.
406 */
407 public static Type getReturnType(final String methodDescriptor) {
408 char[] buf = methodDescriptor.toCharArray();
409 return getType(buf, methodDescriptor.indexOf(')') + 1);
410 }
411
412 /**
413 * Returns the Java type corresponding to the return type of the given
414 * method.
415 *
416 * @param method
417 * a method.
418 * @return the Java type corresponding to the return type of the given
419 * method.
420 */
421 public static Type getReturnType(final Method method) {
422 return getType(method.getReturnType());
423 }
424
425 /**
426 * Computes the size of the arguments and of the return value of a method.
427 *
428 * @param desc
429 * the descriptor of a method.
430 * @return the size of the arguments of the method (plus one for the
431 * implicit this argument), argSize, and the size of its return
432 * value, retSize, packed into a single int i =
433 * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
434 * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
435 */
436 public static int getArgumentsAndReturnSizes(final String desc) {
437 int n = 1;
438 int c = 1;
439 while (true) {
440 char car = desc.charAt(c++);
441 if (car == ')') {
442 car = desc.charAt(c);
443 return n << 2
444 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
445 } else if (car == 'L') {
446 while (desc.charAt(c++) != ';') {
447 }
448 n += 1;
449 } else if (car == '[') {
450 while ((car = desc.charAt(c)) == '[') {
451 ++c;
452 }
453 if (car == 'D' || car == 'J') {
454 n -= 1;
455 }
456 } else if (car == 'D' || car == 'J') {
457 n += 2;
458 } else {
459 n += 1;
460 }
461 }
462 }
463
464 /**
465 * Returns the Java type corresponding to the given type descriptor. For
466 * method descriptors, buf is supposed to contain nothing more than the
467 * descriptor itself.
468 *
469 * @param buf
470 * a buffer containing a type descriptor.
471 * @param off
472 * the offset of this descriptor in the previous buffer.
473 * @return the Java type corresponding to the given type descriptor.
474 */
475 private static Type getType(final char[] buf, final int off) {
476 int len;
477 switch (buf[off]) {
478 case 'V':
479 return VOID_TYPE;
480 case 'Z':
481 return BOOLEAN_TYPE;
482 case 'C':
483 return CHAR_TYPE;
484 case 'B':
485 return BYTE_TYPE;
486 case 'S':
487 return SHORT_TYPE;
488 case 'I':
489 return INT_TYPE;
490 case 'F':
491 return FLOAT_TYPE;
492 case 'J':
493 return LONG_TYPE;
494 case 'D':
495 return DOUBLE_TYPE;
496 case '[':
497 len = 1;
498 while (buf[off + len] == '[') {
499 ++len;
500 }
501 if (buf[off + len] == 'L') {
502 ++len;
503 while (buf[off + len] != ';') {
504 ++len;
505 }
506 }
507 return new Type(ARRAY, buf, off, len + 1);
508 case 'L':
509 len = 1;
510 while (buf[off + len] != ';') {
511 ++len;
512 }
513 return new Type(OBJECT, buf, off + 1, len - 1);
514 // case '(':
515 default:
516 return new Type(METHOD, buf, off, buf.length - off);
517 }
518 }
519
520 // ------------------------------------------------------------------------
521 // Accessors
522 // ------------------------------------------------------------------------
523
524 /**
525 * Returns the sort of this Java type.
526 *
527 * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
528 * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},
529 * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},
530 * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD
531 * METHOD}.
532 */
533 public int getSort() {
534 return sort;
535 }
536
537 /**
538 * Returns the number of dimensions of this array type. This method should
539 * only be used for an array type.
540 *
541 * @return the number of dimensions of this array type.
542 */
543 public int getDimensions() {
544 int i = 1;
545 while (buf[off + i] == '[') {
546 ++i;
547 }
548 return i;
549 }
550
551 /**
552 * Returns the type of the elements of this array type. This method should
553 * only be used for an array type.
554 *
555 * @return Returns the type of the elements of this array type.
556 */
557 public Type getElementType() {
558 return getType(buf, off + getDimensions());
559 }
560
561 /**
562 * Returns the binary name of the class corresponding to this type. This
563 * method must not be used on method types.
564 *
565 * @return the binary name of the class corresponding to this type.
566 */
567 public String getClassName() {
568 switch (sort) {
569 case VOID:
570 return "void";
571 case BOOLEAN:
572 return "boolean";
573 case CHAR:
574 return "char";
575 case BYTE:
576 return "byte";
577 case SHORT:
578 return "short";
579 case INT:
580 return "int";
581 case FLOAT:
582 return "float";
583 case LONG:
584 return "long";
585 case DOUBLE:
586 return "double";
587 case ARRAY:
588 StringBuilder sb = new StringBuilder(getElementType().getClassName());
589 for (int i = getDimensions(); i > 0; --i) {
590 sb.append("[]");
591 }
592 return sb.toString();
593 case OBJECT:
594 return new String(buf, off, len).replace('/', '.');
595 default:
596 return null;
597 }
598 }
599
600 /**
601 * Returns the internal name of the class corresponding to this object or
602 * array type. The internal name of a class is its fully qualified name (as
603 * returned by Class.getName(), where '.' are replaced by '/'. This method
604 * should only be used for an object or array type.
605 *
606 * @return the internal name of the class corresponding to this object type.
607 */
608 public String getInternalName() {
609 return new String(buf, off, len);
610 }
611
612 /**
613 * Returns the argument types of methods of this type. This method should
614 * only be used for method types.
615 *
616 * @return the argument types of methods of this type.
617 */
618 public Type[] getArgumentTypes() {
619 return getArgumentTypes(getDescriptor());
620 }
621
622 /**
623 * Returns the return type of methods of this type. This method should only
624 * be used for method types.
625 *
626 * @return the return type of methods of this type.
627 */
628 public Type getReturnType() {
629 return getReturnType(getDescriptor());
630 }
631
632 /**
633 * Returns the size of the arguments and of the return value of methods of
634 * this type. This method should only be used for method types.
635 *
636 * @return the size of the arguments (plus one for the implicit this
637 * argument), argSize, and the size of the return value, retSize,
638 * packed into a single
639 * int i = <tt>(argSize << 2) | retSize</tt>
640 * (argSize is therefore equal to <tt>i >> 2</tt>,
641 * and retSize to <tt>i & 0x03</tt>).
642 */
643 public int getArgumentsAndReturnSizes() {
644 return getArgumentsAndReturnSizes(getDescriptor());
645 }
646
647 // ------------------------------------------------------------------------
648 // Conversion to type descriptors
649 // ------------------------------------------------------------------------
650
651 /**
652 * Returns the descriptor corresponding to this Java type.
653 *
654 * @return the descriptor corresponding to this Java type.
655 */
656 public String getDescriptor() {
657 StringBuilder buf = new StringBuilder();
658 getDescriptor(buf);
659 return buf.toString();
660 }
661
662 /**
663 * Returns the descriptor corresponding to the given argument and return
664 * types.
665 *
666 * @param returnType
667 * the return type of the method.
668 * @param argumentTypes
669 * the argument types of the method.
670 * @return the descriptor corresponding to the given argument and return
671 * types.
672 */
673 public static String getMethodDescriptor(final Type returnType,
674 final Type... argumentTypes) {
675 StringBuilder buf = new StringBuilder();
676 buf.append('(');
677 for (int i = 0; i < argumentTypes.length; ++i) {
678 argumentTypes[i].getDescriptor(buf);
679 }
680 buf.append(')');
681 returnType.getDescriptor(buf);
682 return buf.toString();
683 }
684
685 /**
686 * Appends the descriptor corresponding to this Java type to the given
687 * string buffer.
688 *
689 * @param buf
690 * the string buffer to which the descriptor must be appended.
691 */
692 private void getDescriptor(final StringBuilder buf) {
693 if (this.buf == null) {
694 // descriptor is in byte 3 of 'off' for primitive types (buf ==
695 // null)
696 buf.append((char) ((off & 0xFF000000) >>> 24));
697 } else if (sort == OBJECT) {
698 buf.append('L');
699 buf.append(this.buf, off, len);
700 buf.append(';');
701 } else { // sort == ARRAY || sort == METHOD
702 buf.append(this.buf, off, len);
703 }
704 }
705
706 // ------------------------------------------------------------------------
707 // Direct conversion from classes to type descriptors,
708 // without intermediate Type objects
709 // ------------------------------------------------------------------------
710
711 /**
712 * Returns the internal name of the given class. The internal name of a
713 * class is its fully qualified name, as returned by Class.getName(), where
714 * '.' are replaced by '/'.
715 *
716 * @param c
717 * an object or array class.
718 * @return the internal name of the given class.
719 */
720 public static String getInternalName(final Class<?> c) {
721 return c.getName().replace('.', '/');
722 }
723
724 /**
725 * Returns the descriptor corresponding to the given Java type.
726 *
727 * @param c
728 * an object class, a primitive class or an array class.
729 * @return the descriptor corresponding to the given class.
730 */
731 public static String getDescriptor(final Class<?> c) {
732 StringBuilder buf = new StringBuilder();
733 getDescriptor(buf, c);
734 return buf.toString();
735 }
736
737 /**
738 * Returns the descriptor corresponding to the given constructor.
739 *
740 * @param c
741 * a {@link Constructor Constructor} object.
742 * @return the descriptor of the given constructor.
743 */
744 public static String getConstructorDescriptor(final Constructor<?> c) {
745 Class<?>[] parameters = c.getParameterTypes();
746 StringBuilder buf = new StringBuilder();
747 buf.append('(');
748 for (int i = 0; i < parameters.length; ++i) {
749 getDescriptor(buf, parameters[i]);
750 }
751 return buf.append(")V").toString();
752 }
753
754 /**
755 * Returns the descriptor corresponding to the given method.
756 *
757 * @param m
758 * a {@link Method Method} object.
759 * @return the descriptor of the given method.
760 */
761 public static String getMethodDescriptor(final Method m) {
762 Class<?>[] parameters = m.getParameterTypes();
763 StringBuilder buf = new StringBuilder();
764 buf.append('(');
765 for (int i = 0; i < parameters.length; ++i) {
766 getDescriptor(buf, parameters[i]);
767 }
768 buf.append(')');
769 getDescriptor(buf, m.getReturnType());
770 return buf.toString();
771 }
772
773 /**
774 * Appends the descriptor of the given class to the given string buffer.
775 *
776 * @param buf
777 * the string buffer to which the descriptor must be appended.
778 * @param c
779 * the class whose descriptor must be computed.
780 */
781 private static void getDescriptor(final StringBuilder buf, final Class<?> c) {
782 Class<?> d = c;
783 while (true) {
784 if (d.isPrimitive()) {
785 char car;
786 if (d == Integer.TYPE) {
787 car = 'I';
788 } else if (d == Void.TYPE) {
789 car = 'V';
790 } else if (d == Boolean.TYPE) {
791 car = 'Z';
792 } else if (d == Byte.TYPE) {
793 car = 'B';
794 } else if (d == Character.TYPE) {
795 car = 'C';
796 } else if (d == Short.TYPE) {
797 car = 'S';
798 } else if (d == Double.TYPE) {
799 car = 'D';
800 } else if (d == Float.TYPE) {
801 car = 'F';
802 } else /* if (d == Long.TYPE) */{
803 car = 'J';
804 }
805 buf.append(car);
806 return;
807 } else if (d.isArray()) {
808 buf.append('[');
809 d = d.getComponentType();
810 } else {
811 buf.append('L');
812 String name = d.getName();
813 int len = name.length();
814 for (int i = 0; i < len; ++i) {
815 char car = name.charAt(i);
816 buf.append(car == '.' ? '/' : car);
817 }
818 buf.append(';');
819 return;
820 }
821 }
822 }
823
824 // ------------------------------------------------------------------------
825 // Corresponding size and opcodes
826 // ------------------------------------------------------------------------
827
828 /**
829 * Returns the size of values of this type. This method must not be used for
830 * method types.
831 *
832 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
833 * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
834 */
835 public int getSize() {
836 // the size is in byte 0 of 'off' for primitive types (buf == null)
837 return buf == null ? (off & 0xFF) : 1;
838 }
839
840 /**
841 * Returns a JVM instruction opcode adapted to this Java type. This method
842 * must not be used for method types.
843 *
844 * @param opcode
845 * a JVM instruction opcode. This opcode must be one of ILOAD,
846 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
847 * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
848 * @return an opcode that is similar to the given opcode, but adapted to
849 * this Java type. For example, if this type is <tt>float</tt> and
850 * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
851 */
852 public int getOpcode(final int opcode) {
853 if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
854 // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
855 // primitive types (buf == null)
856 return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
857 } else {
858 // the offset for other instructions is in byte 2 of 'off' for
859 // primitive types (buf == null)
860 return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
861 }
862 }
863
864 // ------------------------------------------------------------------------
865 // Equals, hashCode and toString
866 // ------------------------------------------------------------------------
867
868 /**
869 * Tests if the given object is equal to this type.
870 *
871 * @param o
872 * the object to be compared to this type.
873 * @return <tt>true</tt> if the given object is equal to this type.
874 */
875 @Override
876 public boolean equals(final Object o) {
877 if (this == o) {
878 return true;
879 }
880 if (!(o instanceof Type)) {
881 return false;
882 }
883 Type t = (Type) o;
884 if (sort != t.sort) {
885 return false;
886 }
887 if (sort >= ARRAY) {
888 if (len != t.len) {
889 return false;
890 }
891 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
892 if (buf[i] != t.buf[j]) {
893 return false;
894 }
895 }
896 }
897 return true;
898 }
899
900 /**
901 * Returns a hash code value for this type.
902 *
903 * @return a hash code value for this type.
904 */
905 @Override
906 public int hashCode() {
907 int hc = 13 * sort;
908 if (sort >= ARRAY) {
909 for (int i = off, end = i + len; i < end; i++) {
910 hc = 17 * (hc + buf[i]);
911 }
912 }
913 return hc;
914 }
915
916 /**
917 * Returns a string representation of this type.
918 *
919 * @return the descriptor of this type.
920 */
921 @Override
922 public String toString() {
923 return getDescriptor();
924 }
925 }
--- EOF ---