1 /*
2 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.lang.invoke;
26
27 import java.util.Optional;
28
29 import jdk.internal.misc.Unsafe;
30 import jdk.internal.util.Preconditions;
31 import jdk.internal.value.ValueClass;
32 import jdk.internal.vm.annotation.ForceInline;
33
34 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
35
36 /// The var handle for polymorphic arrays.
37 final class ArrayVarHandle extends VarHandle {
38 static final int REFERENCE_BASE = Math.toIntExact(Unsafe.ARRAY_OBJECT_BASE_OFFSET);
39 static final int REFERENCE_SHIFT = Integer.numberOfTrailingZeros(Unsafe.ARRAY_OBJECT_INDEX_SCALE);
40 final Class<?> arrayType;
41 final Class<?> componentType;
42
43 ArrayVarHandle(Class<?> arrayType) {
44 this(arrayType, false);
45 }
46
47 private ArrayVarHandle(Class<?> arrayType, boolean exact) {
48 super(ArrayVarHandle.FORM, exact);
49 this.arrayType = arrayType;
50 this.componentType = arrayType.getComponentType();
51 }
52
53 @Override
54 public ArrayVarHandle withInvokeExactBehavior() {
55 return hasInvokeExactBehavior()
56 ? this
57 : new ArrayVarHandle(arrayType, true);
58 }
59
60 @Override
61 public ArrayVarHandle withInvokeBehavior() {
62 return !hasInvokeExactBehavior()
63 ? this
64 : new ArrayVarHandle(arrayType, false);
65 }
66
67 @Override
68 public Optional<VarHandleDesc> describeConstable() {
69 var arrayTypeRef = arrayType.describeConstable();
70 if (arrayTypeRef.isEmpty())
71 return Optional.empty();
72
73 return Optional.of(VarHandleDesc.ofArray(arrayTypeRef.get()));
74 }
75
76 @Override
77 final MethodType accessModeTypeUncached(AccessType at) {
78 return at.accessModeType(arrayType, componentType, int.class);
79 }
80
81 @ForceInline
82 static Object storeCheck(ArrayVarHandle handle, Object[] oarray, Object value) {
83 if (value == null && ValueClass.isNullRestrictedArray(oarray)) {
84 throw new NullPointerException("null not allowed for null-restricted array " + oarray.getClass().toGenericString());
85 }
86 if (handle.arrayType == oarray.getClass()) {
87 // Fast path: static array type same as argument array type
88 return handle.componentType.cast(value);
89 } else {
90 // Slow path: check value against argument array component type
91 return reflectiveTypeCheck(oarray, value);
92 }
93 }
94
95 @ForceInline
96 static Object reflectiveTypeCheck(Object[] oarray, Object value) {
97 try {
98 return oarray.getClass().getComponentType().cast(value);
99 } catch (ClassCastException e) {
100 throw new ArrayStoreException();
101 }
102 }
103
104 @ForceInline
105 static Object get(VarHandle ob, Object oarray, int index) {
106 ArrayVarHandle handle = (ArrayVarHandle) ob;
107 Object[] array = (Object[]) handle.arrayType.cast(oarray);
108 return array[index];
109 }
110
111 @ForceInline
112 static void set(VarHandle ob, Object oarray, int index, Object value) {
113 ArrayVarHandle handle = (ArrayVarHandle) ob;
114 Object[] array = (Object[]) handle.arrayType.cast(oarray);
115 array[index] = storeCheck(handle, array, value);
116 }
117
118 @ForceInline
119 static Object getVolatile(VarHandle ob, Object oarray, int index) {
120 ArrayVarHandle handle = (ArrayVarHandle) ob;
121 Object[] array = (Object[]) handle.arrayType.cast(oarray);
122 Class<?> arrayType = oarray.getClass();
123 if (ValueClass.isFlatArray(oarray)) {
124 // delegate to flat access primitives
125 VarHandles.checkAtomicFlatArray(array);
126 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
127 int ascale = UNSAFE.arrayInstanceIndexScale(array);
128 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
129 int layout = UNSAFE.arrayLayout(array);
130 return UNSAFE.getFlatValueVolatile(array,
131 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType());
132 }
133 return UNSAFE.getReferenceVolatile(array,
134 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE);
135 }
136
137 @ForceInline
138 static void setVolatile(VarHandle ob, Object oarray, int index, Object value) {
139 ArrayVarHandle handle = (ArrayVarHandle) ob;
140 Object[] array = (Object[]) handle.arrayType.cast(oarray);
141 Class<?> arrayType = oarray.getClass();
142 if (ValueClass.isFlatArray(oarray)) {
143 // delegate to flat access primitives
144 VarHandles.checkAtomicFlatArray(array);
145 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
146 int ascale = UNSAFE.arrayInstanceIndexScale(array);
147 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
148 int layout = UNSAFE.arrayLayout(array);
149 UNSAFE.putFlatValueVolatile(array,
150 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
151 storeCheck(handle, array, value));
152 return;
153 }
154 UNSAFE.putReferenceVolatile(array,
155 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE,
156 storeCheck(handle, array, value));
157 }
158
159 @ForceInline
160 static Object getOpaque(VarHandle ob, Object oarray, int index) {
161 ArrayVarHandle handle = (ArrayVarHandle) ob;
162 Object[] array = (Object[]) handle.arrayType.cast(oarray);
163 Class<?> arrayType = oarray.getClass();
164 if (ValueClass.isFlatArray(oarray)) {
165 // delegate to flat access primitives
166 VarHandles.checkAtomicFlatArray(array);
167 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
168 int ascale = UNSAFE.arrayInstanceIndexScale(array);
169 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
170 int layout = UNSAFE.arrayLayout(array);
171 return UNSAFE.getFlatValueOpaque(array,
172 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType());
173 }
174 return UNSAFE.getReferenceOpaque(array,
175 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE);
176 }
177
178 @ForceInline
179 static void setOpaque(VarHandle ob, Object oarray, int index, Object value) {
180 ArrayVarHandle handle = (ArrayVarHandle) ob;
181 Object[] array = (Object[]) handle.arrayType.cast(oarray);
182 Class<?> arrayType = oarray.getClass();
183 if (ValueClass.isFlatArray(oarray)) {
184 // delegate to flat access primitives
185 VarHandles.checkAtomicFlatArray(array);
186 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
187 int ascale = UNSAFE.arrayInstanceIndexScale(array);
188 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
189 int layout = UNSAFE.arrayLayout(array);
190 UNSAFE.putFlatValueOpaque(array,
191 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
192 storeCheck(handle, array, value));
193 return;
194 }
195 UNSAFE.putReferenceOpaque(array,
196 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE,
197 storeCheck(handle, array, value));
198 }
199
200 @ForceInline
201 static Object getAcquire(VarHandle ob, Object oarray, int index) {
202 ArrayVarHandle handle = (ArrayVarHandle) ob;
203 Object[] array = (Object[]) handle.arrayType.cast(oarray);
204 Class<?> arrayType = oarray.getClass();
205 if (ValueClass.isFlatArray(oarray)) {
206 // delegate to flat access primitives
207 VarHandles.checkAtomicFlatArray(array);
208 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
209 int ascale = UNSAFE.arrayInstanceIndexScale(array);
210 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
211 int layout = UNSAFE.arrayLayout(array);
212 return UNSAFE.getFlatValueAcquire(array,
213 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType());
214 }
215 return UNSAFE.getReferenceAcquire(array,
216 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE);
217 }
218
219 @ForceInline
220 static void setRelease(VarHandle ob, Object oarray, int index, Object value) {
221 ArrayVarHandle handle = (ArrayVarHandle) ob;
222 Object[] array = (Object[]) handle.arrayType.cast(oarray);
223 Class<?> arrayType = oarray.getClass();
224 if (ValueClass.isFlatArray(oarray)) {
225 // delegate to flat access primitives
226 VarHandles.checkAtomicFlatArray(array);
227 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
228 int ascale = UNSAFE.arrayInstanceIndexScale(array);
229 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
230 int layout = UNSAFE.arrayLayout(array);
231 UNSAFE.putFlatValueRelease(array,
232 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
233 storeCheck(handle, array, value));
234 return;
235 }
236 UNSAFE.putReferenceRelease(array,
237 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE,
238 storeCheck(handle, array, value));
239 }
240
241 @ForceInline
242 static boolean compareAndSet(VarHandle ob, Object oarray, int index, Object expected, Object value) {
243 ArrayVarHandle handle = (ArrayVarHandle) ob;
244 Object[] array = (Object[]) handle.arrayType.cast(oarray);
245 Class<?> arrayType = oarray.getClass();
246 if (ValueClass.isFlatArray(oarray)) {
247 // delegate to flat access primitives
248 VarHandles.checkAtomicFlatArray(array);
249 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
250 int ascale = UNSAFE.arrayInstanceIndexScale(array);
251 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
252 int layout = UNSAFE.arrayLayout(array);
253 return UNSAFE.compareAndSetFlatValue(array,
254 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
255 arrayType.componentType().cast(expected),
256 storeCheck(handle, array, value));
257 }
258 return UNSAFE.compareAndSetReference(array,
259 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
260 handle.componentType.cast(expected),
261 storeCheck(handle, array, value));
262 }
263
264 @ForceInline
265 static Object compareAndExchange(VarHandle ob, Object oarray, int index, Object expected, Object value) {
266 ArrayVarHandle handle = (ArrayVarHandle) ob;
267 Object[] array = (Object[]) handle.arrayType.cast(oarray);
268 Class<?> arrayType = oarray.getClass();
269 if (ValueClass.isFlatArray(oarray)) {
270 // delegate to flat access primitives
271 VarHandles.checkAtomicFlatArray(array);
272 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
273 int ascale = UNSAFE.arrayInstanceIndexScale(array);
274 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
275 int layout = UNSAFE.arrayLayout(array);
276 return UNSAFE.compareAndExchangeFlatValue(array,
277 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
278 arrayType.componentType().cast(expected),
279 storeCheck(handle, array, value));
280 }
281 return UNSAFE.compareAndExchangeReference(array,
282 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
283 handle.componentType.cast(expected),
284 storeCheck(handle, array, value));
285 }
286
287 @ForceInline
288 static Object compareAndExchangeAcquire(VarHandle ob, Object oarray, int index, Object expected, Object value) {
289 ArrayVarHandle handle = (ArrayVarHandle) ob;
290 Object[] array = (Object[]) handle.arrayType.cast(oarray);
291 Class<?> arrayType = oarray.getClass();
292 if (ValueClass.isFlatArray(oarray)) {
293 // delegate to flat access primitives
294 VarHandles.checkAtomicFlatArray(array);
295 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
296 int ascale = UNSAFE.arrayInstanceIndexScale(array);
297 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
298 int layout = UNSAFE.arrayLayout(array);
299 return UNSAFE.compareAndExchangeFlatValueAcquire(array,
300 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
301 arrayType.componentType().cast(expected),
302 storeCheck(handle, array, value));
303 }
304 return UNSAFE.compareAndExchangeReferenceAcquire(array,
305 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
306 handle.componentType.cast(expected),
307 storeCheck(handle, array, value));
308 }
309
310 @ForceInline
311 static Object compareAndExchangeRelease(VarHandle ob, Object oarray, int index, Object expected, Object value) {
312 ArrayVarHandle handle = (ArrayVarHandle) ob;
313 Object[] array = (Object[]) handle.arrayType.cast(oarray);
314 Class<?> arrayType = oarray.getClass();
315 if (ValueClass.isFlatArray(oarray)) {
316 // delegate to flat access primitives
317 VarHandles.checkAtomicFlatArray(array);
318 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
319 int ascale = UNSAFE.arrayInstanceIndexScale(array);
320 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
321 int layout = UNSAFE.arrayLayout(array);
322 return UNSAFE.compareAndExchangeFlatValueRelease(array,
323 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
324 arrayType.componentType().cast(expected),
325 storeCheck(handle, array, value));
326 }
327 return UNSAFE.compareAndExchangeReferenceRelease(array,
328 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
329 handle.componentType.cast(expected),
330 storeCheck(handle, array, value));
331 }
332
333 @ForceInline
334 static boolean weakCompareAndSetPlain(VarHandle ob, Object oarray, int index, Object expected, Object value) {
335 ArrayVarHandle handle = (ArrayVarHandle) ob;
336 Object[] array = (Object[]) handle.arrayType.cast(oarray);
337 Class<?> arrayType = oarray.getClass();
338 if (ValueClass.isFlatArray(oarray)) {
339 // delegate to flat access primitives
340 VarHandles.checkAtomicFlatArray(array);
341 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
342 int ascale = UNSAFE.arrayInstanceIndexScale(array);
343 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
344 int layout = UNSAFE.arrayLayout(array);
345 return UNSAFE.weakCompareAndSetFlatValuePlain(array,
346 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
347 arrayType.componentType().cast(expected),
348 storeCheck(handle, array, value));
349 }
350 return UNSAFE.weakCompareAndSetReferencePlain(array,
351 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
352 handle.componentType.cast(expected),
353 storeCheck(handle, array, value));
354 }
355
356 @ForceInline
357 static boolean weakCompareAndSet(VarHandle ob, Object oarray, int index, Object expected, Object value) {
358 ArrayVarHandle handle = (ArrayVarHandle) ob;
359 Object[] array = (Object[]) handle.arrayType.cast(oarray);
360 Class<?> arrayType = oarray.getClass();
361 if (ValueClass.isFlatArray(oarray)) {
362 // delegate to flat access primitives
363 VarHandles.checkAtomicFlatArray(array);
364 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
365 int ascale = UNSAFE.arrayInstanceIndexScale(array);
366 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
367 int layout = UNSAFE.arrayLayout(array);
368 return UNSAFE.weakCompareAndSetFlatValue(array,
369 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
370 arrayType.componentType().cast(expected),
371 storeCheck(handle, array, value));
372 }
373 return UNSAFE.weakCompareAndSetReference(array,
374 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
375 handle.componentType.cast(expected),
376 storeCheck(handle, array, value));
377 }
378
379 @ForceInline
380 static boolean weakCompareAndSetAcquire(VarHandle ob, Object oarray, int index, Object expected, Object value) {
381 ArrayVarHandle handle = (ArrayVarHandle) ob;
382 Object[] array = (Object[]) handle.arrayType.cast(oarray);
383 Class<?> arrayType = oarray.getClass();
384 if (ValueClass.isFlatArray(oarray)) {
385 // delegate to flat access primitives
386 VarHandles.checkAtomicFlatArray(array);
387 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
388 int ascale = UNSAFE.arrayInstanceIndexScale(array);
389 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
390 int layout = UNSAFE.arrayLayout(array);
391 return UNSAFE.weakCompareAndSetFlatValueAcquire(array,
392 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
393 arrayType.componentType().cast(expected),
394 storeCheck(handle, array, value));
395 }
396 return UNSAFE.weakCompareAndSetReferenceAcquire(array,
397 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
398 handle.componentType.cast(expected),
399 storeCheck(handle, array, value));
400 }
401
402 @ForceInline
403 static boolean weakCompareAndSetRelease(VarHandle ob, Object oarray, int index, Object expected, Object value) {
404 ArrayVarHandle handle = (ArrayVarHandle) ob;
405 Object[] array = (Object[]) handle.arrayType.cast(oarray);
406 Class<?> arrayType = oarray.getClass();
407 if (ValueClass.isFlatArray(oarray)) {
408 // delegate to flat access primitives
409 VarHandles.checkAtomicFlatArray(array);
410 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
411 int ascale = UNSAFE.arrayInstanceIndexScale(array);
412 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
413 int layout = UNSAFE.arrayLayout(array);
414 return UNSAFE.weakCompareAndSetFlatValueRelease(array,
415 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
416 arrayType.componentType().cast(expected),
417 storeCheck(handle, array, value));
418 }
419 return UNSAFE.weakCompareAndSetReferenceRelease(array,
420 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE, handle.componentType,
421 handle.componentType.cast(expected),
422 storeCheck(handle, array, value));
423 }
424
425 @ForceInline
426 static Object getAndSet(VarHandle ob, Object oarray, int index, Object value) {
427 ArrayVarHandle handle = (ArrayVarHandle) ob;
428 Object[] array = (Object[]) handle.arrayType.cast(oarray);
429 Class<?> arrayType = oarray.getClass();
430 if (ValueClass.isFlatArray(oarray)) {
431 // delegate to flat access primitives
432 VarHandles.checkAtomicFlatArray(array);
433 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
434 int ascale = UNSAFE.arrayInstanceIndexScale(array);
435 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
436 int layout = UNSAFE.arrayLayout(array);
437 return UNSAFE.getAndSetFlatValue(array,
438 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
439 storeCheck(handle, array, value));
440 }
441 return UNSAFE.getAndSetReference(array,
442 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE,
443 handle.componentType, storeCheck(handle, array, value));
444 }
445
446 @ForceInline
447 static Object getAndSetAcquire(VarHandle ob, Object oarray, int index, Object value) {
448 ArrayVarHandle handle = (ArrayVarHandle) ob;
449 Object[] array = (Object[]) handle.arrayType.cast(oarray);
450 Class<?> arrayType = oarray.getClass();
451 if (ValueClass.isFlatArray(oarray)) {
452 // delegate to flat access primitives
453 VarHandles.checkAtomicFlatArray(array);
454 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
455 int ascale = UNSAFE.arrayInstanceIndexScale(array);
456 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
457 int layout = UNSAFE.arrayLayout(array);
458 return UNSAFE.getAndSetFlatValueAcquire(array,
459 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
460 storeCheck(handle, array, value));
461 }
462 return UNSAFE.getAndSetReferenceAcquire(array,
463 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE,
464 handle.componentType, storeCheck(handle, array, value));
465 }
466
467 @ForceInline
468 static Object getAndSetRelease(VarHandle ob, Object oarray, int index, Object value) {
469 ArrayVarHandle handle = (ArrayVarHandle) ob;
470 Object[] array = (Object[]) handle.arrayType.cast(oarray);
471 Class<?> arrayType = oarray.getClass();
472 if (ValueClass.isFlatArray(oarray)) {
473 // delegate to flat access primitives
474 VarHandles.checkAtomicFlatArray(array);
475 int aoffset = (int) UNSAFE.arrayInstanceBaseOffset(array);
476 int ascale = UNSAFE.arrayInstanceIndexScale(array);
477 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
478 int layout = UNSAFE.arrayLayout(array);
479 return UNSAFE.getAndSetFlatValueRelease(array,
480 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << ashift) + aoffset, layout, arrayType.componentType(),
481 storeCheck(handle, array, value));
482 }
483 return UNSAFE.getAndSetReferenceRelease(array,
484 (((long) Preconditions.checkIndex(index, array.length, Preconditions.AIOOBE_FORMATTER)) << REFERENCE_SHIFT) + REFERENCE_BASE,
485 handle.componentType, storeCheck(handle, array, value));
486 }
487
488 static final VarForm FORM = new VarForm(ArrayVarHandle.class, Object[].class, Object.class, int.class);
489 }