1 /*
2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 8013576 8129962
27  * @summary Add stat support to LambdaToMethod
28  * @library /tools/javac/lib
29  * @modules jdk.compiler/com.sun.tools.javac.api
30  *          jdk.compiler/com.sun.tools.javac.code
31  *          jdk.compiler/com.sun.tools.javac.comp
32  *          jdk.compiler/com.sun.tools.javac.main
33  *          jdk.compiler/com.sun.tools.javac.tree
34  *          jdk.compiler/com.sun.tools.javac.util
35  * @build combo.ComboTestHelper
36  * @run main TestLambdaToMethodStats
37  */
38 
39 import java.io.IOException;
40 
41 import javax.tools.Diagnostic;
42 import javax.tools.JavaFileObject;
43 
44 import com.sun.tools.javac.api.ClientCodeWrapper;
45 
46 import com.sun.tools.javac.util.List;
47 import combo.ComboInstance;
48 import combo.ComboParameter;
49 import combo.ComboTask.Result;
50 import combo.ComboTestHelper;
51 
52 public class TestLambdaToMethodStats extends ComboInstance<TestLambdaToMethodStats> {
53 
54     enum ExprKind implements ComboParameter {
55         LAMBDA("()->null"),
56         MREF1("this::g"),
57         MREF2("this::h");
58 
59         String exprStr;
60 
ExprKind(String exprStr)61         ExprKind(String exprStr) {
62             this.exprStr = exprStr;
63         }
64 
65         @Override
expand(String optParameter)66         public String expand(String optParameter) {
67             return exprStr;
68         }
69     }
70 
71     enum TargetKind implements ComboParameter {
72         IMPLICIT(""),
73         SERIALIZABLE("(A & java.io.Serializable)");
74 
75         String targetStr;
76 
TargetKind(String targetStr)77         TargetKind(String targetStr) {
78             this.targetStr = targetStr;
79         }
80 
81         @Override
expand(String optParameter)82         public String expand(String optParameter) {
83             return targetStr;
84         }
85     }
86 
87     enum DiagnosticKind {
88         LAMBDA_STAT("compiler.note.lambda.stat", true, false),
89         MREF_STAT("compiler.note.mref.stat", false, false),
90         MREF_STAT1("compiler.note.mref.stat.1", false, true);
91 
92         String code;
93         boolean lambda;
94         boolean bridge;
95 
DiagnosticKind(String code, boolean lambda, boolean bridge)96         DiagnosticKind(String code, boolean lambda, boolean bridge) {
97             this.code = code;
98             this.lambda = lambda;
99             this.bridge = bridge;
100         }
101     }
102 
main(String... args)103     public static void main(String... args) throws Exception {
104         new ComboTestHelper<TestLambdaToMethodStats>()
105                 .withDimension("EXPR", (x, expr) -> x.ek = expr, ExprKind.values())
106                 .withDimension("CAST", (x, target) -> x.tk = target, TargetKind.values())
107                 .run(TestLambdaToMethodStats::new);
108     }
109 
110     ExprKind ek;
111     TargetKind tk;
112 
113     String template = "interface A {\n" +
114             "   Object o();\n" +
115             "}\n" +
116             "class Test {\n" +
117             "   A a = #{CAST}#{EXPR};\n" +
118             "   Object g() { return null; }\n" +
119             "   Object h(Object... o) { return null; }\n" +
120             "}";
121 
122     @Override
doWork()123     public void doWork() throws IOException {
124         newCompilationTask()
125                 .withOption("--debug=dumpLambdaToMethodStats")
126                 .withSourceFromTemplate(template)
127                 .generate(this::check);
128     }
129 
check(Result<?> res)130     void check(Result<?> res) {
131         DiagnosticKind diag = null;
132         boolean altMetafactory = false;
133         for (DiagnosticKind dk : DiagnosticKind.values()) {
134             List<Diagnostic<? extends JavaFileObject>> jcDiag = res.diagnosticsForKey(dk.code);
135             if (jcDiag.nonEmpty()) {
136                 diag = dk;
137                 ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
138                         (ClientCodeWrapper.DiagnosticSourceUnwrapper)jcDiag.head;
139                 altMetafactory = (Boolean)dsu.d.getArgs()[0];
140                 break;
141             }
142         }
143 
144         if (diag == null) {
145             fail("No diagnostic found; " + res.compilationInfo());
146         }
147 
148         boolean error = diag.lambda !=
149                 (ek == ExprKind.LAMBDA);
150 
151         error |= diag.bridge !=
152                 (ek == ExprKind.MREF2);
153 
154         error |= altMetafactory !=
155                 (tk == TargetKind.SERIALIZABLE);
156 
157         if (error) {
158             fail("Bad stat diagnostic found for source\n" +
159                     "lambda = " + diag.lambda + "\n" +
160                     "bridge = " + diag.bridge + "\n" +
161                     "altMF = " + altMetafactory + "\n" +
162                     res.compilationInfo());
163         }
164     }
165 }
166