From 1294e0a158a8d7eb9b0bc619524aa42a30386ba2 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 10:24:44 +0100 Subject: [PATCH 01/13] TemplateFramework --- .../lib/test_generator/CodeSegment.java | 54 ++++++ .../test_generator/DynamicClassLoader.java | 70 +++++++ .../lib/test_generator/InputTemplate.java | 155 +++++++++++++++ .../lib/test_generator/InputTemplate1.java | 117 +++++++++++ .../lib/test_generator/InputTemplate10.java | 77 ++++++++ .../lib/test_generator/InputTemplate11.java | 96 +++++++++ .../lib/test_generator/InputTemplate12.java | 103 ++++++++++ .../lib/test_generator/InputTemplate13.java | 87 +++++++++ .../lib/test_generator/InputTemplate14.java | 124 ++++++++++++ .../lib/test_generator/InputTemplate15.java | 96 +++++++++ .../lib/test_generator/InputTemplate16.java | 83 ++++++++ .../lib/test_generator/InputTemplate17.java | 75 ++++++++ .../lib/test_generator/InputTemplate2.java | 84 ++++++++ .../lib/test_generator/InputTemplate3.java | 86 +++++++++ .../lib/test_generator/InputTemplate4.java | 90 +++++++++ .../lib/test_generator/InputTemplate5.java | 75 ++++++++ .../lib/test_generator/InputTemplate6.java | 74 +++++++ .../lib/test_generator/InputTemplate7.java | 87 +++++++++ .../lib/test_generator/InputTemplate8.java | 108 +++++++++++ .../lib/test_generator/InputTemplate9.java | 94 +++++++++ .../compiler/lib/test_generator/Template.java | 50 +++++ .../lib/test_generator/Template1.java | 25 +++ .../lib/test_generator/Template10.java | 60 ++++++ .../lib/test_generator/Template11.java | 67 +++++++ .../lib/test_generator/Template12.java | 47 +++++ .../lib/test_generator/Template2.java | 34 ++++ .../lib/test_generator/Template3.java | 37 ++++ .../lib/test_generator/Template4.java | 47 +++++ .../lib/test_generator/Template5.java | 41 ++++ .../lib/test_generator/Template6.java | 70 +++++++ .../lib/test_generator/Template7.java | 58 ++++++ .../lib/test_generator/Template8.java | 58 ++++++ .../lib/test_generator/Template9.java | 60 ++++++ .../lib/test_generator/TemplateGenerator.java | 182 ++++++++++++++++++ 34 files changed, 2671 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template1.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template10.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template11.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template12.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template2.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template3.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template4.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template5.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template6.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template7.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template8.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/Template9.java create mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java b/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java new file mode 100644 index 0000000000000..367c8b2303ffe --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, 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 compiler.lib.test_generator; +public class CodeSegment { + private final String statics; + private final StringBuilder calls; + private final StringBuilder methods; + private final String imports; + public CodeSegment(String statics, String calls, String methods, String imports) { + this.statics = statics; + this.calls = new StringBuilder(calls); + this.methods = new StringBuilder(methods); + this.imports = imports; + } + public String getStatics() { + return statics; + } + public void appendCall(String calls) { + this.calls.append(calls); + } + public String getCalls() { + return calls.toString(); + } + public void appendMethods(String method) { + this.methods.append(method); + } + public String getMethods() { + return methods.toString(); + } + public String getImports() { + return imports; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java b/test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java new file mode 100644 index 0000000000000..19f54486e5798 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024, 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 compiler.lib.test_generator; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; +public class DynamicClassLoader { + public static Class compileAndLoadClass(String filePath) throws Exception { + String className = computeClassName(filePath); + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + int compilationResult = compiler.run(null, null, null, filePath); + if (compilationResult != 0) { + throw new RuntimeException("Compilation failed"); + } + DynamicClassLoaderInternal loader = new DynamicClassLoaderInternal(); + return loader.loadClass(className); + } + private static String computeClassName(String filePath) { + Path path = Paths.get(filePath); + String fileName = path.getFileName().toString(); + String className = fileName.substring(0, fileName.lastIndexOf('.')); + String packageName = ""; + Path parent = path.getParent(); + if (parent != null) { + packageName = parent.toString().replace(File.separator, "."); + } + if (!packageName.isEmpty()) { + className = packageName + "." + className; + } + return className; + } + private static class DynamicClassLoaderInternal extends ClassLoader { + @Override + public Class findClass(String name) throws ClassNotFoundException { + File file = new File(name + ".class"); + if (file.exists()) { + try { + byte[] bytes = java.nio.file.Files.readAllBytes(file.toPath()); + return defineClass(null, bytes, 0, bytes.length); + } catch (Exception e) { + e.printStackTrace(); + } + } + return super.findClass(name); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java new file mode 100644 index 0000000000000..f0d0079d7fe5c --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2024, 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 compiler.lib.test_generator; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; +public abstract class InputTemplate { + private static final Random RAND = new Random(32); + public static Integer[] integerValues = { + -2, -1, 0, 1, 2, + Integer.MIN_VALUE - 2, Integer.MIN_VALUE - 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, + Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 2 + }; + public static Integer[] positiveIntegerValues = { + 1, 2, + Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE + }; + public static Integer[] arraySizes = { + 1, 10, 100, 1000, 10000, 100000, 200000, 500000, 1000000 + }; + public static Integer[] integerValuesNonZero = { + -2, -1, 1, 2, + Integer.MIN_VALUE - 2, Integer.MIN_VALUE - 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, + Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 2 + }; + public static Long[] longValues = { + -2L, -1L, 0L, 1L, 2L, + Integer.MIN_VALUE - 2L, Integer.MIN_VALUE - 1L, (long) Integer.MIN_VALUE, Integer.MIN_VALUE + 1L, Integer.MIN_VALUE + 2L, + Integer.MAX_VALUE - 2L, Integer.MAX_VALUE - 1L, (long) Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MAX_VALUE + 2L, + Long.MIN_VALUE - 2L, Long.MIN_VALUE - 1L, Long.MIN_VALUE, Long.MIN_VALUE + 1L, Long.MIN_VALUE + 2L, + Long.MAX_VALUE - 2L, Long.MAX_VALUE - 1L, Long.MAX_VALUE, Long.MAX_VALUE + 1L, Long.MAX_VALUE + 2L + }; + public static Long[] longValuesNonZero = { + -2L, -1L, 1L, 2L, + Integer.MIN_VALUE - 2L, Integer.MIN_VALUE - 1L, (long) Integer.MIN_VALUE, Integer.MIN_VALUE + 1L, Integer.MIN_VALUE + 2L, + Integer.MAX_VALUE - 2L, Integer.MAX_VALUE - 1L, (long) Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MAX_VALUE + 2L, + Long.MIN_VALUE - 2L, Long.MIN_VALUE - 1L, Long.MIN_VALUE, Long.MIN_VALUE + 1L, Long.MIN_VALUE + 2L, + Long.MAX_VALUE - 2L, Long.MAX_VALUE - 1L, Long.MAX_VALUE, Long.MAX_VALUE + 1L, Long.MAX_VALUE + 2L + }; + public static Short[] shortValuesNonZero = { + -2, -1,0, 1, 2, + (short) (Integer.MIN_VALUE & 0xFFFF), (short) ((Integer.MIN_VALUE + 1) & 0xFFFF), (short) Integer.MIN_VALUE, (short) (Integer.MIN_VALUE + 1), (short) (Integer.MIN_VALUE + 2), + (short) (Integer.MAX_VALUE - 2), (short) (Integer.MAX_VALUE - 1), (short) Integer.MAX_VALUE, (short) (Integer.MAX_VALUE + 1), (short) (Integer.MAX_VALUE + 2), + (short) -32770, (short) -32769, (short) -32768, (short) -32767, (short) -32766, + (short) 32765, (short) 32766, (short) 32767, (short) 32768, (short) 32769 + }; + public static Short[] shortValues = { + -2, -1, 1, 2, + (short) (Integer.MIN_VALUE & 0xFFFF), (short) ((Integer.MIN_VALUE + 1) & 0xFFFF), (short) Integer.MIN_VALUE, (short) (Integer.MIN_VALUE + 1), (short) (Integer.MIN_VALUE + 2), + (short) (Integer.MAX_VALUE - 2), (short) (Integer.MAX_VALUE - 1), (short) Integer.MAX_VALUE, (short) (Integer.MAX_VALUE + 1), (short) (Integer.MAX_VALUE + 2), + (short) -32770, (short) -32769, (short) -32768, (short) -32767, (short) -32766, + (short) 32765, (short) 32766, (short) 32767, (short) 32768, (short) 32769 + }; + public InputTemplate() { + } + public static T getRandomValue(T[] array) { + return array[RAND.nextInt(array.length)]; + } + public static String getRandomValueAsString(T[] array) { + T value = getRandomValue(array); + return String.valueOf(value); // Convert any type T to String + } + public static String getUniqueId() { + return String.valueOf(System.nanoTime()); + } + public static Integer[] getIntegerValues(int size) { + HashSet integers = new HashSet<>(size); + while (integers.size() < size) { + int number = RAND.nextInt(Integer.MAX_VALUE - 1) + 1; + integers.add(number); + } + return integers.toArray(new Integer[0]); + } + public static String getJavaCode(CodeSegment inputTemplate, ArrayList> inputReplacements, long num) { + String template = """ + import java.util.Objects; + \\{imports} + public class GeneratedTest\\{num} { + \\{statics} + public static void main(String args[]) throws Exception { + \\{calls} + System.out.println("Passed"); + } + \\{methods} + } + """; + CodeSegment CodeSegment = fillTemplate(inputTemplate, inputReplacements.getFirst()); + for (int i =1; i replacements = Map.ofEntries( + Map.entry("num", String.valueOf(num)), + Map.entry("statics", CodeSegment.getStatics()), + Map.entry("calls", CodeSegment.getCalls()), + Map.entry("methods", CodeSegment.getMethods()), + Map.entry("imports", CodeSegment.getImports()) + ); + return doReplacements(template, replacements); + } + private static CodeSegment fillTemplate(CodeSegment CodeSegment, Map replacements) { + String statics = doReplacements(CodeSegment.getStatics(), replacements); + String calls = doReplacements(CodeSegment.getCalls(), replacements); + String methods = doReplacements(CodeSegment.getMethods(), replacements); + String imports = doReplacements(CodeSegment.getImports(), replacements); + return new CodeSegment(statics, calls, methods,imports); + } + public static String doReplacements(String template, Map replacements) { + for (Map.Entry entry : replacements.entrySet()) { + String pattern = "\\{%s}".formatted(entry.getKey()); + String replacement = entry.getValue(); + + // Find the pattern in the template and determine its indentation level + int index = template.indexOf(pattern); + if (index != -1) { + int lineStart = template.lastIndexOf('\n', index); + String indentation = template.substring(lineStart + 1, index).replaceAll("\\S", ""); + + // Add indentation to all lines of the replacement (except the first one) + String indentedReplacement = replacement.lines() + .collect(Collectors.joining("\n%s".formatted(indentation))); + template = template.replace(pattern, indentedReplacement); + } + } + return template; + } + public abstract CodeSegment getTemplate(); + public abstract Map getRandomReplacements(int numTest); + public abstract String[] getCompileFlags(); + public abstract int getNumberOfTests(); + public abstract int getNumberOfTestMethods(); +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java new file mode 100644 index 0000000000000..c6f87fcaed5ae --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024, 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 compiler.lib.test_generator; +import java.util.HashMap; +import java.util.Map; +public class InputTemplate1 extends InputTemplate { + public InputTemplate1() { + } + @Override + public CodeSegment getTemplate() { + /* TODO: + * use $limit, $i, $lFld for variables + * all defined functions should use uniqueId to avoid conflict + * Nesting : we want to be able to nest CodeTemplate in another CodeTemplate e.g. at \{thing} + * this would require replacing conflicting variables e.g. $i with $i1 and $i2, + * and also replace \{init} from the inner CodeTemplate with a var $limit from outer CodeTemplate + **/ + String imports= """ + """; + String statics = """ + //InputTemplate1 + static long lFld; + static A a = new A(); + static boolean flag; + static class A { + int i; + } + """; + String call = """ + test_\\{uniqueId}(); + """; + String method = """ + public static void test_\\{uniqueId}() { + long limit = lFld; + for (int i =\\{init1}; i < \\{limit}; i \\{arithm1}= \\{stride1}) { + // Use stride > Integer.MAX_VALUE such that LongCountedLoopNode is not split further into loop nests. + for (long j = \\{init2}; j < limit; j\\{arithm2}=\\{stride2}) { + a.i += \\{val1}; // NullCheck with trap on false path -> reason to peel + \\{thing} + \\{template1} + if (j > 0) { // After peeling: j > 0 always true -> loop folded away + \\{template2} + break; + } + } + } + } + """; + return new CodeSegment(statics, call, method,imports); + } + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template1(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(integerValues); + String stride1 = getRandomValueAsString(integerValuesNonZero); + String stride2 = getRandomValueAsString(integerValuesNonZero); + String arithm1 = getRandomValue(new String[]{"+", "-"}); + String arithm2 = getRandomValue(new String[]{"+", "-"}); + String thing = getRandomValue(new String[]{"", "synchronized (new Object()) { }"}); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit", limit); + replacements.put("val1", val1); + replacements.put("arithm1", arithm1); + replacements.put("arithm2", arithm2); + replacements.put("stride1", stride1); + replacements.put("stride2", stride2); + replacements.put("thing", thing); + replacements.put("uniqueId", uniqueId); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + return replacements; + } + @Override + public String[] getCompileFlags() { + return new String[] { + "-Xcomp", + "-XX:-CreateCoredumpOnCrash" + }; + } + @Override + public int getNumberOfTests(){ + return 1; + } + @Override + public int getNumberOfTestMethods() { + return 10; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java new file mode 100644 index 0000000000000..6f4fcb0d08924 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java @@ -0,0 +1,77 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate10 extends InputTemplate { + public InputTemplate10() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + String statics= """ + //InputTemplate10 + public static int iFld = \\{val}; + """; + String call= """ + for (int i = \\{init1}; i < \\{limit1}; i++) { + test_\\{uniqueId}(i % 2 == 0); + } + """; + String method= """ + public static void test_\\{uniqueId}(boolean flag) { + for (int i = \\{init2}; i < \\{limit2}; i++) { + // Fast loop: If is true -> iFld++ + // Slow loop: If is false -> no update of iFld + if (flag) { + iFld++; + \\{template1} + } + \\{template2} + } + } + """; + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template2(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String val = getRandomValueAsString(integerValues); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("val", val); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java new file mode 100644 index 0000000000000..757adaabbd577 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java @@ -0,0 +1,96 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate11 extends InputTemplate { + public InputTemplate11() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate11 + static int iFld, iFld2; + static boolean flag; + static int[] iArr = new int[\\{size}]; + """; + + String call = "test_\\{uniqueId}();\n"; + + String method = """ + public static void test_\\{uniqueId}() { + int zero =\\{val}; + int limit = \\{limit}; + for (; limit < \\{limit1}; limit \\{arithm}= \\{stride}); + for (int i = \\{init1}; i < limit; i++) { + zero = 0; + } + for (int i = \\{init2}; i < \\{size}; i++) { + if (flag) { // 1) Triggers Loop Peeling + \\{template1} + } + int k = iFld + i * zero; // Loop variant before CCP + if (k == \\{val}) { // 2) After CCP: Loop invariant -> triggers Loop Unswitching + iFld2 = \\{val}; + } else { + iArr[i] = \\{val}; // 3) After Loop Unswitching: Triggers Pre/Main/Post and then 4) Range Check Elimination + \\{template2} + } + + } + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template2(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String val = getRandomValueAsString(integerValues); + String size = getRandomValueAsString(arraySizes); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(positiveIntegerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"+", "-"}); + String uniqueId = String.valueOf(numTest); + replacements.put("val", val); + replacements.put("size", size); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit", limit); + replacements.put("limit1", limit1); + replacements.put("arithm", arithm); + replacements.put("stride", stride); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + @Override + public String[] getCompileFlags() { + return new String[]{"-Xcomp", + "-XX:LoopMaxUnroll=0", + "-XX:CompileOnly=Test::test*"}; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java new file mode 100644 index 0000000000000..4c13b671d8d2c --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java @@ -0,0 +1,103 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate12 extends InputTemplate { + public InputTemplate12() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate12 + static boolean flag; + static long lFld; + static int []iArr=new int[\\{size}]; + """; + + String call = "test_\\{uniqueId}();\n"; + + String method = """ + static void test_\\{uniqueId}() { + long l1 = \\{val1}; + long l2 = \\{val2}; + int zero = \\{val3}; + int limit = \\{limit}; + for (; limit < \\{limit1}; limit \\{arithm}= \\{stride}); + for (int i = \\{init1}; i < limit; i++) { + zero = 0; + } + for (int i = \\{init2}; i < \\{size}; i++) { + iArr[i] = \\{val1}; // Just a reason to pre/main/post (trigger more loop opts) + if (flag) { // Triggers Loop Peeling before CCP + \\{template1} + } + if (zero > i) { // Folded away after CCP. + // DivLs add 30 to the loop body count and we hit LoopUnrollLimit. Add more + // statements/DivLs if you want to use a higher LoopUnrollLimit value. + // After CCP, these statements are folded away and we can unroll this loop. + l1 /= lFld; + l2 /= lFld; + \\{template2} + } + } + } + """; + + return new CodeSegment(statics, call, method,imports); + } + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template1(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("l1"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String size = getRandomValueAsString(arraySizes); + String val3 = getRandomValueAsString(integerValues); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(positiveIntegerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"+", "-"}); + String uniqueId = String.valueOf(numTest); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("size", size); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit", limit); + replacements.put("limit1", limit1); + replacements.put("arithm", arithm); + replacements.put("stride", stride); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[]{"-Xcomp", + "-XX:CompileOnly=Test::test*", + }; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java new file mode 100644 index 0000000000000..a0e3e4b4cdacc --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java @@ -0,0 +1,87 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate13 extends InputTemplate { + public InputTemplate13() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate13 + static int[] iArr = new int[\\{size}]; + static int[] iArr2 = new int[\\{size}]; + """; + + String call = """ + for (int i = \\{init1}; i < \\{limit1}; i++) { + test_\\{uniqueId}(); + } + """; + + + String method = """ + static void test_\\{uniqueId}() { + int z = 0; + for (int i = \\{init2}; i < \\{size}; i++) { + iArr[i] = 12; // Normal Loop Predication can be applied for this check (profiled loop predicate due to the loop exit below). + // This loop exit enables Range Check Elimination + if (i > 56) { + \\{template1} + break; + } + // After pre/main/post, this check can be folded because i > 0 will always be true (main loop starts with i = 1). + if (i > 0) { + z = 3; + \\{template2} + } + // Becomes iArr[i+3] after pre/main/post and we can apply Range Check Elimination. + iArr2[i + z] = 34; + } + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1=new Template1(); + Template template2=new Template4(); + String template_nes1=template1.getTemplate("i"); + String template_nes2=template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String size = getRandomValueAsString(arraySizes); + String init2 = getRandomValueAsString(positiveIntegerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("limit1", limit1); + replacements.put("init2", init2); + replacements.put("uniqueId", uniqueId); + replacements.put("size", size); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + return replacements; + } + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java new file mode 100644 index 0000000000000..826aeaa5ae137 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java @@ -0,0 +1,124 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate14 extends InputTemplate { + public InputTemplate14() {} + + @Override + public CodeSegment getTemplate() { + String imports= """ + """; + + String statics = """ + //InputTemplate14 + static int N = \\{val1}; + static int iFld; + static int[] zeros = new int[N]; + static boolean sinkB; + static int sinkI1; + """; + + String call = """ + for (int i = \\{init1}; i < \\{limit1}; i++) { + test_\\{uniqueId}(); + } + """; + + String method = """ + public static void test_\\{uniqueId}() { + int xxx = \\{val2}; + boolean flag = \\{boole}; + for (; xxx < \\{limit1}; xxx++) { + iFld = xxx; // seems to sometimes show 149, bad + + if (flag) { + \\{template2} + } // required + + for (int ddd = \\{init1}; ddd > \\{limit2}; ddd--) { + for (int ccc = xxx; ccc < \\{limit3}; ) { + } + } + + for (int aaa = \\{init2}; aaa < \\{limit4}; aaa++) { + for (long l = \\{init3}; l < \\{limit5}; ++l) { + for (int bbb = \\{init4}; bbb < \\{limit6}; ++bbb) { + try { + bbb = (209 / zeros[xxx]); + \\{template1} + } catch (ArithmeticException a_e) { + } + } + } + } + + for (int j = \\{init5}; j < \\{limit6}; j++) {} // empty loop + } + sinkB = flag; + sinkI1 = xxx; + System.out.println("iFld = " + iFld); + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template1(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("l"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(integerValues); + String val1 = getRandomValueAsString(positiveIntegerValues); + String val2 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String init3 = getRandomValueAsString(integerValues); + String init4 = getRandomValueAsString(integerValues); + String init5 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String limit3 = getRandomValueAsString(positiveIntegerValues); + String limit4 = getRandomValueAsString(positiveIntegerValues); + String limit5 = getRandomValueAsString(positiveIntegerValues); + String limit6 = getRandomValueAsString(positiveIntegerValues); + String boole = getRandomValue(new String[]{"false", "true"}); + String uniqueId = String.valueOf(numTest); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("init3", init3); + replacements.put("init4", init4); + replacements.put("init5", init5); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("limit3", limit3); + replacements.put("limit4", limit4); + replacements.put("limit5", limit5); + replacements.put("limit6", limit6); + replacements.put("boole", boole); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java new file mode 100644 index 0000000000000..36b0102e9dd99 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java @@ -0,0 +1,96 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate15 extends InputTemplate { + public InputTemplate15() {} + + @Override + public CodeSegment getTemplate() { + String imports= """ + """; + + String statics = """ + //InputTemplate15 + static int iFld, iFld2; + static boolean flag; + static int[] iArr = new int[\\{size}]; + """; + + String call = "test_\\{uniqueId}();\n"; + + String method = """ + public static void test_\\{uniqueId}() { + int zero = \\{val}; + int limit = \\{limit}; + for (; limit < \\{limit1}; limit \\{arithm}= \\{stride}); + for (int i = \\{init1}; i < limit; i++) { + zero = 0; + } + for (int i = 0; i < \\{limit2}; i++) { + if (flag) { // 1) Triggers Loop Peeling + \\{template1} + } + int k = iFld + i * zero; // Loop variant before CCP + if (k == \\{val}) { // 2) After CCP: Loop invariant -> triggers Loop Unswitching + iFld2 = \\{val}; + } else { + iArr[i] = \\{val}; // 3) After Loop Unswitching: Triggers Pre/Main/Post and then 4) Range Check Elimination + \\{template2} + } + } + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template2(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String val = getRandomValueAsString(integerValues); + String size = getRandomValueAsString(arraySizes); + String init1 = getRandomValueAsString(integerValues); + + String limit = getRandomValueAsString(positiveIntegerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"*", "/"}); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("size", size); + + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("val", val); + replacements.put("limit", limit); + replacements.put("arithm", arithm); + replacements.put("stride", stride); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[]{"-Xcomp","-XX:LoopMaxUnroll=0","-XX:CompileOnly=Test::test*"}; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java new file mode 100644 index 0000000000000..6ba612782885c --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java @@ -0,0 +1,83 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate16 extends InputTemplate { + public InputTemplate16() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate16 + static int zero = \\{val}; + static int limit = \\{limit}; + """; + + String call = "test_\\{uniqueId}();\n"; + + String method = """ + static void test_\\{uniqueId}() { + for (; limit < \\{limit1}; limit \\{arithm}= \\{stride}); + for (int i = \\{init}; i < limit; i++) { + zero = 0; + } + // After CCP: zero = 0. Use other "type delaying" template" here depending on when the counted loop should be created. + // Create counted loop from i = 0..20 with single loop exit condition (i < 20) after CCP: + int i = 0; + do { + \\{template} + i++; + } while (i < \\{val1} || zero == \\{val}); // i < 20 becomes only loop exit condition after CCP -> creates a counted loop in next loop opts round. + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template4(); + String template_nes1= template1.getTemplate("j"); + Map replacements = new HashMap<>(); + + String init = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(integerValues); + String val = getRandomValueAsString(integerValues); + String val1 = getRandomValueAsString(integerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"*", "/"}); + String uniqueId = String.valueOf(numTest); + replacements.put("init", init); + replacements.put("val1", val1); + replacements.put("val", val); + replacements.put("limit1", limit1); + replacements.put("limit", limit); + replacements.put("arithm", arithm); + replacements.put("stride", stride); + replacements.put("template", template_nes1); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[]{"-Xcomp", + "-XX:CompileOnly=Test::test*"}; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java new file mode 100644 index 0000000000000..fd5be1e1888f9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java @@ -0,0 +1,75 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate17 extends InputTemplate { + @Override + public CodeSegment getTemplate() { + String imports= """ + """; + String statics = """ + //InputTemplate17 + public static boolean flag = \\{bool}; + """; + String call = """ + test_\\{uniqueId}(); + """; + String method = """ + public static void test_\\{uniqueId}() { + int i = \\{val}; + while (true) { + // Found as loop head in ciTypeFlow, but both path inside loop -> head not cloned. + // As a result, this head has the safepoint as backedge instead of the loop exit test + // and we cannot create a counted loop (yet). We first need to partial peel. + if (flag) { + \\{template1} + } + // Loop exit test. + if (i < 5) { + \\{template2} + return; + } + // <-- Partial Peeling CUT --> + // Safepoint + i--; + } + } + """; + + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template3(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("i"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String bool = getRandomValue(new String[]{"true", "false"}); + String uniqueId = String.valueOf(numTest); + replacements.put("val", val1); + replacements.put("bool", bool); + replacements.put("uniqueId", uniqueId); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + public int getNumberOfTestMethods(){ + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java new file mode 100644 index 0000000000000..ca9ae5c585aff --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java @@ -0,0 +1,84 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate2 extends InputTemplate { + @Override + public CodeSegment getTemplate() { + String imports= """ + """; + String statics = """ + //InputTemplate2 + static int count = 0; + static int acc = 1; + """; + String call = "count_\\{uniqueId}();\n"; + String method = """ + private static void count_\\{uniqueId}() { + boolean cond = false; + for (int i = \\{init1}; i < \\{limit1}; i++) { + switch (i % 3) { + case 0: + System.out.println("count: " + count); + for (int j = \\{init2}; j < \\{limit2}; j++) { + for (int k = \\{init3}; k < \\{init3}; k++) { + count = acc; + } + if (cond) { + break; + } + } + acc++; + break; + case 1: + \\{template1} + break; + case 2: + \\{template2} + break; + } + } + } + """; + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template3(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("i"); + String template_nes2= template2.getTemplate("j"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String init3 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String limit3 = getRandomValueAsString(positiveIntegerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("init3", init3); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("limit3", limit3); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + @Override + public String[] getCompileFlags() { + return new String[0]; + } + @Override + public int getNumberOfTests(){ + return 1; + } + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java new file mode 100644 index 0000000000000..f464c5c5486be --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java @@ -0,0 +1,86 @@ +package compiler.lib.test_generator; +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate3 extends InputTemplate { + public InputTemplate3() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate3 + static int iArrFld[]=new int[\\{size}]; + """; + + String call = "test_\\{uniqueId}();\n"; + + String method = """ + public static int test_\\{uniqueId}() { + int i16 = \\{val1}, i19 = \\{val2}, i20 = \\{val3}; + do { + for (; i19 < \\{limit1}; i19++) { + i20 = 0; + \\{template1} + try { + i20 = iArrFld[i19 - 1]; + } catch (ArithmeticException a_e) { + } + \\{template2} + } + i16++; + } + while (i16 < \\{limit2}); + return i20; + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template5(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("i19"); + String template_nes2= template2.getTemplate("i16"); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String size = getRandomValueAsString(arraySizes); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String init = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("val1", val1); + replacements.put("init", init); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("size", size); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + @Override + public int getNumberOfTests(){ + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java new file mode 100644 index 0000000000000..11a5169b2a43d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java @@ -0,0 +1,90 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate4 extends InputTemplate { + public InputTemplate4() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate4 + public static int foo = \\{fooVar1}; + public static int bar = \\{barVar1}; + """; + String call = """ + int[] array_\\{uniqueId} = new int[\\{size}]; + test_\\{uniqueId}(array_\\{uniqueId}); + """; + + String method = """ + public static int test_\\{uniqueId}(int[] array) { + int result = 0; + int[] iArr = new int[\\{size}]; + for (int i = \\{init1}; i < array.length; i++) { + for (int j = \\{init2}; j < i; j++) { + if (foo == \\{fooVar2}) { + bar = \\{barVar2}; + } + \\{template1} + iArr[j] += array[j]; + result += array[j]; + } + \\{template2} + } + return result; + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template1(); + Template template2 = new Template4(); + String template_nes1= template1.getTemplate("i"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String fooVar1 = getRandomValueAsString(integerValues); + String fooVar2 = getRandomValueAsString(integerValues); + String barVar1 = getRandomValueAsString(integerValues); + String size = getRandomValueAsString(arraySizes); + String barVar2 = getRandomValueAsString(integerValues); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String uniqueId = String.valueOf(numTest);; + replacements.put("fooVar1", fooVar1); + replacements.put("fooVar2", fooVar2); + replacements.put("barVar1", barVar1); + replacements.put("barVar2", barVar2); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("size", size); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java new file mode 100644 index 0000000000000..055f77a2cf41d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java @@ -0,0 +1,75 @@ +package compiler.lib.test_generator; +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate5 extends InputTemplate { + public InputTemplate5() {} + + @Override + public CodeSegment getTemplate() { + String imports= """ + """; + + String statics = """ + //InputTemplate5 + static int N; + """; + + String call = """ + for (int i = \\{init1}; i < \\{limit}; i++) { + test_\\{uniqueId}(\\{num}); + } + """; + + String method = """ + public static void test_\\{uniqueId}(int limit) { + boolean a[] = new boolean[\\{size}]; + for (int i = 0; i < \\{size}; i++) { + a[i] = 80.1f > i; + \\{template2} + } + \\{template1} + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template4(); + Template template2 = new Template10(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(integerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + String size = getRandomValueAsString(arraySizes); + String num = getRandomValueAsString(integerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("limit", limit); + replacements.put("size", size); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("num", num); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java new file mode 100644 index 0000000000000..68662fad057e1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java @@ -0,0 +1,74 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate6 extends InputTemplate { + public InputTemplate6() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + import java.lang.Math; + """; + + String statics = """ + //InputTemplate6 + private static final int SIZE = \\{size}; + private static int val = \\{Val1}; + private static short[] a = new short[SIZE]; + private static short[] b = new short[SIZE]; + """; + + String call = """ + a[SIZE-1] = \\{Val2}; + bar_\\{uniqueId}(); + System.out.println(b[SIZE-1]); + """; + String method = """ + public static void bar_\\{uniqueId}() { + for (int i = \\{init}; i < SIZE; i++) { + b[i] = (short) Math.min(a[i], val); + \\{template1} + } + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template2(); + String template_nes1= template1.getTemplate("i"); + Map replacements = new HashMap<>(); + String size = getRandomValueAsString(arraySizes); + String Val1 = getRandomValueAsString(integerValues); + String Val2 = getRandomValueAsString(shortValues); + String init = getRandomValueAsString(integerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("size", size); + replacements.put("Val1", Val1); + replacements.put("Val2", Val2); + replacements.put("init", init); + replacements.put("template1", template_nes1); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java new file mode 100644 index 0000000000000..1f67144d90d0c --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java @@ -0,0 +1,87 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate7 extends InputTemplate { + public InputTemplate7() {} + + @Override + public CodeSegment getTemplate() { + String imports= """ + """; + + String statics = """ + //InputTemplate7 + static int x, y; + static boolean flag; + """; + + String call = """ + flag=\\{boole}; + test_\\{uniqueId}(); + """; + + + String method = """ + // Use non-const values for assignment of 'a' for more interesting cases + public static int test_\\{uniqueId}() { + int a; + if (flag) { + a = \\{val1}; + \\{template1} + } else { + a = \\{val2}; + } + // y = 34; // Make it more interesting + if (a > \\{val2}) { + x = \\{val1}; + } else { + x = \\{val3}; + \\{template2} + } + return a; + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template2(); + Template template2 = new Template10(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("x"); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(positiveIntegerValues); + String boole = getRandomValue(new String[]{"false", "true"}); + String uniqueId = String.valueOf(numTest); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("boole", boole); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[0]; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java new file mode 100644 index 0000000000000..c3d348f563b5a --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java @@ -0,0 +1,108 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate8 extends InputTemplate { + public InputTemplate8() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate8 + static boolean flag, flag2; + static int iFld; + """; + String call = """ + for (int i = \\{init1}; i < \\{limit1}; i++) { + flag = i % 2 == 0; + flag2 = i % 3 == 0; + test_\\{uniqueId}(); + } + """; + + String method = """ + public static void test_\\{uniqueId}() { + int a; + int b; + for (int i = \\{init2}; i < \\{limit2}; i \\{arithm}= \\{stride}); // Make sure to run with loop opts. + if (flag) { + a = \\{val1}; + } else { + a = \\{val2}; + } + // Region + // --- BLOCK start --- + // CMoveI(Bool(CmpI(flag2))), a, 23) + if (flag2) { + b = \\{val1}; // Use b = a to have an additional Bool -> then Split If only clones down CmpI + } else { + b = \\{val3}; + \\{template1} + } + iFld = b; // iFld = CMoveI -> make sure CMoveI is inside BLOCK + // --- BLOCK end --- + if (a > \\{val3}) { // If to split -> need to empty BLOCK + iFld = \\{val1}; + \\{template2} + } + if (flag2) { // Reuse of Bool(CmpI(flag2)) such that we need to clone CmpI(flag2) down + iFld = \\{val2}; + } + } + """; + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template1(); + Template template2 = new Template10(); + String template_nes1= template1.getTemplate("a"); + String template_nes2= template2.getTemplate("b"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"*", "/"}); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("arithm", arithm); + replacements.put("stride", stride); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + + @Override + public String[] getCompileFlags() { + return new String[]{"-XX:CompileOnly=Test::test*", + "-Xbatch"}; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java new file mode 100644 index 0000000000000..babb26d0672e0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java @@ -0,0 +1,94 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +public class InputTemplate9 extends InputTemplate { + public InputTemplate9() {} + + @Override + public CodeSegment getTemplate() { + + String imports= """ + """; + + String statics = """ + //InputTemplate9 + static int iFld, iFld2, iFld3; + """; + + String call = "test_\\{uniqueId}();\n"; + + String method = """ + public static void test_\\{uniqueId}() { + int x = \\{val1}; + int y = \\{val2}; + for (int i = \\{init1}; i < \\{limit1}; i++) { + // Single iteration loop prevents Parallel IV for outer loop and splitting MulI thru phi + for (int j = \\{init2}; j < \\{limit2}; j++) { // (**) + y++; + \\{template1} + } + // MulI "23 * (y - 1)" has 4 uses (1-4) outside of the loop (all uses have get_loop() == _ltree_root) + // while its get_ctrl() is inside the loop at the loop exit projection of (**). We can therefore sink + // MulI on all paths in try_sink_out_of_loop(). + int toSink = \\{val3} * (y - 1); + try { + // Usage of 'i' prevents Loop Predication + x = \\{val1} / (i + iFld); // (1) + x = \\{val1} / (i + 1 + iFld); // (2) + \\{template2} + } catch (Exception e) {} + x = toSink; // Make sure that MulI is stored in Safepoints of (1) and (2) and has + } + iFld2 = \\{val3} * (y - 1); // (3) + iFld3 = \\{val3}* (y - 1); // (4) + } + """; + + return new CodeSegment(statics, call, method,imports); + } + + @Override + public Map getRandomReplacements(int numTest) { + Template template1 = new Template2(); + Template template2 = new Template10(); + String template_nes1= template1.getTemplate("j"); + String template_nes2= template2.getTemplate("i"); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String init1 = getRandomValueAsString(integerValues); + String init2 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String uniqueId = String.valueOf(numTest); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + replacements.put("uniqueId", uniqueId); + return replacements; + } + @Override + public String[] getCompileFlags() { + return new String[]{"-Xcomp", + "-XX:CompileOnly=Test::test*"}; + } + + @Override + public int getNumberOfTests() { + return 1; + } + + @Override + public int getNumberOfTestMethods() { + return 1; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template.java new file mode 100644 index 0000000000000..f07490670578b --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024, 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 compiler.lib.test_generator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class Template { + public Template() {} + static int variableNumber = 1; + /* + * This method processes a given template string to avoid variable name conflicts by appending a unique identifier. + * It searches for placeholders within the string, identified by a '$' followed by a word (variable name), + * and replaces each placeholder with the variable name concatenated with a unique number. + */ + public static String avoidConflict(String temp){ + StringBuilder result = new StringBuilder(); + String regex="\\$(\\w+)"; + Pattern pat = Pattern.compile(regex); + Matcher mat = pat.matcher(temp); + while(mat.find()){ + String replacement = mat.group(1)+variableNumber; + mat.appendReplacement(result, replacement); + } + mat.appendTail(result); + variableNumber++; + return result.toString(); + } + + public abstract String getTemplate(String variable); +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java new file mode 100644 index 0000000000000..847b86e0679c1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java @@ -0,0 +1,25 @@ +package compiler.lib.test_generator; +import java.util.HashMap; +import java.util.Map; +import static compiler.lib.test_generator.InputTemplate.*; +public class Template1 extends Template { + public String getTemplate(String variable){ + String statics= """ + int $a =\\{val}; + long $b = \\{var}; + """; + String method=""" + do { + $a--; + $b++; + } while ($a > 0); + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val = getRandomValueAsString(integerValues); + replacements.put("val", val); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java new file mode 100644 index 0000000000000..b6dbb7d0bdcfa --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java @@ -0,0 +1,60 @@ +package compiler.lib.test_generator; +import java.util.HashMap; +import java.util.Map; +import static compiler.lib.test_generator.InputTemplate.*; +public class Template10 extends Template { + public Template10() {} + public String getTemplate(String variable){ + String statics= """ + boolean $flag=\\{bool}; + long $lFld=\\{val1}; + int[]iArr=new int[\\{size}]; + """; + String method=""" + long $l1 = \\{val2}; + long $l2 = \\{val3}; + int $zero = \\{val2}; + int $limit = \\{val3}; + for (; $limit < \\{limit1}; $limit \\{arithm}= \\{stride}); + for (int $i = \\{val3}; $i < $limit; $i++) { + $zero = 0; + } + for (int $i = \\{var}; $i < \\{size}; $i++) { + iArr[$i] = \\{val2}; // Just a reason to pre/main/post (trigger more loop opts) + if ($flag) { // Triggers Loop Peeling before CCP + $l1=$zero; + } + if ($zero > $i) { // Folded away after CCP. + // DivLs add 30 to the loop body count and we hit LoopUnrollLimit. Add more + // statements/DivLs if you want to use a higher LoopUnrollLimit value. + // After CCP, these statements are folded away and we can unroll this loop. + $l1 /= $lFld; + $l2 /= $lFld; + } + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String size = getRandomValueAsString(arraySizes); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"+", "-"}); + String bool = getRandomValue(new String[]{"false", "true"}); + replacements.put("val1", val1); + replacements.put("val3", val3); + replacements.put("stride", stride); + replacements.put("arithm", arithm); + replacements.put("bool", bool); + replacements.put("val2", val2); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("size", size); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java new file mode 100644 index 0000000000000..e98eff69239e7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java @@ -0,0 +1,67 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template11 extends Template { + public Template11() {} + public String getTemplate(String variable){ + String statics= """ + boolean $flag=\\{bool}; + long $lFld=\\{var}; + """; + String method=""" + long $l1 = \\{val1}; + long $l2 = \\{val2}; + int $zero = \\{val1}; + int $limit = \\{val3}; + int [] iArr=new int[\\{size}]; + for (; $limit < \\{limit1}; $limit \\{arithm}= \\{stride}); + for (int $i = \\{init1}; $i < $limit; $i++) { + $zero = 0; + } + for (int $i = \\{init2}; $i < \\{limit2}; $i++) { + iArr[$i] = \\{val1}; // Just a reason to pre/main/post (trigger more loop opts) + if ($flag) { // Triggers Loop Peeling before CCP + return; + } + if ($zero > $i) { // Folded away after CCP. + // DivLs add 30 to the loop body count and we hit LoopUnrollLimit. Add more + // statements/DivLs if you want to use a higher LoopUnrollLimit value. + // After CCP, these statements are folded away and we can unroll this loop. + $l1 /= $lFld; + $l2 /= $lFld; + } + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String init1 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String init2 = getRandomValueAsString(integerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String size = getRandomValueAsString(arraySizes); + String stride = getRandomValueAsString(integerValuesNonZero); + String bool = getRandomValue(new String[]{"true", "false"}); + String arithm = getRandomValue(new String[]{"*", "/"}); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("size", size); + replacements.put("limit1", limit1); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit2", limit2); + replacements.put("bool", bool); + replacements.put("stride", stride); + replacements.put("arithm", arithm); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java new file mode 100644 index 0000000000000..4187d57e4ef88 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java @@ -0,0 +1,47 @@ +package compiler.lib.test_generator; +import java.util.HashMap; +import java.util.Map; +import static compiler.lib.test_generator.InputTemplate.*; +public class Template12 extends Template { + public String getTemplate(String variable){ + String statics= """ + int $out;=\\{val1}; + boolean $cond = \\{bool}; + int $i = \\{var}; + """; + String method=""" + while ($i < \\{max_val1}) { + int $j = \\{var}; + while ($j < \\{max_val2}) { + $out = \\{val2}; + if ($cond) { + break; + } + int $k = \\{var}; + while ($k < \\{max_val3}) { + $k++; + } + $j++; + } + i++; + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String max_val1 = getRandomValueAsString(integerValues); + String max_val2 = getRandomValueAsString(integerValues); + String max_val3 = getRandomValueAsString(integerValues); + String bool = getRandomValue(new String[]{"true", "false"}); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("bool", bool); + replacements.put("max_val1", max_val1); + replacements.put("max_val2", max_val2); + replacements.put("max_val3", max_val3); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java new file mode 100644 index 0000000000000..262ebf52ee2e6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java @@ -0,0 +1,34 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template2 extends Template { + public Template2() {} + public String getTemplate(String variable){ + String statics= """ + Integer $a; + boolean $flag=\\{val}; + """; + String method=""" + if ($flag) { + $a = 1; + } else { + $a = 2; + } + if ($a == 3) { + // Not reachable but that's only known after Incremental Boxing Inline + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + + Map replacements = new HashMap<>(); + String val = getRandomValue(new String[]{"true", "false"}); + replacements.put("val", val); + + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java new file mode 100644 index 0000000000000..25fc4fa9af696 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java @@ -0,0 +1,37 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template3 extends Template { + public Template3() {} + public String getTemplate(String variable){ + String statics= """ + int $val = \\{val}; + """; + String method=""" + for (int $i = \\{var}; $i < \\{limit}; $i++) { + if (($i % 2) == 0) { + $val = \\{val1}; + } + } + // val == 1, known after second loop opts round + // it takes two rounds of unrolling (2x, 4x) + """; + String template=statics+method; + String template_com= avoidConflict(template); + + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val = getRandomValueAsString(integerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + replacements.put("val1", val1); + replacements.put("val", val); + replacements.put("var", variable); + replacements.put("limit", limit); + + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java new file mode 100644 index 0000000000000..ad3577978735d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java @@ -0,0 +1,47 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template4 extends Template{ + public Template4(){} + public String getTemplate(String variable){ + String statics= """ + int $x, $y; + boolean $flag=\\{bool}; + """; + String method=""" + int $a; + if ($flag) { + $a = \\{val1}; + } else { + $a = \\{val2}; + } + // y = 34; // Make it more interesting + if ($a > \\{val2}) { + $x = \\{val3}; + } else { + $x = \\{val4}; + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String val4 = getRandomValueAsString(integerValues); + String bool = getRandomValue(new String[]{"false", "true"}); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("val4", val4); + replacements.put("bool", bool); + + + + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java new file mode 100644 index 0000000000000..c53367504371f --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java @@ -0,0 +1,41 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template5 extends Template { + public Template5() {} + public String getTemplate(String variable){ + String statics= """ + class MyValue{ + int nonNull; + public MyValue(int $nonNull) {} + } + MyValue $nonNull = new MyValue(\\{val1}); + MyValue $val = null; + int $zero = \\{val2}; + + """; + String method=""" + int $limit = \\{val3}; + for (; $limit < 4; $limit *= 2); + for (int $i = \\{var}; $i < $limit; $i++) { + $val = $nonNull; + $zero = 0; + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java new file mode 100644 index 0000000000000..2f27f90f71bff --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java @@ -0,0 +1,70 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template6 extends Template { + public Template6() {} + public String getTemplate(String variable){ + String statics= """ + int $a; + int $b; + Boolean $flag=\\{bool1}; + Boolean $flag2=\\{bool2}; + int $iFld; + """; + String method=""" + for (int $i = \\{var}; $i < \\{limit}; $i \\{arithm}= \\{stride}); // Make sure to run with loop opts. + \s + if ($flag) { + $a = \\{val1}; + } else { + $a = \\{val2}; + } + // Region + \s + // --- BLOCK start --- + \s + // CMoveI(Bool(CmpI(flag2))), a, 23) + if ($flag2) { + $b = \\{val1}; // Use b = a to have an additional Bool -> then Split If only clones down CmpI + } else { + $b = \\{val3}; + } + $iFld = $b; // iFld = CMoveI -> make sure CMoveI is inside BLOCK + \s + // --- BLOCK end --- + \s + if ($a > \\{val3}) { // If to split -> need to empty BLOCK + $iFld = \\{val1}; + } + \s + if ($flag2) { // Reuse of Bool(CmpI(flag2)) such that we need to clone CmpI(flag2) down + $iFld = \\{val2}; + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String limit = getRandomValueAsString(positiveIntegerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"+", "-"}); + String bool1 = getRandomValue(new String[]{"false", "true"}); + String bool2 = getRandomValue(new String[]{"false", "true"}); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("limit", limit); + replacements.put("stride", stride); + replacements.put("arithm", arithm); + replacements.put("bool1", bool1); + replacements.put("bool2", bool2); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java new file mode 100644 index 0000000000000..87660a47ef5ea --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java @@ -0,0 +1,58 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template7 extends Template{ + public Template7(){} + public String getTemplate(String variable){ + String statics= """ + int $iFld=\\{val4}, $iFld2, $iFld3; + int $x=\\{val1}; + int $y=\\{val2}; + """; + String method=""" + for (int $i = \\{var}; $i < \\{limit1}; $i++) { + // Single iteration loop prevents Parallel IV for outer loop and splitting MulI thru phi + for (int $j = \\{init}; j < \\{limit2}; $j++) { // (**) + $y++; + } + // MulI "23 * (y - 1)" has 4 uses (1-4) outside of the loop (all uses have get_loop() == _ltree_root) + // while its get_ctrl() is inside the loop at the loop exit projection of (**). We can therefore sink + // MulI on all paths in try_sink_out_of_loop(). + int $toSink = \\{val3} * ($y - 1); + try { + // Usage of 'i' prevents Loop Predication + $x = \\{val1} / ($i + $iFld); // (1) + $x = \\{val1} / ($i + 1 + $iFld); // (2) + } catch (Exception e) {} + $x = $toSink; // Make sure that MulI is stored in Safepoints of (1) and (2) and has + } + $iFld2 = \\{val3} * ($y - 1); // (3) + $iFld3 = \\{val3} * ($y - 1); // (4 + + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String val4 = getRandomValueAsString(integerValues); + String init = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("val4", val4); + replacements.put("init", init); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java new file mode 100644 index 0000000000000..ca93d3f3cf0de --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java @@ -0,0 +1,58 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; + +public class Template8 extends Template{ + public Template8(){} + public String getTemplate(String variable){ + String statics= """ + int $iFld=\\{val3}, $iFld2; + boolean $flag=\\{bool}; + int $zero = \\{val1}; + int $limit = \\{val2}; + """; + String method=""" + for (; $limit < \\{limit1}; $limit \\{arithm}= \\{stride}); + for (int $i = \\{var}; $i < $limit; $i++) { + $zero = 0; + } + \s + for (int $i = \\{var}; $i < \\{limit2}; $i++) { + if ($flag) { // 1) Triggers Loop Peeling + $iFld = $zero; + } + \s + int $k = $iFld + $i * $zero; // Loop variant before CCP + \s + if ($k == \\{val1}) { // 2) After CCP: Loop invariant -> triggers Loop Unswitching \s + $iFld2 = \\{val1}; + } + } + """; + String template=statics+method; + + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String limit2 = getRandomValueAsString(positiveIntegerValues); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"+", "-"}); + String bool = getRandomValue(new String[]{"false", "true"}); + replacements.put("val1", val1); + replacements.put("val3", val3); + replacements.put("stride", stride); + replacements.put("arithm", arithm); + replacements.put("bool", bool); + replacements.put("val2", val2); + replacements.put("limit1", limit1); + replacements.put("limit2", limit2); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java new file mode 100644 index 0000000000000..1f100f861be9d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java @@ -0,0 +1,60 @@ +package compiler.lib.test_generator; + +import java.util.HashMap; +import java.util.Map; + +import static compiler.lib.test_generator.InputTemplate.*; +public class Template9 extends Template { + public Template9() {} + public String getTemplate(String variable){ + String statics= """ + int $iFld=\\{val3}, $iFld2; + boolean $flag=\\{bool}; + int $zero = \\{val1}; + int $limit = \\{val2}; + int[] iArr = new int[\\{size}]; + """; + String method=""" + for (; $limit < \\{limit1}; $limit \\{arithm}= \\{stride}); + for (int $i = \\{var}; $i < $limit; $i++) { + $zero = 0; + } + \s + for (int $i = \\{var}; $i < \\{size}; $i++) { + if ($flag) { // 1) Triggers Loop Peeling + $iFld = $zero; + } + \s + int $k = $iFld + $i * $zero; // Loop variant before CCP + \s + if ($k == \\{val1}) { // 2) After CCP: Loop invariant -> triggers Loop Unswitching \s + $iFld2 = \\{val1}; + } + else{ + iArr[$i] = $zero; + } + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(integerValues); + String val2 = getRandomValueAsString(integerValues); + String val3 = getRandomValueAsString(integerValues); + String limit1 = getRandomValueAsString(positiveIntegerValues); + String size = getRandomValueAsString(arraySizes); + String stride = getRandomValueAsString(integerValuesNonZero); + String arithm = getRandomValue(new String[]{"+", "-"}); + String bool = getRandomValue(new String[]{"false", "true"}); + replacements.put("val1", val1); + replacements.put("val3", val3); + replacements.put("stride", stride); + replacements.put("arithm", arithm); + replacements.put("bool", bool); + replacements.put("val2", val2); + replacements.put("limit1", limit1); + replacements.put("size", size); + replacements.put("var", variable); + return doReplacements(template_com,replacements); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java new file mode 100644 index 0000000000000..e93a6ea5dd886 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2023, 2024, 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 compiler.lib.test_generator; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class TemplateGenerator { + /* + * Use-cases: + * - very narrow: systematically find a bug. very well defined testcase. run extensively + * => manual execution, for limited time, no IR, no JTreg? + * + * - smarter regression tests. start with failing case. make it randomized to search in local search space + * => taking a JTreg test and add holes + * + * - a more guided complete java fuzzer. make use of known code-shapes. use in different combinations + * + * goals: fast, easy to use, general + * - failure modes: assert, crashes, interp vs c1 vs c2 + * + * flags: always on, always off, randomized flags + * + * timeout: - failure vs ok to have + * + * combination with JTReg and IRFramework + * */ + + static final String JAVA_HOME = System.getProperty("java.home"); + static final String[] FLAGS = { + "-XX:CompileCommand=compileonly,GeneratedTest::test*", + "-XX:-TieredCompilation" + }; + static final int TIMEOUT = 120; + static final int NUM_THREADS = Runtime.getRuntime().availableProcessors(); + static final int MAX_TASKS_IN_QUEUE = NUM_THREADS * 330; + static String[] TEMPLATE_FILES = { + "InputTemplate1.java", + "InputTemplate2.java", + "InputTemplate3.java", + "InputTemplate4.java", + "InputTemplate5.java", + "InputTemplate6.java", + "InputTemplate7.java", + "InputTemplate8.java", + "InputTemplate9.java", + "InputTemplate10.java" + }; + private static long testId = 0L; + public static long getID() { + return testId++; + } + + public static void main(String[] args) { + ThreadPoolExecutor threadPool = new ThreadPoolExecutor(NUM_THREADS, NUM_THREADS, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(MAX_TASKS_IN_QUEUE)); + setOutputFolder(OUTPUT_FOLDER); + for (String filePath : TEMPLATE_FILES) { + try { + Class inputTemplateClass = DynamicClassLoader.compileAndLoadClass(filePath); + InputTemplate inputTemplate = (InputTemplate) inputTemplateClass.getDeclaredConstructor().newInstance(); + runTestGen(inputTemplate, threadPool); + } catch (Exception e) { + e.printStackTrace(); + } + } + threadPool.shutdown(); + } + static int nextUniqueId=0; + public static void runTestGen(InputTemplate inputTemplate, ThreadPoolExecutor threadPool) { + String[] compileFlags = inputTemplate.getCompileFlags(); + CodeSegment template = inputTemplate.getTemplate(); + for (int i = 0; i < inputTemplate.getNumberOfTests(); i++) { + ArrayList> replacements = new ArrayList<>(); + for (int j = 0; j < inputTemplate.getNumberOfTestMethods(); j++) { + Map replacement = inputTemplate.getRandomReplacements(nextUniqueId); + replacements.add(replacement); + nextUniqueId++; + } + long id = getID(); + threadPool.submit(() -> doWork(template, replacements, compileFlags, id)); + } + } + public static void doWork(CodeSegment template, ArrayList> replacements, String[] compileFlags, long num) { + try { + String javaCode = InputTemplate.getJavaCode(template, replacements, num); + String fileName = writeJavaCodeToFile(javaCode, num); + boolean success = executeJavaFile(fileName, compileFlags); + } catch (Exception e) { + throw new RuntimeException("Couldn't find test method: ", e); + } + } + + public static String OUTPUT_FOLDER; + + static { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + OUTPUT_FOLDER = System.getProperty("user.dir") + File.separator + timeStamp; + new File(OUTPUT_FOLDER).mkdirs(); + } + + public static void setOutputFolder(String outputFolder) { + OUTPUT_FOLDER= outputFolder; + } + private static String writeJavaCodeToFile(String javaCode, long num) throws IOException { + String fileName = String.format("GeneratedTest%d.java", num); + File OutputFolder = new File(OUTPUT_FOLDER); + if (!OutputFolder.exists()) { + OutputFolder.mkdirs(); + } + File file = new File(OUTPUT_FOLDER,fileName); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + writer.write(javaCode); + } catch (Exception e) { + e.printStackTrace(); + } + return fileName; + } + private static boolean executeJavaFile(String fileName, String[] compileFlags) throws Exception { + ProcessBuilder builder = getProcessBuilder(fileName, compileFlags); + Process process = builder.start(); + boolean exited = process.waitFor(TIMEOUT, TimeUnit.SECONDS); + if (!exited) { + process.destroyForcibly(); + throw new RuntimeException("Process timeout: execution took too long."); + } + String output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + int exitCode = process.exitValue(); + + if (exitCode == 0 && Objects.requireNonNull(output).contains("Passed")) { + System.out.printf("Test passed successfully %s%n", fileName ); + return true; + } else { + System.err.println("Test failed with exit code :"); + System.err.println(output); + return false; + } + } + private static ProcessBuilder getProcessBuilder(String fileName, String[] compileFlags) { + List command = new ArrayList<>(); + command.add("%s/bin/java".formatted(JAVA_HOME)); + command.addAll(Arrays.asList(FLAGS)); + if (compileFlags != null) { + command.addAll(Arrays.asList(compileFlags)); + } + command.add("-cp"); + command.add("."); + command.add(fileName); + File workingDir = new File(OUTPUT_FOLDER); + ProcessBuilder builder = new ProcessBuilder(command); + builder.redirectErrorStream(true); + builder.directory(workingDir); + return builder; + } +} From 8f2b3d3ba2c44fdd7a1125f032b4a46adab8fe5f Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 10:38:06 +0100 Subject: [PATCH 02/13] remove DynamicClassLoader --- .../test_generator/DynamicClassLoader.java | 70 ------------------- .../lib/test_generator/TemplateGenerator.java | 46 +++++++++++- 2 files changed, 45 insertions(+), 71 deletions(-) delete mode 100644 test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java b/test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java deleted file mode 100644 index 19f54486e5798..0000000000000 --- a/test/hotspot/jtreg/compiler/lib/test_generator/DynamicClassLoader.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2024, 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 compiler.lib.test_generator; -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; -public class DynamicClassLoader { - public static Class compileAndLoadClass(String filePath) throws Exception { - String className = computeClassName(filePath); - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - int compilationResult = compiler.run(null, null, null, filePath); - if (compilationResult != 0) { - throw new RuntimeException("Compilation failed"); - } - DynamicClassLoaderInternal loader = new DynamicClassLoaderInternal(); - return loader.loadClass(className); - } - private static String computeClassName(String filePath) { - Path path = Paths.get(filePath); - String fileName = path.getFileName().toString(); - String className = fileName.substring(0, fileName.lastIndexOf('.')); - String packageName = ""; - Path parent = path.getParent(); - if (parent != null) { - packageName = parent.toString().replace(File.separator, "."); - } - if (!packageName.isEmpty()) { - className = packageName + "." + className; - } - return className; - } - private static class DynamicClassLoaderInternal extends ClassLoader { - @Override - public Class findClass(String name) throws ClassNotFoundException { - File file = new File(name + ".class"); - if (file.exists()) { - try { - byte[] bytes = java.nio.file.Files.readAllBytes(file.toPath()); - return defineClass(null, bytes, 0, bytes.length); - } catch (Exception e) { - e.printStackTrace(); - } - } - return super.findClass(name); - } - } -} diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index e93a6ea5dd886..47e0eabd960c8 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -26,12 +26,16 @@ import java.io.FileWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.text.SimpleDateFormat; import java.util.Date; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; public class TemplateGenerator { /* @@ -84,7 +88,7 @@ public static void main(String[] args) { setOutputFolder(OUTPUT_FOLDER); for (String filePath : TEMPLATE_FILES) { try { - Class inputTemplateClass = DynamicClassLoader.compileAndLoadClass(filePath); + Class inputTemplateClass = compileAndLoadClass(filePath); InputTemplate inputTemplate = (InputTemplate) inputTemplateClass.getDeclaredConstructor().newInstance(); runTestGen(inputTemplate, threadPool); } catch (Exception e) { @@ -179,4 +183,44 @@ private static ProcessBuilder getProcessBuilder(String fileName, String[] compil builder.directory(workingDir); return builder; } + + public static Class compileAndLoadClass(String filePath) throws Exception { + String className = computeClassName(filePath); + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + int compilationResult = compiler.run(null, null, null, filePath); + if (compilationResult != 0) { + throw new RuntimeException("Compilation failed"); + } + DynamicClassLoader loader = new DynamicClassLoader(); + return loader.loadClass(className); + } + private static String computeClassName(String filePath) { + Path path = Paths.get(filePath); + String fileName = path.getFileName().toString(); + String className = fileName.substring(0, fileName.lastIndexOf('.')); + String packageName = ""; + Path parent = path.getParent(); + if (parent != null) { + packageName = parent.toString().replace(File.separator, "."); + } + if (!packageName.isEmpty()) { + className = packageName + "." + className; + } + return className; + } + private static class DynamicClassLoader extends ClassLoader { + @Override + public Class findClass(String name) throws ClassNotFoundException { + File file = new File(name + ".class"); + if (file.exists()) { + try { + byte[] bytes = java.nio.file.Files.readAllBytes(file.toPath()); + return defineClass(null, bytes, 0, bytes.length); + } catch (Exception e) { + e.printStackTrace(); + } + } + return super.findClass(name); + } + } } From 0043c990fd365a5c4597015f873b2d317cdbf2bd Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 10:45:30 +0100 Subject: [PATCH 03/13] comments added --- .../lib/test_generator/TemplateGenerator.java | 224 +++++++++++++++++- 1 file changed, 217 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index 47e0eabd960c8..4f7a6921963c8 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -21,6 +21,7 @@ * questions. */ package compiler.lib.test_generator; + import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; @@ -37,6 +38,11 @@ import javax.tools.JavaCompiler; import javax.tools.ToolProvider; +/** + * TemplateGenerator is responsible for generating, compiling, and executing Java test cases + * based on predefined templates. It supports multithreading to efficiently handle multiple + * test generation tasks concurrently. + */ public class TemplateGenerator { /* * Use-cases: @@ -56,16 +62,27 @@ public class TemplateGenerator { * timeout: - failure vs ok to have * * combination with JTReg and IRFramework - * */ + */ + // Path to the Java home directory static final String JAVA_HOME = System.getProperty("java.home"); + + // Compilation flags to control JVM behavior during test execution static final String[] FLAGS = { "-XX:CompileCommand=compileonly,GeneratedTest::test*", "-XX:-TieredCompilation" }; + + // Timeout for test execution in seconds static final int TIMEOUT = 120; + + // Number of threads based on available processors static final int NUM_THREADS = Runtime.getRuntime().availableProcessors(); + + // Maximum number of tasks that can be queued in the thread pool static final int MAX_TASKS_IN_QUEUE = NUM_THREADS * 330; + + // List of Java template files to be used for test generation static String[] TEMPLATE_FILES = { "InputTemplate1.java", "InputTemplate2.java", @@ -78,148 +95,341 @@ public class TemplateGenerator { "InputTemplate9.java", "InputTemplate10.java" }; + + // Atomic counter for generating unique test IDs private static long testId = 0L; + + /** + * Generates and returns a unique test ID. + * + * @return unique test ID + */ public static long getID() { return testId++; } + /** + * The main entry point of the TemplateGenerator. It initializes the thread pool, + * sets the output directory, compiles and loads each input template, and starts + * the test generation process. + * + * @param args command-line arguments (not used) + */ public static void main(String[] args) { - ThreadPoolExecutor threadPool = new ThreadPoolExecutor(NUM_THREADS, NUM_THREADS, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(MAX_TASKS_IN_QUEUE)); + // Initialize a thread pool executor with fixed number of threads and a bounded queue + ThreadPoolExecutor threadPool = new ThreadPoolExecutor( + NUM_THREADS, + NUM_THREADS, + 0L, + TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(MAX_TASKS_IN_QUEUE) + ); + + // Set the output folder where generated tests will be stored setOutputFolder(OUTPUT_FOLDER); + + // Iterate over each template file to compile, load, and generate tests for (String filePath : TEMPLATE_FILES) { try { + // Compile and load the template class Class inputTemplateClass = compileAndLoadClass(filePath); + + // Instantiate the InputTemplate InputTemplate inputTemplate = (InputTemplate) inputTemplateClass.getDeclaredConstructor().newInstance(); + + // Start generating tests based on the template runTestGen(inputTemplate, threadPool); } catch (Exception e) { e.printStackTrace(); } } + + // Shutdown the thread pool after all tasks are submitted threadPool.shutdown(); } - static int nextUniqueId=0; + + // Counter to ensure unique replacements across test methods + static int nextUniqueId = 0; + + /** + * Generates tests based on the provided InputTemplate and submits them to the thread pool. + * + * @param inputTemplate the template defining how tests should be generated + * @param threadPool the thread pool executor to handle test generation tasks + */ public static void runTestGen(InputTemplate inputTemplate, ThreadPoolExecutor threadPool) { + // Retrieve compilation flags specific to the input template String[] compileFlags = inputTemplate.getCompileFlags(); + + // Get the code segment template from the input template CodeSegment template = inputTemplate.getTemplate(); + + // Loop to generate the specified number of tests for (int i = 0; i < inputTemplate.getNumberOfTests(); i++) { + // List to hold replacement maps for each test method ArrayList> replacements = new ArrayList<>(); + + // Generate replacements for each test method within the test for (int j = 0; j < inputTemplate.getNumberOfTestMethods(); j++) { + // Generate a random replacement map using a unique ID Map replacement = inputTemplate.getRandomReplacements(nextUniqueId); replacements.add(replacement); nextUniqueId++; } + + // Get a unique ID for the current test long id = getID(); + + // Submit the test generation task to the thread pool threadPool.submit(() -> doWork(template, replacements, compileFlags, id)); } } + + /** + * Performs the actual work of generating, writing, compiling, and executing a test. + * + * @param template the code segment template + * @param replacements the list of replacement maps for the template + * @param compileFlags the compilation flags to use + * @param num the unique test ID + */ public static void doWork(CodeSegment template, ArrayList> replacements, String[] compileFlags, long num) { try { + // Generate the Java code by applying replacements to the template String javaCode = InputTemplate.getJavaCode(template, replacements, num); + + // Write the generated Java code to a file String fileName = writeJavaCodeToFile(javaCode, num); + + // Compile and execute the generated Java file boolean success = executeJavaFile(fileName, compileFlags); } catch (Exception e) { + // Wrap and rethrow any exceptions encountered during test generation throw new RuntimeException("Couldn't find test method: ", e); } } + // Directory where generated test files will be stored public static String OUTPUT_FOLDER; + // Static block to initialize the output folder with a timestamp static { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); OUTPUT_FOLDER = System.getProperty("user.dir") + File.separator + timeStamp; new File(OUTPUT_FOLDER).mkdirs(); } + /** + * Sets the output folder for generated test files. + * + * @param outputFolder the path to the output folder + */ public static void setOutputFolder(String outputFolder) { - OUTPUT_FOLDER= outputFolder; + OUTPUT_FOLDER = outputFolder; } + + /** + * Writes the generated Java code to a file within the output directory. + * + * @param javaCode the Java source code to write + * @param num the unique test ID used to name the file + * @return the name of the generated Java file + * @throws IOException if an I/O error occurs + */ private static String writeJavaCodeToFile(String javaCode, long num) throws IOException { + // Generate a unique file name based on the test ID String fileName = String.format("GeneratedTest%d.java", num); + + // Ensure the output directory exists File OutputFolder = new File(OUTPUT_FOLDER); if (!OutputFolder.exists()) { OutputFolder.mkdirs(); } - File file = new File(OUTPUT_FOLDER,fileName); + + // Create the new Java file + File file = new File(OUTPUT_FOLDER, fileName); try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { + // Write the Java code to the file writer.write(javaCode); } catch (Exception e) { e.printStackTrace(); } + return fileName; } - private static boolean executeJavaFile(String fileName, String[] compileFlags) throws Exception { + + /** + * Executes the generated Java file by running it as a separate process. + * + * @param fileName the name of the Java file to execute + * @param compileFlags additional compilation flags to use + * @return true if the test passed successfully, false otherwise + * @throws Exception if an error occurs during execution + */ + private static boolean executeJavaFile(String fileName, String[] compileFlags) throws Exception { + // Build the process command to execute the Java file ProcessBuilder builder = getProcessBuilder(fileName, compileFlags); + + // Start the process Process process = builder.start(); + + // Wait for the process to complete within the specified timeout boolean exited = process.waitFor(TIMEOUT, TimeUnit.SECONDS); + if (!exited) { + // If the process times out, forcibly terminate it process.destroyForcibly(); throw new RuntimeException("Process timeout: execution took too long."); } + + // Read the output from the process String output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + + // Get the exit code of the process int exitCode = process.exitValue(); + // Determine if the test passed based on the exit code and output content if (exitCode == 0 && Objects.requireNonNull(output).contains("Passed")) { - System.out.printf("Test passed successfully %s%n", fileName ); + System.out.printf("Test passed successfully %s%n", fileName); return true; } else { + // If the test failed, print the error output System.err.println("Test failed with exit code :"); System.err.println(output); return false; } } + + /** + * Constructs a ProcessBuilder to execute the Java file with the specified flags. + * + * @param fileName the name of the Java file to execute + * @param compileFlags additional compilation flags to use + * @return a configured ProcessBuilder instance + */ private static ProcessBuilder getProcessBuilder(String fileName, String[] compileFlags) { List command = new ArrayList<>(); + + // Add the path to the Java executable command.add("%s/bin/java".formatted(JAVA_HOME)); + + // Add general JVM flags command.addAll(Arrays.asList(FLAGS)); + + // Add any template-specific compilation flags if (compileFlags != null) { command.addAll(Arrays.asList(compileFlags)); } + + // Set the classpath to the current directory command.add("-cp"); command.add("."); + + // Add the name of the Java file to execute command.add(fileName); + + // Set the working directory to the output folder File workingDir = new File(OUTPUT_FOLDER); + + // Initialize the ProcessBuilder with the command ProcessBuilder builder = new ProcessBuilder(command); + + // Redirect error stream to the standard output builder.redirectErrorStream(true); + + // Set the working directory for the process builder.directory(workingDir); + return builder; } + /** + * Compiles a Java source file and loads the resulting class. + * + * @param filePath the path to the Java source file + * @return the compiled Class object + * @throws Exception if compilation or class loading fails + */ public static Class compileAndLoadClass(String filePath) throws Exception { + // Compute the fully qualified class name from the file path String className = computeClassName(filePath); + + // Obtain the system Java compiler JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + + // Compile the Java source file int compilationResult = compiler.run(null, null, null, filePath); + + // Check if the compilation was successful if (compilationResult != 0) { throw new RuntimeException("Compilation failed"); } + + // Create a new instance of the custom class loader DynamicClassLoader loader = new DynamicClassLoader(); + + // Load and return the compiled class return loader.loadClass(className); } + + /** + * Computes the fully qualified class name from a given file path. + * + * @param filePath the path to the Java source file + * @return the fully qualified class name + */ private static String computeClassName(String filePath) { Path path = Paths.get(filePath); String fileName = path.getFileName().toString(); + + // Extract the class name by removing the file extension String className = fileName.substring(0, fileName.lastIndexOf('.')); + String packageName = ""; + + // Determine the package name based on the parent directories Path parent = path.getParent(); if (parent != null) { packageName = parent.toString().replace(File.separator, "."); } + + // Combine package name and class name if package exists if (!packageName.isEmpty()) { className = packageName + "." + className; } + return className; } + + /** + * Custom class loader to load classes from compiled .class files. + */ private static class DynamicClassLoader extends ClassLoader { + /** + * Finds and loads the class with the specified name. + * + * @param name the fully qualified name of the class + * @return the resulting Class object + * @throws ClassNotFoundException if the class cannot be found + */ @Override public Class findClass(String name) throws ClassNotFoundException { + // Construct the path to the .class file File file = new File(name + ".class"); + if (file.exists()) { try { + // Read all bytes from the .class file byte[] bytes = java.nio.file.Files.readAllBytes(file.toPath()); + + // Define the class from the byte array return defineClass(null, bytes, 0, bytes.length); } catch (Exception e) { e.printStackTrace(); } } + + // Delegate to the parent class loader if the class file is not found return super.findClass(name); } } From 9baf16ece12e693b9ca097eaeaf510ce1fcfd16b Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 10:49:18 +0100 Subject: [PATCH 04/13] refactor --- .../lib/test_generator/TemplateGenerator.java | 442 ++++++++---------- 1 file changed, 203 insertions(+), 239 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index 4f7a6921963c8..1fa38cae18a3a 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -29,19 +29,18 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; +import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.text.SimpleDateFormat; -import java.util.Date; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; /** - * TemplateGenerator is responsible for generating, compiling, and executing Java test cases - * based on predefined templates. It supports multithreading to efficiently handle multiple - * test generation tasks concurrently. + * The TemplateGenerator class is responsible for generating and executing test cases + * based on predefined input templates. It compiles the generated Java code and runs + * the tests concurrently using a thread pool. */ public class TemplateGenerator { /* @@ -65,371 +64,336 @@ public class TemplateGenerator { */ // Path to the Java home directory - static final String JAVA_HOME = System.getProperty("java.home"); + private static final String JAVA_HOME = System.getProperty("java.home"); - // Compilation flags to control JVM behavior during test execution - static final String[] FLAGS = { + // JVM flags for compiling the generated tests + private static final String[] FLAGS = { "-XX:CompileCommand=compileonly,GeneratedTest::test*", "-XX:-TieredCompilation" }; - // Timeout for test execution in seconds - static final int TIMEOUT = 120; + // Timeout for each test execution in seconds + private static final int TIMEOUT = 120; - // Number of threads based on available processors - static final int NUM_THREADS = Runtime.getRuntime().availableProcessors(); + // Number of threads in the thread pool, based on available processors + private static final int NUM_THREADS = Runtime.getRuntime().availableProcessors(); // Maximum number of tasks that can be queued in the thread pool - static final int MAX_TASKS_IN_QUEUE = NUM_THREADS * 330; - - // List of Java template files to be used for test generation - static String[] TEMPLATE_FILES = { - "InputTemplate1.java", - "InputTemplate2.java", - "InputTemplate3.java", - "InputTemplate4.java", - "InputTemplate5.java", - "InputTemplate6.java", - "InputTemplate7.java", - "InputTemplate8.java", - "InputTemplate9.java", + private static final int MAX_TASKS_IN_QUEUE = NUM_THREADS * 330; + + // List of template files to be used for generating tests + private static final String[] TEMPLATE_FILES = { + "InputTemplate1.java", "InputTemplate2.java", "InputTemplate3.java", + "InputTemplate4.java", "InputTemplate5.java", "InputTemplate6.java", + "InputTemplate7.java", "InputTemplate8.java", "InputTemplate9.java", "InputTemplate10.java" }; - // Atomic counter for generating unique test IDs + // Counter for assigning unique IDs to tests private static long testId = 0L; - /** - * Generates and returns a unique test ID. - * - * @return unique test ID - */ - public static long getID() { - return testId++; + // Counter for generating unique identifiers within replacements + private static int nextUniqueId = 0; + + // Directory where generated tests will be stored + private static String outputFolder; + + // Static block to initialize the output folder with a timestamped directory + static { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + outputFolder = System.getProperty("user.dir") + File.separator + timeStamp; + new File(outputFolder).mkdirs(); // Create the directory if it doesn't exist } /** - * The main entry point of the TemplateGenerator. It initializes the thread pool, - * sets the output directory, compiles and loads each input template, and starts - * the test generation process. + * The main method initializes the thread pool, sets up the output folder, + * loads each input template, and initiates test generation for each template. * - * @param args command-line arguments (not used) + * @param args Command-line arguments (not used) */ public static void main(String[] args) { - // Initialize a thread pool executor with fixed number of threads and a bounded queue - ThreadPoolExecutor threadPool = new ThreadPoolExecutor( - NUM_THREADS, - NUM_THREADS, - 0L, - TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(MAX_TASKS_IN_QUEUE) - ); + // Create a thread pool executor for concurrent test generation + ThreadPoolExecutor threadPool = createThreadPool(); - // Set the output folder where generated tests will be stored - setOutputFolder(OUTPUT_FOLDER); + // Set up the output folder where generated tests will be saved + setupOutputFolder(outputFolder); - // Iterate over each template file to compile, load, and generate tests - for (String filePath : TEMPLATE_FILES) { + // Iterate over each template file and process it + Arrays.stream(TEMPLATE_FILES).forEach(filePath -> { try { - // Compile and load the template class - Class inputTemplateClass = compileAndLoadClass(filePath); - - // Instantiate the InputTemplate - InputTemplate inputTemplate = (InputTemplate) inputTemplateClass.getDeclaredConstructor().newInstance(); - - // Start generating tests based on the template - runTestGen(inputTemplate, threadPool); + // Load the input template from the specified file + InputTemplate inputTemplate = loadInputTemplate(filePath); + if (inputTemplate != null) { + // Generate and run tests based on the loaded template + runTestGeneration(inputTemplate, threadPool); + } } catch (Exception e) { + // Print stack trace if an exception occurs during processing e.printStackTrace(); } - } + }); - // Shutdown the thread pool after all tasks are submitted + // Shutdown the thread pool after all tasks have been submitted threadPool.shutdown(); } - // Counter to ensure unique replacements across test methods - static int nextUniqueId = 0; + /** + * Creates a ThreadPoolExecutor with a fixed number of threads and a bounded queue. + * + * @return A configured ThreadPoolExecutor instance + */ + private static ThreadPoolExecutor createThreadPool() { + return new ThreadPoolExecutor( + NUM_THREADS, // Core pool size + NUM_THREADS, // Maximum pool size + 0L, // Keep-alive time for idle threads + TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(MAX_TASKS_IN_QUEUE) // Task queue with fixed capacity + ); + } + + /** + * Sets up the output folder for storing generated tests. + * + * @param folder The path to the output folder + */ + private static void setupOutputFolder(String folder) { + outputFolder = folder; + } /** - * Generates tests based on the provided InputTemplate and submits them to the thread pool. + * Loads an input template by compiling and loading the specified Java file. * - * @param inputTemplate the template defining how tests should be generated - * @param threadPool the thread pool executor to handle test generation tasks + * @param filePath The path to the input template Java file + * @return An instance of InputTemplate loaded from the compiled class + * @throws Exception If there is an error during compilation or loading */ - public static void runTestGen(InputTemplate inputTemplate, ThreadPoolExecutor threadPool) { - // Retrieve compilation flags specific to the input template + private static InputTemplate loadInputTemplate(String filePath) throws Exception { + // Compile the Java file and load the resulting class + Class templateClass = compileAndLoadClass(filePath); + // Instantiate the InputTemplate from the loaded class + return (InputTemplate) templateClass.getDeclaredConstructor().newInstance(); + } + + /** + * Initiates the generation of tests based on the provided input template. + * + * @param inputTemplate The input template defining test parameters + * @param threadPool The thread pool executor for concurrent test generation + */ + private static void runTestGeneration(InputTemplate inputTemplate, ThreadPoolExecutor threadPool) { + // Retrieve compile flags specific to the input template String[] compileFlags = inputTemplate.getCompileFlags(); - // Get the code segment template from the input template + // Retrieve the code segment template from the input template CodeSegment template = inputTemplate.getTemplate(); // Loop to generate the specified number of tests for (int i = 0; i < inputTemplate.getNumberOfTests(); i++) { - // List to hold replacement maps for each test method - ArrayList> replacements = new ArrayList<>(); - - // Generate replacements for each test method within the test - for (int j = 0; j < inputTemplate.getNumberOfTestMethods(); j++) { - // Generate a random replacement map using a unique ID - Map replacement = inputTemplate.getRandomReplacements(nextUniqueId); - replacements.add(replacement); - nextUniqueId++; - } - - // Get a unique ID for the current test - long id = getID(); + // Generate replacement mappings for the test methods + ArrayList> replacements = generateReplacements(inputTemplate); + // Assign a unique ID to the test + long id = getNextTestId(); + // Submit a task to the thread pool to generate and execute the test + threadPool.submit(() -> generateAndRunTest(template, replacements, compileFlags, id)); + } + } - // Submit the test generation task to the thread pool - threadPool.submit(() -> doWork(template, replacements, compileFlags, id)); + /** + * Generates a list of replacement mappings for test methods based on the input template. + * + * @param inputTemplate The input template defining replacement rules + * @return A list of maps containing replacement key-value pairs for each test method + */ + private static ArrayList> generateReplacements(InputTemplate inputTemplate) { + ArrayList> replacements = new ArrayList<>(); + // Loop to generate replacements for each test method + for (int j = 0; j < inputTemplate.getNumberOfTestMethods(); j++) { + // Retrieve a random set of replacements and increment the unique ID + replacements.add(inputTemplate.getRandomReplacements(nextUniqueId++)); } + return replacements; } /** - * Performs the actual work of generating, writing, compiling, and executing a test. + * Generates the Java code for a test, writes it to a file, and executes the test. * - * @param template the code segment template - * @param replacements the list of replacement maps for the template - * @param compileFlags the compilation flags to use - * @param num the unique test ID + * @param template The code segment template to be used for generating the test + * @param replacements The list of replacement mappings for the test methods + * @param compileFlags The compile flags to be used during test execution + * @param id The unique identifier for the test */ - public static void doWork(CodeSegment template, ArrayList> replacements, String[] compileFlags, long num) { + private static void generateAndRunTest(CodeSegment template, ArrayList> replacements, String[] compileFlags, long id) { try { - // Generate the Java code by applying replacements to the template - String javaCode = InputTemplate.getJavaCode(template, replacements, num); - - // Write the generated Java code to a file - String fileName = writeJavaCodeToFile(javaCode, num); - - // Compile and execute the generated Java file - boolean success = executeJavaFile(fileName, compileFlags); + // Generate the complete Java code by applying replacements to the template + String javaCode = InputTemplate.getJavaCode(template, replacements, id); + // Write the generated Java code to a file and retrieve the filename + String fileName = writeJavaCodeToFile(javaCode, id); + // Execute the generated Java file with the specified compile flags + executeJavaFile(fileName, compileFlags); } catch (Exception e) { - // Wrap and rethrow any exceptions encountered during test generation - throw new RuntimeException("Couldn't find test method: ", e); + // Wrap and rethrow any exceptions as a runtime exception + throw new RuntimeException("Test generation error", e); } } - // Directory where generated test files will be stored - public static String OUTPUT_FOLDER; - - // Static block to initialize the output folder with a timestamp - static { - String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); - OUTPUT_FOLDER = System.getProperty("user.dir") + File.separator + timeStamp; - new File(OUTPUT_FOLDER).mkdirs(); - } - /** - * Sets the output folder for generated test files. + * Retrieves the next unique test ID in a thread-safe manner. * - * @param outputFolder the path to the output folder + * @return The next unique test ID */ - public static void setOutputFolder(String outputFolder) { - OUTPUT_FOLDER = outputFolder; + private static long getNextTestId() { + return testId++; } /** - * Writes the generated Java code to a file within the output directory. + * Writes the generated Java code to a file in the output folder. * - * @param javaCode the Java source code to write - * @param num the unique test ID used to name the file - * @return the name of the generated Java file - * @throws IOException if an I/O error occurs + * @param javaCode The Java source code to be written + * @param id The unique identifier for the test, used in the filename + * @return The name of the file to which the Java code was written + * @throws IOException If an error occurs during file writing */ - private static String writeJavaCodeToFile(String javaCode, long num) throws IOException { - // Generate a unique file name based on the test ID - String fileName = String.format("GeneratedTest%d.java", num); - - // Ensure the output directory exists - File OutputFolder = new File(OUTPUT_FOLDER); - if (!OutputFolder.exists()) { - OutputFolder.mkdirs(); - } - - // Create the new Java file - File file = new File(OUTPUT_FOLDER, fileName); + private static String writeJavaCodeToFile(String javaCode, long id) throws IOException { + // Construct the filename using the unique test ID + String fileName = String.format("GeneratedTest%d.java", id); + File file = new File(outputFolder, fileName); + // Use BufferedWriter to write the Java code to the file try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { - // Write the Java code to the file writer.write(javaCode); - } catch (Exception e) { - e.printStackTrace(); } - return fileName; } /** - * Executes the generated Java file by running it as a separate process. + * Executes the generated Java file using the specified compile flags. * - * @param fileName the name of the Java file to execute - * @param compileFlags additional compilation flags to use - * @return true if the test passed successfully, false otherwise - * @throws Exception if an error occurs during execution + * @param fileName The name of the Java file to execute + * @param compileFlags The compile flags to be used during execution + * @throws Exception If an error occurs during process execution or if the test fails */ - private static boolean executeJavaFile(String fileName, String[] compileFlags) throws Exception { - // Build the process command to execute the Java file - ProcessBuilder builder = getProcessBuilder(fileName, compileFlags); - - // Start the process - Process process = builder.start(); + private static void executeJavaFile(String fileName, String[] compileFlags) throws Exception { + // Create a ProcessBuilder configured to execute the Java file with the given flags + ProcessBuilder builder = createProcessBuilder(fileName, compileFlags); + Process process = builder.start(); // Start the process // Wait for the process to complete within the specified timeout - boolean exited = process.waitFor(TIMEOUT, TimeUnit.SECONDS); - - if (!exited) { - // If the process times out, forcibly terminate it - process.destroyForcibly(); + if (!process.waitFor(TIMEOUT, TimeUnit.SECONDS)) { + process.destroyForcibly(); // Forcefully terminate the process if it times out throw new RuntimeException("Process timeout: execution took too long."); } // Read the output from the process String output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + int exitCode = process.exitValue(); // Get the exit code of the process - // Get the exit code of the process - int exitCode = process.exitValue(); - - // Determine if the test passed based on the exit code and output content - if (exitCode == 0 && Objects.requireNonNull(output).contains("Passed")) { - System.out.printf("Test passed successfully %s%n", fileName); - return true; + // Check if the test passed based on exit code and output content + if (exitCode == 0 && output.contains("Passed")) { + System.out.printf("Test passed: %s%n", fileName); } else { - // If the test failed, print the error output - System.err.println("Test failed with exit code :"); + // Print error messages if the test failed + System.err.println("Test failed with exit code: " + exitCode); System.err.println(output); - return false; } } /** - * Constructs a ProcessBuilder to execute the Java file with the specified flags. + * Creates a ProcessBuilder configured to execute the specified Java file with given compile flags. * - * @param fileName the name of the Java file to execute - * @param compileFlags additional compilation flags to use - * @return a configured ProcessBuilder instance + * @param fileName The name of the Java file to execute + * @param compileFlags The compile flags to be used during execution + * @return A configured ProcessBuilder instance */ - private static ProcessBuilder getProcessBuilder(String fileName, String[] compileFlags) { - List command = new ArrayList<>(); - - // Add the path to the Java executable - command.add("%s/bin/java".formatted(JAVA_HOME)); - - // Add general JVM flags + private static ProcessBuilder createProcessBuilder(String fileName, String[] compileFlags) { + // Initialize the command list with the Java executable and classpath + List command = new ArrayList<>(Arrays.asList( + String.format("%s/bin/java", JAVA_HOME), + "-cp", "." + )); + + // Add predefined JVM flags command.addAll(Arrays.asList(FLAGS)); - // Add any template-specific compilation flags - if (compileFlags != null) { - command.addAll(Arrays.asList(compileFlags)); - } - - // Set the classpath to the current directory - command.add("-cp"); - command.add("."); + // Add any additional compile flags from the input template + if (compileFlags != null) command.addAll(Arrays.asList(compileFlags)); - // Add the name of the Java file to execute + // Add the name of the Java file to be executed command.add(fileName); - // Set the working directory to the output folder - File workingDir = new File(OUTPUT_FOLDER); - - // Initialize the ProcessBuilder with the command - ProcessBuilder builder = new ProcessBuilder(command); - - // Redirect error stream to the standard output - builder.redirectErrorStream(true); - - // Set the working directory for the process - builder.directory(workingDir); - - return builder; + // Configure the ProcessBuilder with the command and set the working directory + return new ProcessBuilder(command) + .directory(new File(outputFolder)) // Set the working directory to the output folder + .redirectErrorStream(true); // Redirect error stream to the standard output } /** - * Compiles a Java source file and loads the resulting class. + * Compiles the specified Java file and loads the resulting class dynamically. * - * @param filePath the path to the Java source file - * @return the compiled Class object - * @throws Exception if compilation or class loading fails + * @param filePath The path to the Java file to compile + * @return The Class object representing the compiled class + * @throws Exception If compilation fails or the class cannot be loaded */ - public static Class compileAndLoadClass(String filePath) throws Exception { - // Compute the fully qualified class name from the file path + private static Class compileAndLoadClass(String filePath) throws Exception { + // Compute the fully qualified class name based on the file path String className = computeClassName(filePath); // Obtain the system Java compiler JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - - // Compile the Java source file - int compilationResult = compiler.run(null, null, null, filePath); - - // Check if the compilation was successful - if (compilationResult != 0) { - throw new RuntimeException("Compilation failed"); + if (compiler.run(null, null, null, filePath) != 0) { + // Throw an exception if the compilation fails + throw new RuntimeException("Compilation failed for " + filePath); } - // Create a new instance of the custom class loader - DynamicClassLoader loader = new DynamicClassLoader(); - - // Load and return the compiled class - return loader.loadClass(className); + // Use the custom class loader to load the compiled class + return new DynamicClassLoader().loadClass(className); } /** - * Computes the fully qualified class name from a given file path. + * Computes the fully qualified class name from the given file path. * - * @param filePath the path to the Java source file - * @return the fully qualified class name + * @param filePath The path to the Java file + * @return The fully qualified class name */ private static String computeClassName(String filePath) { Path path = Paths.get(filePath); String fileName = path.getFileName().toString(); - // Extract the class name by removing the file extension String className = fileName.substring(0, fileName.lastIndexOf('.')); - String packageName = ""; - - // Determine the package name based on the parent directories + // Determine the package name based on the parent directory structure Path parent = path.getParent(); - if (parent != null) { - packageName = parent.toString().replace(File.separator, "."); - } + String packageName = (parent != null) ? parent.toString().replace(File.separator, ".") : ""; - // Combine package name and class name if package exists - if (!packageName.isEmpty()) { - className = packageName + "." + className; - } - - return className; + // Combine package name and class name if a package exists + return packageName.isEmpty() ? className : packageName + "." + className; } /** - * Custom class loader to load classes from compiled .class files. + * A custom ClassLoader for dynamically loading compiled classes from the file system. */ private static class DynamicClassLoader extends ClassLoader { /** - * Finds and loads the class with the specified name. + * Attempts to find and load the class with the specified name. * - * @param name the fully qualified name of the class - * @return the resulting Class object - * @throws ClassNotFoundException if the class cannot be found + * @param name The fully qualified name of the class + * @return The Class object representing the loaded class + * @throws ClassNotFoundException If the class cannot be found or loaded */ @Override public Class findClass(String name) throws ClassNotFoundException { - // Construct the path to the .class file + // Construct the expected class file path File file = new File(name + ".class"); - if (file.exists()) { try { - // Read all bytes from the .class file + // Read the class file bytes byte[] bytes = java.nio.file.Files.readAllBytes(file.toPath()); - - // Define the class from the byte array + // Define the class using the read bytes return defineClass(null, bytes, 0, bytes.length); - } catch (Exception e) { + } catch (IOException e) { e.printStackTrace(); } } - - // Delegate to the parent class loader if the class file is not found + // Delegate to the parent ClassLoader if the class file does not exist return super.findClass(name); } } From f23495ab853f4ac28699805c2a5ee1190150a936 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 10:51:15 +0100 Subject: [PATCH 05/13] refactor --- .../compiler/lib/test_generator/TemplateGenerator.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index 1fa38cae18a3a..eb380e6ffc642 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -123,10 +123,8 @@ public static void main(String[] args) { try { // Load the input template from the specified file InputTemplate inputTemplate = loadInputTemplate(filePath); - if (inputTemplate != null) { - // Generate and run tests based on the loaded template - runTestGeneration(inputTemplate, threadPool); - } + // Generate and run tests based on the loaded template + runTestGeneration(inputTemplate, threadPool); } catch (Exception e) { // Print stack trace if an exception occurs during processing e.printStackTrace(); From 172d4928115ea02a81c00af4149ee45216e327e1 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 10:57:14 +0100 Subject: [PATCH 06/13] AtomicLong --- .../compiler/lib/test_generator/TemplateGenerator.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index eb380e6ffc642..4ecd9c6a0d240 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -34,6 +34,8 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; @@ -90,10 +92,10 @@ public class TemplateGenerator { }; // Counter for assigning unique IDs to tests - private static long testId = 0L; + private static final AtomicLong testId = new AtomicLong(0L); // Counter for generating unique identifiers within replacements - private static int nextUniqueId = 0; + private static final AtomicInteger nextUniqueId = new AtomicInteger(0); // Directory where generated tests will be stored private static String outputFolder; @@ -208,7 +210,7 @@ private static ArrayList> generateReplacements(InputTemplate // Loop to generate replacements for each test method for (int j = 0; j < inputTemplate.getNumberOfTestMethods(); j++) { // Retrieve a random set of replacements and increment the unique ID - replacements.add(inputTemplate.getRandomReplacements(nextUniqueId++)); + replacements.add(inputTemplate.getRandomReplacements(nextUniqueId.getAndIncrement())); } return replacements; } @@ -241,7 +243,7 @@ private static void generateAndRunTest(CodeSegment template, ArrayList Date: Mon, 4 Nov 2024 11:16:44 +0100 Subject: [PATCH 07/13] rename vars --- .../lib/test_generator/CodeSegment.java | 2 +- .../lib/test_generator/InputTemplate.java | 237 +++++++++++++----- .../lib/test_generator/InputTemplate1.java | 12 +- .../lib/test_generator/InputTemplate10.java | 10 +- .../lib/test_generator/InputTemplate11.java | 14 +- .../lib/test_generator/InputTemplate12.java | 18 +- .../lib/test_generator/InputTemplate13.java | 8 +- .../lib/test_generator/InputTemplate14.java | 26 +- .../lib/test_generator/InputTemplate15.java | 14 +- .../lib/test_generator/InputTemplate16.java | 12 +- .../lib/test_generator/InputTemplate17.java | 2 +- .../lib/test_generator/InputTemplate2.java | 12 +- .../lib/test_generator/InputTemplate3.java | 14 +- .../lib/test_generator/InputTemplate4.java | 14 +- .../lib/test_generator/InputTemplate5.java | 8 +- .../lib/test_generator/InputTemplate6.java | 8 +- .../lib/test_generator/InputTemplate7.java | 6 +- .../lib/test_generator/InputTemplate8.java | 16 +- .../lib/test_generator/InputTemplate9.java | 14 +- .../lib/test_generator/Template1.java | 4 +- .../lib/test_generator/Template10.java | 16 +- .../lib/test_generator/Template11.java | 20 +- .../lib/test_generator/Template12.java | 12 +- .../lib/test_generator/Template2.java | 2 +- .../lib/test_generator/Template3.java | 8 +- .../lib/test_generator/Template4.java | 10 +- .../lib/test_generator/Template5.java | 8 +- .../lib/test_generator/Template6.java | 12 +- .../lib/test_generator/Template7.java | 16 +- .../lib/test_generator/Template8.java | 14 +- .../lib/test_generator/Template9.java | 14 +- .../lib/test_generator/TemplateGenerator.java | 2 +- 32 files changed, 353 insertions(+), 232 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java b/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java index 367c8b2303ffe..09739f20fadc7 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java @@ -36,7 +36,7 @@ public CodeSegment(String statics, String calls, String methods, String imports) public String getStatics() { return statics; } - public void appendCall(String calls) { + public void appendCalls(String calls) { this.calls.append(calls); } public String getCalls() { diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java index f0d0079d7fe5c..9f12ebddcd8a3 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java @@ -21,79 +21,139 @@ * questions. */ package compiler.lib.test_generator; + import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import java.util.Random; import java.util.stream.Collectors; + +/** + * Abstract class representing an input template for test generation. + */ public abstract class InputTemplate { - private static final Random RAND = new Random(32); - public static Integer[] integerValues = { + private static final Random RANDOM = new Random(32); + + // Integer test values including edge cases + public static final Integer[] INTEGER_VALUES = { -2, -1, 0, 1, 2, - Integer.MIN_VALUE - 2, Integer.MIN_VALUE - 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, - Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 2 + Integer.MIN_VALUE, Integer.MAX_VALUE }; - public static Integer[] positiveIntegerValues = { - 1, 2, - Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE + + // Positive integer test values including edge cases + public static final Integer[] POSITIVE_INTEGER_VALUES = { + 1, 2, Integer.MAX_VALUE }; - public static Integer[] arraySizes = { - 1, 10, 100, 1000, 10000, 100000, 200000, 500000, 1000000 + + // Array sizes for testing + public static final Integer[] ARRAY_SIZES = { + 1, 10, 100, 1_000, 10_000, 100_000, 200_000, 500_000, 1_000_000 }; - public static Integer[] integerValuesNonZero = { + + // Non-zero integer values + public static final Integer[] INTEGER_VALUES_NON_ZERO = { -2, -1, 1, 2, - Integer.MIN_VALUE - 2, Integer.MIN_VALUE - 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2, - Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 2 + Integer.MIN_VALUE, Integer.MAX_VALUE }; - public static Long[] longValues = { + + // Long test values including edge cases + public static final Long[] LONG_VALUES = { -2L, -1L, 0L, 1L, 2L, - Integer.MIN_VALUE - 2L, Integer.MIN_VALUE - 1L, (long) Integer.MIN_VALUE, Integer.MIN_VALUE + 1L, Integer.MIN_VALUE + 2L, - Integer.MAX_VALUE - 2L, Integer.MAX_VALUE - 1L, (long) Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MAX_VALUE + 2L, - Long.MIN_VALUE - 2L, Long.MIN_VALUE - 1L, Long.MIN_VALUE, Long.MIN_VALUE + 1L, Long.MIN_VALUE + 2L, - Long.MAX_VALUE - 2L, Long.MAX_VALUE - 1L, Long.MAX_VALUE, Long.MAX_VALUE + 1L, Long.MAX_VALUE + 2L + (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE, + Long.MIN_VALUE, Long.MAX_VALUE }; - public static Long[] longValuesNonZero = { + + // Non-zero long values + public static final Long[] LONG_VALUES_NON_ZERO = { -2L, -1L, 1L, 2L, - Integer.MIN_VALUE - 2L, Integer.MIN_VALUE - 1L, (long) Integer.MIN_VALUE, Integer.MIN_VALUE + 1L, Integer.MIN_VALUE + 2L, - Integer.MAX_VALUE - 2L, Integer.MAX_VALUE - 1L, (long) Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MAX_VALUE + 2L, - Long.MIN_VALUE - 2L, Long.MIN_VALUE - 1L, Long.MIN_VALUE, Long.MIN_VALUE + 1L, Long.MIN_VALUE + 2L, - Long.MAX_VALUE - 2L, Long.MAX_VALUE - 1L, Long.MAX_VALUE, Long.MAX_VALUE + 1L, Long.MAX_VALUE + 2L + (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE, + Long.MIN_VALUE, Long.MAX_VALUE }; - public static Short[] shortValuesNonZero = { - -2, -1,0, 1, 2, - (short) (Integer.MIN_VALUE & 0xFFFF), (short) ((Integer.MIN_VALUE + 1) & 0xFFFF), (short) Integer.MIN_VALUE, (short) (Integer.MIN_VALUE + 1), (short) (Integer.MIN_VALUE + 2), - (short) (Integer.MAX_VALUE - 2), (short) (Integer.MAX_VALUE - 1), (short) Integer.MAX_VALUE, (short) (Integer.MAX_VALUE + 1), (short) (Integer.MAX_VALUE + 2), - (short) -32770, (short) -32769, (short) -32768, (short) -32767, (short) -32766, - (short) 32765, (short) 32766, (short) 32767, (short) 32768, (short) 32769 + + // Short test values including edge cases + public static final Short[] SHORT_VALUES = { + -2, -1, 0, 1, 2, + Short.MIN_VALUE, Short.MAX_VALUE }; - public static Short[] shortValues = { + + // Non-zero short values + public static final Short[] SHORT_VALUES_NON_ZERO = { -2, -1, 1, 2, - (short) (Integer.MIN_VALUE & 0xFFFF), (short) ((Integer.MIN_VALUE + 1) & 0xFFFF), (short) Integer.MIN_VALUE, (short) (Integer.MIN_VALUE + 1), (short) (Integer.MIN_VALUE + 2), - (short) (Integer.MAX_VALUE - 2), (short) (Integer.MAX_VALUE - 1), (short) Integer.MAX_VALUE, (short) (Integer.MAX_VALUE + 1), (short) (Integer.MAX_VALUE + 2), - (short) -32770, (short) -32769, (short) -32768, (short) -32767, (short) -32766, - (short) 32765, (short) 32766, (short) 32767, (short) 32768, (short) 32769 + Short.MIN_VALUE, Short.MAX_VALUE }; + + /** + * Default constructor. + */ public InputTemplate() { + // Initialization if needed } + + /** + * Retrieves a random value from the provided array. + * + * @param array Array of values to choose from. + * @param Type of the array elements. + * @return A randomly selected element from the array. + */ public static T getRandomValue(T[] array) { - return array[RAND.nextInt(array.length)]; + if (array == null || array.length == 0) { + throw new IllegalArgumentException("Array must not be null or empty."); + } + return array[RANDOM.nextInt(array.length)]; } + + /** + * Retrieves a random value from the provided array and converts it to a string. + * + * @param array Array of values to choose from. + * @param Type of the array elements. + * @return A string representation of a randomly selected element from the array. + */ public static String getRandomValueAsString(T[] array) { T value = getRandomValue(array); - return String.valueOf(value); // Convert any type T to String + return String.valueOf(value); } + + /** + * Generates a unique identifier based on the current system time in nanoseconds. + * + * @return A unique identifier as a string. + */ public static String getUniqueId() { return String.valueOf(System.nanoTime()); } - public static Integer[] getIntegerValues(int size) { + + /** + * Generates an array of unique positive integers of the specified size. + * + * @param size The number of unique integers to generate. + * @return An array of unique positive integers. + */ + public static Integer[] getUniquePositiveIntegers(int size) { + if (size <= 0 || size > (Integer.MAX_VALUE - 1)) { + throw new IllegalArgumentException("Size must be between 1 and " + (Integer.MAX_VALUE - 1)); + } + HashSet integers = new HashSet<>(size); while (integers.size() < size) { - int number = RAND.nextInt(Integer.MAX_VALUE - 1) + 1; + int number = RANDOM.nextInt(Integer.MAX_VALUE - 1) + 1; // 1 to Integer.MAX_VALUE - 1 integers.add(number); } return integers.toArray(new Integer[0]); } - public static String getJavaCode(CodeSegment inputTemplate, ArrayList> inputReplacements, long num) { + + /** + * Generates Java code based on the provided template and replacements. + * + * @param inputTemplate The code segment template. + * @param inputReplacements A list of maps containing replacements for each test. + * @param testNumber The unique number for the generated test class. + * @return A string containing the generated Java code. + */ + public static String generateJavaCode(CodeSegment inputTemplate, + ArrayList> inputReplacements, + long testNumber) { String template = """ import java.util.Objects; \\{imports} @@ -106,29 +166,59 @@ public static void main(String args[]) throws Exception { \\{methods} } """; - CodeSegment CodeSegment = fillTemplate(inputTemplate, inputReplacements.getFirst()); - for (int i =1; i replacements = Map.ofEntries( - Map.entry("num", String.valueOf(num)), - Map.entry("statics", CodeSegment.getStatics()), - Map.entry("calls", CodeSegment.getCalls()), - Map.entry("methods", CodeSegment.getMethods()), - Map.entry("imports", CodeSegment.getImports()) + + CodeSegment aggregatedCodeSegment = fillTemplate(inputTemplate, inputReplacements.get(0)); + + for (int i = 1; i < inputReplacements.size(); i++) { + CodeSegment currentSegment = fillTemplate(inputTemplate, inputReplacements.get(i)); + aggregatedCodeSegment.appendCalls(currentSegment.getCalls()); + aggregatedCodeSegment.appendMethods(currentSegment.getMethods()); + // Assuming imports are common and handled separately + } + + Map replacements = Map.of( + "num", String.valueOf(testNumber), + "statics", aggregatedCodeSegment.getStatics(), + "calls", aggregatedCodeSegment.getCalls(), + "methods", aggregatedCodeSegment.getMethods(), + "imports", aggregatedCodeSegment.getImports() ); - return doReplacements(template, replacements); + + return performReplacements(template, replacements); } - private static CodeSegment fillTemplate(CodeSegment CodeSegment, Map replacements) { - String statics = doReplacements(CodeSegment.getStatics(), replacements); - String calls = doReplacements(CodeSegment.getCalls(), replacements); - String methods = doReplacements(CodeSegment.getMethods(), replacements); - String imports = doReplacements(CodeSegment.getImports(), replacements); - return new CodeSegment(statics, calls, methods,imports); + + /** + * Fills the template with the provided replacements. + * + * @param codeSegment The original code segment template. + * @param replacements A map containing replacement values. + * @return A new CodeSegment with replacements applied. + */ + private static CodeSegment fillTemplate(CodeSegment codeSegment, Map replacements) { + String statics = performReplacements(codeSegment.getStatics(), replacements); + String calls = performReplacements(codeSegment.getCalls(), replacements); + String methods = performReplacements(codeSegment.getMethods(), replacements); + String imports = performReplacements(codeSegment.getImports(), replacements); + return new CodeSegment(statics, calls, methods, imports); } - public static String doReplacements(String template, Map replacements) { + + /** + * Performs placeholder replacements in the template string based on the provided map. + * It preserves the indentation of the placeholders. + * + * @param template The template string containing placeholders. + * @param replacements A map of placeholder keys and their replacement values. + * @return The template string with all placeholders replaced. + */ + public static String performReplacements(String template, Map replacements) { + if (template == null || replacements == null) { + throw new IllegalArgumentException("Template and replacements must not be null."); + } + for (Map.Entry entry : replacements.entrySet()) { String pattern = "\\{%s}".formatted(entry.getKey()); String replacement = entry.getValue(); @@ -147,9 +237,40 @@ public static String doReplacements(String template, Map replace } return template; } + + /** + * Abstract method to retrieve the code segment template. + * + * @return The code segment template. + */ public abstract CodeSegment getTemplate(); - public abstract Map getRandomReplacements(int numTest); + + /** + * Abstract method to retrieve random replacements for the tests. + * + * @param numTests The number of tests to generate replacements for. + * @return A map containing replacement values for each test. + */ + public abstract Map getRandomReplacements(int numTests); + + /** + * Abstract method to retrieve compilation flags. + * + * @return An array of compile flags. + */ public abstract String[] getCompileFlags(); + + /** + * Abstract method to retrieve the number of tests. + * + * @return The number of tests. + */ public abstract int getNumberOfTests(); + + /** + * Abstract method to retrieve the number of test methods. + * + * @return The number of test methods. + */ public abstract int getNumberOfTestMethods(); } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java index c6f87fcaed5ae..f04fbd8405264 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate1.java @@ -75,12 +75,12 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); - String limit = getRandomValueAsString(positiveIntegerValues); - String val1 = getRandomValueAsString(integerValues); - String stride1 = getRandomValueAsString(integerValuesNonZero); - String stride2 = getRandomValueAsString(integerValuesNonZero); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String stride1 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); + String stride2 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm1 = getRandomValue(new String[]{"+", "-"}); String arithm2 = getRandomValue(new String[]{"+", "-"}); String thing = getRandomValue(new String[]{"", "synchronized (new Object()) { }"}); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java index 6f4fcb0d08924..3c929e56bf7df 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate10.java @@ -43,11 +43,11 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String val = getRandomValueAsString(integerValues); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); + String val = getRandomValueAsString(INTEGER_VALUES); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("val", val); replacements.put("init1", init1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java index 757adaabbd577..2f5f473778db2 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate11.java @@ -55,13 +55,13 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String val = getRandomValueAsString(integerValues); - String size = getRandomValueAsString(arraySizes); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(positiveIntegerValues); - String limit = getRandomValueAsString(positiveIntegerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String val = getRandomValueAsString(INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"+", "-"}); String uniqueId = String.valueOf(numTest); replacements.put("val", val); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java index 4c13b671d8d2c..007895924d877 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate12.java @@ -57,15 +57,15 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("l1"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String size = getRandomValueAsString(arraySizes); - String val3 = getRandomValueAsString(integerValues); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(positiveIntegerValues); - String limit = getRandomValueAsString(positiveIntegerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"+", "-"}); String uniqueId = String.valueOf(numTest); replacements.put("val1", val1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java index a0e3e4b4cdacc..2ae746b61625d 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate13.java @@ -56,10 +56,10 @@ public Map getRandomReplacements(int numTest) { String template_nes1=template1.getTemplate("i"); String template_nes2=template2.getTemplate("i"); Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String size = getRandomValueAsString(arraySizes); - String init2 = getRandomValueAsString(positiveIntegerValues); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String init2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("init1", init1); replacements.put("limit1", limit1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java index 826aeaa5ae137..5b07676ea4e6c 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate14.java @@ -72,19 +72,19 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("l"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(integerValues); - String val1 = getRandomValueAsString(positiveIntegerValues); - String val2 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); - String init3 = getRandomValueAsString(integerValues); - String init4 = getRandomValueAsString(integerValues); - String init5 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String limit3 = getRandomValueAsString(positiveIntegerValues); - String limit4 = getRandomValueAsString(positiveIntegerValues); - String limit5 = getRandomValueAsString(positiveIntegerValues); - String limit6 = getRandomValueAsString(positiveIntegerValues); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String val1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String init3 = getRandomValueAsString(INTEGER_VALUES); + String init4 = getRandomValueAsString(INTEGER_VALUES); + String init5 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit3 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit4 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit5 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit6 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String boole = getRandomValue(new String[]{"false", "true"}); String uniqueId = String.valueOf(numTest); replacements.put("val1", val1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java index 36b0102e9dd99..ae4f551ce7745 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate15.java @@ -53,14 +53,14 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String val = getRandomValueAsString(integerValues); - String size = getRandomValueAsString(arraySizes); - String init1 = getRandomValueAsString(integerValues); + String val = getRandomValueAsString(INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String init1 = getRandomValueAsString(INTEGER_VALUES); - String limit = getRandomValueAsString(positiveIntegerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"*", "/"}); String uniqueId = String.valueOf(numTest); replacements.put("init1", init1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java index 6ba612782885c..f7770041c2709 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate16.java @@ -45,12 +45,12 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); Map replacements = new HashMap<>(); - String init = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(integerValues); - String val = getRandomValueAsString(integerValues); - String val1 = getRandomValueAsString(integerValues); - String limit = getRandomValueAsString(positiveIntegerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String init = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(INTEGER_VALUES); + String val = getRandomValueAsString(INTEGER_VALUES); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"*", "/"}); String uniqueId = String.valueOf(numTest); replacements.put("init", init); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java index fd5be1e1888f9..9bfca63a72de9 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate17.java @@ -48,7 +48,7 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("i"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); String bool = getRandomValue(new String[]{"true", "false"}); String uniqueId = String.valueOf(numTest); replacements.put("val", val1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java index ca9ae5c585aff..25d6946e34416 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate2.java @@ -51,12 +51,12 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("i"); String template_nes2= template2.getTemplate("j"); Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); - String init3 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String limit3 = getRandomValueAsString(positiveIntegerValues); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String init3 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit3 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("init1", init1); replacements.put("init2", init2); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java index f464c5c5486be..4d08ab0f210f1 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate3.java @@ -48,13 +48,13 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("i19"); String template_nes2= template2.getTemplate("i16"); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String size = getRandomValueAsString(arraySizes); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String init = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String init = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("val1", val1); replacements.put("init", init); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java index 11a5169b2a43d..ef134c4670eb4 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate4.java @@ -51,13 +51,13 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("i"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String fooVar1 = getRandomValueAsString(integerValues); - String fooVar2 = getRandomValueAsString(integerValues); - String barVar1 = getRandomValueAsString(integerValues); - String size = getRandomValueAsString(arraySizes); - String barVar2 = getRandomValueAsString(integerValues); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); + String fooVar1 = getRandomValueAsString(INTEGER_VALUES); + String fooVar2 = getRandomValueAsString(INTEGER_VALUES); + String barVar1 = getRandomValueAsString(INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String barVar2 = getRandomValueAsString(INTEGER_VALUES); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); String uniqueId = String.valueOf(numTest);; replacements.put("fooVar1", fooVar1); replacements.put("fooVar2", fooVar2); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java index 055f77a2cf41d..73208d9c9d8e4 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate5.java @@ -42,10 +42,10 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(integerValues); - String limit = getRandomValueAsString(positiveIntegerValues); - String size = getRandomValueAsString(arraySizes); - String num = getRandomValueAsString(integerValues); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String num = getRandomValueAsString(INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("init1", init1); replacements.put("limit", limit); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java index 68662fad057e1..937b83ca4ee31 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate6.java @@ -43,10 +43,10 @@ public Map getRandomReplacements(int numTest) { Template template1 = new Template2(); String template_nes1= template1.getTemplate("i"); Map replacements = new HashMap<>(); - String size = getRandomValueAsString(arraySizes); - String Val1 = getRandomValueAsString(integerValues); - String Val2 = getRandomValueAsString(shortValues); - String init = getRandomValueAsString(integerValues); + String size = getRandomValueAsString(ARRAY_SIZES); + String Val1 = getRandomValueAsString(INTEGER_VALUES); + String Val2 = getRandomValueAsString(SHORT_VALUES); + String init = getRandomValueAsString(INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("size", size); replacements.put("Val1", Val1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java index 1f67144d90d0c..509c60e2d50f4 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate7.java @@ -54,9 +54,9 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("x"); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String boole = getRandomValue(new String[]{"false", "true"}); String uniqueId = String.valueOf(numTest); replacements.put("val1", val1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java index c3d348f563b5a..cde6a7d1110f6 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate8.java @@ -65,14 +65,14 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("a"); String template_nes2= template2.getTemplate("b"); Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"*", "/"}); String uniqueId = String.valueOf(numTest); replacements.put("init1", init1); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java index babb26d0672e0..7304a37e982e7 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate9.java @@ -56,13 +56,13 @@ public Map getRandomReplacements(int numTest) { String template_nes1= template1.getTemplate("j"); String template_nes2= template2.getTemplate("i"); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String init1 = getRandomValueAsString(integerValues); - String init2 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); String uniqueId = String.valueOf(numTest); replacements.put("val1", val1); replacements.put("val2", val2); diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java index 847b86e0679c1..b7a216ee06143 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java @@ -17,9 +17,9 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val = getRandomValueAsString(integerValues); + String val = getRandomValueAsString(INTEGER_VALUES); replacements.put("val", val); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java index b6dbb7d0bdcfa..9c2faf26f2ed3 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java @@ -36,13 +36,13 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String size = getRandomValueAsString(arraySizes); - String stride = getRandomValueAsString(integerValuesNonZero); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"+", "-"}); String bool = getRandomValue(new String[]{"false", "true"}); replacements.put("val1", val1); @@ -55,6 +55,6 @@ public String getTemplate(String variable){ replacements.put("limit2", limit2); replacements.put("size", size); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java index e98eff69239e7..f64b7c524d05c 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java @@ -39,15 +39,15 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String init1 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String init2 = getRandomValueAsString(integerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String size = getRandomValueAsString(arraySizes); - String stride = getRandomValueAsString(integerValuesNonZero); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String bool = getRandomValue(new String[]{"true", "false"}); String arithm = getRandomValue(new String[]{"*", "/"}); replacements.put("val1", val1); @@ -62,6 +62,6 @@ public String getTemplate(String variable){ replacements.put("stride", stride); replacements.put("arithm", arithm); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java index 4187d57e4ef88..67350d3b1eafa 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java @@ -29,11 +29,11 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String max_val1 = getRandomValueAsString(integerValues); - String max_val2 = getRandomValueAsString(integerValues); - String max_val3 = getRandomValueAsString(integerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String max_val1 = getRandomValueAsString(INTEGER_VALUES); + String max_val2 = getRandomValueAsString(INTEGER_VALUES); + String max_val3 = getRandomValueAsString(INTEGER_VALUES); String bool = getRandomValue(new String[]{"true", "false"}); replacements.put("val1", val1); replacements.put("val2", val2); @@ -42,6 +42,6 @@ public String getTemplate(String variable){ replacements.put("max_val2", max_val2); replacements.put("max_val3", max_val3); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java index 262ebf52ee2e6..eb920bbfee108 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java @@ -29,6 +29,6 @@ public String getTemplate(String variable){ String val = getRandomValue(new String[]{"true", "false"}); replacements.put("val", val); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java index 25fc4fa9af696..a77aaffbf8da9 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java @@ -24,14 +24,14 @@ public String getTemplate(String variable){ String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val = getRandomValueAsString(integerValues); - String limit = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); replacements.put("val1", val1); replacements.put("val", val); replacements.put("var", variable); replacements.put("limit", limit); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java index ad3577978735d..9e67a9e8921e4 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java @@ -29,10 +29,10 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String val4 = getRandomValueAsString(integerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String val4 = getRandomValueAsString(INTEGER_VALUES); String bool = getRandomValue(new String[]{"false", "true"}); replacements.put("val1", val1); replacements.put("val2", val2); @@ -42,6 +42,6 @@ public String getTemplate(String variable){ - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java index c53367504371f..a8162e6a28521 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java @@ -29,13 +29,13 @@ public MyValue(int $nonNull) {} String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); replacements.put("val1", val1); replacements.put("val2", val2); replacements.put("val3", val3); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java index 2f27f90f71bff..fbda1690b5e27 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java @@ -48,11 +48,11 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String limit = getRandomValueAsString(positiveIntegerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"+", "-"}); String bool1 = getRandomValue(new String[]{"false", "true"}); String bool2 = getRandomValue(new String[]{"false", "true"}); @@ -65,6 +65,6 @@ public String getTemplate(String variable){ replacements.put("bool1", bool1); replacements.put("bool2", bool2); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java index 87660a47ef5ea..7eef0484a74b1 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java @@ -37,13 +37,13 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String val4 = getRandomValueAsString(integerValues); - String init = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String val4 = getRandomValueAsString(INTEGER_VALUES); + String init = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); replacements.put("val1", val1); replacements.put("val2", val2); replacements.put("val3", val3); @@ -52,7 +52,7 @@ public String getTemplate(String variable){ replacements.put("limit1", limit1); replacements.put("limit2", limit2); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java index ca93d3f3cf0de..d153634452ea0 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java @@ -36,12 +36,12 @@ public String getTemplate(String variable){ String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String limit2 = getRandomValueAsString(positiveIntegerValues); - String stride = getRandomValueAsString(integerValuesNonZero); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String limit2 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"+", "-"}); String bool = getRandomValue(new String[]{"false", "true"}); replacements.put("val1", val1); @@ -53,6 +53,6 @@ public String getTemplate(String variable){ replacements.put("limit1", limit1); replacements.put("limit2", limit2); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java index 1f100f861be9d..3aeff8ccba90d 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java @@ -38,12 +38,12 @@ public String getTemplate(String variable){ String template=statics+method; String template_com= avoidConflict(template); Map replacements = new HashMap<>(); - String val1 = getRandomValueAsString(integerValues); - String val2 = getRandomValueAsString(integerValues); - String val3 = getRandomValueAsString(integerValues); - String limit1 = getRandomValueAsString(positiveIntegerValues); - String size = getRandomValueAsString(arraySizes); - String stride = getRandomValueAsString(integerValuesNonZero); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String limit1 = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String size = getRandomValueAsString(ARRAY_SIZES); + String stride = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); String arithm = getRandomValue(new String[]{"+", "-"}); String bool = getRandomValue(new String[]{"false", "true"}); replacements.put("val1", val1); @@ -55,6 +55,6 @@ public String getTemplate(String variable){ replacements.put("limit1", limit1); replacements.put("size", size); replacements.put("var", variable); - return doReplacements(template_com,replacements); + return performReplacements(template_com,replacements); } } diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index 4ecd9c6a0d240..f791157f1d27a 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -226,7 +226,7 @@ private static ArrayList> generateReplacements(InputTemplate private static void generateAndRunTest(CodeSegment template, ArrayList> replacements, String[] compileFlags, long id) { try { // Generate the complete Java code by applying replacements to the template - String javaCode = InputTemplate.getJavaCode(template, replacements, id); + String javaCode = InputTemplate.generateJavaCode(template, replacements, id); // Write the generated Java code to a file and retrieve the filename String fileName = writeJavaCodeToFile(javaCode, id); // Execute the generated Java file with the specified compile flags From c331bf515fac8f973b0d7119bc1e183364ead55d Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 11:28:24 +0100 Subject: [PATCH 08/13] refactor Template --- .../compiler/lib/test_generator/Template.java | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template.java index f07490670578b..2c403b984d0df 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template.java @@ -23,28 +23,42 @@ package compiler.lib.test_generator; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.concurrent.atomic.AtomicInteger; public abstract class Template { - public Template() {} - static int variableNumber = 1; - /* - * This method processes a given template string to avoid variable name conflicts by appending a unique identifier. - * It searches for placeholders within the string, identified by a '$' followed by a word (variable name), - * and replaces each placeholder with the variable name concatenated with a unique number. + // Atomic counter to ensure thread-safe unique number generation + private static final AtomicInteger uniqueCounter = new AtomicInteger(1); + + // Pattern to identify placeholders in the format $variableName + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$(\\w+)"); + + /** + * Processes a template string to prevent variable name conflicts by appending a unique identifier. + * + *

This method scans the input template for placeholders, which are denoted by a '$' followed by a word + * representing the variable name. Each detected placeholder is replaced with the variable name concatenated + * with a unique number, ensuring that variable names remain distinct and do not clash within the processed string. + * + * @param template The template string containing placeholders to be processed. + * @return A new string with all placeholders replaced by their corresponding variable names appended with a unique identifier. */ - public static String avoidConflict(String temp){ + public static String avoidConflict(String template){ StringBuilder result = new StringBuilder(); - String regex="\\$(\\w+)"; - Pattern pat = Pattern.compile(regex); - Matcher mat = pat.matcher(temp); + Matcher mat = PLACEHOLDER_PATTERN.matcher(template); while(mat.find()){ - String replacement = mat.group(1)+variableNumber; + String replacement = mat.group(1) + uniqueCounter.get(); mat.appendReplacement(result, replacement); } mat.appendTail(result); - variableNumber++; + uniqueCounter.incrementAndGet(); return result.toString(); } + /** + * Abstract method to retrieve the template string for a given variable. + * + * @param variable The name of the variable whose template is to be retrieved. + * @return The template string associated with the specified variable. + */ public abstract String getTemplate(String variable); } From 273cf192188ad446efd1107c02cffbbd852a7cb9 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 11:30:32 +0100 Subject: [PATCH 09/13] avoidConflict --- .../compiler/lib/test_generator/Template.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template.java index 2c403b984d0df..8c81a68c898d2 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template.java @@ -40,20 +40,24 @@ public abstract class Template { * with a unique number, ensuring that variable names remain distinct and do not clash within the processed string. * * @param template The template string containing placeholders to be processed. - * @return A new string with all placeholders replaced by their corresponding variable names appended with a unique identifier. + * @return The processed string with unique identifiers appended to variable names. */ - public static String avoidConflict(String template){ + public static String avoidConflict(String template) { + int uniqueId = uniqueCounter.getAndIncrement(); StringBuilder result = new StringBuilder(); - Matcher mat = PLACEHOLDER_PATTERN.matcher(template); - while(mat.find()){ - String replacement = mat.group(1) + uniqueCounter.get(); - mat.appendReplacement(result, replacement); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(template); + + while (matcher.find()) { + String variableName = matcher.group(1); + String replacement = variableName + uniqueId; + matcher.appendReplacement(result, Matcher.quoteReplacement(replacement)); } - mat.appendTail(result); - uniqueCounter.incrementAndGet(); + matcher.appendTail(result); + return result.toString(); } + /** * Abstract method to retrieve the template string for a given variable. * From 494f3aac6f86333fda730e94e6c478886f4ee4f4 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 13:06:14 +0100 Subject: [PATCH 10/13] refactor CodeSegment --- .../lib/test_generator/CodeSegment.java | 73 ++++++++++++++++--- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java b/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java index 09739f20fadc7..5e22a66cf255d 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/CodeSegment.java @@ -22,32 +22,87 @@ */ package compiler.lib.test_generator; -public class CodeSegment { +import java.util.Objects; + +/** + * Represents a segment of code, including static declarations, method calls, methods, and import statements. + */ +public final class CodeSegment { private final String statics; private final StringBuilder calls; private final StringBuilder methods; private final String imports; + + /** + * Constructs a CodeSegment with specified components. + * + * @param statics Static declarations. + * @param calls Initial method calls. + * @param methods Initial methods. + * @param imports Import statements. + * @throws NullPointerException if statics or imports are null. + */ public CodeSegment(String statics, String calls, String methods, String imports) { - this.statics = statics; - this.calls = new StringBuilder(calls); - this.methods = new StringBuilder(methods); - this.imports = imports; + this.statics = Objects.requireNonNull(statics, "statics cannot be null"); + this.calls = new StringBuilder(calls != null ? calls : ""); + this.methods = new StringBuilder(methods != null ? methods : ""); + this.imports = Objects.requireNonNull(imports, "imports cannot be null"); } + + /** + * Retrieves the static declarations. + * + * @return Static declarations as a String. + */ public String getStatics() { return statics; } - public void appendCalls(String calls) { - this.calls.append(calls); + + /** + * Appends additional method calls. + * + * @param additionalCalls Method calls to append. + */ + public void appendCalls(String additionalCalls) { + if (additionalCalls != null && !additionalCalls.isEmpty()) { + this.calls.append(additionalCalls); + } } + + /** + * Retrieves the current method calls. + * + * @return Method calls as a String. + */ public String getCalls() { return calls.toString(); } - public void appendMethods(String method) { - this.methods.append(method); + + /** + * Appends an additional method. + * + * @param additionalMethod Method to append. + */ + public void appendMethods(String additionalMethod) { + if (additionalMethod != null && !additionalMethod.isEmpty()) { + this.methods.append(additionalMethod); + } } + + /** + * Retrieves the current methods. + * + * @return Methods as a String. + */ public String getMethods() { return methods.toString(); } + + /** + * Retrieves the import statements. + * + * @return Import statements as a String. + */ public String getImports() { return imports; } From 8cfc24c2e43201dfb4e124eef9c255454d034a8c Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 14:28:12 +0100 Subject: [PATCH 11/13] SimpleTemplateExample --- .../lib/test_generator/InputTemplate.java | 97 -------- .../lib/test_generator/Template1.java | 1 + .../lib/test_generator/Template10.java | 1 + .../lib/test_generator/Template11.java | 1 + .../lib/test_generator/Template12.java | 1 + .../lib/test_generator/Template2.java | 1 + .../lib/test_generator/Template3.java | 1 + .../lib/test_generator/Template4.java | 1 + .../lib/test_generator/Template5.java | 1 + .../lib/test_generator/Template6.java | 1 + .../lib/test_generator/Template7.java | 1 + .../lib/test_generator/Template8.java | 1 + .../lib/test_generator/Template9.java | 1 + .../lib/test_generator/TemplateGenerator.java | 218 +++++++++++++++- .../examples/SimpleTemplateExample.java | 232 ++++++++++++++++++ 15 files changed, 461 insertions(+), 98 deletions(-) create mode 100644 test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java index 9f12ebddcd8a3..26f600b88cfd8 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/InputTemplate.java @@ -22,11 +22,9 @@ */ package compiler.lib.test_generator; -import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import java.util.Random; -import java.util.stream.Collectors; /** * Abstract class representing an input template for test generation. @@ -143,101 +141,6 @@ public static Integer[] getUniquePositiveIntegers(int size) { return integers.toArray(new Integer[0]); } - /** - * Generates Java code based on the provided template and replacements. - * - * @param inputTemplate The code segment template. - * @param inputReplacements A list of maps containing replacements for each test. - * @param testNumber The unique number for the generated test class. - * @return A string containing the generated Java code. - */ - public static String generateJavaCode(CodeSegment inputTemplate, - ArrayList> inputReplacements, - long testNumber) { - String template = """ - import java.util.Objects; - \\{imports} - public class GeneratedTest\\{num} { - \\{statics} - public static void main(String args[]) throws Exception { - \\{calls} - System.out.println("Passed"); - } - \\{methods} - } - """; - - if (inputReplacements == null || inputReplacements.isEmpty()) { - throw new IllegalArgumentException("Input replacements must not be null or empty."); - } - - CodeSegment aggregatedCodeSegment = fillTemplate(inputTemplate, inputReplacements.get(0)); - - for (int i = 1; i < inputReplacements.size(); i++) { - CodeSegment currentSegment = fillTemplate(inputTemplate, inputReplacements.get(i)); - aggregatedCodeSegment.appendCalls(currentSegment.getCalls()); - aggregatedCodeSegment.appendMethods(currentSegment.getMethods()); - // Assuming imports are common and handled separately - } - - Map replacements = Map.of( - "num", String.valueOf(testNumber), - "statics", aggregatedCodeSegment.getStatics(), - "calls", aggregatedCodeSegment.getCalls(), - "methods", aggregatedCodeSegment.getMethods(), - "imports", aggregatedCodeSegment.getImports() - ); - - return performReplacements(template, replacements); - } - - /** - * Fills the template with the provided replacements. - * - * @param codeSegment The original code segment template. - * @param replacements A map containing replacement values. - * @return A new CodeSegment with replacements applied. - */ - private static CodeSegment fillTemplate(CodeSegment codeSegment, Map replacements) { - String statics = performReplacements(codeSegment.getStatics(), replacements); - String calls = performReplacements(codeSegment.getCalls(), replacements); - String methods = performReplacements(codeSegment.getMethods(), replacements); - String imports = performReplacements(codeSegment.getImports(), replacements); - return new CodeSegment(statics, calls, methods, imports); - } - - /** - * Performs placeholder replacements in the template string based on the provided map. - * It preserves the indentation of the placeholders. - * - * @param template The template string containing placeholders. - * @param replacements A map of placeholder keys and their replacement values. - * @return The template string with all placeholders replaced. - */ - public static String performReplacements(String template, Map replacements) { - if (template == null || replacements == null) { - throw new IllegalArgumentException("Template and replacements must not be null."); - } - - for (Map.Entry entry : replacements.entrySet()) { - String pattern = "\\{%s}".formatted(entry.getKey()); - String replacement = entry.getValue(); - - // Find the pattern in the template and determine its indentation level - int index = template.indexOf(pattern); - if (index != -1) { - int lineStart = template.lastIndexOf('\n', index); - String indentation = template.substring(lineStart + 1, index).replaceAll("\\S", ""); - - // Add indentation to all lines of the replacement (except the first one) - String indentedReplacement = replacement.lines() - .collect(Collectors.joining("\n%s".formatted(indentation))); - template = template.replace(pattern, indentedReplacement); - } - } - return template; - } - /** * Abstract method to retrieve the code segment template. * diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java index b7a216ee06143..171182e8618f0 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template1.java @@ -1,4 +1,5 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; import static compiler.lib.test_generator.InputTemplate.*; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java index 9c2faf26f2ed3..25a9c7de44943 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template10.java @@ -1,4 +1,5 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; import static compiler.lib.test_generator.InputTemplate.*; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java index f64b7c524d05c..1164346f09f2f 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template11.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java index 67350d3b1eafa..4fb2720b07d86 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template12.java @@ -1,4 +1,5 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; import static compiler.lib.test_generator.InputTemplate.*; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java index eb920bbfee108..32e4f2a14dd32 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template2.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java index a77aaffbf8da9..3fca70416853e 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template3.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java index 9e67a9e8921e4..c549fb5af3102 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template4.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java index a8162e6a28521..697935fb08e0e 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template5.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java index fbda1690b5e27..be40e17442870 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template6.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java index 7eef0484a74b1..fc20ef79e1eb2 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template7.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java index d153634452ea0..fd24c5b8fad2b 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template8.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java b/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java index 3aeff8ccba90d..1414d93e7949d 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/Template9.java @@ -1,5 +1,6 @@ package compiler.lib.test_generator; +import static compiler.lib.test_generator.TemplateGenerator.performReplacements; import java.util.HashMap; import java.util.Map; diff --git a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java index f791157f1d27a..9000fe51e2e46 100644 --- a/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/test_generator/TemplateGenerator.java @@ -36,6 +36,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; @@ -226,7 +229,7 @@ private static ArrayList> generateReplacements(InputTemplate private static void generateAndRunTest(CodeSegment template, ArrayList> replacements, String[] compileFlags, long id) { try { // Generate the complete Java code by applying replacements to the template - String javaCode = InputTemplate.generateJavaCode(template, replacements, id); + String javaCode = generateJavaCode(template, replacements, id); // Write the generated Java code to a file and retrieve the filename String fileName = writeJavaCodeToFile(javaCode, id); // Execute the generated Java file with the specified compile flags @@ -237,6 +240,102 @@ private static void generateAndRunTest(CodeSegment template, ArrayList> inputReplacements, + long testNumber) { + String template = """ + import java.util.Objects; + \\{imports} + public class GeneratedTest\\{num} { + \\{statics} + public static void main(String args[]) throws Exception { + \\{calls} + System.out.println("Passed"); + } + \\{methods} + } + """; + + if (inputReplacements == null || inputReplacements.isEmpty()) { + throw new IllegalArgumentException("Input replacements must not be null or empty."); + } + + CodeSegment aggregatedCodeSegment = fillTemplate(inputTemplate, inputReplacements.get(0)); + + for (int i = 1; i < inputReplacements.size(); i++) { + CodeSegment currentSegment = fillTemplate(inputTemplate, inputReplacements.get(i)); + aggregatedCodeSegment.appendCalls(currentSegment.getCalls()); + aggregatedCodeSegment.appendMethods(currentSegment.getMethods()); + // Assuming imports are common and handled separately + } + + Map replacements = Map.of( + "num", String.valueOf(testNumber), + "statics", aggregatedCodeSegment.getStatics(), + "calls", aggregatedCodeSegment.getCalls(), + "methods", aggregatedCodeSegment.getMethods(), + "imports", aggregatedCodeSegment.getImports() + ); + + return performReplacements(template, replacements); + } + + + /** + * Performs placeholder replacements in the template string based on the provided map. + * It preserves the indentation of the placeholders. + * + * @param template The template string containing placeholders. + * @param replacements A map of placeholder keys and their replacement values. + * @return The template string with all placeholders replaced. + */ + public static String performReplacements(String template, Map replacements) { + if (template == null || replacements == null) { + throw new IllegalArgumentException("Template and replacements must not be null."); + } + + for (Map.Entry entry : replacements.entrySet()) { + String pattern = "\\{%s}".formatted(entry.getKey()); + String replacement = entry.getValue(); + + // Find the pattern in the template and determine its indentation level + int index = template.indexOf(pattern); + if (index != -1) { + int lineStart = template.lastIndexOf('\n', index); + String indentation = template.substring(lineStart + 1, index).replaceAll("\\S", ""); + + // Add indentation to all lines of the replacement (except the first one) + String indentedReplacement = replacement.lines() + .collect(Collectors.joining("\n%s".formatted(indentation))); + template = template.replace(pattern, indentedReplacement); + } + } + return template; + } + + /** + * Fills the template with the provided replacements. + * + * @param codeSegment The original code segment template. + * @param replacements A map containing replacement values. + * @return A new CodeSegment with replacements applied. + */ + private static CodeSegment fillTemplate(CodeSegment codeSegment, Map replacements) { + String statics = performReplacements(codeSegment.getStatics(), replacements); + String calls = performReplacements(codeSegment.getCalls(), replacements); + String methods = performReplacements(codeSegment.getMethods(), replacements); + String imports = performReplacements(codeSegment.getImports(), replacements); + return new CodeSegment(statics, calls, methods, imports); + } + /** * Retrieves the next unique test ID in a thread-safe manner. * @@ -397,4 +496,121 @@ public Class findClass(String name) throws ClassNotFoundException { return super.findClass(name); } } + + private static final Random RANDOM = new Random(32); + + // Integer test values including edge cases + public static final Integer[] INTEGER_VALUES = { + -2, -1, 0, 1, 2, + Integer.MIN_VALUE, Integer.MAX_VALUE + }; + + // Positive integer test values including edge cases + public static final Integer[] POSITIVE_INTEGER_VALUES = { + 1, 2, Integer.MAX_VALUE + }; + + // Array sizes for testing + public static final Integer[] ARRAY_SIZES = { + 1, 10, 100, 1_000, 10_000, 100_000, 200_000, 500_000, 1_000_000 + }; + + // Non-zero integer values + public static final Integer[] INTEGER_VALUES_NON_ZERO = { + -2, -1, 1, 2, + Integer.MIN_VALUE, Integer.MAX_VALUE + }; + + // Long test values including edge cases + public static final Long[] LONG_VALUES = { + -2L, -1L, 0L, 1L, 2L, + (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE, + Long.MIN_VALUE, Long.MAX_VALUE + }; + + // Non-zero long values + public static final Long[] LONG_VALUES_NON_ZERO = { + -2L, -1L, 1L, 2L, + (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE, + Long.MIN_VALUE, Long.MAX_VALUE + }; + + // Short test values including edge cases + public static final Short[] SHORT_VALUES = { + -2, -1, 0, 1, 2, + Short.MIN_VALUE, Short.MAX_VALUE + }; + + // Non-zero short values + public static final Short[] SHORT_VALUES_NON_ZERO = { + -2, -1, 1, 2, + Short.MIN_VALUE, Short.MAX_VALUE + }; + + + /** + * Retrieves a random value from the provided array. + * + * @param array Array of values to choose from. + * @param Type of the array elements. + * @return A randomly selected element from the array. + */ + public static T getRandomValue(T[] array) { + if (array == null || array.length == 0) { + throw new IllegalArgumentException("Array must not be null or empty."); + } + return array[RANDOM.nextInt(array.length)]; + } + + /** + * Retrieves a random value from the provided array and converts it to a string. + * + * @param array Array of values to choose from. + * @param Type of the array elements. + * @return A string representation of a randomly selected element from the array. + */ + public static String getRandomValueAsString(T[] array) { + T value = getRandomValue(array); + return String.valueOf(value); + } + + /** + * Generates a unique identifier based on the current system time in nanoseconds. + * + * @return A unique identifier as a string. + */ + public static String getUniqueId() { + return String.valueOf(System.nanoTime()); + } + + // Atomic counter to ensure thread-safe unique number generation + private static final AtomicInteger uniqueCounter = new AtomicInteger(1); + + // Pattern to identify placeholders in the format $variableName + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$(\\w+)"); + + /** + * Processes a template string to prevent variable name conflicts by appending a unique identifier. + * + *

This method scans the input template for placeholders, which are denoted by a '$' followed by a word + * representing the variable name. Each detected placeholder is replaced with the variable name concatenated + * with a unique number, ensuring that variable names remain distinct and do not clash within the processed string. + * + * @param template The template string containing placeholders to be processed. + * @return The processed string with unique identifiers appended to variable names. + */ + public static String avoidConflict(String template) { + int uniqueId = uniqueCounter.getAndIncrement(); + StringBuilder result = new StringBuilder(); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(template); + + while (matcher.find()) { + String variableName = matcher.group(1); + String replacement = variableName + uniqueId; + matcher.appendReplacement(result, Matcher.quoteReplacement(replacement)); + } + matcher.appendTail(result); + + return result.toString(); + } } diff --git a/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java b/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java new file mode 100644 index 0000000000000..ce4612a6309c3 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2024, 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 + * @summary Example test to use the Compile Framework with Templates + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @run driver compile_framework.examples.SimpleTemplateExample + */ + +package compile_framework.examples; + +import compiler.lib.compile_framework.*; +import static compiler.lib.test_generator.InputTemplate.INTEGER_VALUES; +import static compiler.lib.test_generator.InputTemplate.getRandomValue; +import static compiler.lib.test_generator.InputTemplate.getRandomValueAsString; +import static compiler.lib.test_generator.TemplateGenerator.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import compiler.lib.test_generator.*; + +/** + * This test shows a simple compilation of java source code, and its invocation. + */ +public class SimpleTemplateExample { + + public static CodeSegment getTemplate() { + /* TODO: + * use $limit, $i, $lFld for variables + * all defined functions should use uniqueId to avoid conflict + * Nesting : we want to be able to nest CodeTemplate in another CodeTemplate e.g. at \{thing} + * this would require replacing conflicting variables e.g. $i with $i1 and $i2, + * and also replace \{init} from the inner CodeTemplate with a var $limit from outer CodeTemplate + **/ + String imports= """ + """; + String statics = """ + //InputTemplate1 + static long lFld; + static A a = new A(); + static boolean flag; + static class A { + int i; + } + """; + String call = """ + test_\\{uniqueId}(); + """; + String method = """ + public static int test_\\{uniqueId}() { + long limit = lFld; + for (int i =\\{init1}; i < \\{limit}; i \\{arithm1}= \\{stride1}) { + // Use stride > Integer.MAX_VALUE such that LongCountedLoopNode is not split further into loop nests. + for (long j = \\{init2}; j < limit; j\\{arithm2}=\\{stride2}) { + a.i += \\{val1}; // NullCheck with trap on false path -> reason to peel + \\{thing} + \\{template1} + if (j > 0) { // After peeling: j > 0 always true -> loop folded away + \\{template2} + break; + } + } + } + return 10; + } + """; + return new CodeSegment(statics, call, method,imports); + } + + public static String getTemplate1(String variable){ + String statics= """ + int $a =\\{val}; + long $b = \\{var}; + """; + String method=""" + do { + $a--; + $b++; + } while ($a > 0); + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val = getRandomValueAsString(INTEGER_VALUES); + replacements.put("val", val); + replacements.put("var", variable); + return performReplacements(template_com,replacements); + } + + public static String getTemplate2(String variable){ + String statics= """ + int $x, $y; + boolean $flag=\\{bool}; + """; + String method=""" + int $a; + if ($flag) { + $a = \\{val1}; + } else { + $a = \\{val2}; + } + // y = 34; // Make it more interesting + if ($a > \\{val2}) { + $x = \\{val3}; + } else { + $x = \\{val4}; + } + """; + String template=statics+method; + String template_com= avoidConflict(template); + Map replacements = new HashMap<>(); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String val2 = getRandomValueAsString(INTEGER_VALUES); + String val3 = getRandomValueAsString(INTEGER_VALUES); + String val4 = getRandomValueAsString(INTEGER_VALUES); + String bool = getRandomValue(new String[]{"false", "true"}); + replacements.put("val1", val1); + replacements.put("val2", val2); + replacements.put("val3", val3); + replacements.put("val4", val4); + replacements.put("bool", bool); + + + + return performReplacements(template_com,replacements); + } + + + public static Map getRandomReplacements(int numTest) { + String template_nes1= getTemplate1("j"); + String template_nes2= getTemplate2("i"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String stride1 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); + String stride2 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); + String arithm1 = getRandomValue(new String[]{"+", "-"}); + String arithm2 = getRandomValue(new String[]{"+", "-"}); + String thing = getRandomValue(new String[]{"", "synchronized (new Object()) { }"}); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit", limit); + replacements.put("val1", val1); + replacements.put("arithm1", arithm1); + replacements.put("arithm2", arithm2); + replacements.put("stride1", stride1); + replacements.put("stride2", stride2); + replacements.put("thing", thing); + replacements.put("uniqueId", uniqueId); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + return replacements; + } + public static String[] getCompileFlags() { + return new String[] { + "-Xcomp", + "-XX:-CreateCoredumpOnCrash" + }; + } + public int getNumberOfTests(){ + return 1; + } + public static int getNumberOfTestMethods() { + return 10; + } + + // Generate a source jasm file as String + public static String generate() { + // Retrieve compile flags specific to the input template + + // Retrieve the code segment template from the input template + CodeSegment inputTemplate = getTemplate(); + + // Generate replacement mappings for the test methods + ArrayList> replacements = new ArrayList<>(); + // Loop to generate replacements for each test method + for (int j = 0; j < getNumberOfTestMethods(); j++) { + // Retrieve a random set of replacements and increment the unique ID + replacements.add(getRandomReplacements(j)); + } + + return generateJavaCode(inputTemplate, replacements, 42); + } + + public static void main(String[] args) { + // Create a new CompileFramework instance. + CompileFramework comp = new CompileFramework(); + + String[] compileFlags = getCompileFlags(); + + // Add a java source file. + comp.addJavaSourceCode("GeneratedTest42", generate()); + + // Compile the source file. + comp.compile(); + + // Object ret = XYZ.test(5); + Object ret = comp.invoke("GeneratedTest42", "test_1", new Object[] {}); + + // Extract return value of invocation, verify its value. + int i = (int)ret; + System.out.println("Result of call: " + i); + if (i != 10) { + throw new RuntimeException("wrong value: " + i); + } + } +} From 75c01439fa5502848755f930ff9d1921e5e178fb Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 14:34:22 +0100 Subject: [PATCH 12/13] $ vars --- .../examples/SimpleTemplateExample.java | 212 +++++++++--------- 1 file changed, 109 insertions(+), 103 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java b/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java index ce4612a6309c3..48ad95f1855f6 100644 --- a/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java +++ b/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java @@ -31,90 +31,98 @@ package compile_framework.examples; -import compiler.lib.compile_framework.*; import static compiler.lib.test_generator.InputTemplate.INTEGER_VALUES; import static compiler.lib.test_generator.InputTemplate.getRandomValue; import static compiler.lib.test_generator.InputTemplate.getRandomValueAsString; import static compiler.lib.test_generator.TemplateGenerator.*; + +import compiler.lib.compile_framework.*; +import compiler.lib.test_generator.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -import compiler.lib.test_generator.*; /** * This test shows a simple compilation of java source code, and its invocation. */ public class SimpleTemplateExample { - public static CodeSegment getTemplate() { - /* TODO: - * use $limit, $i, $lFld for variables - * all defined functions should use uniqueId to avoid conflict - * Nesting : we want to be able to nest CodeTemplate in another CodeTemplate e.g. at \{thing} - * this would require replacing conflicting variables e.g. $i with $i1 and $i2, - * and also replace \{init} from the inner CodeTemplate with a var $limit from outer CodeTemplate - **/ - String imports= """ - """; - String statics = """ - //InputTemplate1 - static long lFld; - static A a = new A(); - static boolean flag; - static class A { - int i; - } - """; - String call = """ - test_\\{uniqueId}(); - """; - String method = """ - public static int test_\\{uniqueId}() { - long limit = lFld; - for (int i =\\{init1}; i < \\{limit}; i \\{arithm1}= \\{stride1}) { - // Use stride > Integer.MAX_VALUE such that LongCountedLoopNode is not split further into loop nests. - for (long j = \\{init2}; j < limit; j\\{arithm2}=\\{stride2}) { - a.i += \\{val1}; // NullCheck with trap on false path -> reason to peel - \\{thing} - \\{template1} - if (j > 0) { // After peeling: j > 0 always true -> loop folded away - \\{template2} - break; - } - } - } - return 10; - } - """; - return new CodeSegment(statics, call, method,imports); - } - - public static String getTemplate1(String variable){ - String statics= """ - int $a =\\{val}; - long $b = \\{var}; - """; - String method=""" + public static CodeSegment getTemplate() { + /* TODO: + * all defined functions should use uniqueId to avoid conflict + * Nesting : we want to be able to nest CodeTemplate in another CodeTemplate e.g. at \{thing} + * this would require replacing conflicting variables e.g. $i with $i1 and $i2, + * and also replace \{init} from the inner CodeTemplate with a var $limit from outer CodeTemplate + **/ + String imports = + """ + """; + String statics = + """ + //InputTemplate1 + static long $lFld; + static A $a = new A(); + static boolean $flag; + static class A { + int $i; + } + """; + String call = + """ + test_\\{uniqueId}(); + """; + String method = + """ + public static int test_\\{uniqueId}() { + long $limit = $lFld; + for (int $i =\\{init1}; $i < \\{limit}; $i \\{arithm1}= \\{stride1}) { + // Use stride > Integer.MAX_VALUE such that LongCountedLoopNode is not split further into loop nests. + for (long $j = \\{init2}; $j < $limit; $j \\{arithm2}=\\{stride2}) { + $a.$i += \\{val1}; // NullCheck with trap on false path -> reason to peel + \\{thing} + \\{template1} + if ($j > 0) { // After peeling: j > 0 always true -> loop folded away + \\{template2} + break; + } + } + } + return 10; + } + """; + return new CodeSegment(statics, call, method, imports); + } + + public static String getTemplate1(String variable) { + String statics = + """ + int $a =\\{val}; + long $b = \\{var}; + """; + String method = + """ do { $a--; $b++; } while ($a > 0); """; - String template=statics+method; - String template_com= avoidConflict(template); + String template = statics + method; + String template_com = avoidConflict(template); Map replacements = new HashMap<>(); String val = getRandomValueAsString(INTEGER_VALUES); replacements.put("val", val); replacements.put("var", variable); - return performReplacements(template_com,replacements); + return performReplacements(template_com, replacements); } - public static String getTemplate2(String variable){ - String statics= """ + public static String getTemplate2(String variable) { + String statics = + """ int $x, $y; boolean $flag=\\{bool}; """; - String method=""" + String method = + """ int $a; if ($flag) { $a = \\{val1}; @@ -128,66 +136,64 @@ public static String getTemplate2(String variable){ $x = \\{val4}; } """; - String template=statics+method; - String template_com= avoidConflict(template); + String template = statics + method; + String template_com = avoidConflict(template); Map replacements = new HashMap<>(); String val1 = getRandomValueAsString(INTEGER_VALUES); String val2 = getRandomValueAsString(INTEGER_VALUES); String val3 = getRandomValueAsString(INTEGER_VALUES); String val4 = getRandomValueAsString(INTEGER_VALUES); - String bool = getRandomValue(new String[]{"false", "true"}); + String bool = getRandomValue(new String[] { "false", "true" }); replacements.put("val1", val1); replacements.put("val2", val2); replacements.put("val3", val3); replacements.put("val4", val4); replacements.put("bool", bool); + return performReplacements(template_com, replacements); + } + public static Map getRandomReplacements(int numTest) { + String template_nes1 = getTemplate1("$j"); + String template_nes2 = getTemplate2("$i"); + Map replacements = new HashMap<>(); + String init1 = getRandomValueAsString(INTEGER_VALUES); + String init2 = getRandomValueAsString(INTEGER_VALUES); + String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); + String val1 = getRandomValueAsString(INTEGER_VALUES); + String stride1 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); + String stride2 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); + String arithm1 = getRandomValue(new String[] { "+", "-" }); + String arithm2 = getRandomValue(new String[] { "+", "-" }); + String thing = getRandomValue( + new String[] { "", "synchronized (new Object()) { }" } + ); + String uniqueId = String.valueOf(numTest); + replacements.put("init1", init1); + replacements.put("init2", init2); + replacements.put("limit", limit); + replacements.put("val1", val1); + replacements.put("arithm1", arithm1); + replacements.put("arithm2", arithm2); + replacements.put("stride1", stride1); + replacements.put("stride2", stride2); + replacements.put("thing", thing); + replacements.put("uniqueId", uniqueId); + replacements.put("template1", template_nes1); + replacements.put("template2", template_nes2); + return replacements; + } - - return performReplacements(template_com,replacements); + public static String[] getCompileFlags() { + return new String[] { "-Xcomp", "-XX:-CreateCoredumpOnCrash" }; } + public int getNumberOfTests() { + return 1; + } - public static Map getRandomReplacements(int numTest) { - String template_nes1= getTemplate1("j"); - String template_nes2= getTemplate2("i"); - Map replacements = new HashMap<>(); - String init1 = getRandomValueAsString(INTEGER_VALUES); - String init2 = getRandomValueAsString(INTEGER_VALUES); - String limit = getRandomValueAsString(POSITIVE_INTEGER_VALUES); - String val1 = getRandomValueAsString(INTEGER_VALUES); - String stride1 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); - String stride2 = getRandomValueAsString(INTEGER_VALUES_NON_ZERO); - String arithm1 = getRandomValue(new String[]{"+", "-"}); - String arithm2 = getRandomValue(new String[]{"+", "-"}); - String thing = getRandomValue(new String[]{"", "synchronized (new Object()) { }"}); - String uniqueId = String.valueOf(numTest); - replacements.put("init1", init1); - replacements.put("init2", init2); - replacements.put("limit", limit); - replacements.put("val1", val1); - replacements.put("arithm1", arithm1); - replacements.put("arithm2", arithm2); - replacements.put("stride1", stride1); - replacements.put("stride2", stride2); - replacements.put("thing", thing); - replacements.put("uniqueId", uniqueId); - replacements.put("template1", template_nes1); - replacements.put("template2", template_nes2); - return replacements; - } - public static String[] getCompileFlags() { - return new String[] { - "-Xcomp", - "-XX:-CreateCoredumpOnCrash" - }; - } - public int getNumberOfTests(){ - return 1; - } - public static int getNumberOfTestMethods() { - return 10; - } + public static int getNumberOfTestMethods() { + return 10; + } // Generate a source jasm file as String public static String generate() { @@ -223,7 +229,7 @@ public static void main(String[] args) { Object ret = comp.invoke("GeneratedTest42", "test_1", new Object[] {}); // Extract return value of invocation, verify its value. - int i = (int)ret; + int i = (int) ret; System.out.println("Result of call: " + i); if (i != 10) { throw new RuntimeException("wrong value: " + i); From b72359c2b41280f87d3b0e6a351dfd0d3ac8ccb7 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 4 Nov 2024 14:48:00 +0100 Subject: [PATCH 13/13] two invoke --- .../compile_framework/examples/SimpleTemplateExample.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java b/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java index 48ad95f1855f6..cb7ec97067017 100644 --- a/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java +++ b/test/hotspot/jtreg/testlibrary_tests/compile_framework/examples/SimpleTemplateExample.java @@ -227,6 +227,7 @@ public static void main(String[] args) { // Object ret = XYZ.test(5); Object ret = comp.invoke("GeneratedTest42", "test_1", new Object[] {}); + Object ret2 = comp.invoke("GeneratedTest42", "test_3", new Object[] {}); // Extract return value of invocation, verify its value. int i = (int) ret;