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 jdk.internal.reflect; 27 28 import java.lang.reflect.*; 29 import jdk.internal.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 if (unsafe.isValueType(c)) { 424 return internalize('Q' + c.getName() + ";"); 425 } else { 426 return internalize('L' + c.getName() + ";"); 427 } 428 } else { 429 return internalize(c.getName()); 430 } 431 } 432 } 433 434 private static String internalize(String className) { 435 return className.replace('.', '/'); 436 } 437 438 protected void emitConstructor() { 439 // Generate code into fresh code buffer 440 ClassFileAssembler cb = new ClassFileAssembler(); 441 // 0 incoming arguments 442 cb.setMaxLocals(1); 443 cb.opc_aload_0(); 444 cb.opc_invokespecial(superCtorIdx, 0, 0); 445 cb.opc_return(); 446 447 // Emit method 448 emitMethod(initIdx, cb.getMaxLocals(), cb, null, null); 449 } 450 451 // The descriptor's index in the constant pool must be (1 + 452 // nameIdx). "numArgs" must indicate ALL arguments, including the 453 // implicit "this" argument; double and long arguments each count 454 // as 2 in this count. The code buffer must NOT contain the code 455 // length. The exception table may be null, but if non-null must 456 // NOT contain the exception table's length. The checked exception 457 // indices may be null. 458 protected void emitMethod(short nameIdx, 459 int numArgs, 460 ClassFileAssembler code, 461 ClassFileAssembler exceptionTable, 462 short[] checkedExceptionIndices) 463 { 464 int codeLen = code.getLength(); 465 int excLen = 0; 466 if (exceptionTable != null) { 467 excLen = exceptionTable.getLength(); 468 if ((excLen % 8) != 0) { 469 throw new IllegalArgumentException("Illegal exception table"); 470 } 471 } 472 int attrLen = 12 + codeLen + excLen; 473 excLen = excLen / 8; // No-op if no exception table 474 475 asm.emitShort(ACC_PUBLIC); 476 asm.emitShort(nameIdx); 477 asm.emitShort(add(nameIdx, S1)); 478 if (checkedExceptionIndices == null) { 479 // Code attribute only 480 asm.emitShort(S1); 481 } else { 482 // Code and Exceptions attributes 483 asm.emitShort(S2); 484 } 485 // Code attribute 486 asm.emitShort(codeIdx); 487 asm.emitInt(attrLen); 488 asm.emitShort(code.getMaxStack()); 489 asm.emitShort((short) Math.max(numArgs, code.getMaxLocals())); 490 asm.emitInt(codeLen); 491 asm.append(code); 492 asm.emitShort((short) excLen); 493 if (exceptionTable != null) { 494 asm.append(exceptionTable); 495 } 496 asm.emitShort(S0); // No additional attributes for Code attribute 497 if (checkedExceptionIndices != null) { 498 // Exceptions attribute 499 asm.emitShort(exceptionsIdx); 500 asm.emitInt(2 + 2 * checkedExceptionIndices.length); 501 asm.emitShort((short) checkedExceptionIndices.length); 502 for (int i = 0; i < checkedExceptionIndices.length; i++) { 503 asm.emitShort(checkedExceptionIndices[i]); 504 } 505 } 506 } 507 508 protected short indexForPrimitiveType(Class<?> type) { 509 if (type == Boolean.TYPE) { 510 return booleanIdx; 511 } else if (type == Byte.TYPE) { 512 return byteIdx; 513 } else if (type == Character.TYPE) { 514 return characterIdx; 515 } else if (type == Double.TYPE) { 516 return doubleIdx; 517 } else if (type == Float.TYPE) { 518 return floatIdx; 519 } else if (type == Integer.TYPE) { 520 return integerIdx; 521 } else if (type == Long.TYPE) { 522 return longIdx; 523 } else if (type == Short.TYPE) { 524 return shortIdx; 525 } 526 throw new InternalError("Should have found primitive type"); 527 } 528 529 protected short boxingMethodForPrimitiveType(Class<?> type) { 530 if (type == Boolean.TYPE) { 531 return booleanBoxIdx; 532 } else if (type == Byte.TYPE) { 533 return byteBoxIdx; 534 } else if (type == Character.TYPE) { 535 return characterBoxIdx; 536 } else if (type == Double.TYPE) { 537 return doubleBoxIdx; 538 } else if (type == Float.TYPE) { 539 return floatBoxIdx; 540 } else if (type == Integer.TYPE) { 541 return integerBoxIdx; 542 } else if (type == Long.TYPE) { 543 return longBoxIdx; 544 } else if (type == Short.TYPE) { 545 return shortBoxIdx; 546 } 547 throw new InternalError("Should have found primitive type"); 548 } 549 550 /** Returns true for widening or identity conversions for primitive 551 types only */ 552 protected static boolean canWidenTo(Class<?> type, Class<?> otherType) { 553 if (!type.isPrimitive()) { 554 return false; 555 } 556 557 // Widening conversions (from JVM spec): 558 // byte to short, int, long, float, or double 559 // short to int, long, float, or double 560 // char to int, long, float, or double 561 // int to long, float, or double 562 // long to float or double 563 // float to double 564 565 if (type == Boolean.TYPE) { 566 if (otherType == Boolean.TYPE) { 567 return true; 568 } 569 } else if (type == Byte.TYPE) { 570 if ( otherType == Byte.TYPE 571 || otherType == Short.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 == Short.TYPE) { 579 if ( otherType == Short.TYPE 580 || otherType == Integer.TYPE 581 || otherType == Long.TYPE 582 || otherType == Float.TYPE 583 || otherType == Double.TYPE) { 584 return true; 585 } 586 } else if (type == Character.TYPE) { 587 if ( otherType == Character.TYPE 588 || otherType == Integer.TYPE 589 || otherType == Long.TYPE 590 || otherType == Float.TYPE 591 || otherType == Double.TYPE) { 592 return true; 593 } 594 } else if (type == Integer.TYPE) { 595 if ( otherType == Integer.TYPE 596 || otherType == Long.TYPE 597 || otherType == Float.TYPE 598 || otherType == Double.TYPE) { 599 return true; 600 } 601 } else if (type == Long.TYPE) { 602 if ( otherType == Long.TYPE 603 || otherType == Float.TYPE 604 || otherType == Double.TYPE) { 605 return true; 606 } 607 } else if (type == Float.TYPE) { 608 if ( otherType == Float.TYPE 609 || otherType == Double.TYPE) { 610 return true; 611 } 612 } else if (type == Double.TYPE) { 613 if (otherType == Double.TYPE) { 614 return true; 615 } 616 } 617 618 return false; 619 } 620 621 /** Emits the widening bytecode for the given primitive conversion 622 (or none if the identity conversion). Requires that a primitive 623 conversion exists; i.e., canWidenTo must have already been 624 called and returned true. */ 625 protected static void emitWideningBytecodeForPrimitiveConversion 626 (ClassFileAssembler cb, 627 Class<?> fromType, 628 Class<?> toType) 629 { 630 // Note that widening conversions for integral types (i.e., "b2s", 631 // "s2i") are no-ops since values on the Java stack are 632 // sign-extended. 633 634 // Widening conversions (from JVM spec): 635 // byte to short, int, long, float, or double 636 // short to int, long, float, or double 637 // char to int, long, float, or double 638 // int to long, float, or double 639 // long to float or double 640 // float to double 641 642 if ( fromType == Byte.TYPE 643 || fromType == Short.TYPE 644 || fromType == Character.TYPE 645 || fromType == Integer.TYPE) { 646 if (toType == Long.TYPE) { 647 cb.opc_i2l(); 648 } else if (toType == Float.TYPE) { 649 cb.opc_i2f(); 650 } else if (toType == Double.TYPE) { 651 cb.opc_i2d(); 652 } 653 } else if (fromType == Long.TYPE) { 654 if (toType == Float.TYPE) { 655 cb.opc_l2f(); 656 } else if (toType == Double.TYPE) { 657 cb.opc_l2d(); 658 } 659 } else if (fromType == Float.TYPE) { 660 if (toType == Double.TYPE) { 661 cb.opc_f2d(); 662 } 663 } 664 665 // Otherwise, was identity or no-op conversion. Fall through. 666 } 667 668 protected short unboxingMethodForPrimitiveType(Class<?> primType) { 669 if (primType == Boolean.TYPE) { 670 return booleanUnboxIdx; 671 } else if (primType == Byte.TYPE) { 672 return byteUnboxIdx; 673 } else if (primType == Character.TYPE) { 674 return characterUnboxIdx; 675 } else if (primType == Short.TYPE) { 676 return shortUnboxIdx; 677 } else if (primType == Integer.TYPE) { 678 return integerUnboxIdx; 679 } else if (primType == Long.TYPE) { 680 return longUnboxIdx; 681 } else if (primType == Float.TYPE) { 682 return floatUnboxIdx; 683 } else if (primType == Double.TYPE) { 684 return doubleUnboxIdx; 685 } 686 throw new InternalError("Illegal primitive type " + primType.getName()); 687 } 688 689 protected static final Class<?>[] primitiveTypes = new Class<?>[] { 690 Boolean.TYPE, 691 Byte.TYPE, 692 Character.TYPE, 693 Short.TYPE, 694 Integer.TYPE, 695 Long.TYPE, 696 Float.TYPE, 697 Double.TYPE 698 }; 699 700 /** We don't consider "Void" to be a primitive type */ 701 protected static boolean isPrimitive(Class<?> c) { 702 return (c.isPrimitive() && c != Void.TYPE); 703 } 704 705 protected int typeSizeInStackSlots(Class<?> c) { 706 if (c == Void.TYPE) { 707 return 0; 708 } 709 if (c == Long.TYPE || c == Double.TYPE) { 710 return 2; 711 } 712 return 1; 713 } 714 715 private ClassFileAssembler illegalArgumentCodeBuffer; 716 protected ClassFileAssembler illegalArgumentCodeBuffer() { 717 if (illegalArgumentCodeBuffer == null) { 718 illegalArgumentCodeBuffer = new ClassFileAssembler(); 719 illegalArgumentCodeBuffer.opc_new(illegalArgumentClass); 720 illegalArgumentCodeBuffer.opc_dup(); 721 illegalArgumentCodeBuffer.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); 722 illegalArgumentCodeBuffer.opc_athrow(); 723 } 724 725 return illegalArgumentCodeBuffer; 726 } 727 }