Mercurial > hg > openjdk > aarch64-port > jdk
changeset 9148:246d1b83d711 jdk8_final
Merge to jdk8 release tip
author | Edward Nevill edward.nevill@linaro.org |
---|---|
date | Wed, 19 Mar 2014 10:45:18 +0000 |
parents | d7fc5ec6c30d (current diff) 687fd7c7986d (diff) |
children | 2a1bf36940ba |
files | .hgtags src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java |
diffstat | 13 files changed, 884 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Mon Mar 10 08:08:36 2014 -0400 +++ b/.hgtags Wed Mar 19 10:45:18 2014 +0000 @@ -257,3 +257,8 @@ cd23c29828584ec3c39c974579079ab97d65874e jdk8_b128_aarch64_rc3 ba03ec7a0b930582517592cf66abba734ec59891 jdk8_b128_aarch64_rc4 5de3e4944a8f100652483cb915959edcb8a2d71d jdk8_b128_aarch64_992 +f644211c59fd7c1d0c81239c55b31e1d377d7650 jdk8-b128 +80568a19aab7300bc92baf2dc225be929f5b03ed jdk8-b129 +43386cc9a017a9f9e704760050086bb18b778ae0 jdk8-b130 +e291ac47c9a90366c3c0787a6f7ce547a2bda308 jdk8-b131 +43cb25339b5500871f41388a5197f1b01c4b57b8 jdk8-b132
--- a/src/macosx/classes/apple/laf/JRSUIUtils.java Mon Mar 10 08:08:36 2014 -0400 +++ b/src/macosx/classes/apple/laf/JRSUIUtils.java Wed Mar 19 10:45:18 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,9 @@ import com.apple.laf.AquaImageFactory.NineSliceMetrics; import apple.laf.JRSUIConstants.*; +import sun.security.action.GetPropertyAction; + +import java.security.AccessController; public class JRSUIUtils { static boolean isLeopard = isMacOSXLeopard(); @@ -47,7 +50,7 @@ static boolean currentMacOSXVersionMatchesGivenVersionRange(final int version, final boolean inclusive, final boolean matchBelow, final boolean matchAbove) { // split the "10.x.y" version number - String osVersion = System.getProperty("os.version"); + String osVersion = AccessController.doPrivileged(new GetPropertyAction("os.version")); String[] fragments = osVersion.split("\\."); // sanity check the "10." part of the version
--- a/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Mon Mar 10 08:08:36 2014 -0400 +++ b/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Wed Mar 19 10:45:18 2014 +0000 @@ -200,6 +200,13 @@ implIsInstanceMethod ? "instance" : "static", implInfo, instantiatedArity, samArity)); } + for (MethodType bridgeMT : additionalBridges) { + if (bridgeMT.parameterCount() != samArity) { + throw new LambdaConversionException( + String.format("Incorrect number of parameters for bridge signature %s; incompatible with %s", + bridgeMT, samMethodType)); + } + } // If instance: first captured arg (receiver) must be subtype of class where impl method is defined final int capturedStart; @@ -232,7 +239,7 @@ throw new LambdaConversionException( String.format("Invalid receiver type %s; not a subtype of implementation receiver type %s", receiverClass, implReceiverClass)); - } + } } else { // no receiver capturedStart = 0; @@ -274,11 +281,18 @@ String.format("Type mismatch for lambda return: %s is not convertible to %s", actualReturnType, expectedType)); } - if (!isAdaptableToAsReturn(expectedType, samReturnType)) { + if (!isAdaptableToAsReturnStrict(expectedType, samReturnType)) { throw new LambdaConversionException( String.format("Type mismatch for lambda expected return: %s is not convertible to %s", expectedType, samReturnType)); } + for (MethodType bridgeMT : additionalBridges) { + if (!isAdaptableToAsReturnStrict(expectedType, bridgeMT.returnType())) { + throw new LambdaConversionException( + String.format("Type mismatch for lambda expected return: %s is not convertible to %s", + expectedType, bridgeMT.returnType())); + } + } } /** @@ -330,6 +344,10 @@ return toType.equals(void.class) || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false); } + private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) { + if (fromType.equals(void.class)) return toType.equals(void.class); + return isAdaptableTo(fromType, toType, true); + } /*********** Logging support -- for debugging only, uncomment as needed
--- a/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Mon Mar 10 08:08:36 2014 -0400 +++ b/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Wed Mar 19 10:45:18 2014 +0000 @@ -212,7 +212,7 @@ * @param functional */ void convertType(Class<?> arg, Class<?> target, Class<?> functional) { - if (arg.equals(target)) { + if (arg.equals(target) && arg.equals(functional)) { return; } if (arg == Void.TYPE || target == Void.TYPE) {
--- a/src/share/classes/java/util/Comparator.java Mon Mar 10 08:08:36 2014 -0400 +++ b/src/share/classes/java/util/Comparator.java Wed Mar 19 10:45:18 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -235,7 +235,7 @@ * @see #thenComparing(Comparator) * @since 1.8 */ - default <U extends Comparable<? super U>> Comparator<T> thenComparing( + default <U> Comparator<T> thenComparing( Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/LambdaReceiver.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035776 + * @summary Consistent Lambda construction + */ + +import java.lang.invoke.CallSite; +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.LambdaConversionException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; + +import LambdaReceiver_anotherpkg.LambdaReceiver_A; + +public class LambdaReceiver extends LambdaReceiver_A { + + interface IA { + int m(LambdaReceiver_A x); + } + + static MethodHandles.Lookup l; + static MethodHandle h; + private static MethodType mt(Class<?> k) { return MethodType.methodType(k); } + private static MethodType mt(Class<?> k, Class<?> k2) { return MethodType.methodType(k, k2); } + private static void mf(List<String> errs, MethodType mts, MethodType mtf, boolean shouldWork) { + } + + public static void main(String[] args) throws Throwable { + l = MethodHandles.lookup(); + h = l.findVirtual(LambdaReceiver_A.class, "f", mt(int.class)); + MethodType X = mt(int.class, LambdaReceiver.class); + MethodType A = mt(int.class, LambdaReceiver_A.class); + MethodType mti = mt(IA.class); + CallSite cs = LambdaMetafactory.metafactory(l, "m", mti,A,h,X); + IA p = (IA)cs.dynamicInvoker().invoke(); + LambdaReceiver_A lra = new LambdaReceiver_A(); + try { + p.m(lra); + } catch (ClassCastException cce) { + return; + } + throw new AssertionError("CCE expected"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/LambdaReceiverBridge.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035776 + * @summary Consistent Lambda construction + */ + +import java.lang.invoke.CallSite; +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.LambdaConversionException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; + +import LambdaReceiver_anotherpkg.LambdaReceiver_A; + +public class LambdaReceiverBridge extends LambdaReceiver_A { + + interface IA { + int m(LambdaReceiver_A x); + } + + static MethodHandles.Lookup l; + static MethodHandle h; + private static MethodType mt(Class<?> k) { return MethodType.methodType(k); } + private static MethodType mt(Class<?> k, Class<?> k2) { return MethodType.methodType(k, k2); } + private static void mf(List<String> errs, MethodType mts, MethodType mtf, boolean shouldWork) { + } + + public static void main(String[] args) throws Throwable { + l = MethodHandles.lookup(); + h = l.findVirtual(LambdaReceiver_A.class, "f", mt(int.class)); + MethodType X = mt(int.class, LambdaReceiverBridge.class); + MethodType A = mt(int.class, LambdaReceiver_A.class); + MethodType mti = mt(IA.class); + CallSite cs = LambdaMetafactory.altMetafactory(l, "m", mti,X,h,X, + LambdaMetafactory.FLAG_BRIDGES, 1, A); + IA p = (IA)cs.dynamicInvoker().invoke(); + LambdaReceiver_A lra = new LambdaReceiver_A(); + try { + p.m(lra); + } catch (ClassCastException cce) { + return; + } + throw new AssertionError("CCE expected"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/LambdaReceiver_anotherpkg/LambdaReceiver_A.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package LambdaReceiver_anotherpkg; + +public class LambdaReceiver_A { + protected final int f() { return 2; } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/LambdaReturn.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035776 + * @summary Consistent Lambda construction + */ + +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.LambdaConversionException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; + +public class LambdaReturn { + + interface I { + void m(); + } + + static void hereV() {} + static String hereS() { return "hi"; } + static MethodHandles.Lookup l; + private static MethodType mt(Class<?> k) { return MethodType.methodType(k); } + private static MethodType mt(Class<?> k, Class<?> k2) { return MethodType.methodType(k, k2); } + private static void amf(List<String> errs, MethodHandle h, MethodType mts, MethodType mtf, MethodType mtb, boolean shouldWork) { + MethodType mti = mt(I.class); + try { + LambdaMetafactory.altMetafactory(l, "m", mti, mts,h,mtf, + LambdaMetafactory.FLAG_BRIDGES, 1, mtb); + } catch(LambdaConversionException e) { + if (shouldWork) errs.add("Error: Should work h=" + h + " s=" + mts + " -- f=" + mtf + " / b=" + mtb + " got: " + e); + return; + } + if (!shouldWork) errs.add("Error: Should fail h=" + h + " s=" + mts + " -- f=" + mtf + " / b=" + mtb); + } + + public static void main(String[] args) throws Throwable { + l = MethodHandles.lookup(); + MethodHandle hV = l.findStatic(LambdaReturn.class, "hereV", mt(void.class)); + MethodHandle hS = l.findStatic(LambdaReturn.class, "hereS", mt(String.class)); + List<String> errs = new ArrayList<>(); + MethodType V = mt(void.class); + MethodType S = mt(String.class); + MethodType O = mt(Object.class); + MethodType I = mt(int.class); + amf(errs, hS, S, S, O, true); + amf(errs, hS, S, S, V, false); + amf(errs, hS, S, S, I, false); + amf(errs, hS, O, S, S, true); + amf(errs, hS, V, S, S, false); + amf(errs, hS, I, S, S, false); + amf(errs, hS, O, O, S, false); + amf(errs, hS, S, O, O, false); + amf(errs, hV, V, V, O, false); + amf(errs, hV, V, V, I, false); + amf(errs, hV, V, V, S, false); + amf(errs, hV, O, V, V, false); + amf(errs, hV, I, V, V, false); + amf(errs, hV, S, V, V, false); + + if (errs.size() > 0) { + for (String err : errs) { + System.err.println(err); + } + throw new AssertionError("Errors: " + errs.size()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/MetafactoryArityTest.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035776 + * @summary metafactory should fail if arities are mismatched + */ +import java.lang.invoke.*; +import java.util.Arrays; +import static java.lang.invoke.MethodType.methodType; + +public class MetafactoryArityTest { + + public interface I {} + public static class C { public static String m(int arg) { return ""; } } + + static final MethodHandles.Lookup lookup = MethodHandles.lookup(); + static final Class<?>[] capInt = { int.class }; + static final MethodHandle C_m; + static { + try { C_m = lookup.findStatic(C.class, "m", methodType(String.class, int.class)); } + catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); } + } + + public static void main(String... args) { + MethodType unary = methodType(String.class, int.class); + MethodType nullary = methodType(String.class); + MethodType binary = methodType(String.class, int.class, int.class); + MethodType unaryCS = methodType(CharSequence.class, int.class); + MethodType nullaryCS = methodType(CharSequence.class); + MethodType binaryCS = methodType(CharSequence.class, int.class, int.class); + MethodType unaryObj = methodType(Object.class, int.class); + MethodType nullaryObj = methodType(Object.class); + MethodType binaryObj = methodType(Object.class, int.class, int.class); + + test(true, C_m, unary, unary); + test(false, C_m, unary, nullary); + test(false, C_m, nullary, unary); + test(false, C_m, unary, binary); + test(false, C_m, binary, unary); + + testBridge(true, C_m, unary, unary, unaryCS); + testBridge(false, C_m, unary, unary, nullaryCS); + testBridge(false, C_m, unary, unary, binaryCS); + + testBridge(true, C_m, unary, unary, unaryCS, unaryObj); + testBridge(false, C_m, unary, unary, unaryCS, nullaryObj); + testBridge(false, C_m, unary, unary, unaryCS, binaryObj); + + testCapture(true, C_m, capInt, nullary, nullary); + testCapture(false, C_m, capInt, binary, binary); + testCapture(false, C_m, capInt, nullary, unary); + testCapture(false, C_m, capInt, nullary, binary); + testCapture(false, C_m, capInt, unary, nullary); + testCapture(false, C_m, capInt, unary, binary); + + testCaptureBridge(true, C_m, capInt, nullary, nullary, nullaryCS); + testCaptureBridge(false, C_m, capInt, unary, unary, unaryCS); + testCaptureBridge(false, C_m, capInt, nullary, nullary, unaryCS); + testCaptureBridge(false, C_m, capInt, nullary, nullary, binaryCS); + + testCaptureBridge(true, C_m, capInt, nullary, nullary, nullaryCS, nullaryObj); + testCaptureBridge(false, C_m, capInt, unary, unary, unaryCS, unaryObj); + testCaptureBridge(false, C_m, capInt, nullary, nullary, nullaryCS, unaryObj); + testCaptureBridge(false, C_m, capInt, nullary, nullary, nullaryCS, binaryObj); + } + + static void test(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT) { + tryMetafactory(correct, mh, new Class<?>[]{}, instMT, samMT); + tryAltMetafactory(correct, mh, new Class<?>[]{}, instMT, samMT); + } + + static void testBridge(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs) { + tryAltMetafactory(correct, mh, new Class<?>[]{}, instMT, samMT, bridgeMTs); + } + + static void testCapture(boolean correct, MethodHandle mh, Class<?>[] captured, MethodType instMT, MethodType samMT) { + tryMetafactory(correct, mh, captured, instMT, samMT); + tryAltMetafactory(correct, mh, captured, instMT, samMT); + } + + static void testCaptureBridge(boolean correct, MethodHandle mh, Class<?>[] captured, + MethodType instMT, MethodType samMT, MethodType... bridgeMTs) { + tryAltMetafactory(correct, mh, captured, instMT, samMT, bridgeMTs); + } + + static void tryMetafactory(boolean correct, MethodHandle mh, Class<?>[] captured, + MethodType instMT, MethodType samMT) { + try { + LambdaMetafactory.metafactory(lookup, "run", methodType(I.class, captured), + samMT, mh, instMT); + if (!correct) { + throw new AssertionError("Uncaught linkage error:" + + " impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT); + } + } + catch (LambdaConversionException e) { + if (correct) { + throw new AssertionError("Unexpected linkage error:" + + " e=" + e + + ", impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT); + } + } + } + + static void tryAltMetafactory(boolean correct, MethodHandle mh, Class<?>[] captured, + MethodType instMT, MethodType samMT, MethodType... bridgeMTs) { + boolean bridge = bridgeMTs.length > 0; + Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4]; + args[0] = samMT; + args[1] = mh; + args[2] = instMT; + args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0; + if (bridge) { + args[4] = bridgeMTs.length; + for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i]; + } + try { + LambdaMetafactory.altMetafactory(lookup, "run", methodType(I.class, captured), args); + if (!correct) { + throw new AssertionError("Uncaught linkage error:" + + " impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT + + ", bridges=" + Arrays.toString(bridgeMTs)); + } + } + catch (LambdaConversionException e) { + if (correct) { + throw new AssertionError("Unexpected linkage error:" + + " e=" + e + + ", impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT + + ", bridges=" + Arrays.toString(bridgeMTs)); + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/MetafactoryParameterCastTest.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035776 + * @summary Ensure that invocation parameters are always cast to the instantiatedMethodType + */ +import java.lang.invoke.*; +import java.util.Arrays; +import static java.lang.invoke.MethodType.methodType; + +public class MetafactoryParameterCastTest { + + static final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + public static class A { + } + + public static class B extends A { + void instance0() {} + void instance1(B arg) {} + static void static1(B arg) {} + static void static2(B arg1, B arg2) {} + } + + public static class C extends B {} + public static class NotC extends B {} + + public interface ASink { void take(A arg); } + public interface BSink { void take(B arg); } + + public static void main(String... args) throws Throwable { + new MetafactoryParameterCastTest().test(); + } + + void test() throws Throwable { + MethodType takeA = methodType(void.class, A.class); + MethodType takeB = methodType(void.class, B.class); + MethodType takeC = methodType(void.class, C.class); + + Class<?>[] noCapture = {}; + Class<?>[] captureB = { B.class }; + + MethodHandle[] oneBParam = { lookup.findVirtual(B.class, "instance0", methodType(void.class)), + lookup.findStatic(B.class, "static1", methodType(void.class, B.class)) }; + MethodHandle[] twoBParams = { lookup.findVirtual(B.class, "instance1", methodType(void.class, B.class)), + lookup.findStatic(B.class, "static2", methodType(void.class, B.class, B.class)) }; + + for (MethodHandle mh : oneBParam) { + // sam + tryASink(invokeMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA)); + tryBSink(invokeMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB)); + tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA)); + tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB)); + + // bridge + tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeC, takeA)); + tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeC, takeB)); + } + + for (MethodHandle mh : twoBParams) { + // sam + tryCapASink(invokeMetafactory(mh, ASink.class, "take", captureB, takeC, takeA)); + tryCapBSink(invokeMetafactory(mh, BSink.class, "take", captureB, takeC, takeB)); + tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeA)); + tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeB)); + + // bridge + tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeC, takeA)); + tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeC, takeB)); + } + } + + void tryASink(CallSite cs) throws Throwable { + ASink sink = (ASink) cs.dynamicInvoker().invoke(); + tryASink(sink); + } + + void tryCapASink(CallSite cs) throws Throwable { + ASink sink = (ASink) cs.dynamicInvoker().invoke(new B()); + tryASink(sink); + } + + void tryBSink(CallSite cs) throws Throwable { + BSink sink = (BSink) cs.dynamicInvoker().invoke(); + tryBSink(sink); + } + + void tryCapBSink(CallSite cs) throws Throwable { + BSink sink = (BSink) cs.dynamicInvoker().invoke(new B()); + tryBSink(sink); + } + + void tryASink(ASink sink) { + try { sink.take(new C()); } + catch (ClassCastException e) { + throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams()); + } + + try { + sink.take(new B()); + throw new AssertionError("Missing cast from A to C: " + lastMFParams()); + } + catch (ClassCastException e) { /* expected */ } + + try { + sink.take(new NotC()); + throw new AssertionError("Missing cast from A to C: " + lastMFParams()); + } + catch (ClassCastException e) { /* expected */ } + } + + void tryBSink(BSink sink) { + try { sink.take(new C()); } + catch (ClassCastException e) { + throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams()); + } + + try { + sink.take(new B()); + throw new AssertionError("Missing cast from B to C: " + lastMFParams()); + } + catch (ClassCastException e) { /* expected */ } + + try { + sink.take(new NotC()); + throw new AssertionError("Missing cast from B to C: " + lastMFParams()); + } + catch (ClassCastException e) { /* expected */ } + } + + MethodHandle lastMH; + Class<?>[] lastCaptured; + MethodType lastInstMT; + MethodType lastSamMT; + MethodType[] lastBridgeMTs; + + String lastMFParams() { + return "mh=" + lastMH + + ", captured=" + Arrays.toString(lastCaptured) + + ", instMT=" + lastInstMT + + ", samMT=" + lastSamMT + + ", bridgeMTs=" + Arrays.toString(lastBridgeMTs); + } + + CallSite invokeMetafactory(MethodHandle mh, Class<?> sam, String methodName, + Class<?>[] captured, MethodType instMT, MethodType samMT) { + lastMH = mh; + lastCaptured = captured; + lastInstMT = instMT; + lastSamMT = samMT; + lastBridgeMTs = new MethodType[]{}; + try { + return LambdaMetafactory.metafactory(lookup, methodName, methodType(sam, captured), + samMT, mh, instMT); + } + catch (LambdaConversionException e) { + // unexpected linkage error + throw new RuntimeException(e); + } + } + + CallSite invokeAltMetafactory(MethodHandle mh, Class<?> sam, String methodName, + Class<?>[] captured, MethodType instMT, + MethodType samMT, MethodType... bridgeMTs) { + lastMH = mh; + lastCaptured = captured; + lastInstMT = instMT; + lastSamMT = samMT; + lastBridgeMTs = bridgeMTs; + try { + boolean bridge = bridgeMTs.length > 0; + Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4]; + args[0] = samMT; + args[1] = mh; + args[2] = instMT; + args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0; + if (bridge) { + args[4] = bridgeMTs.length; + for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i]; + } + return LambdaMetafactory.altMetafactory(lookup, methodName, methodType(sam, captured), args); + } + catch (LambdaConversionException e) { + // unexpected linkage error + throw new RuntimeException(e); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/lambda/MetafactorySamReturnTest.java Wed Mar 19 10:45:18 2014 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8035776 + * @summary metafactory should fail if impl return does not match sam/bridge returns + */ +import java.lang.invoke.*; +import java.util.Arrays; +import static java.lang.invoke.MethodType.methodType; + +public class MetafactorySamReturnTest { + + static final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + public interface I {} + + public static class C { + public static void m_void(String arg) {} + public static boolean m_boolean(String arg) { return true; } + public static char m_char(String arg) { return 'x'; } + public static byte m_byte(String arg) { return 12; } + public static short m_short(String arg) { return 12; } + public static int m_int(String arg) { return 12; } + public static long m_long(String arg) { return 12; } + public static float m_float(String arg) { return 12; } + public static double m_double(String arg) { return 12; } + public static String m_String(String arg) { return ""; } + public static Integer m_Integer(String arg) { return 23; } + public static Object m_Object(String arg) { return new Object(); } + + public static MethodHandle getMH(Class<?> c) { + try { + return lookup.findStatic(C.class, "m_" + c.getSimpleName(), methodType(c, String.class)); + } + catch (NoSuchMethodException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + + public static void main(String... args) { + Class<?>[] t = { void.class, boolean.class, char.class, + byte.class, short.class, int.class, long.class, float.class, double.class, + String.class, Integer.class, Object.class }; + + for (int i = 0; i < t.length; i++) { + MethodHandle mh = C.getMH(t[i]); + for (int j = 0; j < t.length; j++) { + // TEMPORARY EXCEPTIONS + if (t[j] == void.class) continue; + if (t[i].isPrimitive() && t[j] == Object.class) continue; + if (t[i] == char.class && (t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue; + if (t[i] == byte.class && (t[j] == short.class || t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue; + if (t[i] == short.class && (t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue; + if (t[i] == int.class && (t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue; + if (t[i] == long.class && (t[j] == float.class || t[j] == double.class)) continue; + if (t[i] == float.class && t[j] == double.class) continue; + if (t[i] == int.class && t[j] == Integer.class) continue; + if (t[i] == Integer.class && (t[j] == int.class || t[j] == long.class || t[j] == float.class || t[j] == double.class)) continue; + // END TEMPORARY EXCEPTIONS + boolean correct = (t[i].isPrimitive() || t[j].isPrimitive()) + ? t[i] == t[j] + : t[j].isAssignableFrom(t[i]); + MethodType mti = methodType(t[i], String.class); + MethodType mtiCS = methodType(t[i], CharSequence.class); + MethodType mtj = methodType(t[j], String.class); + MethodType mtjObj = methodType(t[j], Object.class); + test(correct, mh, mti, mtj); + testBridge(correct, mh, mti, mti, mtjObj); + testBridge(correct, mh, mti, mti, mtiCS, mtjObj); + } + } + } + + static void test(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT) { + tryMetafactory(correct, mh, new Class<?>[]{}, instMT, samMT); + tryAltMetafactory(correct, mh, new Class<?>[]{}, instMT, samMT); + } + + static void testBridge(boolean correct, MethodHandle mh, MethodType instMT, MethodType samMT, MethodType... bridgeMTs) { + tryAltMetafactory(correct, mh, new Class<?>[]{}, instMT, samMT, bridgeMTs); + } + + static void tryMetafactory(boolean correct, MethodHandle mh, Class<?>[] captured, + MethodType instMT, MethodType samMT) { + try { + LambdaMetafactory.metafactory(lookup, "run", methodType(I.class, captured), + samMT, mh, instMT); + if (!correct) { + throw new AssertionError("Uncaught linkage error:" + + " impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT); + } + } + catch (LambdaConversionException e) { + if (correct) { + throw new AssertionError("Unexpected linkage error:" + + " e=" + e + + ", impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT); + } + } + } + + static void tryAltMetafactory(boolean correct, MethodHandle mh, Class<?>[] captured, + MethodType instMT, MethodType samMT, MethodType... bridgeMTs) { + boolean bridge = bridgeMTs.length > 0; + Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4]; + args[0] = samMT; + args[1] = mh; + args[2] = instMT; + args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0; + if (bridge) { + args[4] = bridgeMTs.length; + for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i]; + } + try { + LambdaMetafactory.altMetafactory(lookup, "run", methodType(I.class, captured), args); + if (!correct) { + throw new AssertionError("Uncaught linkage error:" + + " impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT + + ", bridges=" + Arrays.toString(bridgeMTs)); + } + } + catch (LambdaConversionException e) { + if (correct) { + throw new AssertionError("Unexpected linkage error:" + + " e=" + e + + ", impl=" + mh + + ", captured=" + Arrays.toString(captured) + + ", inst=" + instMT + + ", sam=" + samMT + + ", bridges=" + Arrays.toString(bridgeMTs)); + } + } + } + +}
--- a/test/java/util/Comparator/TypeTest.java Mon Mar 10 08:08:36 2014 -0400 +++ b/test/java/util/Comparator/TypeTest.java Wed Mar 19 10:45:18 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /** * @test * @summary Comparator API narrowing type test + * @bug 8033590 * @run testng TypeTest */ @@ -33,6 +34,8 @@ import java.util.Comparator; import org.testng.annotations.Test; +import static org.testng.Assert.assertTrue; + @Test(groups = "unit") public class TypeTest { static class Person { @@ -66,6 +69,24 @@ } } + static class Department { + Manager mgr; + String hr_code; + + Department(Manager mgr, String hr) { + this.mgr = mgr; + this.hr_code = hr; + } + + Manager getManager() { + return mgr; + } + + String getHR() { + return hr_code; + } + } + static <T> void assertOrder(T o1, T o2, Comparator<? super T> cmp) { if (cmp.compare(o1, o2) > 0) { System.out.println("Fail!!"); @@ -75,6 +96,8 @@ } } + // Type tests just to make sure the code can compile and build + // Not necessarily need a meaningful result public void testOrder() { Manager m1 = new Manager("Manager", 2, 2000); Manager m2 = new Manager("Manager", 4, 1300); @@ -93,4 +116,23 @@ Map<String, Integer> map = new TreeMap<>(); map.entrySet().stream().sorted(Map.Entry.comparingByKey(String.CASE_INSENSITIVE_ORDER)); } + + public void testJDK8033590() { + Manager a = new Manager("John Doe", 1234, 16); + Manager b = new Manager("Jane Roe", 2468, 16); + Department da = new Department(a, "X"); + Department db = new Department(b, "X"); + + Comparator<Department> cmp = Comparator.comparing(Department::getHR) + .thenComparing(Department::getManager, Employee.C); + assertTrue(cmp.compare(da, db) < 0); + + cmp = Comparator.comparing(Department::getHR) + .thenComparing(Department::getManager, Manager.C); + assertTrue(cmp.compare(da, db) == 0); + + cmp = Comparator.comparing(Department::getHR) + .thenComparing(Department::getManager, Person.C); + assertTrue(cmp.compare(da, db) > 0); + } }