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