< prev index next >

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

Print this page
rev 15427 : 8164483: Generate field lambda forms at link time
Reviewed-by: TBD

*** 485,510 **** @ForceInline /*non-public*/ static Object checkCast(Object mh, Object obj) { return ((DirectMethodHandle) mh).checkCast(obj); } Object checkCast(Object obj) { return member.getReturnType().cast(obj); } // Caching machinery for field accessors: ! private static final byte AF_GETFIELD = 0, AF_PUTFIELD = 1, AF_GETSTATIC = 2, AF_PUTSTATIC = 3, AF_GETSTATIC_INIT = 4, AF_PUTSTATIC_INIT = 5, AF_LIMIT = 6; // Enumerate the different field kinds using Wrapper, // with an extra case added for checked references. ! private static final int FT_LAST_WRAPPER = Wrapper.COUNT-1, FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(), FT_CHECKED_REF = FT_LAST_WRAPPER+1, FT_LIMIT = FT_LAST_WRAPPER+2; private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) { --- 485,515 ---- @ForceInline /*non-public*/ static Object checkCast(Object mh, Object obj) { return ((DirectMethodHandle) mh).checkCast(obj); } + @ForceInline + /*non-public*/ static Unsafe unsafe() { + return UNSAFE; + } + Object checkCast(Object obj) { return member.getReturnType().cast(obj); } // Caching machinery for field accessors: ! static final byte AF_GETFIELD = 0, AF_PUTFIELD = 1, AF_GETSTATIC = 2, AF_PUTSTATIC = 3, AF_GETSTATIC_INIT = 4, AF_PUTSTATIC_INIT = 5, AF_LIMIT = 6; // Enumerate the different field kinds using Wrapper, // with an extra case added for checked references. ! static final int FT_LAST_WRAPPER = Wrapper.COUNT-1, FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(), FT_CHECKED_REF = FT_LAST_WRAPPER+1, FT_LIMIT = FT_LAST_WRAPPER+2; private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
*** 513,523 **** + ftypeKind); } @Stable private static final LambdaForm[] ACCESSOR_FORMS = new LambdaForm[afIndex(AF_LIMIT, false, 0)]; ! private static int ftypeKind(Class<?> ftype) { if (ftype.isPrimitive()) return Wrapper.forPrimitiveType(ftype).ordinal(); else if (VerifyType.isNullReferenceConversion(Object.class, ftype)) return FT_UNCHECKED_REF; else --- 518,528 ---- + ftypeKind); } @Stable private static final LambdaForm[] ACCESSOR_FORMS = new LambdaForm[afIndex(AF_LIMIT, false, 0)]; ! static int ftypeKind(Class<?> ftype) { if (ftype.isPrimitive()) return Wrapper.forPrimitiveType(ftype).ordinal(); else if (VerifyType.isNullReferenceConversion(Object.class, ftype)) return FT_UNCHECKED_REF; else
*** 564,601 **** return lform; } private static final Wrapper[] ALL_WRAPPERS = Wrapper.values(); ! private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) { boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1); boolean isStatic = (formOp >= AF_GETSTATIC); boolean needsInit = (formOp >= AF_GETSTATIC_INIT); boolean needsCast = (ftypeKind == FT_CHECKED_REF); Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]); Class<?> ft = fw.primitiveType(); assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind); // getObject, putIntVolatile, etc. ! StringBuilder nameBuilder = new StringBuilder(); ! if (isGetter) { ! nameBuilder.append("get"); ! } else { ! nameBuilder.append("put"); ! } ! nameBuilder.append(fw.primitiveSimpleName()); ! nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3))); ! if (isVolatile) { ! nameBuilder.append("Volatile"); ! } MethodType linkerType; if (isGetter) linkerType = MethodType.methodType(ft, Object.class, long.class); else linkerType = MethodType.methodType(void.class, Object.class, long.class, ft); ! MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual); try { linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } --- 569,653 ---- return lform; } private static final Wrapper[] ALL_WRAPPERS = Wrapper.values(); ! private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) { ! if (isGetter) { ! if (isVolatile) { ! switch (wrapper) { ! case BOOLEAN: return GET_BOOLEAN_VOLATILE; ! case BYTE: return GET_BYTE_VOLATILE; ! case SHORT: return GET_SHORT_VOLATILE; ! case CHAR: return GET_CHAR_VOLATILE; ! case INT: return GET_INT_VOLATILE; ! case LONG: return GET_LONG_VOLATILE; ! case FLOAT: return GET_FLOAT_VOLATILE; ! case DOUBLE: return GET_DOUBLE_VOLATILE; ! case OBJECT: return GET_OBJECT_VOLATILE; ! } ! } else { ! switch (wrapper) { ! case BOOLEAN: return GET_BOOLEAN; ! case BYTE: return GET_BYTE; ! case SHORT: return GET_SHORT; ! case CHAR: return GET_CHAR; ! case INT: return GET_INT; ! case LONG: return GET_LONG; ! case FLOAT: return GET_FLOAT; ! case DOUBLE: return GET_DOUBLE; ! case OBJECT: return GET_OBJECT; ! } ! } ! } else { ! if (isVolatile) { ! switch (wrapper) { ! case BOOLEAN: return PUT_BOOLEAN_VOLATILE; ! case BYTE: return PUT_BYTE_VOLATILE; ! case SHORT: return PUT_SHORT_VOLATILE; ! case CHAR: return PUT_CHAR_VOLATILE; ! case INT: return PUT_INT_VOLATILE; ! case LONG: return PUT_LONG_VOLATILE; ! case FLOAT: return PUT_FLOAT_VOLATILE; ! case DOUBLE: return PUT_DOUBLE_VOLATILE; ! case OBJECT: return PUT_OBJECT_VOLATILE; ! } ! } else { ! switch (wrapper) { ! case BOOLEAN: return PUT_BOOLEAN; ! case BYTE: return PUT_BYTE; ! case SHORT: return PUT_SHORT; ! case CHAR: return PUT_CHAR; ! case INT: return PUT_INT; ! case LONG: return PUT_LONG; ! case FLOAT: return PUT_FLOAT; ! case DOUBLE: return PUT_DOUBLE; ! case OBJECT: return PUT_OBJECT; ! } ! } ! } ! throw new AssertionError("Invalid arguments"); ! } ! ! static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) { boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1); boolean isStatic = (formOp >= AF_GETSTATIC); boolean needsInit = (formOp >= AF_GETSTATIC_INIT); boolean needsCast = (ftypeKind == FT_CHECKED_REF); Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]); Class<?> ft = fw.primitiveType(); assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind); // getObject, putIntVolatile, etc. ! Kind kind = getFieldKind(isGetter, isVolatile, fw); MethodType linkerType; if (isGetter) linkerType = MethodType.methodType(ft, Object.class, long.class); else linkerType = MethodType.methodType(void.class, Object.class, long.class, ft); ! MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual); try { linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); }
*** 618,627 **** --- 670,680 ---- final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1; int nameCursor = ARG_LIMIT; final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any final int F_OFFSET = nameCursor++; // Either static offset or field offset. final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1); + final int U_HOLDER = nameCursor++; // UNSAFE holder final int INIT_BAR = (needsInit ? nameCursor++ : -1); final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1); final int LINKER_CALL = nameCursor++; final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1); final int RESULT = nameCursor-1; // either the call or the cast
*** 630,640 **** names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]); if (needsCast && !isGetter) names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]); Object[] outArgs = new Object[1 + linkerType.parameterCount()]; assert(outArgs.length == (isGetter ? 3 : 4)); ! outArgs[0] = UNSAFE; if (isStatic) { outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]); outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]); } else { outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]); --- 683,693 ---- names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]); if (needsCast && !isGetter) names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]); Object[] outArgs = new Object[1 + linkerType.parameterCount()]; assert(outArgs.length == (isGetter ? 3 : 4)); ! outArgs[0] = names[U_HOLDER] = new Name(NF_unsafe); if (isStatic) { outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]); outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]); } else { outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]);
*** 648,665 **** --- 701,724 ---- if (needsCast && isGetter) names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]); for (Name n : names) assert(n != null); // add some detail to the lambdaForm debugname, // significant only for debugging + StringBuilder nameBuilder = new StringBuilder(kind.methodName); if (isStatic) { nameBuilder.append("Static"); } else { nameBuilder.append("Field"); } if (needsCast) nameBuilder.append("Cast"); if (needsInit) nameBuilder.append("Init"); + if (needsCast || needsInit) { + // can't use the pre-generated form when casting and/or initializing return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT); + } else { + return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind); + } } /** * Pre-initialized NamedFunctions for bootstrapping purposes. * Factored in an inner class to delay initialization until first usage.
*** 672,682 **** NF_checkBase, NF_staticBase, NF_staticOffset, NF_checkCast, NF_allocateInstance, ! NF_constructorMethod; static { try { NamedFunction nfs[] = { NF_internalMemberName = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("internalMemberName", Object.class)), --- 731,742 ---- NF_checkBase, NF_staticBase, NF_staticOffset, NF_checkCast, NF_allocateInstance, ! NF_constructorMethod, ! NF_unsafe; static { try { NamedFunction nfs[] = { NF_internalMemberName = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("internalMemberName", Object.class)),
*** 695,705 **** NF_checkCast = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("checkCast", Object.class, Object.class)), NF_allocateInstance = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("allocateInstance", Object.class)), NF_constructorMethod = new NamedFunction(DirectMethodHandle.class ! .getDeclaredMethod("constructorMethod", Object.class)) }; // Each nf must be statically invocable or we get tied up in our bootstraps. assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs)); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); --- 755,767 ---- NF_checkCast = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("checkCast", Object.class, Object.class)), NF_allocateInstance = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("allocateInstance", Object.class)), NF_constructorMethod = new NamedFunction(DirectMethodHandle.class ! .getDeclaredMethod("constructorMethod", Object.class)), ! NF_unsafe = new NamedFunction(DirectMethodHandle.class ! .getDeclaredMethod("unsafe")) }; // Each nf must be statically invocable or we get tied up in our bootstraps. assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs)); } catch (ReflectiveOperationException ex) { throw newInternalError(ex);
< prev index next >