< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java

Print this page

 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 jdk.incubator.foreign;
 27 
 28 import jdk.internal.access.JavaLangInvokeAccess;
 29 import jdk.internal.access.SharedSecrets;
 30 import jdk.internal.foreign.Utils;
 31 import sun.invoke.util.Wrapper;
 32 
 33 import java.lang.invoke.MethodHandle;
 34 import java.lang.invoke.MethodHandles;
 35 import java.lang.invoke.MethodType;
 36 import java.lang.invoke.VarHandle;
 37 import java.nio.ByteOrder;
 38 import java.util.List;
 39 import java.util.Objects;
 40 
 41 /**
 42  * This class defines several factory methods for constructing and combining memory access var handles.
 43  * To obtain a memory access var handle, clients must start from one of the <em>leaf</em> methods
 44  * (see {@link MemoryHandles#varHandle(Class, ByteOrder)},
 45  * {@link MemoryHandles#varHandle(Class, long, ByteOrder)}). This determines the variable type
 46  * (all primitive types but {@code void} and {@code boolean} are supported), as well as the alignment constraint and the
 47  * byte order associated with a memory access var handle. The resulting memory access var handle can then be combined in various ways
 48  * to emulate different addressing modes. The var handles created by this class feature a <em>mandatory</em> coordinate type
 49  * (of type {@link MemorySegment}), and one {@code long} coordinate type, which represents the offset, in bytes, relative
 50  * to the segment, at which dereference should occur.
 51  * <p>
 52  * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows:
 53  * <blockquote><pre>{@code
 54 GroupLayout seq = MemoryLayout.structLayout(
 55         MemoryLayout.paddingLayout(32),
 56         MemoryLayout.valueLayout(32, ByteOrder.BIG_ENDIAN).withName("value")
 57 );
 58  * }</pre></blockquote>
 59  * To access the member layout named {@code value}, we can construct a memory access var handle as follows:
 60  * <blockquote><pre>{@code
 61 VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.BIG_ENDIAN); //(MemorySegment, long) -> int
 62 handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
 63  * }</pre></blockquote>
 64  *
 65  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 66  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 67  *
 68  * <h2><a id="memaccess-mode"></a>Alignment and access modes</h2>
 69  *
 70  * A memory access var handle is associated with an access size {@code S} and an alignment constraint {@code B}
 71  * (both expressed in bytes). We say that a memory access operation is <em>fully aligned</em> if it occurs
 72  * at a memory address {@code A} which is compatible with both alignment constraints {@code S} and {@code B}.
 73  * If access is fully aligned then following access modes are supported and are
 74  * guaranteed to support atomic access:
 75  * <ul>
 76  * <li>read write access modes for all {@code T}, with the exception of
 77  *     access modes {@code get} and {@code set} for {@code long} and
 78  *     {@code double} on 32-bit platforms.
 79  * <li>atomic update access modes for {@code int}, {@code long},
 80  *     {@code float} or {@code double}.
 81  *     (Future major platform releases of the JDK may support additional
 82  *     types for certain currently unsupported access modes.)
 83  * <li>numeric atomic update access modes for {@code int} and {@code long}.
 84  *     (Future major platform releases of the JDK may support additional
 85  *     numeric types for certain currently unsupported access modes.)
 86  * <li>bitwise atomic update access modes for {@code int} and {@code long}.
 87  *     (Future major platform releases of the JDK may support additional
 88  *     numeric types for certain currently unsupported access modes.)
 89  * </ul>
 90  *
 91  * If {@code T} is {@code float} or {@code double} then atomic
 92  * update access modes compare values using their bitwise representation
 93  * (see {@link Float#floatToRawIntBits} and
 94  * {@link Double#doubleToRawLongBits}, respectively).
 95  * <p>
 96  * Alternatively, a memory access operation is <em>partially aligned</em> if it occurs at a memory address {@code A}
 97  * which is only compatible with the alignment constraint {@code B}; in such cases, access for anything other than the
 98  * {@code get} and {@code set} access modes will result in an {@code IllegalStateException}. If access is partially aligned,
 99  * atomic access is only guaranteed with respect to the largest power of two that divides the GCD of {@code A} and {@code S}.
100  * <p>
101  * Finally, in all other cases, we say that a memory access operation is <em>misaligned</em>; in such cases an
102  * {@code IllegalStateException} is thrown, irrespective of the access mode being used.
103  */
104 public final class MemoryHandles {
105 
106     private static final JavaLangInvokeAccess JLI = SharedSecrets.getJavaLangInvokeAccess();
107 
108     private MemoryHandles() {
109         //sorry, just the one!
110     }
111 
112     private static final MethodHandle LONG_TO_ADDRESS;
113     private static final MethodHandle ADDRESS_TO_LONG;
114     private static final MethodHandle INT_TO_BYTE;
115     private static final MethodHandle BYTE_TO_UNSIGNED_INT;
116     private static final MethodHandle INT_TO_SHORT;
117     private static final MethodHandle SHORT_TO_UNSIGNED_INT;
118     private static final MethodHandle LONG_TO_BYTE;
119     private static final MethodHandle BYTE_TO_UNSIGNED_LONG;
120     private static final MethodHandle LONG_TO_SHORT;
121     private static final MethodHandle SHORT_TO_UNSIGNED_LONG;
122     private static final MethodHandle LONG_TO_INT;
123     private static final MethodHandle INT_TO_UNSIGNED_LONG;
124 
125     static {
126         try {
127             LONG_TO_ADDRESS = MethodHandles.lookup().findStatic(MemoryHandles.class, "longToAddress",
128                     MethodType.methodType(MemoryAddress.class, long.class));
129             ADDRESS_TO_LONG = MethodHandles.lookup().findStatic(MemoryHandles.class, "addressToLong",
130                     MethodType.methodType(long.class, MemoryAddress.class));
131             INT_TO_BYTE = MethodHandles.explicitCastArguments(MethodHandles.identity(byte.class),
132                     MethodType.methodType(byte.class, int.class));
133             BYTE_TO_UNSIGNED_INT = MethodHandles.lookup().findStatic(Byte.class, "toUnsignedInt",
134                     MethodType.methodType(int.class, byte.class));
135             INT_TO_SHORT = MethodHandles.explicitCastArguments(MethodHandles.identity(short.class),
136                     MethodType.methodType(short.class, int.class));
137             SHORT_TO_UNSIGNED_INT = MethodHandles.lookup().findStatic(Short.class, "toUnsignedInt",
138                     MethodType.methodType(int.class, short.class));
139             LONG_TO_BYTE = MethodHandles.explicitCastArguments(MethodHandles.identity(byte.class),
140                     MethodType.methodType(byte.class, long.class));
141             BYTE_TO_UNSIGNED_LONG = MethodHandles.lookup().findStatic(Byte.class, "toUnsignedLong",
142                     MethodType.methodType(long.class, byte.class));
143             LONG_TO_SHORT = MethodHandles.explicitCastArguments(MethodHandles.identity(short.class),
144                     MethodType.methodType(short.class, long.class));
145             SHORT_TO_UNSIGNED_LONG = MethodHandles.lookup().findStatic(Short.class, "toUnsignedLong",
146                     MethodType.methodType(long.class, short.class));
147             LONG_TO_INT = MethodHandles.explicitCastArguments(MethodHandles.identity(int.class),
148                     MethodType.methodType(int.class, long.class));
149             INT_TO_UNSIGNED_LONG = MethodHandles.lookup().findStatic(Integer.class, "toUnsignedLong",
150                     MethodType.methodType(long.class, int.class));
151         } catch (Throwable ex) {
152             throw new ExceptionInInitializerError(ex);
153         }
154     }
155 
156     /**
157      * Creates a memory access var handle with the given carrier type and byte order.
158      *
159      * The returned var handle's type is {@code carrier} and the list of coordinate types is
160      * {@code (MemorySegment, long)}, where the {@code long} coordinate type corresponds to byte offset into
161      * a given memory segment. The returned var handle accesses bytes at an offset in a given
162      * memory segment, composing bytes to or from a value of the type {@code carrier} according to the given endianness;
163      * the alignment constraint (in bytes) for the resulting memory access var handle is the same as the size (in bytes) of the
164      * carrier type {@code carrier}.
165      *
166      * @apiNote the resulting var handle features certain <a href="#memaccess-mode">access mode restrictions</a>,
167      * which are common to all memory access var handles.
168      *
169      * @param carrier the carrier type. Valid carriers are {@code byte}, {@code short}, {@code char}, {@code int},
170      * {@code float}, {@code long}, and {@code double}.
171      * @param byteOrder the required byte order.
172      * @return the new memory access var handle.
173      * @throws IllegalArgumentException when an illegal carrier type is used
174      */
175     public static VarHandle varHandle(Class<?> carrier, ByteOrder byteOrder) {
176         Objects.requireNonNull(carrier);
177         Objects.requireNonNull(byteOrder);
178         return varHandle(carrier,
179                 carrierSize(carrier),
180                 byteOrder);
181     }
182 
183     /**
184      * Creates a memory access var handle with the given carrier type, alignment constraint, and byte order.
185      *
186      * The returned var handle's type is {@code carrier} and the list of coordinate types is
187      * {@code (MemorySegment, long)}, where the {@code long} coordinate type corresponds to byte offset into
188      * a given memory segment. The returned var handle accesses bytes at an offset in a given
189      * memory segment, composing bytes to or from a value of the type {@code carrier} according to the given endianness;
190      * the alignment constraint (in bytes) for the resulting memory access var handle is given by {@code alignmentBytes}.
191      *
192      * @apiNote the resulting var handle features certain <a href="#memaccess-mode">access mode restrictions</a>,
193      * which are common to all memory access var handles.
194      *
195      * @param carrier the carrier type. Valid carriers are {@code byte}, {@code short}, {@code char}, {@code int},
196      * {@code float}, {@code long}, and {@code double}.
197      * @param alignmentBytes the alignment constraint (in bytes). Must be a power of two.
198      * @param byteOrder the required byte order.
199      * @return the new memory access var handle.
200      * @throws IllegalArgumentException if an illegal carrier type is used, or if {@code alignmentBytes} is not a power of two.
201      */
202     public static VarHandle varHandle(Class<?> carrier, long alignmentBytes, ByteOrder byteOrder) {
203         Objects.requireNonNull(carrier);
204         Objects.requireNonNull(byteOrder);
205         checkCarrier(carrier);
206 
207         if (alignmentBytes <= 0
208                 || (alignmentBytes & (alignmentBytes - 1)) != 0) { // is power of 2?
209             throw new IllegalArgumentException("Bad alignment: " + alignmentBytes);
210         }
211 
212         return Utils.fixUpVarHandle(JLI.memoryAccessVarHandle(carrier, false, alignmentBytes - 1, byteOrder));
213     }
214 
215     /**
216      * Adapt an existing var handle into a new var handle whose carrier type is {@link MemorySegment}.
217      * That is, when calling {@link VarHandle#get(Object...)} on the returned var handle,
218      * the read numeric value will be turned into a memory address (as if by calling {@link MemoryAddress#ofLong(long)});
219      * similarly, when calling {@link VarHandle#set(Object...)}, the memory address to be set will be converted
220      * into a numeric value, and then written into memory. The amount of bytes read (resp. written) from (resp. to)
221      * memory depends on the carrier of the original memory access var handle.
222      *
223      * @param target the memory access var handle to be adapted
224      * @return the adapted var handle.
225      * @throws IllegalArgumentException if the carrier type of {@code varHandle} is either {@code boolean},
226      * {@code float}, or {@code double}, or is not a primitive type.
227      */
228     public static VarHandle asAddressVarHandle(VarHandle target) {
229         Objects.requireNonNull(target);
230         Class<?> carrier = target.varType();
231         if (!carrier.isPrimitive() || carrier == boolean.class ||
232                 carrier == float.class || carrier == double.class) {
233             throw new IllegalArgumentException("Unsupported carrier type: " + carrier.getName());
234         }
235 
236         if (carrier != long.class) {
237             // slow-path, we need to adapt
238             return filterValue(target,
239                     MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(carrier, MemoryAddress.class)),
240                     MethodHandles.explicitCastArguments(LONG_TO_ADDRESS, MethodType.methodType(MemoryAddress.class, carrier)));
241         } else {
242             // fast-path
243             return filterValue(target, ADDRESS_TO_LONG, LONG_TO_ADDRESS);
244         }
245     }
246 
247     /**
248      * Adapts a target var handle by narrowing incoming values and widening
249      * outgoing values, to and from the given type, respectively.
250      * <p>
251      * The returned var handle can be used to conveniently treat unsigned
252      * primitive data types as if they were a wider signed primitive type. For
253      * example, it is often convenient to model an <i>unsigned short</i> as a
254      * Java {@code int} to avoid dealing with negative values, which would be
255      * the case if modeled as a Java {@code short}. This is illustrated in the following example:
256      * <blockquote><pre>{@code
257     MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope());
258     VarHandle SHORT_VH = MemoryLayouts.JAVA_SHORT.varHandle(short.class);
259     VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class);
260     SHORT_VH.set(segment, (short)-1);
261     INT_VH.get(segment); // returns 65535
262      * }</pre></blockquote>
263      * <p>
264      * When calling e.g. {@link VarHandle#set(Object...)} on the resulting var
265      * handle, the incoming value (of type {@code adaptedType}) is converted by a
266      * <i>narrowing primitive conversion</i> and then passed to the {@code
267      * target} var handle. A narrowing primitive conversion may lose information
268      * about the overall magnitude of a numeric value. Conversely, when calling
269      * e.g. {@link VarHandle#get(Object...)} on the resulting var handle, the
270      * returned value obtained from the {@code target} var handle is converted
271      * by a <i>unsigned widening conversion</i> before being returned to the
272      * caller. In an unsigned widening conversion the high-order bits greater
273      * than that of the {@code target} carrier type are zero, and the low-order
274      * bits (equal to the width of the {@code target} carrier type) are equal to
275      * the bits of the value obtained from the {@code target} var handle.
276      * <p>
277      * The returned var handle will feature the variable type {@code adaptedType},
278      * and the same access coordinates, the same access modes (see {@link
279      * java.lang.invoke.VarHandle.AccessMode}, and the same atomic access
280      * guarantees, as those featured by the {@code target} var handle.
281      *
282      * @param target the memory access var handle to be adapted
283      * @param adaptedType the adapted type
284      * @return the adapted var handle.
285      * @throws IllegalArgumentException if the carrier type of {@code target}
286      * is not one of {@code byte}, {@code short}, or {@code int}; if {@code
287      * adaptedType} is not one of {@code int}, or {@code long}; if the bitwidth
288      * of the {@code adaptedType} is not greater than that of the {@code target}
289      * carrier type.
290      *
291      * @jls 5.1.3 Narrowing Primitive Conversion
292      */
293     public static VarHandle asUnsigned(VarHandle target, final Class<?> adaptedType) {
294         Objects.requireNonNull(target);
295         Objects.requireNonNull(adaptedType);
296         final Class<?> carrier = target.varType();
297         checkWidenable(carrier);
298         checkNarrowable(adaptedType);
299         checkTargetWiderThanCarrier(carrier, adaptedType);
300 
301         if (adaptedType == int.class && carrier == byte.class) {
302             return filterValue(target, INT_TO_BYTE, BYTE_TO_UNSIGNED_INT);
303         } else if (adaptedType == int.class && carrier == short.class) {
304             return filterValue(target, INT_TO_SHORT, SHORT_TO_UNSIGNED_INT);
305         } else if (adaptedType == long.class && carrier == byte.class) {
306             return filterValue(target, LONG_TO_BYTE, BYTE_TO_UNSIGNED_LONG);
307         } else if (adaptedType == long.class && carrier == short.class) {
308             return filterValue(target, LONG_TO_SHORT, SHORT_TO_UNSIGNED_LONG);
309         } else if (adaptedType == long.class && carrier == int.class) {
310             return filterValue(target, LONG_TO_INT, INT_TO_UNSIGNED_LONG);
311         } else {
312             throw new InternalError("should not reach here");
313         }
314     }
315 
316     /**
317      * Adapts a target var handle by pre-processing incoming and outgoing values using a pair of filter functions.
318      * <p>
319      * When calling e.g. {@link VarHandle#set(Object...)} on the resulting var handle, the incoming value (of type {@code T}, where
320      * {@code T} is the <em>last</em> parameter type of the first filter function) is processed using the first filter and then passed
321      * to the target var handle.
322      * Conversely, when calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, the return value obtained from
323      * the target var handle (of type {@code T}, where {@code T} is the <em>last</em> parameter type of the second filter function)
324      * is processed using the second filter and returned to the caller. More advanced access mode types, such as
325      * {@link java.lang.invoke.VarHandle.AccessMode#COMPARE_AND_EXCHANGE} might apply both filters at the same time.
326      * <p>
327      * For the boxing and unboxing filters to be well formed, their types must be of the form {@code (A... , S) -> T} and
328      * {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle. If this is the case,
329      * the resulting var handle will have type {@code S} and will feature the additional coordinates {@code A...} (which
330      * will be appended to the coordinates of the target var handle).
331      * <p>
332      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode} and



333      * atomic access guarantees as those featured by the target var handle.
334      *
335      * @param target the target var handle
336      * @param filterToTarget a filter to convert some type {@code S} into the type of {@code target}
337      * @param filterFromTarget a filter to convert the type of {@code target} to some type {@code S}
338      * @return an adapter var handle which accepts a new type, performing the provided boxing/unboxing conversions.
339      * @throws IllegalArgumentException if {@code filterFromTarget} and {@code filterToTarget} are not well-formed, that is, they have types
340      * other than {@code (A... , S) -> T} and {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle,
341      * or if either {@code filterFromTarget} or {@code filterToTarget} throws any checked exceptions.
342      */
343     public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) {
344         return JLI.filterValue(target, filterToTarget, filterFromTarget);
345     }
346 
347     /**
348      * Adapts a target var handle by pre-processing incoming coordinate values using unary filter functions.
349      * <p>
350      * When calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, the incoming coordinate values
351      * starting at position {@code pos} (of type {@code C1, C2 ... Cn}, where {@code C1, C2 ... Cn} are the return type
352      * of the unary filter functions) are transformed into new values (of type {@code S1, S2 ... Sn}, where {@code S1, S2 ... Sn} are the
353      * parameter types of the unary filter functions), and then passed (along with any coordinate that was left unaltered
354      * by the adaptation) to the target var handle.
355      * <p>
356      * For the coordinate filters to be well formed, their types must be of the form {@code S1 -> T1, S2 -> T1 ... Sn -> Tn},
357      * where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} of the target var handle.
358      * <p>



359      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
360      * atomic access guarantees as those featured by the target var handle.
361      *
362      * @param target the target var handle
363      * @param pos the position of the first coordinate to be transformed
364      * @param filters the unary functions which are used to transform coordinates starting at position {@code pos}
365      * @return an adapter var handle which accepts new coordinate types, applying the provided transformation
366      * to the new coordinate values.
367      * @throws IllegalArgumentException if the handles in {@code filters} are not well-formed, that is, they have types
368      * other than {@code S1 -> T1, S2 -> T2, ... Sn -> Tn} where {@code T1, T2 ... Tn} are the coordinate types starting
369      * at position {@code pos} of the target var handle, if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
370      * or if more filters are provided than the actual number of coordinate types available starting at {@code pos},
371      * or if any of the filters throws any checked exceptions.
372      */
373     public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandle... filters) {
374         return JLI.filterCoordinates(target, pos, filters);
375     }
376 
377     /**
378      * Provides a target var handle with one or more <em>bound coordinates</em>
379      * in advance of the var handle's invocation. As a consequence, the resulting var handle will feature less
380      * coordinate types than the target var handle.
381      * <p>
382      * When calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, incoming coordinate values
383      * are joined with bound coordinate values, and then passed to the target var handle.
384      * <p>
385      * For the bound coordinates to be well formed, their types must be {@code T1, T2 ... Tn },
386      * where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} of the target var handle.
387      * <p>
388      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
389      * atomic access guarantees as those featured by the target var handle.
390      *
391      * @param target the var handle to invoke after the bound coordinates are inserted
392      * @param pos the position of the first coordinate to be inserted
393      * @param values the series of bound coordinates to insert
394      * @return an adapter var handle which inserts an additional coordinates,
395      *         before calling the target var handle
396      * @throws IllegalArgumentException if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
397      * or if more values are provided than the actual number of coordinate types available starting at {@code pos}.
398      * @throws ClassCastException if the bound coordinates in {@code values} are not well-formed, that is, they have types
399      * other than {@code T1, T2 ... Tn }, where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos}
400      * of the target var handle.
401      */
402     public static VarHandle insertCoordinates(VarHandle target, int pos, Object... values) {
403         return JLI.insertCoordinates(target, pos, values);
404     }
405 
406     /**
407      * Provides a var handle which adapts the coordinate values of the target var handle, by re-arranging them
408      * so that the new coordinates match the provided ones.
409      * <p>
410      * The given array controls the reordering.
411      * Call {@code #I} the number of incoming coordinates (the value
412      * {@code newCoordinates.size()}, and call {@code #O} the number
413      * of outgoing coordinates (the number of coordinates associated with the target var handle).
414      * Then the length of the reordering array must be {@code #O},
415      * and each element must be a non-negative number less than {@code #I}.
416      * For every {@code N} less than {@code #O}, the {@code N}-th
417      * outgoing coordinate will be taken from the {@code I}-th incoming
418      * coordinate, where {@code I} is {@code reorder[N]}.
419      * <p>
420      * No coordinate value conversions are applied.
421      * The type of each incoming coordinate, as determined by {@code newCoordinates},
422      * must be identical to the type of the corresponding outgoing coordinate
423      * in the target var handle.
424      * <p>
425      * The reordering array need not specify an actual permutation.
426      * An incoming coordinate will be duplicated if its index appears
427      * more than once in the array, and an incoming coordinate will be dropped
428      * if its index does not appear in the array.
429      * <p>
430      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
431      * atomic access guarantees as those featured by the target var handle.
432      * @param target the var handle to invoke after the coordinates have been reordered
433      * @param newCoordinates the new coordinate types
434      * @param reorder an index array which controls the reordering
435      * @return an adapter var handle which re-arranges the incoming coordinate values,
436      * before calling the target var handle
437      * @throws IllegalArgumentException if the index array length is not equal to
438      * the number of coordinates of the target var handle, or if any index array element is not a valid index for
439      * a coordinate of {@code newCoordinates}, or if two corresponding coordinate types in
440      * the target var handle and in {@code newCoordinates} are not identical.
441      */
442     public static VarHandle permuteCoordinates(VarHandle target, List<Class<?>> newCoordinates, int... reorder) {
443         return JLI.permuteCoordinates(target, newCoordinates, reorder);
444     }
445 
446     /**
447      * Adapts a target var handle handle by pre-processing
448      * a sub-sequence of its coordinate values with a filter (a method handle).
449      * The pre-processed coordinates are replaced by the result (if any) of the
450      * filter function and the target var handle is then called on the modified (usually shortened)
451      * coordinate list.
452      * <p>
453      * If {@code R} is the return type of the filter (which cannot be void), the target var handle must accept a value of
454      * type {@code R} as its coordinate in position {@code pos}, preceded and/or followed by
455      * any coordinate not passed to the filter.
456      * No coordinates are reordered, and the result returned from the filter
457      * replaces (in order) the whole subsequence of coordinates originally
458      * passed to the adapter.
459      * <p>
460      * The argument types (if any) of the filter
461      * replace zero or one coordinate types of the target var handle, at position {@code pos},
462      * in the resulting adapted var handle.
463      * The return type of the filter must be identical to the
464      * coordinate type of the target var handle at position {@code pos}, and that target var handle
465      * coordinate is supplied by the return value of the filter.
466      * <p>



467      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
468      * atomic access guarantees as those featured by the target var handle.
469      *
470      * @param target the var handle to invoke after the coordinates have been filtered
471      * @param pos the position of the coordinate to be filtered
472      * @param filter the filter method handle
473      * @return an adapter var handle which filters the incoming coordinate values,
474      * before calling the target var handle
475      * @throws IllegalArgumentException if the return type of {@code filter}
476      * is void, or it is not the same as the {@code pos} coordinate of the target var handle,
477      * if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
478      * if the resulting var handle's type would have <a href="MethodHandle.html#maxarity">too many coordinates</a>,
479      * or if {@code filter} throws any checked exceptions.
480      */
481     public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) {
482         return JLI.collectCoordinates(target, pos, filter);
483     }
484 
485     /**
486      * Returns a var handle which will discard some dummy coordinates before delegating to the
487      * target var handle. As a consequence, the resulting var handle will feature more
488      * coordinate types than the target var handle.
489      * <p>
490      * The {@code pos} argument may range between zero and <i>N</i>, where <i>N</i> is the arity of the
491      * target var handle's coordinate types. If {@code pos} is zero, the dummy coordinates will precede
492      * the target's real arguments; if {@code pos} is <i>N</i> they will come after.
493      * <p>
494      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
495      * atomic access guarantees as those featured by the target var handle.
496      *
497      * @param target the var handle to invoke after the dummy coordinates are dropped
498      * @param pos position of first coordinate to drop (zero for the leftmost)
499      * @param valueTypes the type(s) of the coordinate(s) to drop
500      * @return an adapter var handle which drops some dummy coordinates,
501      *         before calling the target var handle
502      * @throws IllegalArgumentException if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive.
503      */
504     public static VarHandle dropCoordinates(VarHandle target, int pos, Class<?>... valueTypes) {
505         return JLI.dropCoordinates(target, pos, valueTypes);
506     }
507 
508     private static void checkAddressFirstCoordinate(VarHandle handle) {
509         if (handle.coordinateTypes().size() < 1 ||
510                 handle.coordinateTypes().get(0) != MemorySegment.class) {
511             throw new IllegalArgumentException("Expected var handle with leading coordinate of type MemorySegment");
512         }
513     }
514 
515     private static void checkCarrier(Class<?> carrier) {
516         if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) {
517             throw new IllegalArgumentException("Illegal carrier: " + carrier.getSimpleName());
518         }
519     }
520 
521     private static long carrierSize(Class<?> carrier) {
522         long bitsAlignment = Math.max(8, Wrapper.forPrimitiveType(carrier).bitWidth());
523         return Utils.bitsToBytesOrThrow(bitsAlignment, IllegalStateException::new);
524     }
525 
526     private static void checkWidenable(Class<?> carrier) {
527         if (!(carrier == byte.class || carrier == short.class || carrier == int.class)) {
528             throw new IllegalArgumentException("illegal carrier:" + carrier.getSimpleName());
529         }
530     }
531 
532     private static void checkNarrowable(Class<?> type) {
533         if (!(type == int.class || type == long.class)) {
534             throw new IllegalArgumentException("illegal adapter type: " + type.getSimpleName());
535         }
536     }
537 
538     private static void checkTargetWiderThanCarrier(Class<?> carrier, Class<?> target) {
539         if (Wrapper.forPrimitiveType(target).bitWidth() <= Wrapper.forPrimitiveType(carrier).bitWidth()) {
540             throw new IllegalArgumentException(
541                     target.getSimpleName() + " is not wider than: " + carrier.getSimpleName());
542         }
543     }
544 
545     private static MemoryAddress longToAddress(long value) {
546         return MemoryAddress.ofLong(value);
547     }
548 
549     private static long addressToLong(MemoryAddress value) {
550         return value.toRawLongValue();
551     }
552 }

 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 jdk.incubator.foreign;
 27 
 28 import jdk.internal.access.JavaLangInvokeAccess;
 29 import jdk.internal.access.SharedSecrets;

 30 import sun.invoke.util.Wrapper;
 31 
 32 import java.lang.invoke.MethodHandle;
 33 import java.lang.invoke.MethodHandles;
 34 import java.lang.invoke.MethodType;
 35 import java.lang.invoke.VarHandle;

 36 import java.util.List;
 37 import java.util.Objects;
 38 
 39 /**
 40  * This class defines several factory methods for constructing and combining memory access var handles.
 41  * Memory access var handles can be obtained using {@link MemoryHandles#varHandle(ValueLayout)}. The provided value layout
 42  * determines the type, as well as the alignment constraint and the byte order associated with the memory access var handle.
 43  * <p>
 44  * The resulting memory access var handle can then be combined in various ways

 45  * to emulate different addressing modes. The var handles created by this class feature a <em>mandatory</em> coordinate type
 46  * (of type {@link MemorySegment}), and one {@code long} coordinate type, which represents the offset, in bytes, relative
 47  * to the segment, at which dereference should occur.
 48  * <p>
 49  * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows:
 50  * <blockquote><pre>{@code
 51 GroupLayout seq = MemoryLayout.structLayout(
 52         MemoryLayout.paddingLayout(32),
 53         ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
 54 );
 55  * }</pre></blockquote>
 56  * To access the member layout named {@code value}, we can construct a memory access var handle as follows:
 57  * <blockquote><pre>{@code
 58 VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int
 59 handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
 60  * }</pre></blockquote>
 61  *
 62  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 63  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 64  *
 65  * <h2><a id="memaccess-mode"></a>Alignment and access modes</h2>
 66  *
 67  * A memory access var handle is associated with an access size {@code S} and an alignment constraint {@code B}
 68  * (both expressed in bytes). We say that a memory access operation is <em>fully aligned</em> if it occurs
 69  * at a memory address {@code A} which is compatible with both alignment constraints {@code S} and {@code B}.
 70  * If access is fully aligned then following access modes are supported and are
 71  * guaranteed to support atomic access:
 72  * <ul>
 73  * <li>read write access modes for all {@code T}, with the exception of
 74  *     access modes {@code get} and {@code set} for {@code long} and
 75  *     {@code double} on 32-bit platforms.
 76  * <li>atomic update access modes for {@code int}, {@code long},
 77  *     {@code float}, {@code double} or {@link MemoryAddress}.
 78  *     (Future major platform releases of the JDK may support additional
 79  *     types for certain currently unsupported access modes.)
 80  * <li>numeric atomic update access modes for {@code int}, {@code long} and {@link MemoryAddress}.
 81  *     (Future major platform releases of the JDK may support additional
 82  *     numeric types for certain currently unsupported access modes.)
 83  * <li>bitwise atomic update access modes for {@code int}, {@code long} and {@link MemoryAddress}.
 84  *     (Future major platform releases of the JDK may support additional
 85  *     numeric types for certain currently unsupported access modes.)
 86  * </ul>
 87  *
 88  * If {@code T} is {@code float}, {@code double} or {@link MemoryAddress} then atomic
 89  * update access modes compare values using their bitwise representation
 90  * (see {@link Float#floatToRawIntBits},
 91  * {@link Double#doubleToRawLongBits} and {@link MemoryAddress#toRawLongValue()}, respectively).
 92  * <p>
 93  * Alternatively, a memory access operation is <em>partially aligned</em> if it occurs at a memory address {@code A}
 94  * which is only compatible with the alignment constraint {@code B}; in such cases, access for anything other than the
 95  * {@code get} and {@code set} access modes will result in an {@code IllegalStateException}. If access is partially aligned,
 96  * atomic access is only guaranteed with respect to the largest power of two that divides the GCD of {@code A} and {@code S}.
 97  * <p>
 98  * Finally, in all other cases, we say that a memory access operation is <em>misaligned</em>; in such cases an
 99  * {@code IllegalStateException} is thrown, irrespective of the access mode being used.
100  */
101 public final class MemoryHandles {
102 
103     private static final JavaLangInvokeAccess JLI = SharedSecrets.getJavaLangInvokeAccess();
104 
105     private MemoryHandles() {
106         //sorry, just the one!
107     }
108 


109     private static final MethodHandle INT_TO_BYTE;
110     private static final MethodHandle BYTE_TO_UNSIGNED_INT;
111     private static final MethodHandle INT_TO_SHORT;
112     private static final MethodHandle SHORT_TO_UNSIGNED_INT;
113     private static final MethodHandle LONG_TO_BYTE;
114     private static final MethodHandle BYTE_TO_UNSIGNED_LONG;
115     private static final MethodHandle LONG_TO_SHORT;
116     private static final MethodHandle SHORT_TO_UNSIGNED_LONG;
117     private static final MethodHandle LONG_TO_INT;
118     private static final MethodHandle INT_TO_UNSIGNED_LONG;
119 
120     static {
121         try {




122             INT_TO_BYTE = MethodHandles.explicitCastArguments(MethodHandles.identity(byte.class),
123                     MethodType.methodType(byte.class, int.class));
124             BYTE_TO_UNSIGNED_INT = MethodHandles.lookup().findStatic(Byte.class, "toUnsignedInt",
125                     MethodType.methodType(int.class, byte.class));
126             INT_TO_SHORT = MethodHandles.explicitCastArguments(MethodHandles.identity(short.class),
127                     MethodType.methodType(short.class, int.class));
128             SHORT_TO_UNSIGNED_INT = MethodHandles.lookup().findStatic(Short.class, "toUnsignedInt",
129                     MethodType.methodType(int.class, short.class));
130             LONG_TO_BYTE = MethodHandles.explicitCastArguments(MethodHandles.identity(byte.class),
131                     MethodType.methodType(byte.class, long.class));
132             BYTE_TO_UNSIGNED_LONG = MethodHandles.lookup().findStatic(Byte.class, "toUnsignedLong",
133                     MethodType.methodType(long.class, byte.class));
134             LONG_TO_SHORT = MethodHandles.explicitCastArguments(MethodHandles.identity(short.class),
135                     MethodType.methodType(short.class, long.class));
136             SHORT_TO_UNSIGNED_LONG = MethodHandles.lookup().findStatic(Short.class, "toUnsignedLong",
137                     MethodType.methodType(long.class, short.class));
138             LONG_TO_INT = MethodHandles.explicitCastArguments(MethodHandles.identity(int.class),
139                     MethodType.methodType(int.class, long.class));
140             INT_TO_UNSIGNED_LONG = MethodHandles.lookup().findStatic(Integer.class, "toUnsignedLong",
141                     MethodType.methodType(long.class, int.class));
142         } catch (Throwable ex) {
143             throw new ExceptionInInitializerError(ex);
144         }
145     }
146 
147     /**
148      * Creates a memory access var handle from given value layout. The provided layout will specify the
149      * {@linkplain ValueLayout#carrier() carrier type}, the {@linkplain ValueLayout#byteSize() the byte size},
150      * the {@linkplain ValueLayout#byteAlignment() byte alignment} and the {@linkplain ValueLayout#order() byte order}
151      * associated to the returned var handle.
























152      *
153      * The returned var handle's type is {@code carrier} and the list of coordinate types is
154      * {@code (MemorySegment, long)}, where the {@code long} coordinate type corresponds to byte offset into
155      * a given memory segment. The returned var handle accesses bytes at an offset in a given
156      * memory segment, composing bytes to or from a value of the type {@code carrier} according to the given endianness;
157      * the alignment constraint (in bytes) for the resulting memory access var handle is given by {@code alignmentBytes}.
158      *
159      * @apiNote the resulting var handle features certain <a href="#memaccess-mode">access mode restrictions</a>,
160      * which are common to all memory access var handles.
161      *
162      * @param layout the value layout for which a memory access handle is to be obtained.



163      * @return the new memory access var handle.
164      * @throws IllegalArgumentException if an illegal carrier type is used, or if {@code alignmentBytes} is not a power of two.
165      */
166     public static VarHandle varHandle(ValueLayout layout) {
167         Objects.requireNonNull(layout);
168         return layout.accessHandle();








































169     }
170 
171     /**
172      * Adapts a target var handle by narrowing incoming values and widening
173      * outgoing values, to and from the given type, respectively.
174      * <p>
175      * The returned var handle can be used to conveniently treat unsigned
176      * primitive data types as if they were a wider signed primitive type. For
177      * example, it is often convenient to model an <i>unsigned short</i> as a
178      * Java {@code int} to avoid dealing with negative values, which would be
179      * the case if modeled as a Java {@code short}. This is illustrated in the following example:
180      * <blockquote><pre>{@code
181     MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope());
182     VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle();
183     VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class);
184     SHORT_VH.set(segment, (short)-1);
185     INT_VH.get(segment); // returns 65535
186      * }</pre></blockquote>
187      * <p>
188      * When calling e.g. {@link VarHandle#set(Object...)} on the resulting var
189      * handle, the incoming value (of type {@code adaptedType}) is converted by a
190      * <i>narrowing primitive conversion</i> and then passed to the {@code
191      * target} var handle. A narrowing primitive conversion may lose information
192      * about the overall magnitude of a numeric value. Conversely, when calling
193      * e.g. {@link VarHandle#get(Object...)} on the resulting var handle, the
194      * returned value obtained from the {@code target} var handle is converted
195      * by a <i>unsigned widening conversion</i> before being returned to the
196      * caller. In an unsigned widening conversion the high-order bits greater
197      * than that of the {@code target} carrier type are zero, and the low-order
198      * bits (equal to the width of the {@code target} carrier type) are equal to
199      * the bits of the value obtained from the {@code target} var handle.
200      * <p>
201      * The returned var handle will feature the variable type {@code adaptedType},
202      * and the same access coordinates, the same access modes (see {@link
203      * java.lang.invoke.VarHandle.AccessMode}), and the same atomic access
204      * guarantees, as those featured by the {@code target} var handle.
205      *
206      * @param target the memory access var handle to be adapted
207      * @param adaptedType the adapted type
208      * @return the adapted var handle.
209      * @throws IllegalArgumentException if the carrier type of {@code target}
210      * is not one of {@code byte}, {@code short}, or {@code int}; if {@code
211      * adaptedType} is not one of {@code int}, or {@code long}; if the bit width
212      * of the {@code adaptedType} is not greater than that of the {@code target}
213      * carrier type.
214      *
215      * @jls 5.1.3 Narrowing Primitive Conversion
216      */
217     public static VarHandle asUnsigned(VarHandle target, final Class<?> adaptedType) {
218         Objects.requireNonNull(target);
219         Objects.requireNonNull(adaptedType);
220         final Class<?> carrier = target.varType();
221         checkWidenable(carrier);
222         checkNarrowable(adaptedType);
223         checkTargetWiderThanCarrier(carrier, adaptedType);
224 
225         if (adaptedType == int.class && carrier == byte.class) {
226             return filterValue(target, INT_TO_BYTE, BYTE_TO_UNSIGNED_INT);
227         } else if (adaptedType == int.class && carrier == short.class) {
228             return filterValue(target, INT_TO_SHORT, SHORT_TO_UNSIGNED_INT);
229         } else if (adaptedType == long.class && carrier == byte.class) {
230             return filterValue(target, LONG_TO_BYTE, BYTE_TO_UNSIGNED_LONG);
231         } else if (adaptedType == long.class && carrier == short.class) {
232             return filterValue(target, LONG_TO_SHORT, SHORT_TO_UNSIGNED_LONG);
233         } else if (adaptedType == long.class && carrier == int.class) {
234             return filterValue(target, LONG_TO_INT, INT_TO_UNSIGNED_LONG);
235         } else {
236             throw new InternalError("should not reach here");
237         }
238     }
239 
240     /**
241      * Adapts a target var handle by pre-processing incoming and outgoing values using a pair of filter functions.
242      * <p>
243      * When calling e.g. {@link VarHandle#set(Object...)} on the resulting var handle, the incoming value (of type {@code T}, where
244      * {@code T} is the <em>last</em> parameter type of the first filter function) is processed using the first filter and then passed
245      * to the target var handle.
246      * Conversely, when calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, the return value obtained from
247      * the target var handle (of type {@code T}, where {@code T} is the <em>last</em> parameter type of the second filter function)
248      * is processed using the second filter and returned to the caller. More advanced access mode types, such as
249      * {@link java.lang.invoke.VarHandle.AccessMode#COMPARE_AND_EXCHANGE} might apply both filters at the same time.
250      * <p>
251      * For the boxing and unboxing filters to be well-formed, their types must be of the form {@code (A... , S) -> T} and
252      * {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle. If this is the case,
253      * the resulting var handle will have type {@code S} and will feature the additional coordinates {@code A...} (which
254      * will be appended to the coordinates of the target var handle).
255      * <p>
256      * If the boxing and unboxing filters throw any checked exceptions when invoked, the resulting var handle will
257      * throw an {@link IllegalStateException}.
258      * <p>
259      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
260      * atomic access guarantees as those featured by the target var handle.
261      *
262      * @param target the target var handle
263      * @param filterToTarget a filter to convert some type {@code S} into the type of {@code target}
264      * @param filterFromTarget a filter to convert the type of {@code target} to some type {@code S}
265      * @return an adapter var handle which accepts a new type, performing the provided boxing/unboxing conversions.
266      * @throws IllegalArgumentException if {@code filterFromTarget} and {@code filterToTarget} are not well-formed, that is, they have types
267      * other than {@code (A... , S) -> T} and {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle,
268      * or if it's determined that either {@code filterFromTarget} or {@code filterToTarget} throws any checked exceptions.
269      */
270     public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) {
271         return JLI.filterValue(target, filterToTarget, filterFromTarget);
272     }
273 
274     /**
275      * Adapts a target var handle by pre-processing incoming coordinate values using unary filter functions.
276      * <p>
277      * When calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, the incoming coordinate values
278      * starting at position {@code pos} (of type {@code C1, C2 ... Cn}, where {@code C1, C2 ... Cn} are the return type
279      * of the unary filter functions) are transformed into new values (of type {@code S1, S2 ... Sn}, where {@code S1, S2 ... Sn} are the
280      * parameter types of the unary filter functions), and then passed (along with any coordinate that was left unaltered
281      * by the adaptation) to the target var handle.
282      * <p>
283      * For the coordinate filters to be well-formed, their types must be of the form {@code S1 -> T1, S2 -> T1 ... Sn -> Tn},
284      * where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} of the target var handle.
285      * <p>
286      * If any of the filters throws a checked exception when invoked, the resulting var handle will
287      * throw an {@link IllegalStateException}.
288      * <p>
289      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
290      * atomic access guarantees as those featured by the target var handle.
291      *
292      * @param target the target var handle
293      * @param pos the position of the first coordinate to be transformed
294      * @param filters the unary functions which are used to transform coordinates starting at position {@code pos}
295      * @return an adapter var handle which accepts new coordinate types, applying the provided transformation
296      * to the new coordinate values.
297      * @throws IllegalArgumentException if the handles in {@code filters} are not well-formed, that is, they have types
298      * other than {@code S1 -> T1, S2 -> T2, ... Sn -> Tn} where {@code T1, T2 ... Tn} are the coordinate types starting
299      * at position {@code pos} of the target var handle, if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
300      * or if more filters are provided than the actual number of coordinate types available starting at {@code pos},
301      * or if it's determined that any of the filters throws any checked exceptions.
302      */
303     public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandle... filters) {
304         return JLI.filterCoordinates(target, pos, filters);
305     }
306 
307     /**
308      * Provides a target var handle with one or more <em>bound coordinates</em>
309      * in advance of the var handle's invocation. As a consequence, the resulting var handle will feature less
310      * coordinate types than the target var handle.
311      * <p>
312      * When calling e.g. {@link VarHandle#get(Object...)} on the resulting var handle, incoming coordinate values
313      * are joined with bound coordinate values, and then passed to the target var handle.
314      * <p>
315      * For the bound coordinates to be well-formed, their types must be {@code T1, T2 ... Tn },
316      * where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} of the target var handle.
317      * <p>
318      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
319      * atomic access guarantees as those featured by the target var handle.
320      *
321      * @param target the var handle to invoke after the bound coordinates are inserted
322      * @param pos the position of the first coordinate to be inserted
323      * @param values the series of bound coordinates to insert
324      * @return an adapter var handle which inserts an additional coordinates,
325      *         before calling the target var handle
326      * @throws IllegalArgumentException if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
327      * or if more values are provided than the actual number of coordinate types available starting at {@code pos}.
328      * @throws ClassCastException if the bound coordinates in {@code values} are not well-formed, that is, they have types
329      * other than {@code T1, T2 ... Tn }, where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos}
330      * of the target var handle.
331      */
332     public static VarHandle insertCoordinates(VarHandle target, int pos, Object... values) {
333         return JLI.insertCoordinates(target, pos, values);
334     }
335 
336     /**
337      * Provides a var handle which adapts the coordinate values of the target var handle, by re-arranging them
338      * so that the new coordinates match the provided ones.
339      * <p>
340      * The given array controls the reordering.
341      * Call {@code #I} the number of incoming coordinates (the value
342      * {@code newCoordinates.size()}), and call {@code #O} the number
343      * of outgoing coordinates (the number of coordinates associated with the target var handle).
344      * Then the length of the reordering array must be {@code #O},
345      * and each element must be a non-negative number less than {@code #I}.
346      * For every {@code N} less than {@code #O}, the {@code N}-th
347      * outgoing coordinate will be taken from the {@code I}-th incoming
348      * coordinate, where {@code I} is {@code reorder[N]}.
349      * <p>
350      * No coordinate value conversions are applied.
351      * The type of each incoming coordinate, as determined by {@code newCoordinates},
352      * must be identical to the type of the corresponding outgoing coordinate
353      * in the target var handle.
354      * <p>
355      * The reordering array need not specify an actual permutation.
356      * An incoming coordinate will be duplicated if its index appears
357      * more than once in the array, and an incoming coordinate will be dropped
358      * if its index does not appear in the array.
359      * <p>
360      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
361      * atomic access guarantees as those featured by the target var handle.
362      * @param target the var handle to invoke after the coordinates have been reordered
363      * @param newCoordinates the new coordinate types
364      * @param reorder an index array which controls the reordering
365      * @return an adapter var handle which re-arranges the incoming coordinate values,
366      * before calling the target var handle
367      * @throws IllegalArgumentException if the index array length is not equal to
368      * the number of coordinates of the target var handle, or if any index array element is not a valid index for
369      * a coordinate of {@code newCoordinates}, or if two corresponding coordinate types in
370      * the target var handle and in {@code newCoordinates} are not identical.
371      */
372     public static VarHandle permuteCoordinates(VarHandle target, List<Class<?>> newCoordinates, int... reorder) {
373         return JLI.permuteCoordinates(target, newCoordinates, reorder);
374     }
375 
376     /**
377      * Adapts a target var handle by pre-processing
378      * a sub-sequence of its coordinate values with a filter (a method handle).
379      * The pre-processed coordinates are replaced by the result (if any) of the
380      * filter function and the target var handle is then called on the modified (usually shortened)
381      * coordinate list.
382      * <p>
383      * If {@code R} is the return type of the filter (which cannot be void), the target var handle must accept a value of
384      * type {@code R} as its coordinate in position {@code pos}, preceded and/or followed by
385      * any coordinate not passed to the filter.
386      * No coordinates are reordered, and the result returned from the filter
387      * replaces (in order) the whole subsequence of coordinates originally
388      * passed to the adapter.
389      * <p>
390      * The argument types (if any) of the filter
391      * replace zero or one coordinate types of the target var handle, at position {@code pos},
392      * in the resulting adapted var handle.
393      * The return type of the filter must be identical to the
394      * coordinate type of the target var handle at position {@code pos}, and that target var handle
395      * coordinate is supplied by the return value of the filter.
396      * <p>
397      * If any of the filters throws a checked exception when invoked, the resulting var handle will
398      * throw an {@link IllegalStateException}.
399      * <p>
400      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
401      * atomic access guarantees as those featured by the target var handle.
402      *
403      * @param target the var handle to invoke after the coordinates have been filtered
404      * @param pos the position of the coordinate to be filtered
405      * @param filter the filter method handle
406      * @return an adapter var handle which filters the incoming coordinate values,
407      * before calling the target var handle
408      * @throws IllegalArgumentException if the return type of {@code filter}
409      * is void, or it is not the same as the {@code pos} coordinate of the target var handle,
410      * if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
411      * if the resulting var handle's type would have <a href="MethodHandle.html#maxarity">too many coordinates</a>,
412      * or if it's determined that {@code filter} throws any checked exceptions.
413      */
414     public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) {
415         return JLI.collectCoordinates(target, pos, filter);
416     }
417 
418     /**
419      * Returns a var handle which will discard some dummy coordinates before delegating to the
420      * target var handle. As a consequence, the resulting var handle will feature more
421      * coordinate types than the target var handle.
422      * <p>
423      * The {@code pos} argument may range between zero and <i>N</i>, where <i>N</i> is the arity of the
424      * target var handle's coordinate types. If {@code pos} is zero, the dummy coordinates will precede
425      * the target's real arguments; if {@code pos} is <i>N</i> they will come after.
426      * <p>
427      * The resulting var handle will feature the same access modes (see {@link java.lang.invoke.VarHandle.AccessMode}) and
428      * atomic access guarantees as those featured by the target var handle.
429      *
430      * @param target the var handle to invoke after the dummy coordinates are dropped
431      * @param pos position of first coordinate to drop (zero for the leftmost)
432      * @param valueTypes the type(s) of the coordinate(s) to drop
433      * @return an adapter var handle which drops some dummy coordinates,
434      *         before calling the target var handle
435      * @throws IllegalArgumentException if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive.
436      */
437     public static VarHandle dropCoordinates(VarHandle target, int pos, Class<?>... valueTypes) {
438         return JLI.dropCoordinates(target, pos, valueTypes);
439     }
440 


















441     private static void checkWidenable(Class<?> carrier) {
442         if (!(carrier == byte.class || carrier == short.class || carrier == int.class)) {
443             throw new IllegalArgumentException("illegal carrier:" + carrier.getSimpleName());
444         }
445     }
446 
447     private static void checkNarrowable(Class<?> type) {
448         if (!(type == int.class || type == long.class)) {
449             throw new IllegalArgumentException("illegal adapter type: " + type.getSimpleName());
450         }
451     }
452 
453     private static void checkTargetWiderThanCarrier(Class<?> carrier, Class<?> target) {
454         if (Wrapper.forPrimitiveType(target).bitWidth() <= Wrapper.forPrimitiveType(carrier).bitWidth()) {
455             throw new IllegalArgumentException(
456                     target.getSimpleName() + " is not wider than: " + carrier.getSimpleName());
457         }
458     }








459 }
< prev index next >