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