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