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 26 package java.lang.invoke; 27 28 import java.lang.reflect.Field; 29 import java.lang.reflect.Modifier; 30 31 import static java.lang.invoke.MethodHandleStatics.UNSAFE; 32 33 final class VarHandles { 34 35 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) { 36 if (!f.isStatic()) { 37 long foffset = MethodHandleNatives.objectFieldOffset(f); 38 if (!type.isPrimitive()) { 39 return f.isFinal() && !isWriteAllowedOnFinalFields 40 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type) 41 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type); 42 } 43 else if (type == boolean.class) { 44 return f.isFinal() && !isWriteAllowedOnFinalFields 45 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset) 46 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset); 47 } 48 else if (type == byte.class) { 49 return f.isFinal() && !isWriteAllowedOnFinalFields 50 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset) 51 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset); 52 } 53 else if (type == short.class) { 54 return f.isFinal() && !isWriteAllowedOnFinalFields 260 if (viewComponentType == long.class) { 261 return new VarHandleByteArrayAsLongs.ByteBufferHandle(be); 262 } 263 else if (viewComponentType == int.class) { 264 return new VarHandleByteArrayAsInts.ByteBufferHandle(be); 265 } 266 else if (viewComponentType == short.class) { 267 return new VarHandleByteArrayAsShorts.ByteBufferHandle(be); 268 } 269 else if (viewComponentType == char.class) { 270 return new VarHandleByteArrayAsChars.ByteBufferHandle(be); 271 } 272 else if (viewComponentType == double.class) { 273 return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be); 274 } 275 else if (viewComponentType == float.class) { 276 return new VarHandleByteArrayAsFloats.ByteBufferHandle(be); 277 } 278 279 throw new UnsupportedOperationException(); 280 } 281 282 // /** 283 // * A helper program to generate the VarHandleGuards class with a set of 284 // * static guard methods each of which corresponds to a particular shape and 285 // * performs a type check of the symbolic type descriptor with the VarHandle 286 // * type descriptor before linking/invoking to the underlying operation as 287 // * characterized by the operation member name on the VarForm of the 288 // * VarHandle. 289 // * <p> 290 // * The generated class essentially encapsulates pre-compiled LambdaForms, 291 // * one for each method, for the most set of common method signatures. 292 // * This reduces static initialization costs, footprint costs, and circular 293 // * dependencies that may arise if a class is generated per LambdaForm. 294 // * <p> 295 // * A maximum of L*T*S methods will be generated where L is the number of 296 // * access modes kinds (or unique operation signatures) and T is the number 297 // * of variable types and S is the number of shapes (such as instance field, 298 // * static field, or array access). 299 // * If there are 4 unique operation signatures, 5 basic types (Object, int, | 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 26 package java.lang.invoke; 27 28 import sun.invoke.util.Wrapper; 29 30 import java.lang.reflect.Field; 31 import java.lang.reflect.Modifier; 32 import java.nio.ByteOrder; 33 import java.util.Map; 34 import java.util.concurrent.ConcurrentHashMap; 35 import java.util.concurrent.ConcurrentMap; 36 37 import static java.lang.invoke.MethodHandleStatics.UNSAFE; 38 39 final class VarHandles { 40 41 static ClassValue<ConcurrentMap<Integer, MethodHandle>> ADDRESS_FACTORIES = new ClassValue<>() { 42 @Override 43 protected ConcurrentMap<Integer, MethodHandle> computeValue(Class<?> type) { 44 return new ConcurrentHashMap<>(); 45 } 46 }; 47 48 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) { 49 if (!f.isStatic()) { 50 long foffset = MethodHandleNatives.objectFieldOffset(f); 51 if (!type.isPrimitive()) { 52 return f.isFinal() && !isWriteAllowedOnFinalFields 53 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type) 54 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type); 55 } 56 else if (type == boolean.class) { 57 return f.isFinal() && !isWriteAllowedOnFinalFields 58 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset) 59 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset); 60 } 61 else if (type == byte.class) { 62 return f.isFinal() && !isWriteAllowedOnFinalFields 63 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset) 64 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset); 65 } 66 else if (type == short.class) { 67 return f.isFinal() && !isWriteAllowedOnFinalFields 273 if (viewComponentType == long.class) { 274 return new VarHandleByteArrayAsLongs.ByteBufferHandle(be); 275 } 276 else if (viewComponentType == int.class) { 277 return new VarHandleByteArrayAsInts.ByteBufferHandle(be); 278 } 279 else if (viewComponentType == short.class) { 280 return new VarHandleByteArrayAsShorts.ByteBufferHandle(be); 281 } 282 else if (viewComponentType == char.class) { 283 return new VarHandleByteArrayAsChars.ByteBufferHandle(be); 284 } 285 else if (viewComponentType == double.class) { 286 return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be); 287 } 288 else if (viewComponentType == float.class) { 289 return new VarHandleByteArrayAsFloats.ByteBufferHandle(be); 290 } 291 292 throw new UnsupportedOperationException(); 293 } 294 295 /** 296 * Creates a memory access VarHandle. 297 * 298 * Resulting VarHandle will take a memory address as first argument, 299 * and a certain number of coordinate {@code long} parameters, depending on the length 300 * of the {@code strides} argument array. 301 * 302 * Coordinates are multiplied with corresponding scale factors ({@code strides}) and added 303 * to a single fixed offset to compute an effective offset from the given MemoryAddress for the access. 304 * 305 * @param carrier the Java carrier type. 306 * @param alignmentMask alignment requirement to be checked upon access. In bytes. Expressed as a mask. 307 * @param byteOrder the byte order. 308 * @param offset a constant offset for the access. 309 * @param strides the scale factors with which to multiply given access coordinates. 310 * @return the created VarHandle. 311 */ 312 static VarHandle makeMemoryAddressViewHandle(Class<?> carrier, long alignmentMask, 313 ByteOrder byteOrder, long offset, long[] strides) { 314 if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) { 315 throw new IllegalArgumentException("Invalid carrier: " + carrier.getName()); 316 } 317 long size = Wrapper.forPrimitiveType(carrier).bitWidth() / 8; 318 boolean be = byteOrder == ByteOrder.BIG_ENDIAN; 319 320 Map<Integer, MethodHandle> carrierFactory = ADDRESS_FACTORIES.get(carrier); 321 MethodHandle fac = carrierFactory.computeIfAbsent(strides.length, 322 dims -> new AddressVarHandleGenerator(carrier, dims) 323 .generateHandleFactory()); 324 325 try { 326 return (VarHandle)fac.invoke(be, size, offset, alignmentMask, strides); 327 } catch (Throwable ex) { 328 throw new IllegalStateException(ex); 329 } 330 } 331 332 // /** 333 // * A helper program to generate the VarHandleGuards class with a set of 334 // * static guard methods each of which corresponds to a particular shape and 335 // * performs a type check of the symbolic type descriptor with the VarHandle 336 // * type descriptor before linking/invoking to the underlying operation as 337 // * characterized by the operation member name on the VarForm of the 338 // * VarHandle. 339 // * <p> 340 // * The generated class essentially encapsulates pre-compiled LambdaForms, 341 // * one for each method, for the most set of common method signatures. 342 // * This reduces static initialization costs, footprint costs, and circular 343 // * dependencies that may arise if a class is generated per LambdaForm. 344 // * <p> 345 // * A maximum of L*T*S methods will be generated where L is the number of 346 // * access modes kinds (or unique operation signatures) and T is the number 347 // * of variable types and S is the number of shapes (such as instance field, 348 // * static field, or array access). 349 // * If there are 4 unique operation signatures, 5 basic types (Object, int, |