001/*
002 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.hotspot.replacements;
024
025import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
026import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
027import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
028import static jdk.internal.jvmci.common.UnsafeAccess.*;
029import jdk.internal.jvmci.code.*;
030import jdk.internal.jvmci.common.*;
031import jdk.internal.jvmci.hotspot.*;
032import jdk.internal.jvmci.meta.Assumptions.AssumptionResult;
033import jdk.internal.jvmci.meta.*;
034
035import com.oracle.graal.api.replacements.*;
036import com.oracle.graal.compiler.common.*;
037import com.oracle.graal.compiler.common.spi.*;
038import com.oracle.graal.compiler.common.type.*;
039import com.oracle.graal.graph.Node.ConstantNodeParameter;
040import com.oracle.graal.graph.Node.NodeIntrinsic;
041import com.oracle.graal.graph.spi.*;
042import com.oracle.graal.hotspot.nodes.*;
043import com.oracle.graal.hotspot.word.*;
044import com.oracle.graal.nodes.*;
045import com.oracle.graal.nodes.extended.*;
046import com.oracle.graal.nodes.memory.*;
047import com.oracle.graal.nodes.memory.address.*;
048import com.oracle.graal.nodes.type.*;
049import com.oracle.graal.replacements.*;
050import com.oracle.graal.replacements.nodes.*;
051import com.oracle.graal.word.*;
052
053//JaCoCo Exclude
054
055/**
056 * A collection of methods used in HotSpot snippets, substitutions and stubs.
057 */
058public class HotSpotReplacementsUtil {
059
060    abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation {
061
062        HotSpotOptimizingLocationIdentity(String name) {
063            super(name, true);
064        }
065
066        @Override
067        public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
068
069        protected ValueNode findReadHub(ValueNode object) {
070            ValueNode base = object;
071            if (base instanceof CompressionNode) {
072                base = ((CompressionNode) base).getValue();
073            }
074            if (base instanceof Access) {
075                Access access = (Access) base;
076                if (access.getLocationIdentity().equals(HUB_LOCATION)) {
077                    AddressNode address = access.getAddress();
078                    if (address instanceof OffsetAddressNode) {
079                        OffsetAddressNode offset = (OffsetAddressNode) address;
080                        return offset.getBase();
081                    }
082                }
083            } else if (base instanceof LoadHubNode) {
084                LoadHubNode loadhub = (LoadHubNode) base;
085                return loadhub.getValue();
086            }
087            return null;
088        }
089
090        /**
091         * Fold reads that convert from Class -> Hub -> Class or vice versa.
092         *
093         * @param read
094         * @param object
095         * @param otherLocation
096         * @return an earlier read or the original {@code read}
097         */
098        protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) {
099            if (object instanceof Access) {
100                Access access = (Access) object;
101                if (access.getLocationIdentity().equals(otherLocation)) {
102                    AddressNode address = access.getAddress();
103                    if (address instanceof OffsetAddressNode) {
104                        OffsetAddressNode offset = (OffsetAddressNode) address;
105                        assert offset.getBase().stamp().isCompatible(read.stamp());
106                        return offset.getBase();
107                    }
108                }
109            }
110            return read;
111        }
112    }
113
114    @Fold
115    public static HotSpotVMConfig config() {
116        return runtime().getConfig();
117    }
118
119    @Fold
120    public static boolean useTLAB() {
121        return config().useTLAB;
122    }
123
124    @Fold
125    public static boolean verifyOops() {
126        return config().verifyOops;
127    }
128
129    public static final LocationIdentity EXCEPTION_OOP_LOCATION = NamedLocationIdentity.mutable("ExceptionOop");
130
131    /**
132     * @see HotSpotVMConfig#threadExceptionOopOffset
133     */
134    @Fold
135    public static int threadExceptionOopOffset() {
136        return config().threadExceptionOopOffset;
137    }
138
139    public static final LocationIdentity EXCEPTION_PC_LOCATION = NamedLocationIdentity.mutable("ExceptionPc");
140
141    @Fold
142    public static int threadExceptionPcOffset() {
143        return config().threadExceptionPcOffset;
144    }
145
146    public static final LocationIdentity LAST_JAVA_PC_LOCATION = NamedLocationIdentity.mutable("LastJavaPc");
147
148    @Fold
149    public static int threadLastJavaPcOffset() {
150        return config().threadLastJavaPcOffset();
151    }
152
153    public static final LocationIdentity LAST_JAVA_FP_LOCATION = NamedLocationIdentity.mutable("LastJavaFp");
154
155    @Fold
156    public static int threadLastJavaFpOffset() {
157        return config().threadLastJavaFpOffset();
158    }
159
160    public static final LocationIdentity TLAB_TOP_LOCATION = NamedLocationIdentity.mutable("TlabTop");
161
162    @Fold
163    public static int threadTlabTopOffset() {
164        return config().threadTlabTopOffset();
165    }
166
167    public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd");
168
169    @Fold
170    private static int threadTlabEndOffset() {
171        return config().threadTlabEndOffset();
172    }
173
174    public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart");
175
176    @Fold
177    private static int threadTlabStartOffset() {
178        return config().threadTlabStartOffset();
179    }
180
181    public static final LocationIdentity PENDING_EXCEPTION_LOCATION = NamedLocationIdentity.mutable("PendingException");
182
183    /**
184     * @see HotSpotVMConfig#pendingExceptionOffset
185     */
186    @Fold
187    private static int threadPendingExceptionOffset() {
188        return config().pendingExceptionOffset;
189    }
190
191    public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = NamedLocationIdentity.mutable("PendingDeoptimization");
192
193    /**
194     * @see HotSpotVMConfig#pendingDeoptimizationOffset
195     */
196    @Fold
197    private static int threadPendingDeoptimizationOffset() {
198        return config().pendingDeoptimizationOffset;
199    }
200
201    public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult");
202
203    @Fold
204    private static int objectResultOffset() {
205        return config().threadObjectResultOffset;
206    }
207
208    /**
209     * @see HotSpotVMConfig#threadExceptionOopOffset
210     */
211    public static Object readExceptionOop(Word thread) {
212        return thread.readObject(threadExceptionOopOffset(), EXCEPTION_OOP_LOCATION);
213    }
214
215    public static Word readExceptionPc(Word thread) {
216        return thread.readWord(threadExceptionPcOffset(), EXCEPTION_PC_LOCATION);
217    }
218
219    /**
220     * @see HotSpotVMConfig#threadExceptionOopOffset
221     */
222    public static void writeExceptionOop(Word thread, Object value) {
223        thread.writeObject(threadExceptionOopOffset(), value, EXCEPTION_OOP_LOCATION);
224    }
225
226    public static void writeExceptionPc(Word thread, Word value) {
227        thread.writeWord(threadExceptionPcOffset(), value, EXCEPTION_PC_LOCATION);
228    }
229
230    public static void writeLastJavaPc(Word thread, Word value) {
231        thread.writeWord(threadLastJavaPcOffset(), value, LAST_JAVA_PC_LOCATION);
232    }
233
234    public static void writeLastJavaFp(Word thread, Word value) {
235        thread.writeWord(threadLastJavaFpOffset(), value, LAST_JAVA_FP_LOCATION);
236    }
237
238    public static Word readTlabTop(Word thread) {
239        return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION);
240    }
241
242    public static Word readTlabEnd(Word thread) {
243        return thread.readWord(threadTlabEndOffset(), TLAB_END_LOCATION);
244    }
245
246    public static Word readTlabStart(Word thread) {
247        return thread.readWord(threadTlabStartOffset(), TLAB_START_LOCATION);
248    }
249
250    public static void writeTlabTop(Word thread, Word top) {
251        thread.writeWord(threadTlabTopOffset(), top, TLAB_TOP_LOCATION);
252    }
253
254    public static void initializeTlab(Word thread, Word start, Word end) {
255        thread.writeWord(threadTlabStartOffset(), start, TLAB_START_LOCATION);
256        thread.writeWord(threadTlabTopOffset(), start, TLAB_TOP_LOCATION);
257        thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION);
258    }
259
260    /**
261     * Clears the pending exception for the given thread.
262     *
263     * @return {@code true} if there was a pending exception
264     */
265    public static boolean clearPendingException(Word thread) {
266        boolean result = thread.readObject(threadPendingExceptionOffset(), PENDING_EXCEPTION_LOCATION) != null;
267        thread.writeObject(threadPendingExceptionOffset(), null, PENDING_EXCEPTION_LOCATION);
268        return result;
269    }
270
271    /**
272     * Reads the pending deoptimization value for the given thread.
273     *
274     * @return {@code true} if there was a pending deoptimization
275     */
276    public static int readPendingDeoptimization(Word thread) {
277        return thread.readInt(threadPendingDeoptimizationOffset(), PENDING_DEOPTIMIZATION_LOCATION);
278    }
279
280    /**
281     * Writes the pending deoptimization value for the given thread.
282     */
283    public static void writePendingDeoptimization(Word thread, int value) {
284        thread.writeInt(threadPendingDeoptimizationOffset(), value, PENDING_DEOPTIMIZATION_LOCATION);
285    }
286
287    /**
288     * Gets and clears the object result from a runtime call stored in a thread local.
289     *
290     * @return the object that was in the thread local
291     */
292    public static Object getAndClearObjectResult(Word thread) {
293        Object result = thread.readObject(objectResultOffset(), OBJECT_RESULT_LOCATION);
294        thread.writeObject(objectResultOffset(), null, OBJECT_RESULT_LOCATION);
295        return result;
296    }
297
298    public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj");
299
300    @Fold
301    public static int threadObjectOffset() {
302        return config().threadObjectOffset;
303    }
304
305    public static final LocationIdentity JAVA_THREAD_OSTHREAD_LOCATION = NamedLocationIdentity.mutable("JavaThread::_osthread");
306
307    @Fold
308    public static int osThreadOffset() {
309        return config().osThreadOffset;
310    }
311
312    @Fold
313    public static int osThreadInterruptedOffset() {
314        return config().osThreadInterruptedOffset;
315    }
316
317    @Fold
318    public static Kind getWordKind() {
319        return runtime().getTarget().wordKind;
320    }
321
322    @Fold
323    public static int wordSize() {
324        return runtime().getTarget().wordSize;
325    }
326
327    @Fold
328    public static int pageSize() {
329        return unsafe.pageSize();
330    }
331
332    @Fold
333    public static int heapWordSize() {
334        return config().heapWordSize;
335    }
336
337    public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord");
338
339    @Fold
340    public static int prototypeMarkWordOffset() {
341        return config().prototypeMarkWordOffset;
342    }
343
344    @Fold
345    public static long arrayPrototypeMarkWord() {
346        return config().arrayPrototypeMarkWord();
347    }
348
349    public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags");
350
351    @Fold
352    public static int klassAccessFlagsOffset() {
353        return config().klassAccessFlagsOffset;
354    }
355
356    @Fold
357    public static int jvmAccWrittenFlags() {
358        return config().jvmAccWrittenFlags;
359    }
360
361    public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") {
362        @Override
363        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
364            ValueNode javaObject = findReadHub(object);
365            if (javaObject != null) {
366                if (javaObject.stamp() instanceof ObjectStamp) {
367                    ObjectStamp stamp = (ObjectStamp) javaObject.stamp();
368                    HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess());
369                    if (type.isArray() && !type.getComponentType().isPrimitive()) {
370                        int layout = ((HotSpotResolvedObjectTypeImpl) type).layoutHelper();
371                        return ConstantNode.forInt(layout);
372                    }
373                }
374            }
375            return read;
376        }
377    };
378
379    @Fold
380    public static int klassLayoutHelperOffset() {
381        return config().klassLayoutHelperOffset;
382    }
383
384    public static int readLayoutHelper(KlassPointer hub) {
385        // return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION);
386        GuardingNode anchorNode = SnippetAnchorNode.anchor();
387        return loadKlassLayoutHelperIntrinsic(hub, anchorNode);
388    }
389
390    @NodeIntrinsic(value = KlassLayoutHelperNode.class)
391    public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object, GuardingNode anchor);
392
393    @NodeIntrinsic(value = KlassLayoutHelperNode.class)
394    public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object);
395
396    /**
397     * Checks if class {@code klass} is an array.
398     *
399     * See: Klass::layout_helper_is_array
400     *
401     * @param klass the class to be checked
402     * @return true if klass is an array, false otherwise
403     */
404    public static boolean klassIsArray(KlassPointer klass) {
405        /*
406         * The less-than check only works if both values are ints. We use local variables to make
407         * sure these are still ints and haven't changed.
408         */
409        final int layoutHelper = readLayoutHelper(klass);
410        final int layoutHelperNeutralValue = config().klassLayoutHelperNeutralValue;
411        return (layoutHelper < layoutHelperNeutralValue);
412    }
413
414    public static final LocationIdentity ARRAY_KLASS_COMPONENT_MIRROR = NamedLocationIdentity.immutable("ArrayKlass::_component_mirror");
415
416    @Fold
417    public static int arrayKlassComponentMirrorOffset() {
418        return config().arrayKlassComponentMirrorOffset;
419    }
420
421    public static final LocationIdentity KLASS_SUPER_KLASS_LOCATION = NamedLocationIdentity.immutable("Klass::_super");
422
423    @Fold
424    public static int klassSuperKlassOffset() {
425        return config().klassSuperKlassOffset;
426    }
427
428    public static final LocationIdentity MARK_WORD_LOCATION = NamedLocationIdentity.mutable("MarkWord");
429
430    @Fold
431    public static int markOffset() {
432        return config().markOffset;
433    }
434
435    public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write");
436
437    public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") {
438        @Override
439        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
440            ResolvedJavaType constantType = LoadHubNode.findSynonymType(read.graph(), tool.getMetaAccess(), object);
441            if (constantType != null) {
442                if (config().useCompressedClassPointers) {
443                    return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) constantType.getObjectHub()).compress(config().getKlassEncoding()), tool.getMetaAccess());
444                } else {
445                    return ConstantNode.forConstant(read.stamp(), constantType.getObjectHub(), tool.getMetaAccess());
446                }
447            }
448            return read;
449        }
450    };
451
452    @Fold
453    private static int hubOffset() {
454        return config().hubOffset;
455    }
456
457    public static void initializeObjectHeader(Word memory, Word markWord, KlassPointer hub) {
458        memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION);
459        StoreHubNode.write(memory, hub);
460    }
461
462    @Fold
463    public static int unlockedMask() {
464        return config().unlockedMask;
465    }
466
467    /**
468     * Mask for a biasable, locked or unlocked mark word.
469     *
470     * <pre>
471     * +----------------------------------+-+-+
472     * |                                 1|1|1|
473     * +----------------------------------+-+-+
474     * </pre>
475     *
476     */
477    @Fold
478    public static int biasedLockMaskInPlace() {
479        return config().biasedLockMaskInPlace;
480    }
481
482    @Fold
483    public static int epochMaskInPlace() {
484        return config().epochMaskInPlace;
485    }
486
487    /**
488     * Pattern for a biasable, unlocked mark word.
489     *
490     * <pre>
491     * +----------------------------------+-+-+
492     * |                                 1|0|1|
493     * +----------------------------------+-+-+
494     * </pre>
495     *
496     */
497    @Fold
498    public static int biasedLockPattern() {
499        return config().biasedLockPattern;
500    }
501
502    @Fold
503    public static int ageMaskInPlace() {
504        return config().ageMaskInPlace;
505    }
506
507    @Fold
508    public static int metaspaceArrayLengthOffset() {
509        return config().metaspaceArrayLengthOffset;
510    }
511
512    @Fold
513    public static int metaspaceArrayBaseOffset() {
514        return config().metaspaceArrayBaseOffset;
515    }
516
517    @Fold
518    public static int arrayLengthOffset() {
519        return config().arrayLengthOffset;
520    }
521
522    @Fold
523    public static int arrayBaseOffset(Kind elementKind) {
524        return runtime().getJVMCIRuntime().getArrayBaseOffset(elementKind);
525    }
526
527    @Fold
528    public static int arrayIndexScale(Kind elementKind) {
529        return runtime().getJVMCIRuntime().getArrayIndexScale(elementKind);
530    }
531
532    @Fold
533    public static int instanceHeaderSize() {
534        return config().useCompressedClassPointers ? (2 * wordSize()) - 4 : 2 * wordSize();
535    }
536
537    @Fold
538    public static byte dirtyCardValue() {
539        return config().dirtyCardValue;
540    }
541
542    @Fold
543    public static byte g1YoungCardValue() {
544        return config().g1YoungCardValue;
545    }
546
547    @Fold
548    public static int cardTableShift() {
549        return config().cardtableShift();
550    }
551
552    @Fold
553    public static long cardTableStart() {
554        return config().cardtableStartAddress();
555    }
556
557    @Fold
558    public static int g1CardQueueIndexOffset() {
559        return config().g1CardQueueIndexOffset();
560    }
561
562    @Fold
563    public static int g1CardQueueBufferOffset() {
564        return config().g1CardQueueBufferOffset();
565    }
566
567    @Fold
568    public static int logOfHeapRegionGrainBytes() {
569        return config().logOfHRGrainBytes;
570    }
571
572    @Fold
573    public static int g1SATBQueueMarkingOffset() {
574        return config().g1SATBQueueMarkingOffset();
575    }
576
577    @Fold
578    public static int g1SATBQueueIndexOffset() {
579        return config().g1SATBQueueIndexOffset();
580    }
581
582    @Fold
583    public static int g1SATBQueueBufferOffset() {
584        return config().g1SATBQueueBufferOffset();
585    }
586
587    public static final LocationIdentity KLASS_SUPER_CHECK_OFFSET_LOCATION = NamedLocationIdentity.immutable("Klass::_super_check_offset");
588
589    @Fold
590    public static int superCheckOffsetOffset() {
591        return config().superCheckOffsetOffset;
592    }
593
594    public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = NamedLocationIdentity.mutable("SecondarySuperCache");
595
596    @Fold
597    public static int secondarySuperCacheOffset() {
598        return config().secondarySuperCacheOffset;
599    }
600
601    public static final LocationIdentity SECONDARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("SecondarySupers");
602
603    @Fold
604    public static int secondarySupersOffset() {
605        return config().secondarySupersOffset;
606    }
607
608    public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord");
609
610    @Fold
611    public static int lockDisplacedMarkOffset() {
612        return config().basicLockDisplacedHeaderOffset;
613    }
614
615    @Fold
616    public static boolean useBiasedLocking() {
617        return config().useBiasedLocking;
618    }
619
620    @Fold
621    public static boolean useDeferredInitBarriers() {
622        return config().useDeferredInitBarriers;
623    }
624
625    @Fold
626    public static boolean useG1GC() {
627        return config().useG1GC;
628    }
629
630    @Fold
631    public static boolean useCompressedOops() {
632        return config().useCompressedOops;
633    }
634
635    @Fold
636    static int uninitializedIdentityHashCodeValue() {
637        return config().uninitializedIdentityHashCodeValue;
638    }
639
640    @Fold
641    static int identityHashCodeShift() {
642        return config().identityHashCodeShift;
643    }
644
645    /**
646     * Loads the hub of an object (without null checking it first).
647     */
648    public static KlassPointer loadHub(Object object) {
649        return loadHubIntrinsic(object);
650    }
651
652    public static Object verifyOop(Object object) {
653        if (verifyOops()) {
654            verifyOopStub(VERIFY_OOP, object);
655        }
656        return object;
657    }
658
659    @NodeIntrinsic(ForeignCallNode.class)
660    private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
661
662    public static Word loadWordFromObject(Object object, int offset) {
663        ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject");
664        return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any());
665    }
666
667    public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) {
668        ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject");
669        return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity);
670    }
671
672    public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
673        ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject");
674        return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity);
675    }
676
677    /**
678     * Reads the value of a given register.
679     *
680     * @param register a register which must not be available to the register allocator
681     * @return the value of {@code register} as a word
682     */
683    public static Word registerAsWord(@ConstantNodeParameter Register register) {
684        return registerAsWord(register, true, false);
685    }
686
687    @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true)
688    public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
689
690    @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true)
691    public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value);
692
693    @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
694    private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
695
696    @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true)
697    private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity);
698
699    @NodeIntrinsic(value = LoadHubNode.class)
700    public static native KlassPointer loadHubIntrinsic(Object object, GuardingNode anchor);
701
702    @NodeIntrinsic(value = LoadHubNode.class)
703    public static native KlassPointer loadHubIntrinsic(Object object);
704
705    @Fold
706    public static int log2WordSize() {
707        return CodeUtil.log2(wordSize());
708    }
709
710    public static final LocationIdentity CLASS_STATE_LOCATION = NamedLocationIdentity.mutable("ClassState");
711
712    @Fold
713    public static int instanceKlassInitStateOffset() {
714        return config().instanceKlassInitStateOffset;
715    }
716
717    @Fold
718    public static int instanceKlassStateFullyInitialized() {
719        return config().instanceKlassStateFullyInitialized;
720    }
721
722    public static final LocationIdentity INSTANCE_KLASS_CONSTANTS = NamedLocationIdentity.immutable("InstanceKlass::_constants");
723
724    @Fold
725    public static int instanceKlassConstantsOffset() {
726        return config().instanceKlassConstantsOffset;
727    }
728
729    /**
730     *
731     * @param hub the hub of an InstanceKlass
732     * @return true is the InstanceKlass represented by hub is fully initialized
733     */
734    public static boolean isInstanceKlassFullyInitialized(KlassPointer hub) {
735        return readInstanceKlassState(hub) == instanceKlassStateFullyInitialized();
736    }
737
738    private static byte readInstanceKlassState(KlassPointer hub) {
739        return hub.readByte(instanceKlassInitStateOffset(), CLASS_STATE_LOCATION);
740    }
741
742    public static final LocationIdentity KLASS_MODIFIER_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_modifier_flags");
743
744    @Fold
745    public static int klassModifierFlagsOffset() {
746        return config().klassModifierFlagsOffset;
747    }
748
749    public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") {
750        @Override
751        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
752            return foldIndirection(read, object, CLASS_MIRROR_LOCATION);
753        }
754    };
755
756    @Fold
757    public static int klassOffset() {
758        return config().klassOffset;
759    }
760
761    public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") {
762        @Override
763        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
764            return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR);
765        }
766    };
767
768    @Fold
769    public static int arrayKlassOffset() {
770        return config().arrayKlassOffset;
771    }
772
773    public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror");
774
775    @Fold
776    public static int classMirrorOffset() {
777        return config().classMirrorOffset;
778    }
779
780    @Fold
781    public static int constantPoolSize() {
782        return config().constantPoolSize;
783    }
784
785    @Fold
786    public static int constantPoolHolderOffset() {
787        return config().constantPoolHolderOffset;
788    }
789
790    @Fold
791    public static int constantPoolLengthOffset() {
792        return config().constantPoolLengthOffset;
793    }
794
795    public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop");
796
797    @Fold
798    public static long heapTopAddress() {
799        return config().heapTopAddress;
800    }
801
802    public static final LocationIdentity HEAP_END_LOCATION = NamedLocationIdentity.mutable("HeapEnd");
803
804    @Fold
805    public static long heapEndAddress() {
806        return config().heapEndAddress;
807    }
808
809    @Fold
810    public static long tlabIntArrayMarkWord() {
811        return config().tlabIntArrayMarkWord();
812    }
813
814    @Fold
815    public static boolean inlineContiguousAllocationSupported() {
816        return config().inlineContiguousAllocationSupported;
817    }
818
819    @Fold
820    public static int tlabAlignmentReserveInHeapWords() {
821        return config().tlabAlignmentReserve;
822    }
823
824    public static final LocationIdentity TLAB_SIZE_LOCATION = NamedLocationIdentity.mutable("TlabSize");
825
826    @Fold
827    public static int threadTlabSizeOffset() {
828        return config().threadTlabSizeOffset();
829    }
830
831    public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = NamedLocationIdentity.mutable("TlabThreadAllocatedBytes");
832
833    @Fold
834    public static int threadAllocatedBytesOffset() {
835        return config().threadAllocatedBytesOffset;
836    }
837
838    public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = NamedLocationIdentity.mutable("RefillWasteLimit");
839
840    @Fold
841    public static int tlabRefillWasteLimitOffset() {
842        return config().tlabRefillWasteLimitOffset();
843    }
844
845    public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = NamedLocationIdentity.mutable("TlabNOfRefills");
846
847    @Fold
848    public static int tlabNumberOfRefillsOffset() {
849        return config().tlabNumberOfRefillsOffset();
850    }
851
852    public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = NamedLocationIdentity.mutable("TlabFastRefillWaste");
853
854    @Fold
855    public static int tlabFastRefillWasteOffset() {
856        return config().tlabFastRefillWasteOffset();
857    }
858
859    public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = NamedLocationIdentity.mutable("TlabSlowAllocations");
860
861    @Fold
862    public static int tlabSlowAllocationsOffset() {
863        return config().tlabSlowAllocationsOffset();
864    }
865
866    @Fold
867    public static int tlabRefillWasteIncrement() {
868        return config().tlabRefillWasteIncrement;
869    }
870
871    @Fold
872    public static boolean tlabStats() {
873        return config().tlabStats;
874    }
875
876    @Fold
877    public static int layoutHelperHeaderSizeShift() {
878        return config().layoutHelperHeaderSizeShift;
879    }
880
881    @Fold
882    public static int layoutHelperHeaderSizeMask() {
883        return config().layoutHelperHeaderSizeMask;
884    }
885
886    @Fold
887    public static int layoutHelperLog2ElementSizeShift() {
888        return config().layoutHelperLog2ElementSizeShift;
889    }
890
891    @Fold
892    public static int layoutHelperLog2ElementSizeMask() {
893        return config().layoutHelperLog2ElementSizeMask;
894    }
895
896    @Fold
897    public static int layoutHelperElementTypeShift() {
898        return config().layoutHelperElementTypeShift;
899    }
900
901    @Fold
902    public static int layoutHelperElementTypeMask() {
903        return config().layoutHelperElementTypeMask;
904    }
905
906    @Fold
907    public static int layoutHelperElementTypePrimitiveInPlace() {
908        return config().layoutHelperElementTypePrimitiveInPlace();
909    }
910
911    static int computeHashCode(Object x) {
912        Word mark = loadWordFromObject(x, markOffset());
913
914        // this code is independent from biased locking (although it does not look that way)
915        final Word biasedLock = mark.and(biasedLockMaskInPlace());
916        if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(Word.unsigned(unlockedMask())))) {
917            int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue();
918            if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue())) {
919                return hash;
920            }
921        }
922
923        return identityHashCode(IDENTITY_HASHCODE, x);
924    }
925
926    @NodeIntrinsic(ForeignCallNode.class)
927    public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
928
929    @Fold
930    public static boolean isImmutableCode() {
931        return GraalOptions.ImmutableCode.getValue();
932    }
933
934    @Fold
935    public static boolean generatePIC() {
936        return GraalOptions.GeneratePIC.getValue();
937    }
938
939    @Fold
940    public static int verifiedEntryPointOffset() {
941        return config().nmethodEntryOffset;
942    }
943
944    @Fold
945    public static long gcTotalCollectionsAddress() {
946        return config().gcTotalCollectionsAddress();
947    }
948
949    @Fold
950    public static long referentOffset() {
951        try {
952            return unsafe.objectFieldOffset(java.lang.ref.Reference.class.getDeclaredField("referent"));
953        } catch (Exception e) {
954            throw new JVMCIError(e);
955        }
956    }
957
958    public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
959        @Override
960        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
961            ValueNode javaObject = findReadHub(object);
962            if (javaObject != null) {
963                ResolvedJavaType type = StampTool.typeOrNull(javaObject);
964                if (type != null && type.isArray()) {
965                    ResolvedJavaType element = type.getComponentType();
966                    if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) {
967                        AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype();
968                        if (leafType != null) {
969                            object.graph().getAssumptions().record(leafType);
970                            return ConstantNode.forConstant(read.stamp(), leafType.getResult().getObjectHub(), tool.getMetaAccess());
971                        }
972                    }
973                }
974            }
975            return read;
976        }
977    };
978
979    @Fold
980    public static int arrayClassElementOffset() {
981        return config().arrayClassElementOffset;
982    }
983
984    public static final LocationIdentity PRIMARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("PrimarySupers");
985
986    public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength");
987
988    public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement");
989}