1 /*
  2  * Copyright (c) 2023, 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 /*
 26  * @test
 27  * @bug 8293336
 28  * @summary Test for archiving resolved invokedynamic call sites
 29  * @requires vm.cds.write.archived.java.heap
 30  * @modules java.base/sun.invoke.util java.logging
 31  * @library /test/jdk/lib/testlibrary /test/lib
 32  *          /test/hotspot/jtreg/runtime/cds/appcds
 33  *          /test/hotspot/jtreg/runtime/cds/appcds/test-classes
 34  * @build IndyStringConcat
 35  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar ConcatA ConcatA$DummyClass ConcatB
 36  * @run driver IndyStringConcat
 37  */
 38 
 39 
 40 // NOTE: to run a subset of the tests, use something like
 41 //
 42 // jtreg .... -vmoptions:-DIndyStringConcat.test.only='(1)|(2)' \
 43 //            -vmoptions:-DIndyStringConcat.test.skip='2' IndyStringConcat.java
 44 //
 45 // A regexp can be specified in these two properties. Note that the specified regexp must be a full match.
 46 // E.g., -DIndyStringConcat.test.only='1.*' matches "1" and "12", but does NOT match "21".
 47 // (Search for ")$" in the code below)
 48 //
 49 // Also, some tests may be forced to be skipped. To run them, edit the variable forceSkip below.
 50 
 51 import jdk.test.lib.helpers.ClassFileInstaller;
 52 
 53 public class IndyStringConcat extends IndyTestBase {
 54     static final String appJar = ClassFileInstaller.getJarPath("app.jar");
 55     static final String mainClass_ConcatA = ConcatA.class.getName();
 56     static final String mainClass_ConcatB = ConcatB.class.getName();
 57 
 58     // Force some tests to be disabled during development.
 59     static String forceSkip = null;
 60 
 61     public static void main(String[] args) throws Exception {
 62         setup(forceSkip, appJar);
 63 
 64         // ------------------------------------------------------------
 65         test("\"LIT\" + (String)b", mainClass_ConcatA, "a");
 66         checkExec("LIT222");
 67 
 68         // ------------------------------------------------------------
 69         test("(String)a + (String)b", mainClass_ConcatA, "b");
 70         checkExec("aaa222");
 71 
 72         // ------------------------------------------------------------
 73         test("(String)a + (int)b", mainClass_ConcatA, "c");
 74         checkExec("aaa333");
 75 
 76         // ------------------------------------------------------------
 77         test("Test with ConcatB", mainClass_ConcatB, "B1");
 78         checkExec("ConcatBLIT333");
 79 
 80         // ------------------------------------------------------------
 81         test("Run ConcatB.foo() without dump-time resolution of its invokedynamic callsite", mainClass_ConcatB, "", "B1");
 82         checkExec("ConcatBLIT333", /* lambdaFormsMustBeArchived*/ false);
 83 
 84         // ------------------------------------------------------------
 85         test("WithAOT (no loop) for \"LIT\" + (String)b", mainClass_ConcatA, "a", "a",  RUN_AOT);
 86         checkExec("LIT222");
 87         shouldUseDynamicArchive();
 88 
 89         // ------------------------------------------------------------
 90         test("WithAOT (with loop) for \"LIT\" + (String)b", mainClass_ConcatA, "loopa", "loopa",  RUN_STATIC | RUN_AOT);
 91         checkExec("LITL");
 92         shouldUseDynamicArchive();
 93     }
 94 
 95     static void shouldUseDynamicArchive() throws Exception {
 96         shouldMatch("Opened archive IndyStringConcat-[0-9]+-dyn.jsa");
 97     }
 98 }
 99 
100 class ConcatA {
101     public static void main(String args[]) throws Exception {
102         if (args[0].equals("a")) {
103             foo("222");
104             System.out.print("OUTPUT = ");
105             System.out.println(x); // Avoid using + in diagnostic output.
106         } else if (args[0].equals("b")) {
107             bar("aaa", "222");
108             System.out.print("OUTPUT = ");
109             System.out.println(x); // Avoid using + in diagnostic output.
110         } else if (args[0].equals("c")) {
111             baz("aaa", 333);
112             System.out.print("OUTPUT = ");
113             System.out.println(x); // Avoid using + in diagnostic output.
114         } else if (args[0].equals("loopa")) {
115             loopa();
116             loopa();
117             System.out.print("OUTPUT = ");
118             System.out.println(x); // Avoid using + in diagnostic output.
119         }
120 
121         if (args.length > 1 && args[1].equals("load-extra-class")) {
122             // Work around "There is no class to be included in the dynamic archive." problem, where the
123             // dynamic archive is not generated.
124             DummyClass.doit();
125         }
126     }
127 
128     static void loopa() {
129         for (int i = 0; i < 100000; i++) {
130             foo("L");
131         }
132     }
133 
134     static String x;
135     static void foo(String b) {
136         x = "LIT" + b;
137     }
138     static void bar(String a, String b) {
139         x = a + b;
140     }
141     static void baz(String a, int b) {
142         x = a + b;
143     }
144 
145     static class DummyClass {
146         static void doit() {}
147     }
148 }
149 
150 
151 class ConcatB {
152     public static void main(String args[]) throws Exception {
153         if (args[0].equals("B1")) {
154             foo("333");
155             System.out.print("OUTPUT = ");
156             System.out.println(x); // Avoid using + in diagnostic output.
157         }
158     }
159 
160     static String x;
161     static void foo(String b) {
162         x = "ConcatBLIT" + b;
163     }
164 }