< prev index next >

src/java.base/share/classes/jdk/internal/misc/Unsafe.java

Print this page

        

*** 175,193 **** --- 175,212 ---- * {@link NullPointerException} */ @HotSpotIntrinsicCandidate public native void putInt(Object o, long offset, int x); + private static final int JVM_ACC_FLATTENED = 0x00008000; // HotSpot-specific bit + + /** + * Returns true if the given field is flattened. + */ + public boolean isFlattened(Field f) { + return (f.getModifiers() & JVM_ACC_FLATTENED) == JVM_ACC_FLATTENED; + } + + /** + * Returns true if the given class is a flattened array. + */ + public native boolean isFlattenedArray(Class<?> arrayClass); + /** * Fetches a reference value from a given Java variable. + * This method can return a reference to either an object or value + * or a null reference. + * * @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native Object getReference(Object o, long offset); /** * Stores a reference value into a given Java variable. + * This method can store a reference to either an object or value + * or a null reference. * <p> * Unless the reference {@code x} being stored is either null * or matches the field type, the results are undefined. * If the reference {@code o} is non-null, card marks or * other store barriers for that object (if the VM requires them)
*** 195,204 **** --- 214,324 ---- * @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putReference(Object o, long offset, Object x); + /** + * Fetches a value of type {@code <V>} from a given Java variable. + * More specifically, fetches a field or array element within the given + * {@code o} object at the given offset, or (if {@code o} is null) + * from the memory address whose numerical value is the given offset. + * + * @param o Java heap object in which the variable resides, if any, else + * null + * @param offset indication of where the variable resides in a Java heap + * object, if any, else a memory address locating the variable + * statically + * @param vc inline class + * @param <V> the type of a value + * @return the value fetched from the indicated Java variable + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + */ + @HotSpotIntrinsicCandidate + public native <V> V getValue(Object o, long offset, Class<?> vc); + + /** + * Stores the given value into a given Java variable. + * + * Unless the reference {@code o} being stored is either null + * or matches the field type, the results are undefined. + * + * @param o Java heap object in which the variable resides, if any, else + * null + * @param offset indication of where the variable resides in a Java heap + * object, if any, else a memory address locating the variable + * statically + * @param vc inline class + * @param v the value to store into the indicated Java variable + * @param <V> the type of a value + * @throws RuntimeException No defined exceptions are thrown, not even + * {@link NullPointerException} + */ + @HotSpotIntrinsicCandidate + public native <V> void putValue(Object o, long offset, Class<?> vc, V v); + + /** + * Fetches a reference value of type {@code vc} from a given Java variable. + * This method can return a reference to a value or a null reference + * for a nullable-projection of an inline type. + * + * @param vc inline class + */ + public Object getReference(Object o, long offset, Class<?> vc) { + Object ref = getReference(o, offset); + if (ref == null && vc.isInlineClass() && !vc.isIndirectType()) { + // If the type of the returned reference is a regular inline type + // return an uninitialized default value if null + ref = uninitializedDefaultValue(vc); + } + return ref; + } + + public Object getReferenceVolatile(Object o, long offset, Class<?> vc) { + Object ref = getReferenceVolatile(o, offset); + if (ref == null && vc.isInlineClass() && !vc.isIndirectType()) { + // If the type of the returned reference is a regular inline type + // return an uninitialized default value if null + ref = uninitializedDefaultValue(vc); + } + return ref; + } + + /** + * Returns an uninitialized default value of the given inline class. + */ + public native <V> V uninitializedDefaultValue(Class<?> vc); + + /** + * Returns an object instance with a private buffered value whose layout + * and contents is exactly the given value instance. The return object + * is in the larval state that can be updated using the unsafe put operation. + * + * @param value a value instance + * @param <V> the type of the given value instance + */ + @HotSpotIntrinsicCandidate + public native <V> V makePrivateBuffer(V value); + + /** + * Exits the larval state and returns a value instance. + * + * @param value a value instance + * @param <V> the type of the given value instance + */ + @HotSpotIntrinsicCandidate + public native <V> V finishPrivateBuffer(V value); + + /** + * Returns the header size of the given inline class + * + * @param vc inline class + * @param <V> value clas + * @return the header size of the inline class + */ + public native <V> long valueHeaderSize(Class<V> vc); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native boolean getBoolean(Object o, long offset); /** @see #putInt(Object, long, int) */
*** 1301,1357 **** --- 1421,1661 ---- @HotSpotIntrinsicCandidate public final native boolean compareAndSetReference(Object o, long offset, Object expected, Object x); + private final boolean isInlineType(Object o) { + return o != null && o.getClass().isInlineClass(); + } + + /* + * For inline type, CAS should do substitutability test as opposed + * to two pointers comparison. + * + * Perhaps we can keep the xxxObject methods for compatibility and + * change the JDK 13 xxxReference method signature freely. + */ + public final <V> boolean compareAndSetReference(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + if (valueType.isInlineClass() || isInlineType(expected)) { + synchronized (valueLock) { + Object witness = getReference(o, offset); + if (witness == expected) { + putReference(o, offset, x); + return true; + } else { + return false; + } + } + } else { + return compareAndSetReference(o, offset, expected, x); + } + } + + @ForceInline + public final <V> boolean compareAndSetValue(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + synchronized (valueLock) { + Object witness = getValue(o, offset, valueType); + if (witness == expected) { + putValue(o, offset, valueType, x); + return true; + } + else { + return false; + } + } + } + @HotSpotIntrinsicCandidate public final native Object compareAndExchangeReference(Object o, long offset, Object expected, Object x); + public final <V> Object compareAndExchangeReference(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + if (valueType.isInlineClass() || isInlineType(expected)) { + synchronized (valueLock) { + Object witness = getReference(o, offset); + if (witness == expected) { + putReference(o, offset, x); + } + return witness; + } + } else { + return compareAndExchangeReference(o, offset, expected, x); + } + } + + @ForceInline + public final <V> Object compareAndExchangeValue(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + synchronized (valueLock) { + Object witness = getValue(o, offset, valueType); + if (witness == expected) { + putValue(o, offset, valueType, x); + } + return witness; + } + } + @HotSpotIntrinsicCandidate public final Object compareAndExchangeReferenceAcquire(Object o, long offset, Object expected, Object x) { return compareAndExchangeReference(o, offset, expected, x); } + public final <V> Object compareAndExchangeReferenceAcquire(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndExchangeReference(o, offset, valueType, expected, x); + } + + @ForceInline + public final <V> Object compareAndExchangeValueAcquire(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndExchangeValue(o, offset, valueType, expected, x); + } + @HotSpotIntrinsicCandidate public final Object compareAndExchangeReferenceRelease(Object o, long offset, Object expected, Object x) { return compareAndExchangeReference(o, offset, expected, x); } + public final <V> Object compareAndExchangeReferenceRelease(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndExchangeReference(o, offset, valueType, expected, x); + } + + @ForceInline + public final <V> Object compareAndExchangeValueRelease(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndExchangeValue(o, offset, valueType, expected, x); + } + @HotSpotIntrinsicCandidate public final boolean weakCompareAndSetReferencePlain(Object o, long offset, Object expected, Object x) { return compareAndSetReference(o, offset, expected, x); } + public final <V> boolean weakCompareAndSetReferencePlain(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + if (valueType.isInlineClass() || isInlineType(expected)) { + return compareAndSetReference(o, offset, valueType, expected, x); + } else { + return weakCompareAndSetReferencePlain(o, offset, expected, x); + } + } + + @ForceInline + public final <V> boolean weakCompareAndSetValuePlain(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndSetValue(o, offset, valueType, expected, x); + } + @HotSpotIntrinsicCandidate public final boolean weakCompareAndSetReferenceAcquire(Object o, long offset, Object expected, Object x) { return compareAndSetReference(o, offset, expected, x); } + public final <V> boolean weakCompareAndSetReferenceAcquire(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + if (valueType.isInlineClass() || isInlineType(expected)) { + return compareAndSetReference(o, offset, valueType, expected, x); + } else { + return weakCompareAndSetReferencePlain(o, offset, expected, x); + } + } + + @ForceInline + public final <V> boolean weakCompareAndSetValueAcquire(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndSetValue(o, offset, valueType, expected, x); + } + @HotSpotIntrinsicCandidate public final boolean weakCompareAndSetReferenceRelease(Object o, long offset, Object expected, Object x) { return compareAndSetReference(o, offset, expected, x); } + public final <V> boolean weakCompareAndSetReferenceRelease(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + if (valueType.isInlineClass() || isInlineType(expected)) { + return compareAndSetReference(o, offset, valueType, expected, x); + } else { + return weakCompareAndSetReferencePlain(o, offset, expected, x); + } + } + + @ForceInline + public final <V> boolean weakCompareAndSetValueRelease(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndSetValue(o, offset, valueType, expected, x); + } + @HotSpotIntrinsicCandidate public final boolean weakCompareAndSetReference(Object o, long offset, Object expected, Object x) { return compareAndSetReference(o, offset, expected, x); } + public final <V> boolean weakCompareAndSetReference(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + if (valueType.isInlineClass() || isInlineType(expected)) { + return compareAndSetReference(o, offset, valueType, expected, x); + } else { + return weakCompareAndSetReferencePlain(o, offset, expected, x); + } + } + + @ForceInline + public final <V> boolean weakCompareAndSetValue(Object o, long offset, + Class<?> valueType, + V expected, + V x) { + return compareAndSetValue(o, offset, valueType, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. * * <p>This operation has memory semantics of a {@code volatile} read
*** 1964,1979 **** --- 2268,2302 ---- */ @HotSpotIntrinsicCandidate public native Object getReferenceVolatile(Object o, long offset); /** + * Global lock for atomic and volatile strength access to any value of + * an inline type. This is a temporary workaround until better localized + * atomic access mechanisms are supported for inline types. + */ + private static final Object valueLock = new Object(); + + public final <V> Object getValueVolatile(Object base, long offset, Class<?> valueType) { + synchronized (valueLock) { + return getValue(base, offset, valueType); + } + } + + /** * Stores a reference value into a given Java variable, with * volatile store semantics. Otherwise identical to {@link #putReference(Object, long, Object)} */ @HotSpotIntrinsicCandidate public native void putReferenceVolatile(Object o, long offset, Object x); + public final <V> void putValueVolatile(Object o, long offset, Class<?> valueType, V x) { + synchronized (valueLock) { + putValue(o, offset, valueType, x); + } + } + /** Volatile version of {@link #getInt(Object, long)} */ @HotSpotIntrinsicCandidate public native int getIntVolatile(Object o, long offset); /** Volatile version of {@link #putInt(Object, long, int)} */
*** 2042,2051 **** --- 2365,2378 ---- @HotSpotIntrinsicCandidate public final Object getReferenceAcquire(Object o, long offset) { return getReferenceVolatile(o, offset); } + public final <V> Object getValueAcquire(Object base, long offset, Class<?> valueType) { + return getValueVolatile(base, offset, valueType); + } + /** Acquire version of {@link #getBooleanVolatile(Object, long)} */ @HotSpotIntrinsicCandidate public final boolean getBooleanAcquire(Object o, long offset) { return getBooleanVolatile(o, offset); }
*** 2106,2115 **** --- 2433,2446 ---- @HotSpotIntrinsicCandidate public final void putReferenceRelease(Object o, long offset, Object x) { putReferenceVolatile(o, offset, x); } + public final <V> void putValueRelease(Object o, long offset, Class<?> valueType, V x) { + putValueVolatile(o, offset, valueType, x); + } + /** Release version of {@link #putBooleanVolatile(Object, long, boolean)} */ @HotSpotIntrinsicCandidate public final void putBooleanRelease(Object o, long offset, boolean x) { putBooleanVolatile(o, offset, x); }
*** 2162,2171 **** --- 2493,2506 ---- @HotSpotIntrinsicCandidate public final Object getReferenceOpaque(Object o, long offset) { return getReferenceVolatile(o, offset); } + public final <V> Object getValueOpaque(Object base, long offset, Class<?> valueType) { + return getValueVolatile(base, offset, valueType); + } + /** Opaque version of {@link #getBooleanVolatile(Object, long)} */ @HotSpotIntrinsicCandidate public final boolean getBooleanOpaque(Object o, long offset) { return getBooleanVolatile(o, offset); }
*** 2216,2225 **** --- 2551,2564 ---- @HotSpotIntrinsicCandidate public final void putReferenceOpaque(Object o, long offset, Object x) { putReferenceVolatile(o, offset, x); } + public final <V> void putValueOpaque(Object o, long offset, Class<?> valueType, V x) { + putValueVolatile(o, offset, valueType, x); + } + /** Opaque version of {@link #putBooleanVolatile(Object, long, boolean)} */ @HotSpotIntrinsicCandidate public final void putBooleanOpaque(Object o, long offset, boolean x) { putBooleanVolatile(o, offset, x); }
*** 2650,2677 **** --- 2989,3035 ---- v = getReferenceVolatile(o, offset); } while (!weakCompareAndSetReference(o, offset, v, newValue)); return v; } + @SuppressWarnings("unchecked") + public final <V> Object getAndSetValue(Object o, long offset, Class<?> valueType, V newValue) { + synchronized (valueLock) { + Object oldValue = getValue(o, offset, valueType); + putValue(o, offset, valueType, newValue); + return oldValue; + } + } + @ForceInline public final Object getAndSetReferenceRelease(Object o, long offset, Object newValue) { Object v; do { v = getReference(o, offset); } while (!weakCompareAndSetReferenceRelease(o, offset, v, newValue)); return v; } @ForceInline + public final <V> Object getAndSetValueRelease(Object o, long offset, Class<?> valueType, V newValue) { + return getAndSetValue(o, offset, valueType, newValue); + } + + @ForceInline public final Object getAndSetReferenceAcquire(Object o, long offset, Object newValue) { Object v; do { v = getReferenceAcquire(o, offset); } while (!weakCompareAndSetReferenceAcquire(o, offset, v, newValue)); return v; } + @ForceInline + public final <V> Object getAndSetValueAcquire(Object o, long offset, Class<?> valueType, V newValue) { + return getAndSetValue(o, offset, valueType, newValue); + } + @HotSpotIntrinsicCandidate public final byte getAndSetByte(Object o, long offset, byte newValue) { byte v; do { v = getByteVolatile(o, offset);
< prev index next >