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