use of org.graalvm.compiler.hotspot.word.KlassPointer in project graal by oracle.
the class InstanceOfSnippets method isAssignableFrom.
@Snippet
public static Object isAssignableFrom(@NonNullParameter Class<?> thisClassNonNull, Class<?> otherClass, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
if (otherClass == null) {
DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
return false;
}
GuardingNode anchorNode = SnippetAnchorNode.anchor();
Class<?> otherClassNonNull = PiNode.piCastNonNullClass(otherClass, anchorNode);
if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, thisClassNonNull == otherClassNonNull)) {
return trueValue;
}
KlassPointer thisHub = ClassGetHubNode.readClass(thisClassNonNull);
KlassPointer otherHub = ClassGetHubNode.readClass(otherClassNonNull);
if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !thisHub.isNull())) {
if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !otherHub.isNull())) {
GuardingNode guardNonNull = SnippetAnchorNode.anchor();
KlassPointer nonNullOtherHub = ClassGetHubNode.piCastNonNull(otherHub, guardNonNull);
if (TypeCheckSnippetUtils.checkUnknownSubType(thisHub, nonNullOtherHub, counters)) {
return trueValue;
}
}
}
// equal, return false.
return falseValue;
}
use of org.graalvm.compiler.hotspot.word.KlassPointer in project graal by oracle.
the class StubUtil method verifyObject.
/**
* Verifies that a given object value is well formed if {@code -XX:+VerifyOops} is enabled.
*/
public static Object verifyObject(Object object) {
if (verifyOops(INJECTED_VMCONFIG)) {
Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG));
verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1);
Pointer oop = Word.objectToTrackedPointer(object);
if (object != null) {
GuardingNode anchorNode = SnippetAnchorNode.anchor();
// make sure object is 'reasonable'
if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) {
fatal("oop not in heap: %p", oop.rawValue());
}
KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
if (klass.isNull()) {
fatal("klass for oop %p is null", oop.rawValue());
}
}
}
return object;
}
use of org.graalvm.compiler.hotspot.word.KlassPointer in project graal by oracle.
the class MonitorSnippets method tryEnterBiased.
private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) {
// See whether the lock is currently biased toward our thread and
// whether the epoch is still valid.
// Note that the runtime guarantees sufficient alignment of JavaThread
// pointers to allow age to be placed into low bits.
final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG));
// Check whether the bias pattern is present in the object's mark word
// and the bias owner and the epoch are both still current.
final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION);
final Word thread = registerAsWord(threadRegister);
final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG));
trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord);
trace(trace, " thread: 0x%016lx\n", thread);
trace(trace, " tmp: 0x%016lx\n", tmp);
if (probability(FAST_PATH_PROBABILITY, tmp.equal(0))) {
// Object is already biased to current thread -> done
traceObject(trace, "+lock{bias:existing}", object, true, options);
counters.lockBiasExisting.inc();
FastAcquireBiasedLockNode.mark(object);
return true;
}
// Now check to see whether biasing is enabled for this object
if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) {
Pointer objectPointer = Word.objectToTrackedPointer(object);
// the bias on this object.
if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) {
// illegal.
if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) {
// The epoch of the current bias is still valid but we know nothing
// about the owner; it might be set or it might be clear. Try to
// acquire the bias of the object using an atomic operation. If this
// fails we will go in to the runtime to revoke the object's bias.
// Note that we first construct the presumed unbiased header so we
// don't accidentally blow away another thread's valid bias.
Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG));
Word biasedMark = unbiasedMark.or(thread);
trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark);
trace(trace, " biasedMark: 0x%016lx\n", biasedMark);
if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), unbiasedMark, biasedMark, MARK_WORD_LOCATION))) {
// Object is now biased to current thread -> done
traceObject(trace, "+lock{bias:acquired}", object, true, options);
counters.lockBiasAcquired.inc();
return true;
}
// If the biasing toward our thread failed, this means that another thread
// owns the bias and we need to revoke that bias. The revocation will occur
// in the interpreter runtime.
traceObject(trace, "+lock{stub:revoke}", object, true, options);
counters.lockStubRevoke.inc();
} else {
// At this point we know the epoch has expired, meaning that the
// current bias owner, if any, is actually invalid. Under these
// circumstances _only_, are we allowed to use the current mark word
// value as the comparison value when doing the CAS to acquire the
// bias in the current epoch. In other words, we allow transfer of
// the bias from one thread to another directly in this situation.
Word biasedMark = prototypeMarkWord.or(thread);
trace(trace, " biasedMark: 0x%016lx\n", biasedMark);
if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, biasedMark, MARK_WORD_LOCATION))) {
// Object is now biased to current thread -> done
traceObject(trace, "+lock{bias:transfer}", object, true, options);
counters.lockBiasTransfer.inc();
return true;
}
// If the biasing toward our thread failed, then another thread
// succeeded in biasing it toward itself and we need to revoke that
// bias. The revocation will occur in the runtime in the slow case.
traceObject(trace, "+lock{stub:epoch-expired}", object, true, options);
counters.lockStubEpochExpired.inc();
}
// slow-path runtime-call
monitorenterStubC(MONITORENTER, object, lock);
return true;
} else {
// The prototype mark word doesn't have the bias bit set any
// more, indicating that objects of this data type are not supposed
// to be biased any more. We are going to try to reset the mark of
// this object to the prototype value and fall through to the
// CAS-based locking scheme. Note that if our CAS fails, it means
// that another thread raced us for the privilege of revoking the
// bias of this particular object, so it's okay to continue in the
// normal locking code.
Word result = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, prototypeMarkWord, MARK_WORD_LOCATION);
if (ENABLE_BREAKPOINT) {
bkpt(object, mark, tmp, result);
}
counters.revokeBias.inc();
return false;
}
} else {
// Biasing not enabled -> fall through to lightweight locking
counters.unbiasable.inc();
return false;
}
}
use of org.graalvm.compiler.hotspot.word.KlassPointer in project graal by oracle.
the class MonitorSnippets method monitorenter.
@Snippet
public static void monitorenter(Object object, KlassPointer hub, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister, @ConstantParameter boolean trace, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) {
verifyOop(object);
// Load the mark word - this includes a null-check on object
final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG));
final Word lock = beginLockScope(lockDepth);
Pointer objectPointer = Word.objectToTrackedPointer(object);
trace(trace, " object: 0x%016lx\n", objectPointer);
trace(trace, " lock: 0x%016lx\n", lock);
trace(trace, " mark: 0x%016lx\n", mark);
incCounter(options);
if (useBiasedLocking(INJECTED_VMCONFIG)) {
if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, options, counters)) {
return;
}
// not biased, fall-through
}
if (inlineFastLockSupported(options) && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) {
// Inflated case
if (tryEnterInflated(object, lock, mark, threadRegister, trace, options, counters)) {
return;
}
} else {
// Create the unlocked mark word pattern
Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG));
trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark);
// Copy this unlocked mark word into the lock slot on the stack
lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION);
// make sure previous store does not float below compareAndSwap
MembarNode.memoryBarrier(STORE_STORE);
// Test if the object's mark word is unlocked, and if so, store the
// (address of) the lock slot into the object's mark word.
Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION);
if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) {
traceObject(trace, "+lock{cas}", object, true, options);
counters.lockCas.inc();
AcquiredCASLockNode.mark(object);
return;
} else {
trace(trace, " currentMark: 0x%016lx\n", currentMark);
// The mark word in the object header was not the same.
// Either the object is locked by another thread or is already locked
// by the current thread. The latter is true if the mark word
// is a stack pointer into the current thread's stack, i.e.:
//
// 1) (currentMark & aligned_mask) == 0
// 2) rsp <= currentMark
// 3) currentMark <= rsp + page_size
//
// These 3 tests can be done by evaluating the following expression:
//
// (currentMark - rsp) & (aligned_mask - page_size)
//
// assuming both the stack pointer and page_size have their least
// significant 2 bits cleared and page_size is a power of 2
final Word alignedMask = WordFactory.unsigned(wordSize() - 1);
final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias);
if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).equal(0))) {
// Recursively locked => write 0 to the lock slot
lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), WordFactory.zero(), DISPLACED_MARK_WORD_LOCATION);
traceObject(trace, "+lock{cas:recursive}", object, true, options);
counters.lockCasRecursive.inc();
return;
}
traceObject(trace, "+lock{stub:failed-cas/stack}", object, true, options);
counters.lockStubFailedCas.inc();
}
}
// slow-path runtime-call
monitorenterStubC(MONITORENTER, object, lock);
}
use of org.graalvm.compiler.hotspot.word.KlassPointer in project graal by oracle.
the class InstanceOfSnippets method instanceofExact.
/**
* A test against a final type.
*/
@Snippet
public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
counters.isNull.inc();
return falseValue;
}
GuardingNode anchorNode = SnippetAnchorNode.anchor();
KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode));
if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) {
counters.exactMiss.inc();
return falseValue;
}
counters.exactHit.inc();
return trueValue;
}
Aggregations