src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Cdiff src/share/classes/java/lang/invoke/MethodHandleImpl.java

src/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 9490 : 8037210: Get rid of char-based descriptions 'J' of basic types
Reviewed-by: ?
Contributed-by: john.r.rose@oracle.com
rev 9491 : 8037209: Improvements and cleanups to bytecode assembly for lambda forms
Reviewed-by: ?
Contributed-by: john.r.rose@oracle.com

*** 50,80 **** // Trigger selected static initializations. MemberName.Factory.INSTANCE.getClass(); } static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) { if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); ! MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter); ! MethodType srcType = accessor.type().erase(); ! MethodType lambdaType = srcType.invokerType(); ! Name[] names = arguments(1, lambdaType); ! Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount()); ! names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args); ! LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names); ! MethodHandle mh = SimpleMethodHandle.make(srcType, form); ! if (ArrayAccessor.needCast(arrayClass)) { ! mh = mh.bindTo(arrayClass); } ! mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter)); return mh; } static final class ArrayAccessor { /// Support for array element access ! static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>(); // TODO use it ! static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>(); // TODO use it static int getElementI(int[] a, int i) { return a[i]; } static long getElementJ(long[] a, int i) { return a[i]; } static float getElementF(float[] a, int i) { return a[i]; } static double getElementD(double[] a, int i) { return a[i]; } --- 50,96 ---- // Trigger selected static initializations. MemberName.Factory.INSTANCE.getClass(); } static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) { + if (arrayClass == Object[].class) + return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER); if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); ! MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass); ! int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX); ! MethodHandle mh = cache[cacheIndex]; ! if (mh != null) return mh; ! mh = ArrayAccessor.getAccessor(arrayClass, isSetter); ! MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter); ! if (mh.type() != correctType) { ! assert(mh.type().parameterType(0) == Object[].class); ! assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class); ! assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType()); ! // safe to view non-strictly, because element type follows from array type ! mh = mh.viewAsType(correctType); } ! cache[cacheIndex] = mh; return mh; } static final class ArrayAccessor { /// Support for array element access ! static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2; ! static final ClassValue<MethodHandle[]> TYPED_ACCESSORS ! = new ClassValue<MethodHandle[]>() { ! @Override ! protected MethodHandle[] computeValue(Class<?> type) { ! return new MethodHandle[INDEX_LIMIT]; ! } ! }; ! static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER; ! static { ! MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class); ! cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = getAccessor(Object[].class, false); ! cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = getAccessor(Object[].class, true); ! } static int getElementI(int[] a, int i) { return a[i]; } static long getElementJ(long[] a, int i) { return a[i]; } static float getElementF(float[] a, int i) { return a[i]; } static double getElementD(double[] a, int i) { return a[i]; }
*** 92,140 **** static void setElementB(byte[] a, int i, byte x) { a[i] = x; } static void setElementS(short[] a, int i, short x) { a[i] = x; } static void setElementC(char[] a, int i, char x) { a[i] = x; } static void setElementL(Object[] a, int i, Object x) { a[i] = x; } - static Object getElementL(Class<?> arrayClass, Object[] a, int i) { arrayClass.cast(a); return a[i]; } - static void setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; } - - // Weakly typed wrappers of Object[] accessors: - static Object getElementL(Object a, int i) { return getElementL((Object[])a, i); } - static void setElementL(Object a, int i, Object x) { setElementL((Object[]) a, i, x); } - static Object getElementL(Object arrayClass, Object a, int i) { return getElementL((Class<?>) arrayClass, (Object[])a, i); } - static void setElementL(Object arrayClass, Object a, int i, Object x) { setElementL((Class<?>) arrayClass, (Object[])a, i, x); } - - static boolean needCast(Class<?> arrayClass) { - Class<?> elemClass = arrayClass.getComponentType(); - return !elemClass.isPrimitive() && elemClass != Object.class; - } static String name(Class<?> arrayClass, boolean isSetter) { Class<?> elemClass = arrayClass.getComponentType(); ! if (elemClass == null) throw new IllegalArgumentException(); return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass); } - static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false; // FIXME: decide static MethodType type(Class<?> arrayClass, boolean isSetter) { Class<?> elemClass = arrayClass.getComponentType(); Class<?> arrayArgClass = arrayClass; if (!elemClass.isPrimitive()) { arrayArgClass = Object[].class; ! if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS) ! arrayArgClass = Object.class; } - if (!needCast(arrayClass)) { return !isSetter ? MethodType.methodType(elemClass, arrayArgClass, int.class) : MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); - } else { - Class<?> classArgClass = Class.class; - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS) - classArgClass = Object.class; - return !isSetter ? - MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) : - MethodType.methodType(void.class, classArgClass, arrayArgClass, int.class, Object.class); - } } static MethodType correctType(Class<?> arrayClass, boolean isSetter) { Class<?> elemClass = arrayClass.getComponentType(); return !isSetter ? MethodType.methodType(elemClass, arrayClass, int.class) : --- 108,132 ---- static void setElementB(byte[] a, int i, byte x) { a[i] = x; } static void setElementS(short[] a, int i, short x) { a[i] = x; } static void setElementC(char[] a, int i, char x) { a[i] = x; } static void setElementL(Object[] a, int i, Object x) { a[i] = x; } static String name(Class<?> arrayClass, boolean isSetter) { Class<?> elemClass = arrayClass.getComponentType(); ! if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass); return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass); } static MethodType type(Class<?> arrayClass, boolean isSetter) { Class<?> elemClass = arrayClass.getComponentType(); Class<?> arrayArgClass = arrayClass; if (!elemClass.isPrimitive()) { arrayArgClass = Object[].class; ! elemClass = Object.class; } return !isSetter ? MethodType.methodType(elemClass, arrayArgClass, int.class) : MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); } static MethodType correctType(Class<?> arrayClass, boolean isSetter) { Class<?> elemClass = arrayClass.getComponentType(); return !isSetter ? MethodType.methodType(elemClass, arrayClass, int.class) :
*** 177,200 **** int conversions = 0; boolean[] needConv = new boolean[1+INARG_COUNT]; for (int i = 0; i <= INARG_COUNT; i++) { Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i); Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i); ! if (!VerifyType.isNullConversion(src, dst) || level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) { needConv[i] = true; conversions++; } } boolean retConv = needConv[INARG_COUNT]; final int IN_MH = 0; final int INARG_BASE = 1; final int INARG_LIMIT = INARG_BASE + INARG_COUNT; final int NAME_LIMIT = INARG_LIMIT + conversions + 1; final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; // Now build a LambdaForm. MethodType lambdaType = srcType.basicType().invokerType(); Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType); --- 169,197 ---- int conversions = 0; boolean[] needConv = new boolean[1+INARG_COUNT]; for (int i = 0; i <= INARG_COUNT; i++) { Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i); Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i); ! if (!VerifyType.isNullConversion(src, dst, false) || level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) { needConv[i] = true; conversions++; } } boolean retConv = needConv[INARG_COUNT]; + if (retConv && srcType.returnType() == void.class) { + retConv = false; + conversions--; + } final int IN_MH = 0; final int INARG_BASE = 1; final int INARG_LIMIT = INARG_BASE + INARG_COUNT; final int NAME_LIMIT = INARG_LIMIT + conversions + 1; final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; + final int RESULT = (srcType.returnType() == void.class ? -1 : NAME_LIMIT - 1); // Now build a LambdaForm. MethodType lambdaType = srcType.basicType().invokerType(); Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
*** 228,238 **** } } else { if (dst.isPrimitive()) { // Caller has boxed a primitive. Unbox it for the target. Wrapper w = Wrapper.forPrimitiveType(dst); ! if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) { fn = ValueConversions.unbox(dst); } else if (src == Object.class || !Wrapper.isWrapperType(src)) { // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int // must include additional conversions // src must be examined at runtime, to detect Byte, Character, etc. --- 225,235 ---- } } else { if (dst.isPrimitive()) { // Caller has boxed a primitive. Unbox it for the target. Wrapper w = Wrapper.forPrimitiveType(dst); ! if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType(), false)) { fn = ValueConversions.unbox(dst); } else if (src == Object.class || !Wrapper.isWrapperType(src)) { // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int // must include additional conversions // src must be examined at runtime, to detect Byte, Character, etc.
*** 287,297 **** assert(names[RETURN_CONV] == null); names[RETURN_CONV] = new Name(fn, arg); assert(RETURN_CONV == names.length-1); } ! LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names); return SimpleMethodHandle.make(srcType, form); } /** * Identity function, with reference cast. --- 284,294 ---- assert(names[RETURN_CONV] == null); names[RETURN_CONV] = new Name(fn, arg); assert(RETURN_CONV == names.length-1); } ! LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT); return SimpleMethodHandle.make(srcType, form); } /** * Identity function, with reference cast.
src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File