diff --git a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index d31b6f4217aecccd5278f53bc6cf88a1d2dc2fdb..bc3340cd43053691229a3474a95b931f3559b04b 100644 --- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -48,6 +48,7 @@ import sun.invoke.util.VerifyType; class InvokerBytecodeGenerator { /** Define class names for convenience. */ private static final String MH = "java/lang/invoke/MethodHandle"; + private static final String MHI = "java/lang/invoke/MethodHandleImpl"; private static final String LF = "java/lang/invoke/LambdaForm"; private static final String LFN = "java/lang/invoke/LambdaForm$Name"; private static final String CLS = "java/lang/Class"; @@ -57,6 +58,7 @@ class InvokerBytecodeGenerator { private static final String LF_SIG = "L" + LF + ";"; private static final String LFN_SIG = "L" + LFN + ";"; private static final String LL_SIG = "(L" + OBJ + ";)L" + OBJ + ";"; + private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; /** Name of its super class*/ private static final String superName = LF; @@ -433,7 +435,7 @@ class InvokerBytecodeGenerator { mv.visitLdcInsn(constantPlaceholder(pclass)); mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG); if (pclass.isArray()) mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); } diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java index b551ced3a300cb8f00a1cfd49303484e0317a542..cdf6e5a75ce7d71d5712d62060c9dc66f390e5d1 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -253,7 +253,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // Note: Do not check for a class hierarchy relation // between src and dst. In all cases a 'null' argument // will pass the cast conversion. - fn = ValueConversions.cast(dst); + fn = ValueConversions.cast(dst, Lazy.MH_castReference); } } Name conv = new Name(fn, names[INARG_BASE + i]); @@ -293,6 +293,25 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return SimpleMethodHandle.make(srcType, form); } + /** + * Identity function, with reference cast. + * @param t an arbitrary reference type + * @param x an arbitrary reference value + * @return the same value x + */ + @ForceInline + @SuppressWarnings("unchecked") + static T castReference(Class t, U x) { + // inlined Class.cast because we can't ForceInline it + if (x != null && !t.isInstance(x)) + throw newClassCastException(t, x); + return (T) x; + } + + private static ClassCastException newClassCastException(Class t, Object obj) { + return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); + } + static MethodHandle makeReferenceIdentity(Class refType) { MethodType lambdaType = MethodType.genericMethodType(1).invokerType(); Name[] names = arguments(1, lambdaType); @@ -488,6 +507,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static final NamedFunction NF_selectAlternative; static final NamedFunction NF_throwException; + static final MethodHandle MH_castReference; + static { try { NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); @@ -501,6 +522,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; NF_guardWithCatch.resolve(); NF_selectAlternative.resolve(); NF_throwException.resolve(); + + MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class); + MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } diff --git a/src/share/classes/sun/invoke/util/ValueConversions.java b/src/share/classes/sun/invoke/util/ValueConversions.java index bf0f13d4ef251151e1d88ab6744e2178f1536892..e3095fce2d7128373b7ad2ba36595b44925eb21a 100644 --- a/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/src/share/classes/sun/invoke/util/ValueConversions.java @@ -443,20 +443,6 @@ public class ValueConversions { return x; } - /** - * Identity function, with reference cast. - * @param t an arbitrary reference type - * @param x an arbitrary reference value - * @return the same value x - */ - @SuppressWarnings("unchecked") - static T castReference(Class t, U x) { - // inlined Class.cast because we can't ForceInline it - if (x != null && !t.isInstance(x)) - throw newClassCastException(t, x); - return (T) x; - } - private static ClassCastException newClassCastException(Class t, Object obj) { return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); } @@ -466,12 +452,10 @@ public class ValueConversions { static { try { MethodType idType = MethodType.genericMethodType(1); - MethodType castType = idType.insertParameterTypes(0, Class.class); MethodType ignoreType = idType.changeReturnType(void.class); MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); - //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); - CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType); + CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); 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)); @@ -509,6 +493,9 @@ public class ValueConversions { * and returns it as the given type. */ public static MethodHandle cast(Class type) { + return cast(type, CAST_REFERENCE); + } + public static MethodHandle cast(Class type, MethodHandle castReference) { if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); MethodHandle mh; Wrapper wrap = null; @@ -519,7 +506,7 @@ public class ValueConversions { mh = cache.get(wrap); if (mh != null) return mh; } - mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); + mh = MethodHandles.insertArguments(castReference, 0, type); if (cache != null) cache.put(wrap, mh); return mh;