|
23 | 23 | * questions. |
24 | 24 | */ |
25 | 25 |
|
| 26 | +/* |
| 27 | + * =========================================================================== |
| 28 | + * (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved |
| 29 | + * =========================================================================== |
| 30 | + */ |
| 31 | + |
26 | 32 | package java.lang.invoke; |
27 | 33 |
|
28 | 34 | import java.lang.constant.ClassDesc; |
|
35 | 41 | import java.util.Objects; |
36 | 42 | import java.util.Optional; |
37 | 43 |
|
| 44 | +import jdk.internal.misc.Unsafe; |
38 | 45 | import jdk.internal.vm.annotation.DontInline; |
39 | 46 | import jdk.internal.vm.annotation.ForceInline; |
40 | 47 | import jdk.internal.vm.annotation.IntrinsicCandidate; |
@@ -2173,15 +2180,32 @@ public Optional<VarHandleDesc> describeConstable() { |
2173 | 2180 | @Stable |
2174 | 2181 | MethodHandle[] methodHandleTable; |
2175 | 2182 |
|
| 2183 | + private static final long METHOD_HANDLE_TABLE_OFFSET; |
| 2184 | + |
| 2185 | + static { |
| 2186 | + METHOD_HANDLE_TABLE_OFFSET = UNSAFE.objectFieldOffset(VarHandle.class, "methodHandleTable"); |
| 2187 | + } |
| 2188 | + |
2176 | 2189 | @ForceInline |
2177 | 2190 | final MethodHandle getMethodHandle(int mode) { |
2178 | 2191 | MethodHandle[] mhTable = methodHandleTable; |
2179 | 2192 | if (mhTable == null) { |
2180 | | - mhTable = methodHandleTable = new MethodHandle[AccessMode.COUNT]; |
| 2193 | + mhTable = new MethodHandle[AccessMode.COUNT]; |
| 2194 | + Object other = UNSAFE.compareAndExchangeReference(this, METHOD_HANDLE_TABLE_OFFSET, null, mhTable); |
| 2195 | + if (other != null) { |
| 2196 | + // We lost the race. Use the winning table instead. |
| 2197 | + mhTable = (MethodHandle[])other; |
| 2198 | + } |
2181 | 2199 | } |
2182 | 2200 | MethodHandle mh = mhTable[mode]; |
2183 | 2201 | if (mh == null) { |
2184 | | - mh = mhTable[mode] = getMethodHandleUncached(mode); |
| 2202 | + mh = getMethodHandleUncached(mode); |
| 2203 | + long offset = Unsafe.ARRAY_OBJECT_BASE_OFFSET + (Unsafe.ARRAY_OBJECT_INDEX_SCALE * mode); |
| 2204 | + Object other = UNSAFE.compareAndExchangeReference(mhTable, offset, null, mh); |
| 2205 | + if (other != null) { |
| 2206 | + // We lost the race. Use the winning handle instead. |
| 2207 | + mh = (MethodHandle)other; |
| 2208 | + } |
2185 | 2209 | } |
2186 | 2210 | return mh; |
2187 | 2211 | } |
|
0 commit comments