--- a/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java Wed Sep 10 19:19:47 2014 +0400
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java Wed Sep 10 19:19:47 2014 +0400
@@ -29,30 +29,10 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.EnumMap;
-import java.util.List;
public class ValueConversions {
private static final Class<?> THIS_CLASS = ValueConversions.class;
- // Do not adjust this except for special platforms:
- private static final int MAX_ARITY;
- static {
- final Object[] values = { 255 };
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
- return null;
- }
- });
- MAX_ARITY = (Integer) values[0];
- }
-
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
@@ -443,12 +423,7 @@
return x;
}
- private static ClassCastException newClassCastException(Class<?> t, Object obj) {
- return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
- }
-
- private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
- ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
+ private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY;
static {
try {
MethodType idType = MethodType.genericMethodType(1);
@@ -459,33 +434,11 @@
ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
- ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
- FILL_NEW_ARRAY = IMPL_LOOKUP
- .findStatic(THIS_CLASS, "fillNewArray",
- MethodType.methodType(Object[].class, Integer.class, Object[].class));
- FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
- .findStatic(THIS_CLASS, "fillNewTypedArray",
- MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
} catch (NoSuchMethodException | IllegalAccessException ex) {
throw newInternalError("uncaught exception", ex);
}
}
- // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
- static class LazyStatics {
- private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
- static {
- try {
- //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
- COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
- COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
- MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
- } catch (ReflectiveOperationException ex) {
- throw newInternalError("uncaught exception", ex);
- }
- }
- }
-
private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
= newWrapperCaches(1);
@@ -808,363 +761,6 @@
return Character.toUpperCase(x.charAt(0))+x.substring(1);
}
- /// Collection of multiple arguments.
-
- public static Object convertArrayElements(Class<?> arrayType, Object array) {
- Class<?> src = array.getClass().getComponentType();
- Class<?> dst = arrayType.getComponentType();
- if (src == null || dst == null) throw new IllegalArgumentException("not array type");
- Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
- Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
- int length;
- if (sw == null) {
- Object[] a = (Object[]) array;
- length = a.length;
- if (dw == null)
- return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
- Object res = dw.makeArray(length);
- dw.copyArrayUnboxing(a, 0, res, 0, length);
- return res;
- }
- length = java.lang.reflect.Array.getLength(array);
- Object[] res;
- if (dw == null) {
- res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
- } else {
- res = new Object[length];
- }
- sw.copyArrayBoxing(array, 0, res, 0, length);
- if (dw == null) return res;
- Object a = dw.makeArray(length);
- dw.copyArrayUnboxing(res, 0, a, 0, length);
- return a;
- }
-
- private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
- MethodType type = MethodType.genericMethodType(nargs)
- .changeReturnType(rtype)
- .insertParameterTypes(0, ptypes);
- try {
- return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
- } catch (ReflectiveOperationException ex) {
- return null;
- }
- }
-
- private static final Object[] NO_ARGS_ARRAY = {};
- private static Object[] makeArray(Object... args) { return args; }
- private static Object[] array() { return NO_ARGS_ARRAY; }
- private static Object[] array(Object a0)
- { return makeArray(a0); }
- private static Object[] array(Object a0, Object a1)
- { return makeArray(a0, a1); }
- private static Object[] array(Object a0, Object a1, Object a2)
- { return makeArray(a0, a1, a2); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3)
- { return makeArray(a0, a1, a2, a3); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { return makeArray(a0, a1, a2, a3, a4); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { return makeArray(a0, a1, a2, a3, a4, a5); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- private static MethodHandle[] makeArrays() {
- ArrayList<MethodHandle> mhs = new ArrayList<>();
- for (;;) {
- MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
- if (mh == null) break;
- mhs.add(mh);
- }
- assert(mhs.size() == 11); // current number of methods
- return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
- }
- private static final MethodHandle[] ARRAYS = makeArrays();
-
- // filling versions of the above:
- // using Integer len instead of int len and no varargs to avoid bootstrapping problems
- private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
- Object[] a = new Object[len];
- fillWithArguments(a, 0, args);
- return a;
- }
- private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
- Object[] a = Arrays.copyOf(example, len);
- fillWithArguments(a, 0, args);
- return a;
- }
- private static void fillWithArguments(Object[] a, int pos, Object... args) {
- System.arraycopy(args, 0, a, pos, args.length);
- }
- // using Integer pos instead of int pos to avoid bootstrapping problems
- private static Object[] fillArray(Integer pos, Object[] a, Object a0)
- { fillWithArguments(a, pos, a0); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
- { fillWithArguments(a, pos, a0, a1); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
- { fillWithArguments(a, pos, a0, a1, a2); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
- { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
- private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
- private static MethodHandle[] makeFillArrays() {
- ArrayList<MethodHandle> mhs = new ArrayList<>();
- mhs.add(null); // there is no empty fill; at least a0 is required
- for (;;) {
- MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
- if (mh == null) break;
- mhs.add(mh);
- }
- assert(mhs.size() == 11); // current number of methods
- return mhs.toArray(new MethodHandle[0]);
- }
- private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
-
- private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
- return Arrays.copyOf(a, a.length, arrayType);
- }
- private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
- Object a = w.makeArray(boxes.length);
- w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
- return a;
- }
-
- /** Return a method handle that takes the indicated number of Object
- * arguments and returns an Object array of them, as if for varargs.
- */
- public static MethodHandle varargsArray(int nargs) {
- MethodHandle mh = ARRAYS[nargs];
- if (mh != null) return mh;
- mh = findCollector("array", nargs, Object[].class);
- if (mh != null) return ARRAYS[nargs] = mh;
- mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
- assert(assertCorrectArity(mh, nargs));
- return ARRAYS[nargs] = mh;
- }
-
- private static boolean assertCorrectArity(MethodHandle mh, int arity) {
- assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
- return true;
- }
-
- private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
- // Build up the result mh as a sequence of fills like this:
- // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
- // The various fill(_,10*I,___*[J]) are reusable.
- int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately
- int rightLen = nargs - leftLen;
- MethodHandle leftCollector = newArray.bindTo(nargs);
- leftCollector = leftCollector.asCollector(Object[].class, leftLen);
- MethodHandle mh = finisher;
- if (rightLen > 0) {
- MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
- if (mh == ARRAY_IDENTITY)
- mh = rightFiller;
- else
- mh = MethodHandles.collectArguments(mh, 0, rightFiller);
- }
- if (mh == ARRAY_IDENTITY)
- mh = leftCollector;
- else
- mh = MethodHandles.collectArguments(mh, 0, leftCollector);
- return mh;
- }
-
- private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
- private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
- /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
- * fills a[L]..a[N-1] with corresponding arguments,
- * and then returns a. The value L is a global constant (LEFT_ARGS).
- */
- private static MethodHandle fillToRight(int nargs) {
- MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
- if (filler != null) return filler;
- filler = buildFiller(nargs);
- assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
- return FILL_ARRAY_TO_RIGHT[nargs] = filler;
- }
- private static MethodHandle buildFiller(int nargs) {
- if (nargs <= LEFT_ARGS)
- return ARRAY_IDENTITY; // no args to fill; return the array unchanged
- // we need room for both mh and a in mh.invoke(a, arg*[nargs])
- final int CHUNK = LEFT_ARGS;
- int rightLen = nargs % CHUNK;
- int midLen = nargs - rightLen;
- if (rightLen == 0) {
- midLen = nargs - (rightLen = CHUNK);
- if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
- // build some precursors from left to right
- for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
- if (j > LEFT_ARGS) fillToRight(j);
- }
- }
- if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
- assert(rightLen > 0);
- MethodHandle midFill = fillToRight(midLen); // recursive fill
- MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1]
- assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS);
- assert(rightFill.type().parameterCount() == 1 + rightLen);
-
- // Combine the two fills:
- // right(mid(a, x10..x19), x20..x23)
- // The final product will look like this:
- // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
- if (midLen == LEFT_ARGS)
- return rightFill;
- else
- return MethodHandles.collectArguments(rightFill, 0, midFill);
- }
-
- // Type-polymorphic version of varargs maker.
- private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
- = new ClassValue<MethodHandle[]>() {
- @Override
- protected MethodHandle[] computeValue(Class<?> type) {
- return new MethodHandle[256];
- }
- };
-
- static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM
-
- /** Return a method handle that takes the indicated number of
- * typed arguments and returns an array of them.
- * The type argument is the array type.
- */
- public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
- Class<?> elemType = arrayType.getComponentType();
- if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType);
- // FIXME: Need more special casing and caching here.
- if (nargs >= MAX_JVM_ARITY/2 - 1) {
- int slots = nargs;
- final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH
- if (arrayType == double[].class || arrayType == long[].class)
- slots *= 2;
- if (slots > MAX_ARRAY_SLOTS)
- throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
- }
- if (elemType == Object.class)
- return varargsArray(nargs);
- // other cases: primitive arrays, subtypes of Object[]
- MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
- MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
- if (mh != null) return mh;
- if (elemType.isPrimitive()) {
- MethodHandle builder = FILL_NEW_ARRAY;
- MethodHandle producer = buildArrayProducer(arrayType);
- mh = buildVarargsArray(builder, producer, nargs);
- } else {
- @SuppressWarnings("unchecked")
- Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
- Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
- MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
- MethodHandle producer = ARRAY_IDENTITY;
- mh = buildVarargsArray(builder, producer, nargs);
- }
- mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
- assert(assertCorrectArity(mh, nargs));
- if (nargs < cache.length)
- cache[nargs] = mh;
- return mh;
- }
-
- private static MethodHandle buildArrayProducer(Class<?> arrayType) {
- Class<?> elemType = arrayType.getComponentType();
- if (elemType.isPrimitive())
- return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType));
- else
- return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType);
- }
-
- // List version of varargs maker.
-
- private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
- private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
- private static List<Object> list() { return NO_ARGS_LIST; }
- private static List<Object> list(Object a0)
- { return makeList(a0); }
- private static List<Object> list(Object a0, Object a1)
- { return makeList(a0, a1); }
- private static List<Object> list(Object a0, Object a1, Object a2)
- { return makeList(a0, a1, a2); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
- { return makeList(a0, a1, a2, a3); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { return makeList(a0, a1, a2, a3, a4); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { return makeList(a0, a1, a2, a3, a4, a5); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { return makeList(a0, a1, a2, a3, a4, a5, a6); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- private static MethodHandle[] makeLists() {
- ArrayList<MethodHandle> mhs = new ArrayList<>();
- for (;;) {
- MethodHandle mh = findCollector("list", mhs.size(), List.class);
- if (mh == null) break;
- mhs.add(mh);
- }
- assert(mhs.size() == 11); // current number of methods
- return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
- }
- private static final MethodHandle[] LISTS = makeLists();
-
- /** Return a method handle that takes the indicated number of Object
- * arguments and returns a List.
- */
- public static MethodHandle varargsList(int nargs) {
- MethodHandle mh = LISTS[nargs];
- if (mh != null) return mh;
- mh = findCollector("list", nargs, List.class);
- if (mh != null) return LISTS[nargs] = mh;
- return LISTS[nargs] = buildVarargsList(nargs);
- }
- private static MethodHandle buildVarargsList(int nargs) {
- return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST);
- }
-
// handy shared exception makers (they simplify the common case code)
private static InternalError newInternalError(String message, Throwable cause) {
return new InternalError(message, cause);