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.arrayBaseOffset(array); 127 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 146 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 168 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 187 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 209 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 228 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 250 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 273 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 296 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 319 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 342 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 365 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 388 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 411 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 434 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 455 int ascale = UNSAFE.arrayIndexScale(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.arrayBaseOffset(array); 476 int ascale = UNSAFE.arrayIndexScale(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 }