< prev index next >

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

Print this page




   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,


< prev index next >