1 /* 2 * Copyright (c) 2011, 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.internal.jvmci.hotspot; 24 25 import static jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*; 26 import static jdk.internal.jvmci.hotspot.UnsafeAccess.UNSAFE; 27 28 import java.lang.invoke.*; 29 30 import jdk.internal.jvmci.common.*; 31 import jdk.internal.jvmci.meta.*; 32 33 /** 34 * Implementation of {@link ConstantPool} for HotSpot. 35 */ 36 public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, MetaspaceWrapperObject { 37 38 /** 39 * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}. 40 */ 41 public static class Bytecodes { 42 public static final int LDC = 18; // 0x12 43 public static final int LDC_W = 19; // 0x13 44 public static final int LDC2_W = 20; // 0x14 45 public static final int GETSTATIC = 178; // 0xB2 46 public static final int PUTSTATIC = 179; // 0xB3 47 public static final int GETFIELD = 180; // 0xB4 48 public static final int PUTFIELD = 181; // 0xB5 49 public static final int INVOKEVIRTUAL = 182; // 0xB6 50 public static final int INVOKESPECIAL = 183; // 0xB7 51 public static final int INVOKESTATIC = 184; // 0xB8 52 public static final int INVOKEINTERFACE = 185; // 0xB9 53 public static final int INVOKEDYNAMIC = 186; // 0xBA 54 public static final int NEW = 187; // 0xBB 55 public static final int NEWARRAY = 188; // 0xBC 56 public static final int ANEWARRAY = 189; // 0xBD 57 public static final int CHECKCAST = 192; // 0xC0 58 public static final int INSTANCEOF = 193; // 0xC1 59 public static final int MULTIANEWARRAY = 197; // 0xC5 60 61 static boolean isInvoke(int opcode) { 62 switch (opcode) { 63 case INVOKEVIRTUAL: 64 case INVOKESPECIAL: 65 case INVOKESTATIC: 66 case INVOKEINTERFACE: 67 case INVOKEDYNAMIC: 68 return true; 69 default: 70 return false; 71 } 72 } 73 74 /** 75 * See: {@code Rewriter::maybe_rewrite_invokehandle}. 76 */ 77 static boolean isInvokeHandleAlias(int opcode) { 78 switch (opcode) { 79 case INVOKEVIRTUAL: 80 case INVOKESPECIAL: 81 return true; 82 default: 83 return false; 84 } 85 } 86 } 87 88 /** 89 * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and 90 * internal ones. 91 */ 92 private enum JVM_CONSTANT { 93 // @formatter:off 94 Utf8(config().jvmConstantUtf8), 95 Integer(config().jvmConstantInteger), 96 Long(config().jvmConstantLong), 97 Float(config().jvmConstantFloat), 98 Double(config().jvmConstantDouble), 99 Class(config().jvmConstantClass), 100 UnresolvedClass(config().jvmConstantUnresolvedClass), 101 UnresolvedClassInError(config().jvmConstantUnresolvedClassInError), 102 String(config().jvmConstantString), 103 Fieldref(config().jvmConstantFieldref), 104 MethodRef(config().jvmConstantMethodref), 105 InterfaceMethodref(config().jvmConstantInterfaceMethodref), 106 NameAndType(config().jvmConstantNameAndType), 107 MethodHandle(config().jvmConstantMethodHandle), 108 MethodHandleInError(config().jvmConstantMethodHandleInError), 109 MethodType(config().jvmConstantMethodType), 110 MethodTypeInError(config().jvmConstantMethodTypeInError), 111 InvokeDynamic(config().jvmConstantInvokeDynamic); 112 // @formatter:on 113 114 private final int tag; 115 116 private static final int ExternalMax = config().jvmConstantExternalMax; 117 private static final int InternalMin = config().jvmConstantInternalMin; 118 private static final int InternalMax = config().jvmConstantInternalMax; 119 120 private JVM_CONSTANT(int tag) { 121 this.tag = tag; 122 } 123 124 private static HotSpotVMConfig config() { 125 return runtime().getConfig(); 126 } 127 128 /** 129 * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy 130 * initialization. 131 */ 132 static class TagValueMap { 133 private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1]; 134 135 static { 136 assert InternalMin > ExternalMax; 137 for (JVM_CONSTANT e : values()) { 138 table[indexOf(e.tag)] = e; 139 } 140 } 141 142 private static int indexOf(int tag) { 143 if (tag >= InternalMin) { 144 return tag - InternalMin + ExternalMax + 1; 145 } else { 146 assert tag <= ExternalMax; 147 } 148 return tag; 149 } 150 151 static JVM_CONSTANT get(int tag) { 152 JVM_CONSTANT res = table[indexOf(tag)]; 153 if (res != null) { 154 return res; 155 } 156 throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag); 157 } 158 } 159 160 public static JVM_CONSTANT getEnum(int tag) { 161 return TagValueMap.get(tag); 162 } 163 } 164 165 private static class LookupTypeCacheElement { 166 int lastCpi = Integer.MIN_VALUE; 167 JavaType javaType; 168 169 public LookupTypeCacheElement(int lastCpi, JavaType javaType) { 170 super(); 171 this.lastCpi = lastCpi; 172 this.javaType = javaType; 173 } 174 } 175 176 /** 177 * Reference to the C++ ConstantPool object. 178 */ 179 private final long metaspaceConstantPool; 180 private volatile LookupTypeCacheElement lastLookupType; 181 182 /** 183 * Gets the JVMCI mirror from a HotSpot constant pool.The VM is responsible for ensuring that 184 * the ConstantPool is kept alive for the duration of this call and the 185 * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that. 186 * 187 * Called from the VM. 188 * 189 * @param metaspaceConstantPool a metaspace ConstantPool object 190 * @return the {@link HotSpotConstantPool} corresponding to {@code metaspaceConstantPool} 191 */ 192 @SuppressWarnings("unused") 193 private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) { 194 return new HotSpotConstantPool(metaspaceConstantPool); 195 } 196 197 private HotSpotConstantPool(long metaspaceConstantPool) { 198 this.metaspaceConstantPool = metaspaceConstantPool; 199 } 200 201 /** 202 * Gets the holder for this constant pool as {@link HotSpotResolvedObjectTypeImpl}. 203 * 204 * @return holder for this constant pool 205 */ 206 private HotSpotResolvedObjectType getHolder() { 207 return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().constantPoolHolderOffset, false); 208 } 209 210 /** 211 * Converts a raw index from the bytecodes to a constant pool index by adding a 212 * {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}. 213 * 214 * @param rawIndex index from the bytecode 215 * @param opcode bytecode to convert the index for 216 * @return constant pool index 217 */ 218 private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) { 219 int index; 220 if (opcode == Bytecodes.INVOKEDYNAMIC) { 221 index = rawIndex; 222 // See: ConstantPool::is_invokedynamic_index 223 assert index < 0 : "not an invokedynamic constant pool index " + index; 224 } else { 225 assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE || 226 opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode; 227 index = rawIndex + runtime().getConfig().constantPoolCpCacheIndexTag; 228 } 229 return index; 230 } 231 232 /** 233 * Decode a constant pool cache index to a constant pool index. 234 * 235 * See {@code ConstantPool::decode_cpcache_index}. 236 * 237 * @param index constant pool cache index 238 * @return decoded index 239 */ 240 private static int decodeConstantPoolCacheIndex(int index) { 241 if (isInvokedynamicIndex(index)) { 242 return decodeInvokedynamicIndex(index); 243 } else { 244 return index - runtime().getConfig().constantPoolCpCacheIndexTag; 245 } 246 } 247 248 /** 249 * See {@code ConstantPool::is_invokedynamic_index}. 250 */ 251 private static boolean isInvokedynamicIndex(int index) { 252 return index < 0; 253 } 254 255 /** 256 * See {@code ConstantPool::decode_invokedynamic_index}. 257 */ 258 private static int decodeInvokedynamicIndex(int i) { 259 assert isInvokedynamicIndex(i) : i; 260 return ~i; 261 } 262 263 public long getMetaspaceConstantPool() { 264 return metaspaceConstantPool; 265 } 266 267 public long getMetaspacePointer() { 268 return getMetaspaceConstantPool(); 269 } 270 271 /** 272 * Gets the constant pool tag at index {@code index}. 273 * 274 * @param index constant pool index 275 * @return constant pool tag 276 */ 277 private JVM_CONSTANT getTagAt(int index) { 278 assertBounds(index); 279 HotSpotVMConfig config = runtime().getConfig(); 280 final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset); 281 final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index); 282 if (tag == 0) { 283 return null; 284 } 285 return JVM_CONSTANT.getEnum(tag); 286 } 287 288 /** 289 * Gets the constant pool entry at index {@code index}. 290 * 291 * @param index constant pool index 292 * @return constant pool entry 293 */ 294 private long getEntryAt(int index) { 295 assertBounds(index); 296 return UNSAFE.getAddress(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 297 } 298 299 /** 300 * Gets the integer constant pool entry at index {@code index}. 301 * 302 * @param index constant pool index 303 * @return integer constant pool entry at index 304 */ 305 private int getIntAt(int index) { 306 assertTag(index, JVM_CONSTANT.Integer); 307 return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 308 } 309 310 /** 311 * Gets the long constant pool entry at index {@code index}. 312 * 313 * @param index constant pool index 314 * @return long constant pool entry 315 */ 316 private long getLongAt(int index) { 317 assertTag(index, JVM_CONSTANT.Long); 318 return UNSAFE.getLong(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 319 } 320 321 /** 322 * Gets the float constant pool entry at index {@code index}. 323 * 324 * @param index constant pool index 325 * @return float constant pool entry 326 */ 327 private float getFloatAt(int index) { 328 assertTag(index, JVM_CONSTANT.Float); 329 return UNSAFE.getFloat(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 330 } 331 332 /** 333 * Gets the double constant pool entry at index {@code index}. 334 * 335 * @param index constant pool index 336 * @return float constant pool entry 337 */ 338 private double getDoubleAt(int index) { 339 assertTag(index, JVM_CONSTANT.Double); 340 return UNSAFE.getDouble(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 341 } 342 343 /** 344 * Gets the {@code JVM_CONSTANT_NameAndType} constant pool entry at index {@code index}. 345 * 346 * @param index constant pool index 347 * @return {@code JVM_CONSTANT_NameAndType} constant pool entry 348 */ 349 private int getNameAndTypeAt(int index) { 350 assertTag(index, JVM_CONSTANT.NameAndType); 351 return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 352 } 353 354 /** 355 * Gets the {@code JVM_CONSTANT_NameAndType} reference index constant pool entry at index 356 * {@code index}. 357 * 358 * @param index constant pool index 359 * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry 360 */ 361 private int getNameAndTypeRefIndexAt(int index) { 362 return runtime().getCompilerToVM().lookupNameAndTypeRefIndexInPool(this, index); 363 } 364 365 /** 366 * Gets the name of a {@code JVM_CONSTANT_NameAndType} constant pool entry at index 367 * {@code index}. 368 * 369 * @param index constant pool index 370 * @return name as {@link String} 371 */ 372 private String getNameRefAt(int index) { 373 return runtime().getCompilerToVM().lookupNameRefInPool(this, index); 374 } 375 376 /** 377 * Gets the name reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry at 378 * index {@code index}. 379 * 380 * @param index constant pool index 381 * @return name reference index 382 */ 383 private int getNameRefIndexAt(int index) { 384 final int refIndex = getNameAndTypeAt(index); 385 // name ref index is in the low 16-bits. 386 return refIndex & 0xFFFF; 387 } 388 389 /** 390 * Gets the signature of a {@code JVM_CONSTANT_NameAndType} constant pool entry at index 391 * {@code index}. 392 * 393 * @param index constant pool index 394 * @return signature as {@link String} 395 */ 396 private String getSignatureRefAt(int index) { 397 return runtime().getCompilerToVM().lookupSignatureRefInPool(this, index); 398 } 399 400 /** 401 * Gets the signature reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry 402 * at index {@code index}. 403 * 404 * @param index constant pool index 405 * @return signature reference index 406 */ 407 private int getSignatureRefIndexAt(int index) { 408 final int refIndex = getNameAndTypeAt(index); 409 // signature ref index is in the high 16-bits. 410 return refIndex >>> 16; 411 } 412 413 /** 414 * Gets the klass reference index constant pool entry at index {@code index}. 415 * 416 * @param index constant pool index 417 * @return klass reference index 418 */ 419 private int getKlassRefIndexAt(int index) { 420 return runtime().getCompilerToVM().lookupKlassRefIndexInPool(this, index); 421 } 422 423 /** 424 * Gets the uncached klass reference index constant pool entry at index {@code index}. See: 425 * {@code ConstantPool::uncached_klass_ref_index_at}. 426 * 427 * @param index constant pool index 428 * @return klass reference index 429 */ 430 private int getUncachedKlassRefIndexAt(int index, JVM_CONSTANT tag) { 431 int resultIndex; 432 if (tag == JVM_CONSTANT.MethodRef || tag == JVM_CONSTANT.Fieldref || tag == JVM_CONSTANT.InterfaceMethodref) { 433 assertTagIsFieldOrMethod(index); 434 final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize); 435 // klass ref index is in the low 16-bits. 436 resultIndex = refIndex & 0xFFFF; 437 } else { 438 resultIndex = index; 439 } 440 441 // Read the tag only once because it could change between multiple reads. 442 final JVM_CONSTANT klassTag = getTagAt(resultIndex); 443 assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag; 444 445 return resultIndex; 446 } 447 448 /** 449 * Asserts that the constant pool index {@code index} is in the bounds of the constant pool. 450 * 451 * @param index constant pool index 452 */ 453 private void assertBounds(int index) { 454 assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length(); 455 } 456 457 /** 458 * Asserts that the constant pool tag at index {@code index} is equal to {@code tag}. 459 * 460 * @param index constant pool index 461 * @param tag expected tag 462 */ 463 private void assertTag(int index, JVM_CONSTANT tag) { 464 final JVM_CONSTANT tagAt = getTagAt(index); 465 assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag; 466 } 467 468 /** 469 * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref}, 470 * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}. 471 * 472 * @param index constant pool index 473 */ 474 private void assertTagIsFieldOrMethod(int index) { 475 final JVM_CONSTANT tagAt = getTagAt(index); 476 assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt; 477 } 478 479 @Override 480 public int length() { 481 return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolLengthOffset); 482 } 483 484 @Override 485 public Object lookupConstant(int cpi) { 486 assert cpi != 0; 487 final JVM_CONSTANT tag = getTagAt(cpi); 488 switch (tag) { 489 case Integer: 490 return JavaConstant.forInt(getIntAt(cpi)); 491 case Long: 492 return JavaConstant.forLong(getLongAt(cpi)); 493 case Float: 494 return JavaConstant.forFloat(getFloatAt(cpi)); 495 case Double: 496 return JavaConstant.forDouble(getDoubleAt(cpi)); 497 case Class: 498 case UnresolvedClass: 499 case UnresolvedClassInError: 500 final int opcode = -1; // opcode is not used 501 return lookupType(cpi, opcode); 502 case String: 503 /* 504 * Normally, we would expect a String here, but anonymous classes can have 505 * "pseudo strings" (arbitrary live objects) patched into a String entry. Such 506 * entries do not have a symbol in the constant pool slot. 507 */ 508 Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(this, cpi); 509 return HotSpotObjectConstantImpl.forObject(string); 510 case MethodHandle: 511 case MethodHandleInError: 512 case MethodType: 513 case MethodTypeInError: 514 Object obj = runtime().getCompilerToVM().resolveConstantInPool(this, cpi); 515 return HotSpotObjectConstantImpl.forObject(obj); 516 default: 517 throw new JVMCIError("Unknown constant pool tag %s", tag); 518 } 519 } 520 521 @Override 522 public String lookupUtf8(int cpi) { 523 assertTag(cpi, JVM_CONSTANT.Utf8); 524 return runtime().getCompilerToVM().getSymbol(getEntryAt(cpi)); 525 } 526 527 @Override 528 public Signature lookupSignature(int cpi) { 529 return new HotSpotSignature(runtime(), lookupUtf8(cpi)); 530 } 531 532 @Override 533 public JavaConstant lookupAppendix(int cpi, int opcode) { 534 assert Bytecodes.isInvoke(opcode); 535 final int index = rawIndexToConstantPoolIndex(cpi, opcode); 536 Object appendix = runtime().getCompilerToVM().lookupAppendixInPool(this, index); 537 if (appendix == null) { 538 return null; 539 } else { 540 return HotSpotObjectConstantImpl.forObject(appendix); 541 } 542 } 543 544 /** 545 * Gets a {@link JavaType} corresponding a given resolved or unresolved type. 546 * 547 * @param type either a ResolvedJavaType or a String naming a unresolved type. 548 */ 549 private static JavaType getJavaType(final Object type) { 550 if (type instanceof String) { 551 String name = (String) type; 552 return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";"); 553 } else { 554 return (JavaType) type; 555 } 556 } 557 558 @Override 559 public JavaMethod lookupMethod(int cpi, int opcode) { 560 final int index = rawIndexToConstantPoolIndex(cpi, opcode); 561 final HotSpotResolvedJavaMethod method = runtime().getCompilerToVM().lookupMethodInPool(this, index, (byte) opcode); 562 if (method != null) { 563 return method; 564 } else { 565 // Get the method's name and signature. 566 String name = getNameRefAt(index); 567 HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureRefAt(index)); 568 if (opcode == Bytecodes.INVOKEDYNAMIC) { 569 HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class); 570 return new HotSpotMethodUnresolved(name, signature, holder); 571 } else { 572 final int klassIndex = getKlassRefIndexAt(index); 573 final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, klassIndex); 574 JavaType holder = getJavaType(type); 575 return new HotSpotMethodUnresolved(name, signature, holder); 576 } 577 } 578 } 579 580 @Override 581 public JavaType lookupType(int cpi, int opcode) { 582 final LookupTypeCacheElement elem = this.lastLookupType; 583 if (elem != null && elem.lastCpi == cpi) { 584 return elem.javaType; 585 } else { 586 final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, cpi); 587 JavaType result = getJavaType(type); 588 if (result instanceof ResolvedJavaType) { 589 this.lastLookupType = new LookupTypeCacheElement(cpi, result); 590 } 591 return result; 592 } 593 } 594 595 @Override 596 public JavaField lookupField(int cpi, int opcode) { 597 final int index = rawIndexToConstantPoolIndex(cpi, opcode); 598 final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index); 599 final int nameIndex = getNameRefIndexAt(nameAndTypeIndex); 600 String name = lookupUtf8(nameIndex); 601 final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex); 602 String typeName = lookupUtf8(typeIndex); 603 JavaType type = runtime().lookupType(typeName, getHolder(), false); 604 605 final int holderIndex = getKlassRefIndexAt(index); 606 JavaType holder = lookupType(holderIndex, opcode); 607 608 if (holder instanceof HotSpotResolvedObjectTypeImpl) { 609 long[] info = new long[2]; 610 HotSpotResolvedObjectTypeImpl resolvedHolder; 611 try { 612 resolvedHolder = runtime().getCompilerToVM().resolveFieldInPool(this, index, (byte) opcode, info); 613 } catch (Throwable t) { 614 /* 615 * If there was an exception resolving the field we give up and return an unresolved 616 * field. 617 */ 618 return new HotSpotUnresolvedField(holder, name, type); 619 } 620 final int flags = (int) info[0]; 621 final long offset = info[1]; 622 HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags); 623 return result; 624 } else { 625 return new HotSpotUnresolvedField(holder, name, type); 626 } 627 } 628 629 @Override 630 @SuppressWarnings("fallthrough") 631 public void loadReferencedType(int cpi, int opcode) { 632 int index; 633 switch (opcode) { 634 case Bytecodes.CHECKCAST: 635 case Bytecodes.INSTANCEOF: 636 case Bytecodes.NEW: 637 case Bytecodes.ANEWARRAY: 638 case Bytecodes.MULTIANEWARRAY: 639 case Bytecodes.LDC: 640 case Bytecodes.LDC_W: 641 case Bytecodes.LDC2_W: 642 index = cpi; 643 break; 644 case Bytecodes.INVOKEDYNAMIC: { 645 // invokedynamic instructions point to a constant pool cache entry. 646 index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag; 647 index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); 648 break; 649 } 650 case Bytecodes.GETSTATIC: 651 case Bytecodes.PUTSTATIC: 652 case Bytecodes.GETFIELD: 653 case Bytecodes.PUTFIELD: 654 case Bytecodes.INVOKEVIRTUAL: 655 case Bytecodes.INVOKESPECIAL: 656 case Bytecodes.INVOKESTATIC: 657 case Bytecodes.INVOKEINTERFACE: { 658 // invoke and field instructions point to a constant pool cache entry. 659 index = rawIndexToConstantPoolIndex(cpi, opcode); 660 index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); 661 break; 662 } 663 default: 664 throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode); 665 } 666 667 final JVM_CONSTANT tag = getTagAt(index); 668 if (tag == null) { 669 assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long; 670 return; 671 } 672 switch (tag) { 673 case MethodRef: 674 case Fieldref: 675 case InterfaceMethodref: 676 case Class: 677 case UnresolvedClass: 678 case UnresolvedClassInError: 679 index = getUncachedKlassRefIndexAt(index, tag); 680 final HotSpotResolvedObjectTypeImpl type = runtime().getCompilerToVM().resolveTypeInPool(this, index); 681 Class<?> klass = type.mirror(); 682 if (!klass.isPrimitive() && !klass.isArray()) { 683 UNSAFE.ensureClassInitialized(klass); 684 } 685 switch (tag) { 686 case MethodRef: 687 if (Bytecodes.isInvokeHandleAlias(opcode)) { 688 final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode); 689 if (isInvokeHandle(methodRefCacheIndex, type)) { 690 runtime().getCompilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex); 691 } 692 } 693 } 694 break; 695 case InvokeDynamic: 696 if (isInvokedynamicIndex(cpi)) { 697 runtime().getCompilerToVM().resolveInvokeDynamicInPool(this, cpi); 698 } 699 break; 700 default: 701 // nothing 702 break; 703 } 704 } 705 706 private boolean isInvokeHandle(int methodRefCacheIndex, HotSpotResolvedObjectTypeImpl klass) { 707 assertTag(runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef); 708 return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameRefAt(methodRefCacheIndex), runtime().getHostJVMCIBackend().getMetaAccess()); 709 } 710 711 @Override 712 public String toString() { 713 HotSpotResolvedObjectType holder = getHolder(); 714 return "HotSpotConstantPool<" + holder.toJavaName() + ">"; 715 } 716 }