1 /* 2 * Copyright (c) 2001, 2013, 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 sun.misc.Unsafe; 30 31 /** Shared functionality for all accessor generators */ 32 33 class AccessorGenerator implements ClassFileConstants { 34 static final Unsafe unsafe = Unsafe.getUnsafe(); 35 36 // Constants because there's no way to say "short integer constant", 37 // i.e., "1S" 38 protected static final short S0 = (short) 0; 39 protected static final short S1 = (short) 1; 40 protected static final short S2 = (short) 2; 41 protected static final short S3 = (short) 3; 42 protected static final short S4 = (short) 4; 43 protected static final short S5 = (short) 5; 44 protected static final short S6 = (short) 6; 45 46 // Instance variables for shared functionality between 47 // FieldAccessorGenerator and MethodAccessorGenerator 48 protected ClassFileAssembler asm; 49 protected int modifiers; 50 protected short thisClass; 51 protected short superClass; 52 protected short targetClass; 53 // Common constant pool entries to FieldAccessor and MethodAccessor 54 protected short throwableClass; 55 protected short classCastClass; 56 protected short nullPointerClass; 57 protected short illegalArgumentClass; 58 protected short invocationTargetClass; 59 protected short initIdx; 60 protected short initNameAndTypeIdx; 61 protected short initStringNameAndTypeIdx; 62 protected short nullPointerCtorIdx; 63 protected short illegalArgumentCtorIdx; 64 protected short illegalArgumentStringCtorIdx; 65 protected short invocationTargetCtorIdx; 66 protected short superCtorIdx; 67 protected short objectClass; 68 protected short toStringIdx; 69 protected short codeIdx; 70 protected short exceptionsIdx; 71 // Boxing 72 protected short valueOfIdx; 73 protected short booleanIdx; 74 protected short booleanBoxIdx; 75 protected short booleanUnboxIdx; 76 protected short byteIdx; 77 protected short byteBoxIdx; 78 protected short byteUnboxIdx; 79 protected short characterIdx; 80 protected short characterBoxIdx; 81 protected short characterUnboxIdx; 82 protected short doubleIdx; 83 protected short doubleBoxIdx; 84 protected short doubleUnboxIdx; 85 protected short floatIdx; 86 protected short floatBoxIdx; 87 protected short floatUnboxIdx; 88 protected short integerIdx; 89 protected short integerBoxIdx; 90 protected short integerUnboxIdx; 91 protected short longIdx; 92 protected short longBoxIdx; 93 protected short longUnboxIdx; 94 protected short shortIdx; 95 protected short shortBoxIdx; 96 protected short shortUnboxIdx; 97 98 protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30; 99 protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 73; 100 101 // Requires that superClass has been set up 102 protected void emitCommonConstantPoolEntries() { 103 // + [UTF-8] "java/lang/Throwable" 104 // + [CONSTANT_Class_info] for above 105 // + [UTF-8] "java/lang/ClassCastException" 106 // + [CONSTANT_Class_info] for above 107 // + [UTF-8] "java/lang/NullPointerException" 108 // + [CONSTANT_Class_info] for above 109 // + [UTF-8] "java/lang/IllegalArgumentException" 110 // + [CONSTANT_Class_info] for above 111 // + [UTF-8] "java/lang/InvocationTargetException" 112 // + [CONSTANT_Class_info] for above 113 // + [UTF-8] "<init>" 114 // + [UTF-8] "()V" 115 // + [CONSTANT_NameAndType_info] for above 116 // + [CONSTANT_Methodref_info] for NullPointerException's constructor 117 // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor 118 // + [UTF-8] "(Ljava/lang/String;)V" 119 // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V" 120 // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String 121 // + [UTF-8] "(Ljava/lang/Throwable;)V" 122 // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V" 123 // + [CONSTANT_Methodref_info] for InvocationTargetException's constructor 124 // + [CONSTANT_Methodref_info] for "super()" 125 // + [UTF-8] "java/lang/Object" 126 // + [CONSTANT_Class_info] for above 127 // + [UTF-8] "toString" 128 // + [UTF-8] "()Ljava/lang/String;" 129 // + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;" 130 // + [CONSTANT_Methodref_info] for Object's toString method 131 // + [UTF-8] "Code" 132 // + [UTF-8] "Exceptions" 133 asm.emitConstantPoolUTF8("java/lang/Throwable"); 134 asm.emitConstantPoolClass(asm.cpi()); 135 throwableClass = asm.cpi(); 136 asm.emitConstantPoolUTF8("java/lang/ClassCastException"); 137 asm.emitConstantPoolClass(asm.cpi()); 138 classCastClass = asm.cpi(); 139 asm.emitConstantPoolUTF8("java/lang/NullPointerException"); 140 asm.emitConstantPoolClass(asm.cpi()); 141 nullPointerClass = asm.cpi(); 142 asm.emitConstantPoolUTF8("java/lang/IllegalArgumentException"); 143 asm.emitConstantPoolClass(asm.cpi()); 144 illegalArgumentClass = asm.cpi(); 145 asm.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, initNameAndTypeIdx); 154 nullPointerCtorIdx = asm.cpi(); 155 asm.emitConstantPoolMethodref(illegalArgumentClass, initNameAndTypeIdx); 156 illegalArgumentCtorIdx = asm.cpi(); 157 asm.emitConstantPoolUTF8("(Ljava/lang/String;)V"); 158 asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); 159 initStringNameAndTypeIdx = asm.cpi(); 160 asm.emitConstantPoolMethodref(illegalArgumentClass, initStringNameAndTypeIdx); 161 illegalArgumentStringCtorIdx = asm.cpi(); 162 asm.emitConstantPoolUTF8("(Ljava/lang/Throwable;)V"); 163 asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); 164 asm.emitConstantPoolMethodref(invocationTargetClass, asm.cpi()); 165 invocationTargetCtorIdx = asm.cpi(); 166 asm.emitConstantPoolMethodref(superClass, initNameAndTypeIdx); 167 superCtorIdx = asm.cpi(); 168 asm.emitConstantPoolUTF8("java/lang/Object"); 169 asm.emitConstantPoolClass(asm.cpi()); 170 objectClass = asm.cpi(); 171 asm.emitConstantPoolUTF8("toString"); 172 asm.emitConstantPoolUTF8("()Ljava/lang/String;"); 173 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 174 asm.emitConstantPoolMethodref(objectClass, asm.cpi()); 175 toStringIdx = asm.cpi(); 176 asm.emitConstantPoolUTF8("Code"); 177 codeIdx = asm.cpi(); 178 asm.emitConstantPoolUTF8("Exceptions"); 179 exceptionsIdx = asm.cpi(); 180 } 181 182 /** Constant pool entries required to be able to box/unbox primitive 183 types. Note that we don't emit these if we don't need them. */ 184 protected void emitBoxingContantPoolEntries() { 185 // * [UTF-8] "valueOf" 186 // * [UTF-8] "java/lang/Boolean" 187 // * [CONSTANT_Class_info] for above 188 // * [UTF-8] "(Z)Ljava/lang/Boolean;" 189 // * [CONSTANT_NameAndType_info] for above 190 // * [CONSTANT_Methodref_info] for above 191 // * [UTF-8] "booleanValue" 192 // * [UTF-8] "()Z" 193 // * [CONSTANT_NameAndType_info] for above 194 // * [CONSTANT_Methodref_info] for above 195 // * [UTF-8] "java/lang/Byte" 196 // * [CONSTANT_Class_info] for above 197 // * [UTF-8] "(B)Ljava/lang/Byte;" 198 // * [CONSTANT_NameAndType_info] for above 199 // * [CONSTANT_Methodref_info] for above 200 // * [UTF-8] "byteValue" 201 // * [UTF-8] "()B" 202 // * [CONSTANT_NameAndType_info] for above 203 // * [CONSTANT_Methodref_info] for above 204 // * [UTF-8] "java/lang/Character" 205 // * [CONSTANT_Class_info] for above 206 // * [UTF-8] "(C)Ljava/lang/Character;" 207 // * [CONSTANT_NameAndType_info] for above 208 // * [CONSTANT_Methodref_info] for above 209 // * [UTF-8] "charValue" 210 // * [UTF-8] "()C" 211 // * [CONSTANT_NameAndType_info] for above 212 // * [CONSTANT_Methodref_info] for above 213 // * [UTF-8] "java/lang/Double" 214 // * [CONSTANT_Class_info] for above 215 // * [UTF-8] "(D)Ljava/lang/Double;" 216 // * [CONSTANT_NameAndType_info] for above 217 // * [CONSTANT_Methodref_info] for above 218 // * [UTF-8] "doubleValue" 219 // * [UTF-8] "()D" 220 // * [CONSTANT_NameAndType_info] for above 221 // * [CONSTANT_Methodref_info] for above 222 // * [UTF-8] "java/lang/Float" 223 // * [CONSTANT_Class_info] for above 224 // * [UTF-8] "(F)Ljava/lang/Float;" 225 // * [CONSTANT_NameAndType_info] for above 226 // * [CONSTANT_Methodref_info] for above 227 // * [UTF-8] "floatValue" 228 // * [UTF-8] "()F" 229 // * [CONSTANT_NameAndType_info] for above 230 // * [CONSTANT_Methodref_info] for above 231 // * [UTF-8] "java/lang/Integer" 232 // * [CONSTANT_Class_info] for above 233 // * [UTF-8] "(I)Ljava/lang/Integer;" 234 // * [CONSTANT_NameAndType_info] for above 235 // * [CONSTANT_Methodref_info] for above 236 // * [UTF-8] "intValue" 237 // * [UTF-8] "()I" 238 // * [CONSTANT_NameAndType_info] for above 239 // * [CONSTANT_Methodref_info] for above 240 // * [UTF-8] "java/lang/Long" 241 // * [CONSTANT_Class_info] for above 242 // * [UTF-8] "(J)Ljava/lang/Long;" 243 // * [CONSTANT_NameAndType_info] for above 244 // * [CONSTANT_Methodref_info] for above 245 // * [UTF-8] "longValue" 246 // * [UTF-8] "()J" 247 // * [CONSTANT_NameAndType_info] for above 248 // * [CONSTANT_Methodref_info] for above 249 // * [UTF-8] "java/lang/Short" 250 // * [CONSTANT_Class_info] for above 251 // * [UTF-8] "(S)Ljava/lang/Short;" 252 // * [CONSTANT_NameAndType_info] for above 253 // * [CONSTANT_Methodref_info] for above 254 // * [UTF-8] "shortValue" 255 // * [UTF-8] "()S" 256 // * [CONSTANT_NameAndType_info] for above 257 // * [CONSTANT_Methodref_info] for above 258 259 // valueOf-method name 260 asm.emitConstantPoolUTF8("valueOf"); 261 valueOfIdx = asm.cpi(); 262 263 // Boolean 264 asm.emitConstantPoolUTF8("java/lang/Boolean"); 265 asm.emitConstantPoolClass(asm.cpi()); 266 booleanIdx = asm.cpi(); 267 asm.emitConstantPoolUTF8("(Z)Ljava/lang/Boolean;"); 268 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 269 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 270 booleanBoxIdx = asm.cpi(); 271 asm.emitConstantPoolUTF8("booleanValue"); 272 asm.emitConstantPoolUTF8("()Z"); 273 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 274 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 275 booleanUnboxIdx = asm.cpi(); 276 277 // Byte 278 asm.emitConstantPoolUTF8("java/lang/Byte"); 279 asm.emitConstantPoolClass(asm.cpi()); 280 byteIdx = asm.cpi(); 281 asm.emitConstantPoolUTF8("(B)Ljava/lang/Byte;"); 282 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 283 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 284 byteBoxIdx = asm.cpi(); 285 asm.emitConstantPoolUTF8("byteValue"); 286 asm.emitConstantPoolUTF8("()B"); 287 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 288 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 289 byteUnboxIdx = asm.cpi(); 290 291 // Character 292 asm.emitConstantPoolUTF8("java/lang/Character"); 293 asm.emitConstantPoolClass(asm.cpi()); 294 characterIdx = asm.cpi(); 295 asm.emitConstantPoolUTF8("(C)Ljava/lang/Character;"); 296 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 297 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 298 characterBoxIdx = asm.cpi(); 299 asm.emitConstantPoolUTF8("charValue"); 300 asm.emitConstantPoolUTF8("()C"); 301 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 302 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 303 characterUnboxIdx = asm.cpi(); 304 305 // Double 306 asm.emitConstantPoolUTF8("java/lang/Double"); 307 asm.emitConstantPoolClass(asm.cpi()); 308 doubleIdx = asm.cpi(); 309 asm.emitConstantPoolUTF8("(D)Ljava/lang/Double;"); 310 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 311 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 312 doubleBoxIdx = asm.cpi(); 313 asm.emitConstantPoolUTF8("doubleValue"); 314 asm.emitConstantPoolUTF8("()D"); 315 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 316 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 317 doubleUnboxIdx = asm.cpi(); 318 319 // Float 320 asm.emitConstantPoolUTF8("java/lang/Float"); 321 asm.emitConstantPoolClass(asm.cpi()); 322 floatIdx = asm.cpi(); 323 asm.emitConstantPoolUTF8("(F)Ljava/lang/Float;"); 324 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 325 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 326 floatBoxIdx = asm.cpi(); 327 asm.emitConstantPoolUTF8("floatValue"); 328 asm.emitConstantPoolUTF8("()F"); 329 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 330 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 331 floatUnboxIdx = asm.cpi(); 332 333 // Integer 334 asm.emitConstantPoolUTF8("java/lang/Integer"); 335 asm.emitConstantPoolClass(asm.cpi()); 336 integerIdx = asm.cpi(); 337 asm.emitConstantPoolUTF8("(I)Ljava/lang/Integer;"); 338 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 339 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 340 integerBoxIdx = asm.cpi(); 341 asm.emitConstantPoolUTF8("intValue"); 342 asm.emitConstantPoolUTF8("()I"); 343 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 344 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 345 integerUnboxIdx = asm.cpi(); 346 347 // Long 348 asm.emitConstantPoolUTF8("java/lang/Long"); 349 asm.emitConstantPoolClass(asm.cpi()); 350 longIdx = asm.cpi(); 351 asm.emitConstantPoolUTF8("(J)Ljava/lang/Long;"); 352 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 353 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 354 longBoxIdx = asm.cpi(); 355 asm.emitConstantPoolUTF8("longValue"); 356 asm.emitConstantPoolUTF8("()J"); 357 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 358 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 359 longUnboxIdx = asm.cpi(); 360 361 // Short 362 asm.emitConstantPoolUTF8("java/lang/Short"); 363 asm.emitConstantPoolClass(asm.cpi()); 364 shortIdx = asm.cpi(); 365 asm.emitConstantPoolUTF8("(S)Ljava/lang/Short;"); 366 asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); 367 asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); 368 shortBoxIdx = asm.cpi(); 369 asm.emitConstantPoolUTF8("shortValue"); 370 asm.emitConstantPoolUTF8("()S"); 371 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 372 asm.emitConstantPoolMethodref(sub(asm.cpi(), S6), asm.cpi()); 373 shortUnboxIdx = asm.cpi(); 374 } 375 376 // Necessary because of Java's annoying promotion rules 377 protected static short add(short s1, short s2) { 378 return (short) (s1 + s2); 379 } 380 381 protected static short sub(short s1, short s2) { 382 return (short) (s1 - s2); 383 } 384 385 protected boolean isStatic() { 386 return Modifier.isStatic(modifiers); 387 } 388 389 protected boolean isPrivate() { 390 return Modifier.isPrivate(modifiers); 391 } 392 393 /** Returns class name in "internal" form (i.e., '/' separators 394 instead of '.') */ 395 protected static String getClassName 396 (Class<?> c, boolean addPrefixAndSuffixForNonPrimitiveTypes) 397 { 398 if (c.isPrimitive()) { 399 if (c == Boolean.TYPE) { 400 return "Z"; 401 } else if (c == Byte.TYPE) { 402 return "B"; 403 } else if (c == Character.TYPE) { 404 return "C"; 405 } else if (c == Double.TYPE) { 406 return "D"; 407 } else if (c == Float.TYPE) { 408 return "F"; 409 } else if (c == Integer.TYPE) { 410 return "I"; 411 } else if (c == Long.TYPE) { 412 return "J"; 413 } else if (c == Short.TYPE) { 414 return "S"; 415 } else if (c == Void.TYPE) { 416 return "V"; 417 } 418 throw new InternalError("Should have found primitive type"); 419 } else if (c.isArray()) { 420 return "[" + getClassName(c.getComponentType(), true); 421 } else { 422 if (addPrefixAndSuffixForNonPrimitiveTypes) { 423 return internalize("L" + c.getName() + ";"); 424 } else { 425 return internalize(c.getName()); 426 } 427 } 428 } 429 430 private static String internalize(String className) { 431 return className.replace('.', '/'); 432 } 433 434 protected void emitConstructor() { 435 // Generate code into fresh code buffer 436 ClassFileAssembler cb = new ClassFileAssembler(); 437 // 0 incoming arguments 438 cb.setMaxLocals(1); 439 cb.opc_aload_0(); 440 cb.opc_invokespecial(superCtorIdx, 0, 0); 441 cb.opc_return(); 442 443 // Emit method 444 emitMethod(initIdx, cb.getMaxLocals(), cb, null, null); 445 } 446 447 // The descriptor's index in the constant pool must be (1 + 448 // nameIdx). "numArgs" must indicate ALL arguments, including the 449 // implicit "this" argument; double and long arguments each count 450 // as 2 in this count. The code buffer must NOT contain the code 451 // length. The exception table may be null, but if non-null must 452 // NOT contain the exception table's length. The checked exception 453 // indices may be null. 454 protected void emitMethod(short nameIdx, 455 int numArgs, 456 ClassFileAssembler code, 457 ClassFileAssembler exceptionTable, 458 short[] checkedExceptionIndices) 459 { 460 int codeLen = code.getLength(); 461 int excLen = 0; 462 if (exceptionTable != null) { 463 excLen = exceptionTable.getLength(); 464 if ((excLen % 8) != 0) { 465 throw new IllegalArgumentException("Illegal exception table"); 466 } 467 } 468 int attrLen = 12 + codeLen + excLen; 469 excLen = excLen / 8; // No-op if no exception table 470 471 asm.emitShort(ACC_PUBLIC); 472 asm.emitShort(nameIdx); 473 asm.emitShort(add(nameIdx, S1)); 474 if (checkedExceptionIndices == null) { 475 // Code attribute only 476 asm.emitShort(S1); 477 } else { 478 // Code and Exceptions attributes 479 asm.emitShort(S2); 480 } 481 // Code attribute 482 asm.emitShort(codeIdx); 483 asm.emitInt(attrLen); 484 asm.emitShort(code.getMaxStack()); 485 asm.emitShort((short) Math.max(numArgs, code.getMaxLocals())); 486 asm.emitInt(codeLen); 487 asm.append(code); 488 asm.emitShort((short) excLen); 489 if (exceptionTable != null) { 490 asm.append(exceptionTable); 491 } 492 asm.emitShort(S0); // No additional attributes for Code attribute 493 if (checkedExceptionIndices != null) { 494 // Exceptions attribute 495 asm.emitShort(exceptionsIdx); 496 asm.emitInt(2 + 2 * checkedExceptionIndices.length); 497 asm.emitShort((short) checkedExceptionIndices.length); 498 for (int i = 0; i < checkedExceptionIndices.length; i++) { 499 asm.emitShort(checkedExceptionIndices[i]); 500 } 501 } 502 } 503 504 protected short indexForPrimitiveType(Class<?> type) { 505 if (type == Boolean.TYPE) { 506 return booleanIdx; 507 } else if (type == Byte.TYPE) { 508 return byteIdx; 509 } else if (type == Character.TYPE) { 510 return characterIdx; 511 } else if (type == Double.TYPE) { 512 return doubleIdx; 513 } else if (type == Float.TYPE) { 514 return floatIdx; 515 } else if (type == Integer.TYPE) { 516 return integerIdx; 517 } else if (type == Long.TYPE) { 518 return longIdx; 519 } else if (type == Short.TYPE) { 520 return shortIdx; 521 } 522 throw new InternalError("Should have found primitive type"); 523 } 524 525 protected short boxingMethodForPrimitiveType(Class<?> type) { 526 if (type == Boolean.TYPE) { 527 return booleanBoxIdx; 528 } else if (type == Byte.TYPE) { 529 return byteBoxIdx; 530 } else if (type == Character.TYPE) { 531 return characterBoxIdx; 532 } else if (type == Double.TYPE) { 533 return doubleBoxIdx; 534 } else if (type == Float.TYPE) { 535 return floatBoxIdx; 536 } else if (type == Integer.TYPE) { 537 return integerBoxIdx; 538 } else if (type == Long.TYPE) { 539 return longBoxIdx; 540 } else if (type == Short.TYPE) { 541 return shortBoxIdx; 542 } 543 throw new InternalError("Should have found primitive type"); 544 } 545 546 /** Returns true for widening or identity conversions for primitive 547 types only */ 548 protected static boolean canWidenTo(Class<?> type, Class<?> otherType) { 549 if (!type.isPrimitive()) { 550 return false; 551 } 552 553 // Widening conversions (from JVM spec): 554 // byte to short, int, long, float, or double 555 // short to int, long, float, or double 556 // char to int, long, float, or double 557 // int to long, float, or double 558 // long to float or double 559 // float to double 560 561 if (type == Boolean.TYPE) { 562 if (otherType == Boolean.TYPE) { 563 return true; 564 } 565 } else if (type == Byte.TYPE) { 566 if ( otherType == Byte.TYPE 567 || otherType == Short.TYPE 568 || otherType == Integer.TYPE 569 || otherType == Long.TYPE 570 || otherType == Float.TYPE 571 || otherType == Double.TYPE) { 572 return true; 573 } 574 } else if (type == Short.TYPE) { 575 if ( otherType == Short.TYPE 576 || otherType == Integer.TYPE 577 || otherType == Long.TYPE 578 || otherType == Float.TYPE 579 || otherType == Double.TYPE) { 580 return true; 581 } 582 } else if (type == Character.TYPE) { 583 if ( otherType == Character.TYPE 584 || otherType == Integer.TYPE 585 || otherType == Long.TYPE 586 || otherType == Float.TYPE 587 || otherType == Double.TYPE) { 588 return true; 589 } 590 } else if (type == Integer.TYPE) { 591 if ( otherType == Integer.TYPE 592 || otherType == Long.TYPE 593 || otherType == Float.TYPE 594 || otherType == Double.TYPE) { 595 return true; 596 } 597 } else if (type == Long.TYPE) { 598 if ( otherType == Long.TYPE 599 || otherType == Float.TYPE 600 || otherType == Double.TYPE) { 601 return true; 602 } 603 } else if (type == Float.TYPE) { 604 if ( otherType == Float.TYPE 605 || otherType == Double.TYPE) { 606 return true; 607 } 608 } else if (type == Double.TYPE) { 609 if (otherType == Double.TYPE) { 610 return true; 611 } 612 } 613 614 return false; 615 } 616 617 /** Emits the widening bytecode for the given primitive conversion 618 (or none if the identity conversion). Requires that a primitive 619 conversion exists; i.e., canWidenTo must have already been 620 called and returned true. */ 621 protected static void emitWideningBytecodeForPrimitiveConversion 622 (ClassFileAssembler cb, 623 Class<?> fromType, 624 Class<?> toType) 625 { 626 // Note that widening conversions for integral types (i.e., "b2s", 627 // "s2i") are no-ops since values on the Java stack are 628 // sign-extended. 629 630 // Widening conversions (from JVM spec): 631 // byte to short, int, long, float, or double 632 // short to int, long, float, or double 633 // char to int, long, float, or double 634 // int to long, float, or double 635 // long to float or double 636 // float to double 637 638 if ( fromType == Byte.TYPE 639 || fromType == Short.TYPE 640 || fromType == Character.TYPE 641 || fromType == Integer.TYPE) { 642 if (toType == Long.TYPE) { 643 cb.opc_i2l(); 644 } else if (toType == Float.TYPE) { 645 cb.opc_i2f(); 646 } else if (toType == Double.TYPE) { 647 cb.opc_i2d(); 648 } 649 } else if (fromType == Long.TYPE) { 650 if (toType == Float.TYPE) { 651 cb.opc_l2f(); 652 } else if (toType == Double.TYPE) { 653 cb.opc_l2d(); 654 } 655 } else if (fromType == Float.TYPE) { 656 if (toType == Double.TYPE) { 657 cb.opc_f2d(); 658 } 659 } 660 661 // Otherwise, was identity or no-op conversion. Fall through. 662 } 663 664 protected short unboxingMethodForPrimitiveType(Class<?> primType) { 665 if (primType == Boolean.TYPE) { 666 return booleanUnboxIdx; 667 } else if (primType == Byte.TYPE) { 668 return byteUnboxIdx; 669 } else if (primType == Character.TYPE) { 670 return characterUnboxIdx; 671 } else if (primType == Short.TYPE) { 672 return shortUnboxIdx; 673 } else if (primType == Integer.TYPE) { 674 return integerUnboxIdx; 675 } else if (primType == Long.TYPE) { 676 return longUnboxIdx; 677 } else if (primType == Float.TYPE) { 678 return floatUnboxIdx; 679 } else if (primType == Double.TYPE) { 680 return doubleUnboxIdx; 681 } 682 throw new InternalError("Illegal primitive type " + primType.getName()); 683 } 684 685 protected static final Class<?>[] primitiveTypes = new Class<?>[] { 686 Boolean.TYPE, 687 Byte.TYPE, 688 Character.TYPE, 689 Short.TYPE, 690 Integer.TYPE, 691 Long.TYPE, 692 Float.TYPE, 693 Double.TYPE 694 }; 695 696 /** We don't consider "Void" to be a primitive type */ 697 protected static boolean isPrimitive(Class<?> c) { 698 return (c.isPrimitive() && c != Void.TYPE); 699 } 700 701 protected int typeSizeInStackSlots(Class<?> c) { 702 if (c == Void.TYPE) { 703 return 0; 704 } 705 if (c == Long.TYPE || c == Double.TYPE) { 706 return 2; 707 } 708 return 1; 709 } 710 711 private ClassFileAssembler illegalArgumentCodeBuffer; 712 protected ClassFileAssembler illegalArgumentCodeBuffer() { 713 if (illegalArgumentCodeBuffer == null) { 714 illegalArgumentCodeBuffer = new ClassFileAssembler(); 715 illegalArgumentCodeBuffer.opc_new(illegalArgumentClass); 716 illegalArgumentCodeBuffer.opc_dup(); 717 illegalArgumentCodeBuffer.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); 718 illegalArgumentCodeBuffer.opc_athrow(); 719 } 720 721 return illegalArgumentCodeBuffer; 722 } 723 }