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 int off = 1; 410 while (true) { 411 char car = buf[off++]; 412 if (car == ')') { 413 return getType(buf, off); 414 } else if (car == 'L') { 415 while (buf[off++] != ';') { 416 } 417 } 418 } 419 } 420 421 /** 422 * Returns the Java type corresponding to the return type of the given 423 * method. 424 * 425 * @param method 426 * a method. 427 * @return the Java type corresponding to the return type of the given 428 * method. 429 */ 430 public static Type getReturnType(final Method method) { 431 return getType(method.getReturnType()); 432 } 433 434 /** 435 * Computes the size of the arguments and of the return value of a method. 436 * 437 * @param desc 438 * the descriptor of a method. 439 * @return the size of the arguments of the method (plus one for the 440 * implicit this argument), argSize, and the size of its return 441 * value, retSize, packed into a single int i = 442 * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to 443 * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). 444 */ 445 public static int getArgumentsAndReturnSizes(final String desc) { 446 int n = 1; 447 int c = 1; 448 while (true) { 449 char car = desc.charAt(c++); 450 if (car == ')') { 451 car = desc.charAt(c); 452 return n << 2 453 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 454 } else if (car == 'L' || car == 'Q') { 455 while (desc.charAt(c++) != ';') { 456 } 457 n += 1; 458 } else if (car == '[') { 459 while ((car = desc.charAt(c)) == '[') { 460 ++c; 461 } 462 if (car == 'D' || car == 'J') { 463 n -= 1; 464 } 465 } else if (car == 'D' || car == 'J') { 466 n += 2; 467 } else { 468 n += 1; 469 } 470 } 471 } 472 473 /** 474 * Returns the Java type corresponding to the given type descriptor. For 475 * method descriptors, buf is supposed to contain nothing more than the 476 * descriptor itself. 477 * 478 * @param buf 479 * a buffer containing a type descriptor. 480 * @param off 481 * the offset of this descriptor in the previous buffer. 482 * @return the Java type corresponding to the given type descriptor. 483 */ 484 private static Type getType(final char[] buf, final int off) { 485 int len; 486 switch (buf[off]) { 487 case 'V': 488 return VOID_TYPE; 489 case 'Z': 490 return BOOLEAN_TYPE; 491 case 'C': 492 return CHAR_TYPE; 493 case 'B': 494 return BYTE_TYPE; 495 case 'S': 496 return SHORT_TYPE; 497 case 'I': 498 return INT_TYPE; 499 case 'F': 500 return FLOAT_TYPE; 501 case 'J': 502 return LONG_TYPE; 503 case 'D': 504 return DOUBLE_TYPE; 505 case '[': 506 len = 1; 507 while (buf[off + len] == '[') { 508 ++len; 509 } 510 if (buf[off + len] == 'L' || buf[off + len] == 'Q') { 511 ++len; 512 while (buf[off + len] != ';') { 513 ++len; 514 } 515 } 516 return new Type(ARRAY, buf, off, len + 1); 517 case 'L': 518 case 'Q': 519 len = 1; 520 while (buf[off + len] != ';') { 521 ++len; 522 } 523 return new Type(OBJECT, buf, off + 1, len - 1); 524 // case '(': 525 default: 526 return new Type(METHOD, buf, off, buf.length - off); 527 } 528 } 529 530 // ------------------------------------------------------------------------ 531 // Accessors 532 // ------------------------------------------------------------------------ 533 534 /** 535 * Returns the sort of this Java type. 536 * 537 * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, 538 * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, 539 * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, 540 * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD 541 * METHOD}. 542 */ 543 public int getSort() { 544 return sort; 545 } 546 547 /** 548 * Returns the number of dimensions of this array type. This method should 549 * only be used for an array type. 550 * 551 * @return the number of dimensions of this array type. 552 */ 553 public int getDimensions() { 554 int i = 1; 555 while (buf[off + i] == '[') { 556 ++i; 557 } 558 return i; 559 } 560 561 /** 562 * Returns the type of the elements of this array type. This method should 563 * only be used for an array type. 564 * 565 * @return Returns the type of the elements of this array type. 566 */ 567 public Type getElementType() { 568 return getType(buf, off + getDimensions()); 569 } 570 571 /** 572 * Returns the binary name of the class corresponding to this type. This 573 * method must not be used on method types. 574 * 575 * @return the binary name of the class corresponding to this type. 576 */ 577 public String getClassName() { 578 switch (sort) { 579 case VOID: 580 return "void"; 581 case BOOLEAN: 582 return "boolean"; 583 case CHAR: 584 return "char"; 585 case BYTE: 586 return "byte"; 587 case SHORT: 588 return "short"; 589 case INT: 590 return "int"; 591 case FLOAT: 592 return "float"; 593 case LONG: 594 return "long"; 595 case DOUBLE: 596 return "double"; 597 case ARRAY: 598 StringBuilder sb = new StringBuilder(getElementType().getClassName()); 599 for (int i = getDimensions(); i > 0; --i) { 600 sb.append("[]"); 601 } 602 return sb.toString(); 603 case OBJECT: 604 return new String(buf, off, len).replace('/', '.'); 605 default: 606 return null; 607 } 608 } 609 610 /** 611 * Returns the internal name of the class corresponding to this object or 612 * array type. The internal name of a class is its fully qualified name (as 613 * returned by Class.getName(), where '.' are replaced by '/'. This method 614 * should only be used for an object or array type. 615 * 616 * @return the internal name of the class corresponding to this object type. 617 */ 618 public String getInternalName() { 619 return new String(buf, off, len); 620 } 621 622 /** 623 * Returns the argument types of methods of this type. This method should 624 * only be used for method types. 625 * 626 * @return the argument types of methods of this type. 627 */ 628 public Type[] getArgumentTypes() { 629 return getArgumentTypes(getDescriptor()); 630 } 631 632 /** 633 * Returns the return type of methods of this type. This method should only 634 * be used for method types. 635 * 636 * @return the return type of methods of this type. 637 */ 638 public Type getReturnType() { 639 return getReturnType(getDescriptor()); 640 } 641 642 /** 643 * Returns the size of the arguments and of the return value of methods of 644 * this type. This method should only be used for method types. 645 * 646 * @return the size of the arguments (plus one for the implicit this 647 * argument), argSize, and the size of the return value, retSize, 648 * packed into a single 649 * int i = <tt>(argSize << 2) | retSize</tt> 650 * (argSize is therefore equal to <tt>i >> 2</tt>, 651 * and retSize to <tt>i & 0x03</tt>). 652 */ 653 public int getArgumentsAndReturnSizes() { 654 return getArgumentsAndReturnSizes(getDescriptor()); 655 } 656 657 // ------------------------------------------------------------------------ 658 // Conversion to type descriptors 659 // ------------------------------------------------------------------------ 660 661 /** 662 * Returns the descriptor corresponding to this Java type. 663 * 664 * @return the descriptor corresponding to this Java type. 665 */ 666 public String getDescriptor() { 667 StringBuilder buf = new StringBuilder(); 668 getDescriptor(buf); 669 return buf.toString(); 670 } 671 672 /** 673 * Returns the descriptor corresponding to the given argument and return 674 * types. 675 * 676 * @param returnType 677 * the return type of the method. 678 * @param argumentTypes 679 * the argument types of the method. 680 * @return the descriptor corresponding to the given argument and return 681 * types. 682 */ 683 public static String getMethodDescriptor(final Type returnType, 684 final Type... argumentTypes) { 685 StringBuilder buf = new StringBuilder(); 686 buf.append('('); 687 for (int i = 0; i < argumentTypes.length; ++i) { 688 argumentTypes[i].getDescriptor(buf); 689 } 690 buf.append(')'); 691 returnType.getDescriptor(buf); 692 return buf.toString(); 693 } 694 695 /** 696 * Appends the descriptor corresponding to this Java type to the given 697 * string buffer. 698 * 699 * @param buf 700 * the string buffer to which the descriptor must be appended. 701 */ 702 private void getDescriptor(final StringBuilder buf) { 703 if (this.buf == null) { 704 // descriptor is in byte 3 of 'off' for primitive types (buf == 705 // null) 706 buf.append((char) ((off & 0xFF000000) >>> 24)); 707 } else if (sort == OBJECT) { 708 buf.append('L'); 709 buf.append(this.buf, off, len); 710 buf.append(';'); 711 } else { // sort == ARRAY || sort == METHOD 712 buf.append(this.buf, off, len); 713 } 714 } 715 716 // ------------------------------------------------------------------------ 717 // Direct conversion from classes to type descriptors, 718 // without intermediate Type objects 719 // ------------------------------------------------------------------------ 720 721 /** 722 * Returns the internal name of the given class. The internal name of a 723 * class is its fully qualified name, as returned by Class.getName(), where 724 * '.' are replaced by '/'. 725 * 726 * @param c 727 * an object or array class. 728 * @return the internal name of the given class. 729 */ 730 public static String getInternalName(final Class<?> c) { 731 return c.getName().replace('.', '/'); 732 } 733 734 /** 735 * Returns the descriptor corresponding to the given Java type. 736 * 737 * @param c 738 * an object class, a primitive class or an array class. 739 * @return the descriptor corresponding to the given class. 740 */ 741 public static String getDescriptor(final Class<?> c) { 742 StringBuilder buf = new StringBuilder(); 743 getDescriptor(buf, c); 744 return buf.toString(); 745 } 746 747 /** 748 * Returns the descriptor corresponding to the given constructor. 749 * 750 * @param c 751 * a {@link Constructor Constructor} object. 752 * @return the descriptor of the given constructor. 753 */ 754 public static String getConstructorDescriptor(final Constructor<?> c) { 755 Class<?>[] parameters = c.getParameterTypes(); 756 StringBuilder buf = new StringBuilder(); 757 buf.append('('); 758 for (int i = 0; i < parameters.length; ++i) { 759 getDescriptor(buf, parameters[i]); 760 } 761 return buf.append(")V").toString(); 762 } 763 764 /** 765 * Returns the descriptor corresponding to the given method. 766 * 767 * @param m 768 * a {@link Method Method} object. 769 * @return the descriptor of the given method. 770 */ 771 public static String getMethodDescriptor(final Method m) { 772 Class<?>[] parameters = m.getParameterTypes(); 773 StringBuilder buf = new StringBuilder(); 774 buf.append('('); 775 for (int i = 0; i < parameters.length; ++i) { 776 getDescriptor(buf, parameters[i]); 777 } 778 buf.append(')'); 779 getDescriptor(buf, m.getReturnType()); 780 return buf.toString(); 781 } 782 783 /** 784 * Appends the descriptor of the given class to the given string buffer. 785 * 786 * @param buf 787 * the string buffer to which the descriptor must be appended. 788 * @param c 789 * the class whose descriptor must be computed. 790 */ 791 private static void getDescriptor(final StringBuilder buf, final Class<?> c) { 792 Class<?> d = c; 793 while (true) { 794 if (d.isPrimitive()) { 795 char car; 796 if (d == Integer.TYPE) { 797 car = 'I'; 798 } else if (d == Void.TYPE) { 799 car = 'V'; 800 } else if (d == Boolean.TYPE) { 801 car = 'Z'; 802 } else if (d == Byte.TYPE) { 803 car = 'B'; 804 } else if (d == Character.TYPE) { 805 car = 'C'; 806 } else if (d == Short.TYPE) { 807 car = 'S'; 808 } else if (d == Double.TYPE) { 809 car = 'D'; 810 } else if (d == Float.TYPE) { 811 car = 'F'; 812 } else /* if (d == Long.TYPE) */{ 813 car = 'J'; 814 } 815 buf.append(car); 816 return; 817 } else if (d.isArray()) { 818 buf.append('['); 819 d = d.getComponentType(); 820 } else { 821 String name = d.getName(); 822 // Workarounds nasgen build that depends on ASM but compiled with 823 // the bootstrap JDK. Can't use Class::isValue and Class::asValueType 824 int index = d.getTypeName().lastIndexOf("/val"); 825 if (index > 0) { 826 buf.append('Q'); 827 } else { 828 buf.append('L'); 829 } 830 int len = name.length(); 831 for (int i = 0; i < len; ++i) { 832 char car = name.charAt(i); 833 buf.append(car == '.' ? '/' : car); 834 } 835 buf.append(';'); 836 return; 837 } 838 } 839 } 840 841 // ------------------------------------------------------------------------ 842 // Corresponding size and opcodes 843 // ------------------------------------------------------------------------ 844 845 /** 846 * Returns the size of values of this type. This method must not be used for 847 * method types. 848 * 849 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and 850 * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. 851 */ 852 public int getSize() { 853 // the size is in byte 0 of 'off' for primitive types (buf == null) 854 return buf == null ? (off & 0xFF) : 1; 855 } 856 857 /** 858 * Returns a JVM instruction opcode adapted to this Java type. This method 859 * must not be used for method types. 860 * 861 * @param opcode 862 * a JVM instruction opcode. This opcode must be one of ILOAD, 863 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, 864 * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. 865 * @return an opcode that is similar to the given opcode, but adapted to 866 * this Java type. For example, if this type is <tt>float</tt> and 867 * <tt>opcode</tt> is IRETURN, this method returns FRETURN. 868 */ 869 public int getOpcode(final int opcode) { 870 if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { 871 // the offset for IALOAD or IASTORE is in byte 1 of 'off' for 872 // primitive types (buf == null) 873 return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); 874 } else { 875 // the offset for other instructions is in byte 2 of 'off' for 876 // primitive types (buf == null) 877 return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); 878 } 879 } 880 881 // ------------------------------------------------------------------------ 882 // Equals, hashCode and toString 883 // ------------------------------------------------------------------------ 884 885 /** 886 * Tests if the given object is equal to this type. 887 * 888 * @param o 889 * the object to be compared to this type. 890 * @return <tt>true</tt> if the given object is equal to this type. 891 */ 892 @Override 893 public boolean equals(final Object o) { 894 if (this == o) { 895 return true; 896 } 897 if (!(o instanceof Type)) { 898 return false; 899 } 900 Type t = (Type) o; 901 if (sort != t.sort) { 902 return false; 903 } 904 if (sort >= ARRAY) { 905 if (len != t.len) { 906 return false; 907 } 908 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 909 if (buf[i] != t.buf[j]) { 910 return false; 911 } 912 } 913 } 914 return true; 915 } 916 917 /** 918 * Returns a hash code value for this type. 919 * 920 * @return a hash code value for this type. 921 */ 922 @Override 923 public int hashCode() { 924 int hc = 13 * sort; 925 if (sort >= ARRAY) { 926 for (int i = off, end = i + len; i < end; i++) { 927 hc = 17 * (hc + buf[i]); 928 } 929 } 930 return hc; 931 } 932 933 /** 934 * Returns a string representation of this type. 935 * 936 * @return the descriptor of this type. 937 */ 938 @Override 939 public String toString() { 940 return getDescriptor(); 941 } 942 }