Skip to content

Commit f0a7818

Browse files
authored
Merge pull request #759 from nbhuiyan/vh-cas
Use Unsafe.compareAndExchange for writing to Stable field and array
2 parents 9f480ba + 33eb270 commit f0a7818

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

src/java.base/share/classes/java/lang/invoke/VarHandle.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,16 @@
2323
* questions.
2424
*/
2525

26+
/*
27+
* ===========================================================================
28+
* (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved
29+
* ===========================================================================
30+
*/
31+
2632
package java.lang.invoke;
2733

2834
import jdk.internal.HotSpotIntrinsicCandidate;
35+
import jdk.internal.misc.Unsafe;
2936
import jdk.internal.util.Preconditions;
3037
import jdk.internal.vm.annotation.ForceInline;
3138
import jdk.internal.vm.annotation.Stable;
@@ -1964,11 +1971,22 @@ static class TypesAndInvokers {
19641971
new MethodHandle[AccessMode.values().length];
19651972
}
19661973

1974+
private static final long TYPES_AND_INVOKERS_OFFSET;
1975+
1976+
static {
1977+
TYPES_AND_INVOKERS_OFFSET = UNSAFE.objectFieldOffset(VarHandle.class, "typesAndInvokers");
1978+
}
1979+
19671980
@ForceInline
19681981
private final TypesAndInvokers getTypesAndInvokers() {
19691982
TypesAndInvokers tis = typesAndInvokers;
19701983
if (tis == null) {
1971-
tis = typesAndInvokers = new TypesAndInvokers();
1984+
tis = new TypesAndInvokers();
1985+
Object other = UNSAFE.compareAndExchangeObject(this, TYPES_AND_INVOKERS_OFFSET, null, tis);
1986+
if (other != null) {
1987+
// Lost the race, so use what was set by winning thread.
1988+
tis = (TypesAndInvokers) other;
1989+
}
19721990
}
19731991
return tis;
19741992
}
@@ -1978,7 +1996,13 @@ final MethodHandle getMethodHandle(int mode) {
19781996
TypesAndInvokers tis = getTypesAndInvokers();
19791997
MethodHandle mh = tis.methodHandle_table[mode];
19801998
if (mh == null) {
1981-
mh = tis.methodHandle_table[mode] = getMethodHandleUncached(mode);
1999+
mh = getMethodHandleUncached(mode);
2000+
long offset = Unsafe.ARRAY_OBJECT_BASE_OFFSET + (Unsafe.ARRAY_OBJECT_INDEX_SCALE * mode);
2001+
Object other = UNSAFE.compareAndExchangeObject(tis.methodHandle_table, offset, null, mh);
2002+
if (other != null) {
2003+
// We lost the race. Use the winning thread's handle instead.
2004+
mh = (MethodHandle) other;
2005+
}
19822006
}
19832007
return mh;
19842008
}

0 commit comments

Comments
 (0)