changeset 2643:10e9228e77b0

8048121: javac complex method references: revamp and simplify 8037404: javac NPE or VerifyError for code with constructor reference of inner class 8047341: lambda reference to inner class in base class causes LambdaConversionException 8044748: JVM cannot access constructor though ::new reference although can call it directly 8044737: Lambda: NPE while obtaining method reference through lambda expression 8038776: VerifyError when running successfully compiled java class Reviewed-by: dlsmith, vromero
author rfield
date Fri, 14 Nov 2014 21:10:58 -0800
parents f7f3f96999ba
children da01c2706e5d
files src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java test/tools/javac/T8019486/WrongLNTForLambdaTest.java test/tools/javac/lambda/methodReference/MethodRefNewInnerBootstrap.java test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE1.java test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE2.java test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify1.java test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2.java test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2simple.java test/tools/javac/lambda/methodReference/MethodRefQualifier1.java test/tools/javac/lambda/methodReference/MethodRefSingleRefEvalBridge.java test/tools/javac/lambda/methodReference/MethodRefToInner.java test/tools/javac/lambda/methodReference/MethodReferenceComplexNullCheckTest.java
diffstat 12 files changed, 690 insertions(+), 220 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Nov 14 20:27:08 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Nov 14 21:10:58 2014 -0800
@@ -321,7 +321,9 @@
 
         ListBuffer<JCExpression> syntheticInits = new ListBuffer<>();
 
-        if (!sym.isStatic()) {
+        if (localContext.methodReferenceReceiver != null) {
+            syntheticInits.append(localContext.methodReferenceReceiver);
+        } else if (!sym.isStatic()) {
             syntheticInits.append(makeThis(
                     sym.owner.enclClass().asType(),
                     localContext.owner.enclClass()));
@@ -364,17 +366,10 @@
 
         //first determine the method symbol to be used to generate the sam instance
         //this is either the method reference symbol, or the bridged reference symbol
-        Symbol refSym = localContext.needsBridge()
-                ? localContext.bridgeSym
-                : localContext.isSignaturePolymorphic()
+        Symbol refSym = localContext.isSignaturePolymorphic()
                 ? localContext.sigPolySym
                 : tree.sym;
 
-        //build the bridge method, if needed
-        if (localContext.needsBridge()) {
-            bridgeMemberReference(tree, localContext);
-        }
-
         //the qualifying expression is treated as a special captured arg
         JCExpression init;
         switch(tree.kind) {
@@ -744,54 +739,51 @@
     // </editor-fold>
 
     /**
-     * Generate an adapter method "bridge" for a method reference which cannot
-     * be used directly.
+     * Converts a method reference which cannot be used directly into a lambda
      */
-    private class MemberReferenceBridger {
+    private class MemberReferenceToLambda {
 
         private final JCMemberReference tree;
         private final ReferenceTranslationContext localContext;
+        private final Symbol owner;
         private final ListBuffer<JCExpression> args = new ListBuffer<>();
         private final ListBuffer<JCVariableDecl> params = new ListBuffer<>();
 
-        MemberReferenceBridger(JCMemberReference tree, ReferenceTranslationContext localContext) {
+        private JCExpression receiverExpression = null;
+
+        MemberReferenceToLambda(JCMemberReference tree, ReferenceTranslationContext localContext, Symbol owner) {
             this.tree = tree;
             this.localContext = localContext;
+            this.owner = owner;
         }
 
-        /**
-         * Generate the bridge
-         */
-        JCMethodDecl bridge() {
+        JCLambda lambda() {
             int prevPos = make.pos;
             try {
                 make.at(tree);
                 Type samDesc = localContext.bridgedRefSig();
                 List<Type> samPTypes = samDesc.getParameterTypes();
 
-                //an extra argument is prepended to the signature of the bridge in case
-                //the member reference is an instance method reference (in which case
-                //the receiver expression is passed to the bridge itself).
-                Type recType = null;
+                // an extra argument is prepended in the case where the member
+                // reference is an unbound instance method reference (in which
+                // case the receiver expression in passed.
+                VarSymbol rcvr;
                 switch (tree.kind) {
-                    case IMPLICIT_INNER:
-                        recType = tree.sym.owner.type.getEnclosingType();
-                        break;
                     case BOUND:
-                        recType = tree.getQualifierExpression().type;
+                        rcvr = addParameter("rec$", tree.getQualifierExpression().type, false);
+                        receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
                         break;
                     case UNBOUND:
-                        recType = samPTypes.head;
+                        rcvr = addParameter("rec$", samPTypes.head, false);
                         samPTypes = samPTypes.tail;
                         break;
+                    default:
+                        rcvr = null;
+                        break;
                 }
 
-                //generate the parameter list for the bridged member reference - the
-                //bridge signature will match the signature of the target sam descriptor
-
-                VarSymbol rcvr = (recType == null)
-                        ? null
-                        : addParameter("rec$", recType, false);
+                // generate the parameter list for the coverted member reference.
+                // the signature will match the signature of the target sam descriptor
 
                 List<Type> refPTypes = tree.sym.type.getParameterTypes();
                 int refSize = refPTypes.size();
@@ -810,64 +802,50 @@
                     addParameter("xva$" + i, tree.varargsElement, true);
                 }
 
-                //generate the bridge method declaration
-                JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(localContext.bridgeSym.flags()),
-                        localContext.bridgeSym.name,
-                        make.QualIdent(samDesc.getReturnType().tsym),
-                        List.<JCTypeParameter>nil(),
-                        params.toList(),
-                        tree.sym.type.getThrownTypes() == null
-                        ? List.<JCExpression>nil()
-                        : make.Types(tree.sym.type.getThrownTypes()),
-                        null,
-                        null);
-                bridgeDecl.sym = (MethodSymbol) localContext.bridgeSym;
-                bridgeDecl.type = localContext.bridgeSym.type =
-                        types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList()));
+                //body generation - this can be either a method call or a
+                //new instance creation expression, depending on the member reference kind
+                JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE)
+                        ? expressionInvoke(rcvr)
+                        : expressionNew();
 
-                //bridge method body generation - this can be either a method call or a
-                //new instance creation expression, depending on the member reference kind
-                JCExpression bridgeExpr = (tree.getMode() == ReferenceMode.INVOKE)
-                        ? bridgeExpressionInvoke(makeReceiver(rcvr))
-                        : bridgeExpressionNew();
-
-                //the body is either a return expression containing a method call,
-                //or the method call itself, depending on whether the return type of
-                //the bridge is non-void/void.
-                bridgeDecl.body = makeLambdaExpressionBody(bridgeExpr, bridgeDecl);
-
-                return bridgeDecl;
+                JCLambda slam = make.Lambda(params.toList(), expr);
+                slam.targets = tree.targets;
+                slam.type = tree.type;
+                slam.pos = tree.pos;
+                return slam;
             } finally {
                 make.at(prevPos);
             }
         }
-        //where
-            private JCExpression makeReceiver(VarSymbol rcvr) {
-                if (rcvr == null) return null;
-                JCExpression rcvrExpr = make.Ident(rcvr);
-                Type rcvrType = tree.sym.enclClass().type;
-                if (rcvrType == syms.arrayClass.type) {
-                    // Map the receiver type to the actually type, not just "array"
-                    rcvrType = tree.getQualifierExpression().type;
-                }
-                if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
-                    rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
-                }
-                return rcvrExpr;
+
+        JCExpression getReceiverExpression() {
+            return receiverExpression;
+        }
+
+        private JCExpression makeReceiver(VarSymbol rcvr) {
+            if (rcvr == null) return null;
+            JCExpression rcvrExpr = make.Ident(rcvr);
+            Type rcvrType = tree.sym.enclClass().type;
+            if (rcvrType == syms.arrayClass.type) {
+                // Map the receiver type to the actually type, not just "array"
+                rcvrType = tree.getQualifierExpression().type;
             }
+            if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
+                rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
+            }
+            return rcvrExpr;
+        }
 
         /**
-         * determine the receiver of the bridged method call - the receiver can
-         * be either the synthetic receiver parameter or a type qualifier; the
-         * original qualifier expression is never used here, as it might refer
-         * to symbols not available in the static context of the bridge
+         * determine the receiver of the method call - the receiver can
+         * be a type qualifier, the synthetic receiver parameter or 'super'.
          */
-        private JCExpression bridgeExpressionInvoke(JCExpression rcvr) {
+        private JCExpression expressionInvoke(VarSymbol rcvr) {
             JCExpression qualifier =
                     tree.sym.isStatic() ?
                         make.Type(tree.sym.owner.type) :
                         (rcvr != null) ?
-                            rcvr :
+                            makeReceiver(rcvr) :
                             tree.getQualifierExpression();
 
             //create the qualifier expression
@@ -886,10 +864,9 @@
         }
 
         /**
-         * the enclosing expression is either 'null' (no enclosing type) or set
-         * to the first bridge synthetic parameter
+         * Lambda body to use for a 'new'.
          */
-        private JCExpression bridgeExpressionNew() {
+        private JCExpression expressionNew() {
             if (tree.kind == ReferenceKind.ARRAY_CTOR) {
                 //create the array creation expression
                 JCNewArray newArr = make.NewArray(
@@ -899,15 +876,10 @@
                 newArr.type = tree.getQualifierExpression().type;
                 return newArr;
             } else {
-                JCExpression encl = null;
-                switch (tree.kind) {
-                    case UNBOUND:
-                    case IMPLICIT_INNER:
-                        encl = make.Ident(params.first());
-                }
-
                 //create the instance creation expression
-                JCNewClass newClass = make.NewClass(encl,
+                //note that method reference syntax does not allow an explicit
+                //enclosing class (so the enclosing class is null)
+                JCNewClass newClass = make.NewClass(null,
                         List.<JCExpression>nil(),
                         make.Type(tree.getQualifierExpression().type),
                         convertArgs(tree.sym, args.toList(), tree.varargsElement),
@@ -921,7 +893,8 @@
         }
 
         private VarSymbol addParameter(String name, Type p, boolean genArg) {
-            VarSymbol vsym = new VarSymbol(0, names.fromString(name), p, localContext.bridgeSym);
+            VarSymbol vsym = new VarSymbol(PARAMETER | SYNTHETIC, names.fromString(name), p, owner);
+            vsym.pos = tree.pos;
             params.append(make.VarDef(vsym, null));
             if (genArg) {
                 args.append(make.Ident(vsym));
@@ -930,15 +903,6 @@
         }
     }
 
-    /**
-     * Bridges a member reference - this is needed when:
-     * * Var args in the referenced method need to be flattened away
-     * * super is used
-     */
-    private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) {
-        kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge());
-    }
-
     private MethodType typeToMethodType(Type mt) {
         Type type = types.erasure(mt);
         return new MethodType(type.getParameterTypes(),
@@ -1258,9 +1222,25 @@
 
         @Override
         public void visitLambda(JCLambda tree) {
+            analyzeLambda(tree, "lambda.stat");
+        }
+
+        private void analyzeLambda(JCLambda tree, JCExpression methodReferenceReceiver) {
+            // Translation of the receiver expression must occur first
+            JCExpression rcvr = translate(methodReferenceReceiver);
+            LambdaTranslationContext context = analyzeLambda(tree, "mref.stat.1");
+            if (rcvr != null) {
+                context.methodReferenceReceiver = rcvr;
+            }
+        }
+
+        private LambdaTranslationContext analyzeLambda(JCLambda tree, String statKey) {
             List<Frame> prevStack = frameStack;
             try {
-                LambdaTranslationContext context = (LambdaTranslationContext)makeLambdaContext(tree);
+                LambdaTranslationContext context = new LambdaTranslationContext(tree);
+                if (dumpLambdaToMethodStats) {
+                    log.note(tree, statKey, context.needsAltMetafactory(), context.translatedSym);
+                }
                 frameStack = frameStack.prepend(new Frame(tree));
                 for (JCVariableDecl param : tree.params) {
                     context.addSymbol(param.sym, PARAM);
@@ -1269,6 +1249,7 @@
                 contextMap.put(tree, context);
                 super.visitLambda(tree);
                 context.complete();
+                return context;
             }
             finally {
                 frameStack = prevStack;
@@ -1357,47 +1338,24 @@
          * information added in the LambdaToMethod pass will have the wrong
          * signature. Hooks between Lower and LambdaToMethod have been added to
          * handle normal "new" in this case. This visitor converts potentially
-         * effected method references into a lambda containing a normal "new" of
-         * the class.
+         * affected method references into a lambda containing a normal
+         * expression.
          *
          * @param tree
          */
         @Override
         public void visitReference(JCMemberReference tree) {
-            if (tree.getMode() == ReferenceMode.NEW
-                    && tree.kind != ReferenceKind.ARRAY_CTOR
-                    && tree.sym.owner.isLocal()) {
-                MethodSymbol consSym = (MethodSymbol) tree.sym;
-                List<Type> ptypes = ((MethodType) consSym.type).getParameterTypes();
-                Type classType = consSym.owner.type;
-
-                // Build lambda parameters
-                // partially cloned from TreeMaker.Params until 8014021 is fixed
-                Symbol owner = owner();
-                ListBuffer<JCVariableDecl> paramBuff = new ListBuffer<JCVariableDecl>();
-                int i = 0;
-                for (List<Type> l = ptypes; l.nonEmpty(); l = l.tail) {
-                    JCVariableDecl param = make.Param(make.paramName(i++), l.head, owner);
-                    param.sym.pos = tree.pos;
-                    paramBuff.append(param);
-                }
-                List<JCVariableDecl> params = paramBuff.toList();
-
-                // Make new-class call
-                JCNewClass nc = makeNewClass(classType, make.Idents(params));
-                nc.pos = tree.pos;
-
-                // Make lambda holding the new-class call
-                JCLambda slam = make.Lambda(params, nc);
-                slam.targets = tree.targets;
-                slam.type = tree.type;
-                slam.pos = tree.pos;
-
-                // Now it is a lambda, process as such
-                visitLambda(slam);
+            ReferenceTranslationContext rcontext = new ReferenceTranslationContext(tree);
+            contextMap.put(tree, rcontext);
+            if (rcontext.needsConversionToLambda()) {
+                 // Convert to a lambda, and process as such
+                MemberReferenceToLambda conv = new MemberReferenceToLambda(tree, rcontext, owner());
+                analyzeLambda(conv.lambda(), conv.getReceiverExpression());
             } else {
                 super.visitReference(tree);
-                contextMap.put(tree, makeReferenceContext(tree));
+                if (dumpLambdaToMethodStats) {
+                    log.note(tree, "mref.stat", rcontext.needsAltMetafactory(), null);
+                }
             }
         }
 
@@ -1652,14 +1610,6 @@
             }
         }
 
-        private TranslationContext<JCLambda> makeLambdaContext(JCLambda tree) {
-            return new LambdaTranslationContext(tree);
-        }
-
-        private TranslationContext<JCMemberReference> makeReferenceContext(JCMemberReference tree) {
-            return new ReferenceTranslationContext(tree);
-        }
-
         private class Frame {
             final JCTree tree;
             List<Symbol> locals;
@@ -1779,6 +1729,13 @@
              */
             final Set<Symbol> freeVarProcessedLocalClasses;
 
+            /**
+             * For method references converted to lambdas.  The method
+             * reference receiver expression. Must be treated like a captured
+             * variable.
+             */
+            JCExpression methodReferenceReceiver;
+
             LambdaTranslationContext(JCLambda tree) {
                 super(tree);
                 Frame frame = frameStack.head;
@@ -1798,9 +1755,6 @@
                 // This symbol will be filled-in in complete
                 this.translatedSym = makePrivateSyntheticMethod(0, null, null, owner.enclClass());
 
-                if (dumpLambdaToMethodStats) {
-                    log.note(tree, "lambda.stat", needsAltMetafactory(), translatedSym);
-                }
                 translatedSymbols = new EnumMap<>(LambdaSymbolKind.class);
 
                 translatedSymbols.put(PARAM, new LinkedHashMap<Symbol, Symbol>());
@@ -2017,6 +1971,13 @@
                 for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) {
                     params.append(make.VarDef((VarSymbol) thisSym, null));
                 }
+                if (methodReferenceReceiver != null) {
+                    params.append(make.VarDef(
+                            make.Modifiers(PARAMETER|FINAL),
+                            names.fromString("$rcvr$"),
+                            make.Type(methodReferenceReceiver.type),
+                            null));
+                }
                 for (Symbol thisSym : getSymbolMap(PARAM).values()) {
                     params.append(make.VarDef((VarSymbol) thisSym, null));
                 }
@@ -2044,40 +2005,27 @@
          * and the used by the main translation routines in order to adjust method
          * references (i.e. in case a bridge is needed)
          */
-        private class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
+        private final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
 
             final boolean isSuper;
-            final Symbol bridgeSym;
             final Symbol sigPolySym;
 
             ReferenceTranslationContext(JCMemberReference tree) {
                 super(tree);
                 this.isSuper = tree.hasKind(ReferenceKind.SUPER);
-                this.bridgeSym = needsBridge()
-                        ? makePrivateSyntheticMethod(isSuper ? 0 : STATIC,
-                                              referenceBridgeName(), null,
-                                              owner.enclClass())
-                        : null;
                 this.sigPolySym = isSignaturePolymorphic()
                         ? makePrivateSyntheticMethod(tree.sym.flags(),
                                               tree.sym.name,
                                               bridgedRefSig(),
                                               tree.sym.enclClass())
                         : null;
-                if (dumpLambdaToMethodStats) {
-                    String key = bridgeSym == null ?
-                            "mref.stat" : "mref.stat.1";
-                    log.note(tree, key, needsAltMetafactory(), bridgeSym);
-                }
             }
 
             /**
              * Get the opcode associated with this method reference
              */
             int referenceKind() {
-                return LambdaToMethod.this.referenceKind(needsBridge()
-                        ? bridgeSym
-                        : tree.sym);
+                return LambdaToMethod.this.referenceKind(tree.sym);
             }
 
             boolean needsVarArgsConversion() {
@@ -2085,62 +2033,6 @@
             }
 
             /**
-             * Generate a disambiguating string to increase stability (important
-             * if serialized)
-             *
-             * @return String to differentiate synthetic lambda method names
-             */
-            private String referenceBridgeDisambiguation() {
-                StringBuilder buf = new StringBuilder();
-                // Append the enclosing method signature to differentiate
-                // overloaded enclosing methods.
-                if (owner.type != null) {
-                    buf.append(typeSig(owner.type));
-                    buf.append(":");
-                }
-
-                // Append qualifier type
-                buf.append(classSig(tree.sym.owner.type));
-
-                // Note static/instance
-                buf.append(tree.sym.isStatic()? " S " : " I ");
-
-                // Append referenced signature
-                buf.append(typeSig(tree.sym.erasure(types)));
-
-                return buf.toString();
-            }
-
-            /**
-             * Construct a unique stable name for the method reference bridge
-             *
-             * @return Name to use for the synthetic method name
-             */
-            private Name referenceBridgeName() {
-                StringBuilder buf = new StringBuilder();
-                // Append lambda ID, this is semantically significant
-                buf.append(names.lambda);
-                // Note that it is a method reference bridge
-                buf.append("MR$");
-                // Append the enclosing method name
-                buf.append(enclosingMethodName());
-                buf.append('$');
-                // Append the referenced method name
-                buf.append(syntheticMethodNameComponent(tree.sym.name));
-                buf.append('$');
-                // Append a hash of the disambiguating string : enclosing method
-                // signature, etc.
-                String disam = referenceBridgeDisambiguation();
-                buf.append(Integer.toHexString(disam.hashCode()));
-                buf.append('$');
-                // The above appended name components may not be unique, append
-                // a count based on the above name components.
-                buf.append(syntheticMethodNameCounts.getIndex(buf));
-                String result = buf.toString();
-                return names.fromString(result);
-            }
-
-            /**
              * @return Is this an array operation like clone()
              */
             boolean isArrayOp() {
@@ -2175,13 +2067,16 @@
             }
 
             /**
-             * Does this reference needs a bridge (i.e. var args need to be
-             * expanded or "super" is used)
+             * Does this reference need to be converted to a lambda
+             * (i.e. var args need to be expanded or "super" is used)
              */
-            final boolean needsBridge() {
+            final boolean needsConversionToLambda() {
                 return isSuper || needsVarArgsConversion() || isArrayOp() ||
                         isPrivateInOtherClass() ||
-                        !receiverAccessible();
+                        !receiverAccessible() ||
+                        (tree.getMode() == ReferenceMode.NEW &&
+                          tree.kind != ReferenceKind.ARRAY_CTOR &&
+                          (tree.sym.owner.isLocal() || tree.sym.owner.isInner()));
             }
 
             Type generatedRefSig() {
--- a/test/tools/javac/T8019486/WrongLNTForLambdaTest.java	Fri Nov 14 20:27:08 2014 +0100
+++ b/test/tools/javac/T8019486/WrongLNTForLambdaTest.java	Fri Nov 14 21:10:58 2014 -0800
@@ -138,7 +138,7 @@
         checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
                 "Foo.class").toUri()), "$deserializeLambda$", deserializeExpectedLNT);
         checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
-                "Foo.class").toUri()), "lambda$MR$variablesInLambdas$notify$8bc4f5bd$1", lambdaBridgeExpectedLNT);
+                "Foo.class").toUri()), "lambda$variablesInLambdas$3", lambdaBridgeExpectedLNT);
         checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
                 "Foo.class").toUri()), "assignLambda", assignmentExpectedLNT);
         checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerBootstrap.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,72 @@
+/*
+ * 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 8044748
+ * @summary JVM cannot access constructor though ::new reference although can call it directly
+ */
+
+public class MethodRefNewInnerBootstrap {
+
+    interface Constructor {
+        public MyTest execute(int i);
+    }
+
+    public class MyTest {
+        public MyTest(int i) { System.out.println("Constructor executed " + i); }
+    }
+
+    public Constructor getConstructor() {
+        return MyTest::new;
+    }
+
+    public static void main(String argv[]) {
+        new MethodRefNewInnerBootstrap().call();
+    }
+
+    public void call() {
+        MyTest mt = new MyTest(0);
+
+        Constructor c1 = MyTest::new;
+        c1.execute(1);
+
+        Constructor c2 = getConstructor();
+        c2.execute(2);
+
+        Constructor c3 = new Constructor() {
+            public MyTest execute(int i) {
+                return new MyTest(3);
+            }
+        };
+        c3.execute(3);
+
+        Constructor c4 = new Constructor() {
+            public MyTest execute(int i) {
+                Constructor c = MyTest::new;
+                return c.execute(i);
+            }
+        };
+        c4.execute(4);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE1.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,48 @@
+/*
+ * 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 8037404
+ * @summary javac NPE or VerifyError for code with constructor reference of inner class
+ */
+
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+public class MethodRefNewInnerInLambdaNPE1 {
+    public static void main(String[] args) {
+        if (new MethodRefNewInnerInLambdaNPE1().getList().get().getClass() != TT.class)
+            throw new AssertionError("sanity failed");
+    }
+
+    Supplier<TT> getList() {
+        return () -> Stream.of(1).map(TT::new).findFirst().get();
+    }
+
+    class TT {
+        public TT(int i) {
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE2.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,57 @@
+/*
+ * 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 8044737
+ * @summary Lambda: NPE while obtaining method reference through lambda expression
+ * @compile MethodRefNewInnerInLambdaNPE2.java
+ */
+
+public class MethodRefNewInnerInLambdaNPE2 {
+
+    interface Constructor {
+        MyTest execute();
+    }
+
+    class MyTest {
+        MyTest() { System.out.println("Constructor executed"); }
+    }
+
+    public Constructor getConstructor() {
+        return getConstructor(() -> { return MyTest::new; });
+    }
+
+    public static void main(String argv[]) {
+        MethodRefNewInnerInLambdaNPE2 t = new MethodRefNewInnerInLambdaNPE2();
+        MyTest mytest = t.getConstructor().execute();
+    }
+
+    Constructor getConstructor(Wrapper arg) {
+        return arg.unwrap();
+    }
+
+    interface Wrapper {
+        Constructor unwrap();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify1.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,48 @@
+/*
+ * 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 8037404
+ * @summary javac NPE or VerifyError for code with constructor reference of inner class
+ */
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+public class MethodRefNewInnerInLambdaVerify1 {
+    public static void main(String[] args) {
+        if (new MethodRefNewInnerInLambdaVerify1().map().apply(1).getClass() != TT.class)
+            throw new AssertionError("sanity failed");
+    }
+
+    Function<Integer,TT> map() {
+        return (i) -> Stream.of(i).map(TT::new).findFirst().get();
+    }
+
+    class TT {
+        public TT(int i) {
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,62 @@
+/*
+ * 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 8038776
+ * @summary VerifyError when running successfully compiled java class
+ */
+
+import java.util.function.Function;
+
+/**
+ * Derived from code by:
+ * @author Yawkat
+ */
+public class MethodRefNewInnerInLambdaVerify2 {
+    public static void main(String[] args) { new MethodRefNewInnerInLambdaVerify2().runTest(); }
+
+    private void runTest() {
+        Worker worker = new Worker();
+        run(() -> worker.check(field -> new SomeClass(field)));
+        run(() -> worker.check(SomeClass::new));
+    }
+
+    private void run(Runnable runnable) {
+        runnable.run();
+    }
+
+    private class SomeClass {
+        final Object field;
+
+        SomeClass(Object field) {
+            this.field = field;
+        }
+    }
+
+    private static class Worker {
+        void check(Function<Object, SomeClass> i) {
+            if (!i.apply("frank").field.equals("frank")) throw new AssertionError("sanity failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2simple.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,50 @@
+/*
+ * 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 8038776
+ * @summary VerifyError when running successfully compiled java class
+ */
+
+import java.util.function.Function;
+
+/**
+ * Derived from code by:
+ * @author Yawkat
+ */
+public class MethodRefNewInnerInLambdaVerify2simple {
+    public static void main(String[] args) { new MethodRefNewInnerInLambdaVerify2simple().runTest(); }
+
+    private void runTest() {
+        Runnable r = (() -> { Sup w = SomeClass::new; } );
+    }
+
+    private class SomeClass {
+        SomeClass() {  }
+    }
+}
+
+interface Sup {
+  Object get();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefQualifier1.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,62 @@
+/*
+ * 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 8048121
+ * @summary javac complex method references: revamp and simplify
+ */
+
+public class MethodRefQualifier1 {
+
+    interface SAM {
+       void m();
+    }
+
+    static int count = 0;
+
+    static void assertTrue(boolean cond, String msg) {
+        if (!cond)
+            throw new AssertionError(msg);
+    }
+
+    MethodRefQualifier1 check() {
+        count++;
+        return this;
+    }
+
+    void ido(Object... args) { }
+
+    public static void main(String[] args) {
+       new MethodRefQualifier1().test();
+    }
+
+    void test() {
+       count = 0;
+       SAM s = check()::ido;
+       assertTrue(count == 1, "creation: unexpected: " + count);
+       count = 0;
+       s.m();
+       assertTrue(count == 0, "evaluation: unexpected: " + count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefSingleRefEvalBridge.java	Fri Nov 14 21:10:58 2014 -0800
@@ -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 8048121
+ * @summary javac complex method references: revamp and simplify
+ *
+ * Make sure that the method reference receiver is evaluated exactly once
+ * even in this bridging case.
+ */
+
+ public class MethodRefSingleRefEvalBridge {
+
+    interface SAM {
+       int m();
+    }
+
+    class ZZ {
+        // private to force bridging
+        private int four() { return 4; }
+    }
+
+    static int count = 0;
+    ZZ azz = new ZZ();
+
+    static void assertEqual(int expected, int got) {
+        if (got != expected)
+            throw new AssertionError("Expected " + expected + " got " + got);
+    }
+
+    public static void main(String[] args) {
+       new MethodRefSingleRefEvalBridge().test();
+    }
+
+    ZZ check() {
+        count++;
+        return azz;
+    }
+
+    void test() {
+       count = 0;
+       SAM s = check()::four;
+       assertEqual(1, count);
+
+       count = 0;
+       assertEqual(4, s.m());
+       assertEqual(0, count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodRefToInner.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,52 @@
+/*
+ * 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 8047341
+ * @summary lambda reference to inner class in base class causes LambdaConversionException
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+
+class MethodRefToInnerBase {
+  class TestString {
+    String str;
+    TestString(String strin) {
+      str = strin;
+    }
+  }
+}
+public class MethodRefToInner extends MethodRefToInnerBase {
+  public static void main(String[] args) {
+    new MethodRefToInner().run();
+  }
+  MethodRefToInner() {
+    super();
+  }
+  void run() {
+    List<String> list = new ArrayList<>();
+    list.stream().forEach(TestString::new);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/methodReference/MethodReferenceComplexNullCheckTest.java	Fri Nov 14 21:10:58 2014 -0800
@@ -0,0 +1,54 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 8048121
+ * @summary javac complex method references: revamp and simplify
+ *
+ * Make sure NPE check is done even in the convert to Lambda case
+ */
+
+public class MethodReferenceComplexNullCheckTest {
+    public static void main(String[] args) {
+        F fr = null;
+        boolean npeFired = false;
+        try {
+            IForm frf = fr::doit;
+        } catch (NullPointerException npe) {
+            npeFired = true;
+        } finally {
+            if (!npeFired) throw new AssertionError( "NPE should have been thrown");
+        }
+    }
+
+    interface IForm {
+       void xyz(Object... args);
+    }
+
+    class F {
+       private void doit(Object... args) { }
+    }
+}