< prev index next >

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

Print this page

        

@@ -23,17 +23,30 @@
  * questions.
  */
 
 package java.lang.invoke;
 
+import sun.invoke.util.Wrapper;
+
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.nio.ByteOrder;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
 
 final class VarHandles {
 
+    static ClassValue<ConcurrentMap<Integer, MethodHandle>> ADDRESS_FACTORIES = new ClassValue<>() {
+        @Override
+        protected ConcurrentMap<Integer, MethodHandle> computeValue(Class<?> type) {
+            return new ConcurrentHashMap<>();
+        }
+    };
+
     static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
         if (!f.isStatic()) {
             long foffset = MethodHandleNatives.objectFieldOffset(f);
             if (!type.isPrimitive()) {
                 return f.isFinal() && !isWriteAllowedOnFinalFields

@@ -277,10 +290,47 @@
         }
 
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * Creates a memory access VarHandle.
+     *
+     * Resulting VarHandle will take a memory address as first argument,
+     * and a certain number of coordinate {@code long} parameters, depending on the length
+     * of the {@code strides} argument array.
+     *
+     * Coordinates are multiplied with corresponding scale factors ({@code strides}) and added
+     * to a single fixed offset to compute an effective offset from the given MemoryAddress for the access.
+     *
+     * @param carrier the Java carrier type.
+     * @param alignmentMask alignment requirement to be checked upon access. In bytes. Expressed as a mask.
+     * @param byteOrder the byte order.
+     * @param offset a constant offset for the access.
+     * @param strides the scale factors with which to multiply given access coordinates.
+     * @return the created VarHandle.
+     */
+    static VarHandle makeMemoryAddressViewHandle(Class<?> carrier, long alignmentMask,
+                                                 ByteOrder byteOrder, long offset, long[] strides) {
+        if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) {
+            throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
+        }
+        long size = Wrapper.forPrimitiveType(carrier).bitWidth() / 8;
+        boolean be = byteOrder == ByteOrder.BIG_ENDIAN;
+
+        Map<Integer, MethodHandle> carrierFactory = ADDRESS_FACTORIES.get(carrier);
+        MethodHandle fac = carrierFactory.computeIfAbsent(strides.length,
+                dims -> new AddressVarHandleGenerator(carrier, dims)
+                            .generateHandleFactory());
+
+        try {
+            return (VarHandle)fac.invoke(be, size, offset, alignmentMask, strides);
+        } catch (Throwable ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
 //    /**
 //     * A helper program to generate the VarHandleGuards class with a set of
 //     * static guard methods each of which corresponds to a particular shape and
 //     * performs a type check of the symbolic type descriptor with the VarHandle
 //     * type descriptor before linking/invoking to the underlying operation as
< prev index next >