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