1 /*
   2  * Copyright (c) 2012, 2016, 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 org.graalvm.compiler.hotspot.replacements;
  24 
  25 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
  26 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP;
  27 import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
  28 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
  29 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
  30 
  31 import org.graalvm.compiler.api.replacements.Fold;
  32 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
  33 import org.graalvm.compiler.core.common.LocationIdentity;
  34 import org.graalvm.compiler.core.common.SuppressFBWarnings;
  35 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
  36 import org.graalvm.compiler.core.common.type.ObjectStamp;
  37 import org.graalvm.compiler.core.common.type.TypeReference;
  38 import org.graalvm.compiler.debug.GraalError;
  39 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
  40 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
  41 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
  42 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  43 import org.graalvm.compiler.hotspot.nodes.CompressionNode;
  44 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
  45 import org.graalvm.compiler.hotspot.word.KlassPointer;
  46 import org.graalvm.compiler.nodes.CanonicalizableLocation;
  47 import org.graalvm.compiler.nodes.ConstantNode;
  48 import org.graalvm.compiler.nodes.NamedLocationIdentity;
  49 import org.graalvm.compiler.nodes.ValueNode;
  50 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
  51 import org.graalvm.compiler.nodes.extended.LoadHubNode;
  52 import org.graalvm.compiler.nodes.extended.StoreHubNode;
  53 import org.graalvm.compiler.nodes.extended.RawLoadNode;
  54 import org.graalvm.compiler.nodes.memory.Access;
  55 import org.graalvm.compiler.nodes.memory.address.AddressNode;
  56 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
  57 import org.graalvm.compiler.nodes.type.StampTool;
  58 import org.graalvm.compiler.replacements.ReplacementsUtil;
  59 import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
  60 import org.graalvm.compiler.replacements.nodes.WriteRegisterNode;
  61 import org.graalvm.compiler.word.Word;
  62 
  63 import jdk.vm.ci.code.CodeUtil;
  64 import jdk.vm.ci.code.Register;
  65 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
  66 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
  67 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
  68 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
  69 import jdk.vm.ci.meta.Assumptions;
  70 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
  71 import jdk.vm.ci.meta.JavaKind;
  72 import jdk.vm.ci.meta.ResolvedJavaType;
  73 
  74 //JaCoCo Exclude
  75 
  76 /**
  77  * A collection of methods used in HotSpot snippets, substitutions and stubs.
  78  */
  79 public class HotSpotReplacementsUtil {
  80 
  81     abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation {
  82 
  83         HotSpotOptimizingLocationIdentity(String name) {
  84             super(name, true);
  85         }
  86 
  87         @Override
  88         public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
  89 
  90         protected ValueNode findReadHub(ValueNode object) {
  91             ValueNode base = object;
  92             if (base instanceof CompressionNode) {
  93                 base = ((CompressionNode) base).getValue();
  94             }
  95             if (base instanceof Access) {
  96                 Access access = (Access) base;
  97                 if (access.getLocationIdentity().equals(HUB_LOCATION) || access.getLocationIdentity().equals(COMPRESSED_HUB_LOCATION)) {
  98                     AddressNode address = access.getAddress();
  99                     if (address instanceof OffsetAddressNode) {
 100                         OffsetAddressNode offset = (OffsetAddressNode) address;
 101                         return offset.getBase();
 102                     }
 103                 }
 104             } else if (base instanceof LoadHubNode) {
 105                 LoadHubNode loadhub = (LoadHubNode) base;
 106                 return loadhub.getValue();
 107             }
 108             return null;
 109         }
 110 
 111         /**
 112          * Fold reads that convert from Class -> Hub -> Class or vice versa.
 113          *
 114          * @param read
 115          * @param object
 116          * @param otherLocation
 117          * @return an earlier read or the original {@code read}
 118          */
 119         protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) {
 120             if (object instanceof Access) {
 121                 Access access = (Access) object;
 122                 if (access.getLocationIdentity().equals(otherLocation)) {
 123                     AddressNode address = access.getAddress();
 124                     if (address instanceof OffsetAddressNode) {
 125                         OffsetAddressNode offset = (OffsetAddressNode) address;
 126                         assert offset.getBase().stamp().isCompatible(read.stamp());
 127                         return offset.getBase();
 128                     }
 129                 }
 130             }
 131             return read;
 132         }
 133     }
 134 
 135     public static HotSpotJVMCIRuntimeProvider runtime() {
 136         return HotSpotJVMCIRuntime.runtime();
 137     }
 138 
 139     @Fold
 140     public static GraalHotSpotVMConfig config(@InjectedParameter GraalHotSpotVMConfig config) {
 141         assert config != null;
 142         return config;
 143     }
 144 
 145     @Fold
 146     public static boolean useTLAB(@InjectedParameter GraalHotSpotVMConfig config) {
 147         return config.useTLAB;
 148     }
 149 
 150     @Fold
 151     public static boolean verifyOops(@InjectedParameter GraalHotSpotVMConfig config) {
 152         return config.verifyOops;
 153     }
 154 
 155     public static final LocationIdentity EXCEPTION_OOP_LOCATION = NamedLocationIdentity.mutable("ExceptionOop");
 156 
 157     /**
 158      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
 159      */
 160     @Fold
 161     public static int threadExceptionOopOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 162         return config.threadExceptionOopOffset;
 163     }
 164 
 165     public static final LocationIdentity EXCEPTION_PC_LOCATION = NamedLocationIdentity.mutable("ExceptionPc");
 166 
 167     @Fold
 168     public static int threadExceptionPcOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 169         return config.threadExceptionPcOffset;
 170     }
 171 
 172     public static final LocationIdentity TLAB_TOP_LOCATION = NamedLocationIdentity.mutable("TlabTop");
 173 
 174     @Fold
 175     public static int threadTlabTopOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 176         return config.threadTlabTopOffset();
 177     }
 178 
 179     public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd");
 180 
 181     @Fold
 182     static int threadTlabEndOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 183         return config.threadTlabEndOffset();
 184     }
 185 
 186     public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart");
 187 
 188     @Fold
 189     static int threadTlabStartOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 190         return config.threadTlabStartOffset();
 191     }
 192 
 193     public static final LocationIdentity PENDING_EXCEPTION_LOCATION = NamedLocationIdentity.mutable("PendingException");
 194 
 195     /**
 196      * @see GraalHotSpotVMConfig#pendingExceptionOffset
 197      */
 198     @Fold
 199     static int threadPendingExceptionOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 200         return config.pendingExceptionOffset;
 201     }
 202 
 203     public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = NamedLocationIdentity.mutable("PendingDeoptimization");
 204 
 205     /**
 206      * @see GraalHotSpotVMConfig#pendingDeoptimizationOffset
 207      */
 208     @Fold
 209     static int threadPendingDeoptimizationOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 210         return config.pendingDeoptimizationOffset;
 211     }
 212 
 213     public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
 214 
 215     @Fold
 216     static int objectResultOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 217         return config.threadObjectResultOffset;
 218     }
 219 
 220     /**
 221      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
 222      */
 223     public static Object readExceptionOop(Word thread) {
 224         return thread.readObject(threadExceptionOopOffset(INJECTED_VMCONFIG), EXCEPTION_OOP_LOCATION);
 225     }
 226 
 227     public static Word readExceptionPc(Word thread) {
 228         return thread.readWord(threadExceptionPcOffset(INJECTED_VMCONFIG), EXCEPTION_PC_LOCATION);
 229     }
 230 
 231     /**
 232      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
 233      */
 234     public static void writeExceptionOop(Word thread, Object value) {
 235         thread.writeObject(threadExceptionOopOffset(INJECTED_VMCONFIG), value, EXCEPTION_OOP_LOCATION);
 236     }
 237 
 238     public static void writeExceptionPc(Word thread, Word value) {
 239         thread.writeWord(threadExceptionPcOffset(INJECTED_VMCONFIG), value, EXCEPTION_PC_LOCATION);
 240     }
 241 
 242     public static Word readTlabTop(Word thread) {
 243         return thread.readWord(threadTlabTopOffset(INJECTED_VMCONFIG), TLAB_TOP_LOCATION);
 244     }
 245 
 246     public static Word readTlabEnd(Word thread) {
 247         return thread.readWord(threadTlabEndOffset(INJECTED_VMCONFIG), TLAB_END_LOCATION);
 248     }
 249 
 250     public static Word readTlabStart(Word thread) {
 251         return thread.readWord(threadTlabStartOffset(INJECTED_VMCONFIG), TLAB_START_LOCATION);
 252     }
 253 
 254     public static void writeTlabTop(Word thread, Word top) {
 255         thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), top, TLAB_TOP_LOCATION);
 256     }
 257 
 258     @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected")
 259     public static void initializeTlab(Word thread, Word start, Word end) {
 260         thread.writeWord(threadTlabStartOffset(INJECTED_VMCONFIG), start, TLAB_START_LOCATION);
 261         thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), start, TLAB_TOP_LOCATION);
 262         thread.writeWord(threadTlabEndOffset(INJECTED_VMCONFIG), end, TLAB_END_LOCATION);
 263     }
 264 
 265     /**
 266      * Clears the pending exception for the given thread.
 267      *
 268      * @return the pending exception, or null if there was none
 269      */
 270     @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected")
 271     public static Object clearPendingException(Word thread) {
 272         Object result = thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION);
 273         thread.writeObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), null, PENDING_EXCEPTION_LOCATION);
 274         return result;
 275     }
 276 
 277     /**
 278      * Reads the pending deoptimization value for the given thread.
 279      *
 280      * @return {@code true} if there was a pending deoptimization
 281      */
 282     public static int readPendingDeoptimization(Word thread) {
 283         return thread.readInt(threadPendingDeoptimizationOffset(INJECTED_VMCONFIG), PENDING_DEOPTIMIZATION_LOCATION);
 284     }
 285 
 286     /**
 287      * Writes the pending deoptimization value for the given thread.
 288      */
 289     public static void writePendingDeoptimization(Word thread, int value) {
 290         thread.writeInt(threadPendingDeoptimizationOffset(INJECTED_VMCONFIG), value, PENDING_DEOPTIMIZATION_LOCATION);
 291     }
 292 
 293     /**
 294      * Gets and clears the object result from a runtime call stored in a thread local.
 295      *
 296      * @return the object that was in the thread local
 297      */
 298     public static Object getAndClearObjectResult(Word thread) {
 299         Object result = thread.readObject(objectResultOffset(INJECTED_VMCONFIG), OBJECT_RESULT_LOCATION);
 300         thread.writeObject(objectResultOffset(INJECTED_VMCONFIG), null, OBJECT_RESULT_LOCATION);
 301         return result;
 302     }
 303 
 304     public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj");
 305 
 306     @Fold
 307     public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 308         return config.threadObjectOffset;
 309     }
 310 
 311     public static final LocationIdentity JAVA_THREAD_OSTHREAD_LOCATION = NamedLocationIdentity.mutable("JavaThread::_osthread");
 312 
 313     @Fold
 314     public static int osThreadOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 315         return config.osThreadOffset;
 316     }
 317 
 318     @Fold
 319     public static int osThreadInterruptedOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 320         return config.osThreadInterruptedOffset;
 321     }
 322 
 323     @Fold
 324     public static JavaKind getWordKind() {
 325         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
 326     }
 327 
 328     @Fold
 329     public static int wordSize() {
 330         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
 331     }
 332 
 333     @Fold
 334     public static int pageSize() {
 335         return UNSAFE.pageSize();
 336     }
 337 
 338     @Fold
 339     public static int heapWordSize(@InjectedParameter GraalHotSpotVMConfig config) {
 340         return config.heapWordSize;
 341     }
 342 
 343     public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord");
 344 
 345     @Fold
 346     public static int prototypeMarkWordOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 347         return config.prototypeMarkWordOffset;
 348     }
 349 
 350     @Fold
 351     public static long arrayPrototypeMarkWord(@InjectedParameter GraalHotSpotVMConfig config) {
 352         return config.arrayPrototypeMarkWord();
 353     }
 354 
 355     public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags");
 356 
 357     @Fold
 358     public static int klassAccessFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 359         return config.klassAccessFlagsOffset;
 360     }
 361 
 362     @Fold
 363     public static int jvmAccWrittenFlags(@InjectedParameter GraalHotSpotVMConfig config) {
 364         return config.jvmAccWrittenFlags;
 365     }
 366 
 367     public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") {
 368         @Override
 369         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 370             ValueNode javaObject = findReadHub(object);
 371             if (javaObject != null) {
 372                 if (javaObject.stamp() instanceof ObjectStamp) {
 373                     ObjectStamp stamp = (ObjectStamp) javaObject.stamp();
 374                     HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess());
 375                     if (type.isArray() && !type.getComponentType().isPrimitive()) {
 376                         int layout = type.layoutHelper();
 377                         return ConstantNode.forInt(layout);
 378                     }
 379                 }
 380             }
 381             return read;
 382         }
 383     };
 384 
 385     @Fold
 386     public static int klassLayoutHelperOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 387         return config.klassLayoutHelperOffset;
 388     }
 389 
 390     @NodeIntrinsic(value = KlassLayoutHelperNode.class)
 391     public static native int readLayoutHelper(KlassPointer object);
 392 
 393     /**
 394      * Checks if class {@code klass} is an array.
 395      *
 396      * See: Klass::layout_helper_is_array
 397      *
 398      * @param klassNonNull the class to be checked
 399      * @return true if klassNonNull is an array, false otherwise
 400      */
 401     public static boolean klassIsArray(KlassPointer klassNonNull) {
 402         /*
 403          * The less-than check only works if both values are ints. We use local variables to make
 404          * sure these are still ints and haven't changed.
 405          */
 406         final int layoutHelper = readLayoutHelper(klassNonNull);
 407         final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue;
 408         return (layoutHelper < layoutHelperNeutralValue);
 409     }
 410 
 411     public static final LocationIdentity ARRAY_KLASS_COMPONENT_MIRROR = NamedLocationIdentity.immutable("ArrayKlass::_component_mirror");
 412 
 413     @Fold
 414     public static int arrayKlassComponentMirrorOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 415         return config.getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop");
 416     }
 417 
 418     public static final LocationIdentity KLASS_SUPER_KLASS_LOCATION = NamedLocationIdentity.immutable("Klass::_super");
 419 
 420     @Fold
 421     public static int klassSuperKlassOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 422         return config.klassSuperKlassOffset;
 423     }
 424 
 425     public static final LocationIdentity MARK_WORD_LOCATION = NamedLocationIdentity.mutable("MarkWord");
 426 
 427     @Fold
 428     public static int markOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 429         return config.markOffset;
 430     }
 431 
 432     public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write");
 433 
 434     public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") {
 435         @Override
 436         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 437             TypeReference constantType = StampTool.typeReferenceOrNull(object);
 438             if (constantType != null && constantType.isExact()) {
 439                 return ConstantNode.forConstant(read.stamp(), tool.getConstantReflection().asObjectHub(constantType.getType()), tool.getMetaAccess());
 440             }
 441             return read;
 442         }
 443     };
 444 
 445     public static final LocationIdentity COMPRESSED_HUB_LOCATION = new HotSpotOptimizingLocationIdentity("CompressedHub") {
 446         @Override
 447         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 448             TypeReference constantType = StampTool.typeReferenceOrNull(object);
 449             if (constantType != null && constantType.isExact()) {
 450                 return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) tool.getConstantReflection().asObjectHub(constantType.getType())).compress(), tool.getMetaAccess());
 451             }
 452             return read;
 453         }
 454     };
 455 
 456     @Fold
 457     static int hubOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 458         return config.hubOffset;
 459     }
 460 
 461     public static void initializeObjectHeader(Word memory, Word markWord, KlassPointer hub) {
 462         memory.writeWord(markOffset(INJECTED_VMCONFIG), markWord, MARK_WORD_LOCATION);
 463         StoreHubNode.write(memory, hub);
 464     }
 465 
 466     @Fold
 467     public static int unlockedMask(@InjectedParameter GraalHotSpotVMConfig config) {
 468         return config.unlockedMask;
 469     }
 470 
 471     @Fold
 472     public static int monitorMask(@InjectedParameter GraalHotSpotVMConfig config) {
 473         return config.monitorMask;
 474     }
 475 
 476     @Fold
 477     public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 478         return config.objectMonitorOwner;
 479     }
 480 
 481     @Fold
 482     public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 483         return config.objectMonitorRecursions;
 484     }
 485 
 486     @Fold
 487     public static int objectMonitorCxqOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 488         return config.objectMonitorCxq;
 489     }
 490 
 491     @Fold
 492     public static int objectMonitorEntryListOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 493         return config.objectMonitorEntryList;
 494     }
 495 
 496     /**
 497      * Mask for a biasable, locked or unlocked mark word.
 498      *
 499      * <pre>
 500      * +----------------------------------+-+-+
 501      * |                                 1|1|1|
 502      * +----------------------------------+-+-+
 503      * </pre>
 504      *
 505      */
 506     @Fold
 507     public static int biasedLockMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 508         return config.biasedLockMaskInPlace;
 509     }
 510 
 511     @Fold
 512     public static int epochMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 513         return config.epochMaskInPlace;
 514     }
 515 
 516     /**
 517      * Pattern for a biasable, unlocked mark word.
 518      *
 519      * <pre>
 520      * +----------------------------------+-+-+
 521      * |                                 1|0|1|
 522      * +----------------------------------+-+-+
 523      * </pre>
 524      *
 525      */
 526     @Fold
 527     public static int biasedLockPattern(@InjectedParameter GraalHotSpotVMConfig config) {
 528         return config.biasedLockPattern;
 529     }
 530 
 531     @Fold
 532     public static int ageMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 533         return config.ageMaskInPlace;
 534     }
 535 
 536     @Fold
 537     public static int metaspaceArrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 538         return config.metaspaceArrayLengthOffset;
 539     }
 540 
 541     @Fold
 542     public static int metaspaceArrayBaseOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 543         return config.metaspaceArrayBaseOffset;
 544     }
 545 
 546     @Fold
 547     public static int arrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 548         return config.arrayOopDescLengthOffset();
 549     }
 550 
 551     @Fold
 552     public static int arrayBaseOffset(JavaKind elementKind) {
 553         return getArrayBaseOffset(elementKind);
 554     }
 555 
 556     @Fold
 557     public static int arrayIndexScale(JavaKind elementKind) {
 558         return getArrayIndexScale(elementKind);
 559     }
 560 
 561     public static Word arrayStart(int[] a) {
 562         return Word.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int)));
 563     }
 564 
 565     @Fold
 566     public static int instanceHeaderSize(@InjectedParameter GraalHotSpotVMConfig config) {
 567         return config.useCompressedClassPointers ? (2 * wordSize()) - 4 : 2 * wordSize();
 568     }
 569 
 570     @Fold
 571     public static byte dirtyCardValue(@InjectedParameter GraalHotSpotVMConfig config) {
 572         return config.dirtyCardValue;
 573     }
 574 
 575     @Fold
 576     public static byte g1YoungCardValue(@InjectedParameter GraalHotSpotVMConfig config) {
 577         return config.g1YoungCardValue;
 578     }
 579 
 580     @Fold
 581     public static int cardTableShift(@InjectedParameter GraalHotSpotVMConfig config) {
 582         return config.cardtableShift;
 583     }
 584 
 585     @Fold
 586     public static long cardTableStart(@InjectedParameter GraalHotSpotVMConfig config) {
 587         return config.cardtableStartAddress;
 588     }
 589 
 590     @Fold
 591     public static int g1CardQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 592         return config.g1CardQueueIndexOffset();
 593     }
 594 
 595     @Fold
 596     public static int g1CardQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 597         return config.g1CardQueueBufferOffset();
 598     }
 599 
 600     @Fold
 601     public static int logOfHeapRegionGrainBytes(@InjectedParameter GraalHotSpotVMConfig config) {
 602         return config.logOfHRGrainBytes;
 603     }
 604 
 605     @Fold
 606     public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 607         return config.g1SATBQueueMarkingOffset();
 608     }
 609 
 610     @Fold
 611     public static int g1SATBQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 612         return config.g1SATBQueueIndexOffset();
 613     }
 614 
 615     @Fold
 616     public static int g1SATBQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 617         return config.g1SATBQueueBufferOffset();
 618     }
 619 
 620     public static final LocationIdentity KLASS_SUPER_CHECK_OFFSET_LOCATION = NamedLocationIdentity.immutable("Klass::_super_check_offset");
 621 
 622     @Fold
 623     public static int superCheckOffsetOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 624         return config.superCheckOffsetOffset;
 625     }
 626 
 627     public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = NamedLocationIdentity.mutable("SecondarySuperCache");
 628 
 629     @Fold
 630     public static int secondarySuperCacheOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 631         return config.secondarySuperCacheOffset;
 632     }
 633 
 634     public static final LocationIdentity SECONDARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("SecondarySupers");
 635 
 636     @Fold
 637     public static int secondarySupersOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 638         return config.secondarySupersOffset;
 639     }
 640 
 641     public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord");
 642 
 643     public static final LocationIdentity OBJECT_MONITOR_OWNER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_owner");
 644 
 645     public static final LocationIdentity OBJECT_MONITOR_RECURSION_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_recursions");
 646 
 647     public static final LocationIdentity OBJECT_MONITOR_CXQ_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_cxq");
 648 
 649     public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList");
 650 
 651     @Fold
 652     public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 653         return config.basicLockDisplacedHeaderOffset;
 654     }
 655 
 656     @Fold
 657     public static boolean useBiasedLocking(@InjectedParameter GraalHotSpotVMConfig config) {
 658         return config.useBiasedLocking;
 659     }
 660 
 661     @Fold
 662     public static boolean useDeferredInitBarriers(@InjectedParameter GraalHotSpotVMConfig config) {
 663         return config.useDeferredInitBarriers;
 664     }
 665 
 666     @Fold
 667     public static boolean useG1GC(@InjectedParameter GraalHotSpotVMConfig config) {
 668         return config.useG1GC;
 669     }
 670 
 671     @Fold
 672     public static boolean useCompressedOops(@InjectedParameter GraalHotSpotVMConfig config) {
 673         return config.useCompressedOops;
 674     }
 675 
 676     @Fold
 677     static int uninitializedIdentityHashCodeValue(@InjectedParameter GraalHotSpotVMConfig config) {
 678         return config.uninitializedIdentityHashCodeValue;
 679     }
 680 
 681     @Fold
 682     static int identityHashCodeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 683         return config.identityHashCodeShift;
 684     }
 685 
 686     /**
 687      * Loads the hub of an object (without null checking it first).
 688      */
 689     public static KlassPointer loadHub(Object object) {
 690         return loadHubIntrinsic(object);
 691     }
 692 
 693     public static Object verifyOop(Object object) {
 694         if (verifyOops(INJECTED_VMCONFIG)) {
 695             verifyOopStub(VERIFY_OOP, object);
 696         }
 697         return object;
 698     }
 699 
 700     @NodeIntrinsic(ForeignCallNode.class)
 701     private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
 702 
 703     public static Word loadWordFromObject(Object object, int offset) {
 704         ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
 705         return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any());
 706     }
 707 
 708     public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) {
 709         ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
 710         return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity);
 711     }
 712 
 713     public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
 714         ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
 715         return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity);
 716     }
 717 
 718     /**
 719      * Reads the value of a given register.
 720      *
 721      * @param register a register which must not be available to the register allocator
 722      * @return the value of {@code register} as a word
 723      */
 724     public static Word registerAsWord(@ConstantNodeParameter Register register) {
 725         return registerAsWord(register, true, false);
 726     }
 727 
 728     @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
 729     public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
 730 
 731     @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true)
 732     public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value);
 733 
 734     @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true)
 735     private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
 736 
 737     @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true)
 738     private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
 739 
 740     @NodeIntrinsic(value = LoadHubNode.class)
 741     public static native KlassPointer loadHubIntrinsic(Object object);
 742 
 743     @Fold
 744     public static int log2WordSize() {
 745         return CodeUtil.log2(wordSize());
 746     }
 747 
 748     public static final LocationIdentity CLASS_STATE_LOCATION = NamedLocationIdentity.mutable("ClassState");
 749 
 750     @Fold
 751     public static int instanceKlassInitStateOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 752         return config.instanceKlassInitStateOffset;
 753     }
 754 
 755     @Fold
 756     public static int instanceKlassStateFullyInitialized(@InjectedParameter GraalHotSpotVMConfig config) {
 757         return config.instanceKlassStateFullyInitialized;
 758     }
 759 
 760     /**
 761      *
 762      * @param hub the hub of an InstanceKlass
 763      * @return true is the InstanceKlass represented by hub is fully initialized
 764      */
 765     public static boolean isInstanceKlassFullyInitialized(KlassPointer hub) {
 766         return readInstanceKlassState(hub) == instanceKlassStateFullyInitialized(INJECTED_VMCONFIG);
 767     }
 768 
 769     private static byte readInstanceKlassState(KlassPointer hub) {
 770         return hub.readByte(instanceKlassInitStateOffset(INJECTED_VMCONFIG), CLASS_STATE_LOCATION);
 771     }
 772 
 773     public static final LocationIdentity KLASS_MODIFIER_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_modifier_flags");
 774 
 775     @Fold
 776     public static int klassModifierFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 777         return config.klassModifierFlagsOffset;
 778     }
 779 
 780     public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") {
 781         @Override
 782         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 783             return foldIndirection(read, object, CLASS_MIRROR_LOCATION);
 784         }
 785     };
 786 
 787     @Fold
 788     public static int klassOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 789         return config.klassOffset;
 790     }
 791 
 792     public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") {
 793         @Override
 794         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 795             return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR);
 796         }
 797     };
 798 
 799     @Fold
 800     public static int arrayKlassOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 801         return config.arrayKlassOffset;
 802     }
 803 
 804     public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror");
 805 
 806     public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop");
 807 
 808     @Fold
 809     public static long heapTopAddress(@InjectedParameter GraalHotSpotVMConfig config) {
 810         return config.heapTopAddress;
 811     }
 812 
 813     public static final LocationIdentity HEAP_END_LOCATION = NamedLocationIdentity.mutable("HeapEnd");
 814 
 815     @Fold
 816     public static long heapEndAddress(@InjectedParameter GraalHotSpotVMConfig config) {
 817         return config.heapEndAddress;
 818     }
 819 
 820     @Fold
 821     public static long tlabIntArrayMarkWord(@InjectedParameter GraalHotSpotVMConfig config) {
 822         return config.tlabIntArrayMarkWord();
 823     }
 824 
 825     @Fold
 826     public static boolean inlineContiguousAllocationSupported(@InjectedParameter GraalHotSpotVMConfig config) {
 827         return config.inlineContiguousAllocationSupported;
 828     }
 829 
 830     @Fold
 831     public static int tlabAlignmentReserveInHeapWords(@InjectedParameter GraalHotSpotVMConfig config) {
 832         return config.tlabAlignmentReserve;
 833     }
 834 
 835     public static final LocationIdentity TLAB_SIZE_LOCATION = NamedLocationIdentity.mutable("TlabSize");
 836 
 837     @Fold
 838     public static int threadTlabSizeOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 839         return config.threadTlabSizeOffset();
 840     }
 841 
 842     public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = NamedLocationIdentity.mutable("TlabThreadAllocatedBytes");
 843 
 844     @Fold
 845     public static int threadAllocatedBytesOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 846         return config.threadAllocatedBytesOffset;
 847     }
 848 
 849     public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = NamedLocationIdentity.mutable("RefillWasteLimit");
 850 
 851     @Fold
 852     public static int tlabRefillWasteLimitOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 853         return config.tlabRefillWasteLimitOffset();
 854     }
 855 
 856     public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = NamedLocationIdentity.mutable("TlabNOfRefills");
 857 
 858     @Fold
 859     public static int tlabNumberOfRefillsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 860         return config.tlabNumberOfRefillsOffset();
 861     }
 862 
 863     public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = NamedLocationIdentity.mutable("TlabFastRefillWaste");
 864 
 865     @Fold
 866     public static int tlabFastRefillWasteOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 867         return config.tlabFastRefillWasteOffset();
 868     }
 869 
 870     public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = NamedLocationIdentity.mutable("TlabSlowAllocations");
 871 
 872     @Fold
 873     public static int tlabSlowAllocationsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 874         return config.tlabSlowAllocationsOffset();
 875     }
 876 
 877     @Fold
 878     public static int tlabRefillWasteIncrement(@InjectedParameter GraalHotSpotVMConfig config) {
 879         return config.tlabRefillWasteIncrement;
 880     }
 881 
 882     @Fold
 883     public static boolean tlabStats(@InjectedParameter GraalHotSpotVMConfig config) {
 884         return config.tlabStats;
 885     }
 886 
 887     @Fold
 888     public static int layoutHelperHeaderSizeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 889         return config.layoutHelperHeaderSizeShift;
 890     }
 891 
 892     @Fold
 893     public static int layoutHelperHeaderSizeMask(@InjectedParameter GraalHotSpotVMConfig config) {
 894         return config.layoutHelperHeaderSizeMask;
 895     }
 896 
 897     @Fold
 898     public static int layoutHelperLog2ElementSizeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 899         return config.layoutHelperLog2ElementSizeShift;
 900     }
 901 
 902     @Fold
 903     public static int layoutHelperLog2ElementSizeMask(@InjectedParameter GraalHotSpotVMConfig config) {
 904         return config.layoutHelperLog2ElementSizeMask;
 905     }
 906 
 907     @Fold
 908     public static int layoutHelperElementTypeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 909         return config.layoutHelperElementTypeShift;
 910     }
 911 
 912     @Fold
 913     public static int layoutHelperElementTypeMask(@InjectedParameter GraalHotSpotVMConfig config) {
 914         return config.layoutHelperElementTypeMask;
 915     }
 916 
 917     @Fold
 918     public static int layoutHelperElementTypePrimitiveInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 919         return config.layoutHelperElementTypePrimitiveInPlace();
 920     }
 921 
 922     @NodeIntrinsic(ForeignCallNode.class)
 923     public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
 924 
 925     @Fold
 926     public static int verifiedEntryPointOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 927         return config.nmethodEntryOffset;
 928     }
 929 
 930     @Fold
 931     public static long gcTotalCollectionsAddress(@InjectedParameter GraalHotSpotVMConfig config) {
 932         return config.gcTotalCollectionsAddress();
 933     }
 934 
 935     @Fold
 936     public static long referentOffset() {
 937         try {
 938             return UNSAFE.objectFieldOffset(java.lang.ref.Reference.class.getDeclaredField("referent"));
 939         } catch (Exception e) {
 940             throw new GraalError(e);
 941         }
 942     }
 943 
 944     public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
 945         @Override
 946         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 947             ValueNode javaObject = findReadHub(object);
 948             if (javaObject != null) {
 949                 ResolvedJavaType type = StampTool.typeOrNull(javaObject);
 950                 if (type != null && type.isArray()) {
 951                     ResolvedJavaType element = type.getComponentType();
 952                     if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) {
 953                         Assumptions assumptions = object.graph().getAssumptions();
 954                         AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype();
 955                         if (leafType != null && leafType.canRecordTo(assumptions)) {
 956                             leafType.recordTo(assumptions);
 957                             return ConstantNode.forConstant(read.stamp(), tool.getConstantReflection().asObjectHub(leafType.getResult()), tool.getMetaAccess());
 958                         }
 959                     }
 960                 }
 961             }
 962             return read;
 963         }
 964     };
 965 
 966     @Fold
 967     public static int arrayClassElementOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 968         return config.arrayClassElementOffset;
 969     }
 970 
 971     public static final LocationIdentity PRIMARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("PrimarySupers");
 972 
 973     public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength");
 974 
 975     public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement");
 976 }