From 98ba68d5572a59d5c968452552bd06c1153d8c89 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 6 Jun 2025 15:25:05 +0200 Subject: [PATCH 01/15] JDK-8358772 --- .../library/TestFrameworkClass.java | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java new file mode 100644 index 0000000000000..dad344726dd3d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025, 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.template_framework.library; + +import java.util.List; +import java.util.Set; + +import compiler.lib.ir_framework.TestFramework; +import compiler.lib.compile_framework.CompileFramework; +import compiler.lib.template_framework.Template; +import compiler.lib.template_framework.TemplateToken; +import static compiler.lib.template_framework.Template.body; +import static compiler.lib.template_framework.Template.let; + +/** + * This class provides a {@link #render} method that can be used to simplify generating + * source code when using the {@link TestFramework} (also known as IR Framework) to run + * a list of tests. + * + *

+ * The idea is that the user only has to generate the code for the individual tests, + * and can then pass the corresponding list of {@link TemplateToken}s to this + * provided {@link #render} method which generates the surrounding class and the main + * method that invokes the {@link TestFramework}, so that all the generated tests + * are run. + */ +public final class TestFrameworkClass { + + // Ensure there can be no instance, and we do not have to document the constructor. + private TestFrameworkClass() {} + + /** + * This method renders a list of {@code testTemplateTokens} into the body of a class + * and generates a {@code main} method which launches the {@link TestFramework} + * to run the generated tests. + * + *

+ * The generated {@code main} method is to be invoked with a {@code vmFlags} argument, + * which must be a {@link String[]}, specifying the VM flags for the Test VM, in which + * the tests will be run. Thus, one can generate the test class once, and invoke its + * {@code main} method multiple times, each time with a different set of VM flags. + * + * @param packageName The package name of the test class. + * @param className The name of the test class. + * @param imports A set of imports. + * @param classpath The classpath from {@link CompileFramework#getEscapedClassPathOfCompiledClasses}, + * so that the Test VM has access to the class files that are compiled from the + * generated source code. + * @param testTemplateTokens The list of tests to be generated into the test class. + * Every test must be annotated with {@code @Test}, so that + * the {@link TestFramework} can later find and run them. + * @return The generated source code of the test class as a {@link String}. + */ + public static String render(final String packageName, + final String className, + final Set imports, + final String classpath, + final List testTemplateTokens) { + var template = Template.make(() -> body( + let("packageName", packageName), + let("className", className), + let("classpath", classpath), + """ + package #packageName; + // --- IMPORTS start --- + import compiler.lib.ir_framework.*; + """, + imports.stream().map(i -> "import " + i + ";\n").toList(), + """ + // --- IMPORTS end --- + public class #className { + // --- CLASS_HOOK insertions start --- + """, + Hooks.CLASS_HOOK.anchor( + """ + // --- CLASS_HOOK insertions end --- + public static void main(String[] vmFlags) { + TestFramework framework = new TestFramework(#className.class); + framework.addFlags("-classpath", "#classpath"); + framework.addFlags(vmFlags); + framework.start(); + } + // --- LIST OF TESTS start --- + """, + testTemplateTokens + ), + """ + // --- LIST OF TESTS end --- + } + """ + )); + return template.render(); + } +} From 4def43aa7e964a2ad0bb17da997e6bdb55805703 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 6 Jun 2025 16:45:50 +0200 Subject: [PATCH 02/15] types --- .../library/CodeGenerationDataNameType.java | 90 ++++++++++++ .../library/PrimitiveType.java | 134 ++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java new file mode 100644 index 0000000000000..6dbf8c8beea32 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025, 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.template_framework.library; + +import java.util.List; + +import compiler.lib.template_framework.DataName; +import compiler.lib.template_framework.Template; + +/** + * The {@link CodeGenerationDataNameType} extends the {@link DataName.Type} with + * additional functionality for code generation. These types with their extended + * functionality can be used with many other code generation facilities in the + * lbrary, such as generating random {@code Expression}s. + */ +public interface CodeGenerationDataNameType extends DataName.Type { + + /** + * This method provides a random constant value for the type, which can + * be used as a token inside a {@link Template}. + * + * @return A random constant value. + */ + public Object con(); + + public static PrimitiveType bytes() { return PrimitiveType.BYTES; } + public static PrimitiveType shorts() { return PrimitiveType.SHORTS; } + public static PrimitiveType chars() { return PrimitiveType.CHARS; } + public static PrimitiveType ints() { return PrimitiveType.INTS; } + public static PrimitiveType longs() { return PrimitiveType.LONGS; } + public static PrimitiveType floats() { return PrimitiveType.FLOATS; } + public static PrimitiveType doubles() { return PrimitiveType.DOUBLES; } + public static PrimitiveType booleans() { return PrimitiveType.BOOLEANS; } + + public static final List PRIMITIVE_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs(), + floats(), + doubles(), + booleans() + ); + + public static final List INTEGRAL_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs() + ); + + public static final List SUBWORD_TYPES = List.of( + bytes(), + chars(), + shorts() + ); + + public static final List INT_LONG_TYPES = List.of( + ints(), + longs() + ); + + public static final List FLOATING_TYPES = List.of( + floats(), + doubles() + ); +} diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java new file mode 100644 index 0000000000000..78998fb3f3e27 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025, 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.template_framework.library; + +import java.util.Random; +import jdk.test.lib.Utils; + +import compiler.lib.generators.Generators; +import compiler.lib.generators.Generator; +import compiler.lib.generators.RestrictableGenerator; + +import compiler.lib.template_framework.DataName; + +public final class PrimitiveType implements CodeGenerationDataNameType { + private static final Random RANDOM = Utils.getRandomInstance(); + private static final RestrictableGenerator GEN_BYTE = Generators.G.safeRestrict(Generators.G.ints(), Byte.MIN_VALUE, Byte.MAX_VALUE); + private static final RestrictableGenerator GEN_CHAR = Generators.G.safeRestrict(Generators.G.ints(), Character.MIN_VALUE, Character.MAX_VALUE); + private static final RestrictableGenerator GEN_SHORT = Generators.G.safeRestrict(Generators.G.ints(), Short.MIN_VALUE, Short.MAX_VALUE); + private static final RestrictableGenerator GEN_INT = Generators.G.ints(); + private static final RestrictableGenerator GEN_LONG = Generators.G.longs(); + private static final Generator GEN_DOUBLE = Generators.G.doubles(); + private static final Generator GEN_FLOAT = Generators.G.floats(); + + private static enum Kind { BYTE, SHORT, CHAR, INT, LONG, FLOAT, DOUBLE, BOOLEAN }; + + // We have one static instance each, so we do not have duplicat instances. + static final PrimitiveType BYTES = new PrimitiveType(BYTE ); + static final PrimitiveType SHORTS = new PrimitiveType(SHORT ); + static final PrimitiveType CHARS = new PrimitiveType(CHAR ); + static final PrimitiveType INTS = new PrimitiveType(INT ); + static final PrimitiveType LONGS = new PrimitiveType(LONG ); + static final PrimitiveType FLOATS = new PrimitiveType(FLOAT ); + static final PrimitiveType DOUBLES = new PrimitiveType(DOUBLE ); + static final PrimitiveType BOOLEANS = new PrimitiveType(BOOLEAN); + + private Kind kind; + + // Private constructor so nobody can create duplicate instances. + private PrimitiveType(Kind kind) { + this.kind = kind; + } + + @Override + public boolean isSubtypeOf(DataName.Type other) { + return (other instanceof PrimitiveType pt) && pt.kind() == kind(); + } + + @Override + public String name() { + return switch(kind) { + case BYTE -> "byte"; + case SHORT -> "short"; + case CHAR -> "char"; + case INT -> "int"; + case LONG -> "long"; + case FLOAT -> "float"; + case DOUBLE -> "double"; + case BOOLEAN -> "boolean"; + }; + } + + public Object con() { + return switch(kind) { + case BYTE -> "(byte)" + GEN_BYTE.next(); + case SHORT -> "(short)" + GEN_SHORT.next(); + case CHAR -> "(char)" + GEN_CHAR.next(); + case INT -> GEN_INT.next(); + case LONG -> GEN_LONG.next(); + case FLOAT -> GEN_FLOAT.next(); + case DOUBLE -> GEN_DOUBLE.next(); + case BOOLEAN -> RANDOM.nextInt() % 2 == 0; + }; + } + + public String boxedTypeName() { + return switch(kind) { + case BYTE -> "Byte"; + case SHORT -> "Short"; + case CHAR -> "Character"; + case INT -> "Integer"; + case LONG -> "Long"; + case FLOAT -> "Float"; + case DOUBLE -> "Double"; + case BOOLEAN -> "Boolean"; + }; + } + + public int byteSize() { + return switch(kind) { + case BYTE -> 1; + case SHORT -> 2; + case CHAR -> 2; + case INT -> 4; + case LONG -> 8; + case FLOAT -> 4; + case DOUBLE -> 8; + case BOOLEAN -> { throw new UnsupportedOperationException("boolean does not have a defined 'size'"); } + }; + } + + public String isFloating() { + return switch(kind) { + case BYTE -> false; + case SHORT -> false; + case CHAR -> false; + case INT -> false; + case LONG -> false; + case FLOAT -> true; + case DOUBLE -> true; + case BOOLEAN -> false; + }; + } +} From 16527d035f2512e2a2ce88683b51baf3b31842ca Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 6 Jun 2025 16:58:24 +0200 Subject: [PATCH 03/15] add test, does not compile now --- .../examples/TestPrimitiveTypes.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java new file mode 100644 index 0000000000000..f31543c098486 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8358772 + * @summary Demonstrate the use of PrimitiveTypes form the Template Library. + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @run main template_framework.examples.TestPrimitiveTypes + */ + +package template_framework.examples; + +import compiler.lib.template_framework.library.PrimitiveType; + +public class TestPrimitiveTypes { + public static void main(String[] args) { + var l = PrimitiveType.PRIMITIVE_TYPES; + } + + // TODO: write tests + // + // - use all functions and lists of types. + // - use DataNames for sampling + // - generate random constants with con + // - cast to boxed types and back + // - Use byteSize with MemorySegment -> check if correct via strides. + // - isFloating -> check for rounding or something? + // - boolean -> no size?? +} From c377093948bfcef8f74eddbdee5de2e29e98305f Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 11 Jun 2025 17:43:14 +0200 Subject: [PATCH 04/15] update tests --- .../library/CodeGenerationDataNameType.java | 16 ++-- .../library/PrimitiveType.java | 27 +++--- .../examples/TestPrimitiveTypes.java | 86 ++++++++++++++++++- 3 files changed, 109 insertions(+), 20 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java index 6dbf8c8beea32..68aa2e86dc41c 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -78,13 +78,19 @@ public interface CodeGenerationDataNameType extends DataName.Type { shorts() ); - public static final List INT_LONG_TYPES = List.of( - ints(), - longs() - ); - public static final List FLOATING_TYPES = List.of( floats(), doubles() ); + + public static final List INTEGRAL_AND_FLOATING_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs(), + floats(), + doubles(), + booleans() + ); } diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java index 78998fb3f3e27..6d710b515a470 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java @@ -45,16 +45,16 @@ public final class PrimitiveType implements CodeGenerationDataNameType { private static enum Kind { BYTE, SHORT, CHAR, INT, LONG, FLOAT, DOUBLE, BOOLEAN }; // We have one static instance each, so we do not have duplicat instances. - static final PrimitiveType BYTES = new PrimitiveType(BYTE ); - static final PrimitiveType SHORTS = new PrimitiveType(SHORT ); - static final PrimitiveType CHARS = new PrimitiveType(CHAR ); - static final PrimitiveType INTS = new PrimitiveType(INT ); - static final PrimitiveType LONGS = new PrimitiveType(LONG ); - static final PrimitiveType FLOATS = new PrimitiveType(FLOAT ); - static final PrimitiveType DOUBLES = new PrimitiveType(DOUBLE ); - static final PrimitiveType BOOLEANS = new PrimitiveType(BOOLEAN); + static final PrimitiveType BYTES = new PrimitiveType(Kind.BYTE ); + static final PrimitiveType SHORTS = new PrimitiveType(Kind.SHORT ); + static final PrimitiveType CHARS = new PrimitiveType(Kind.CHAR ); + static final PrimitiveType INTS = new PrimitiveType(Kind.INT ); + static final PrimitiveType LONGS = new PrimitiveType(Kind.LONG ); + static final PrimitiveType FLOATS = new PrimitiveType(Kind.FLOAT ); + static final PrimitiveType DOUBLES = new PrimitiveType(Kind.DOUBLE ); + static final PrimitiveType BOOLEANS = new PrimitiveType(Kind.BOOLEAN); - private Kind kind; + final Kind kind; // Private constructor so nobody can create duplicate instances. private PrimitiveType(Kind kind) { @@ -63,7 +63,7 @@ private PrimitiveType(Kind kind) { @Override public boolean isSubtypeOf(DataName.Type other) { - return (other instanceof PrimitiveType pt) && pt.kind() == kind(); + return (other instanceof PrimitiveType pt) && pt.kind == kind; } @Override @@ -80,6 +80,11 @@ public String name() { }; } + @Override + public String toString() { + return name(); + } + public Object con() { return switch(kind) { case BYTE -> "(byte)" + GEN_BYTE.next(); @@ -119,7 +124,7 @@ public int byteSize() { }; } - public String isFloating() { + public boolean isFloating() { return switch(kind) { case BYTE -> false; case SHORT -> false; diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java index f31543c098486..f8016543d146f 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -27,18 +27,26 @@ * @summary Demonstrate the use of PrimitiveTypes form the Template Library. * @modules java.base/jdk.internal.misc * @library /test/lib / + * @compile ../../../compiler/lib/verify/Verify.java * @run main template_framework.examples.TestPrimitiveTypes */ package template_framework.examples; +import java.util.List; +import java.util.Map; +import java.util.HashMap; + +import compiler.lib.compile_framework.*; +import compiler.lib.template_framework.Template; +import compiler.lib.template_framework.TemplateToken; +import static compiler.lib.template_framework.Template.body; +import static compiler.lib.template_framework.Template.let; + +import compiler.lib.template_framework.library.CodeGenerationDataNameType; import compiler.lib.template_framework.library.PrimitiveType; public class TestPrimitiveTypes { - public static void main(String[] args) { - var l = PrimitiveType.PRIMITIVE_TYPES; - } - // TODO: write tests // // - use all functions and lists of types. @@ -48,4 +56,74 @@ public static void main(String[] args) { // - Use byteSize with MemorySegment -> check if correct via strides. // - isFloating -> check for rounding or something? // - boolean -> no size?? + + public static void main(String[] args) { + // Create a new CompileFramework instance. + CompileFramework comp = new CompileFramework(); + + // Add a java source file. + comp.addJavaSourceCode("p.xyz.InnerTest", generate()); + + // Compile the source file. + comp.compile(); + + // p.xyz.InnerTest.main(); + comp.invoke("p.xyz.InnerTest", "main", new Object[] {}); + } + + // Generate a source Java file as String + public static String generate() { + Map tests = new HashMap<>(); + + var boxingTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( + let("CON1", type.con()), + let("CON2", type.con()), + let("Boxed", type.boxedTypeName()), + """ + public static void #name() { + #type c1 = #CON1; + #type c2 = #CON2; + #Boxed b1 = c1; + #Boxed b2 = c2; + Verify.checkEQ(c1, b1); + Verify.checkEQ(c2, b2); + } + """ + )); + + for (PrimitiveType type : CodeGenerationDataNameType.PRIMITIVE_TYPES) { + String name = "test_boxing_" + type.name(); + tests.put(name, boxingTemplate.asToken(name, type)); + } + + var l = CodeGenerationDataNameType.PRIMITIVE_TYPES; + // Create a Template with two arguments. + var template = Template.make(() -> body( + """ + package p.xyz; + + import compiler.lib.verify.*; + + public class InnerTest { + public static void main() { + """, + // Call all test methods from main. + tests.keySet().stream().map( + n -> List.of(n, "();\n") + ).toList(), + """ + } + """, + // Now add all the test methods. + tests.values().stream().toList(), + """ + } + """ + )); + + // Render the template to a String. + return template.render(); + } + + } From fe28093690196e130c23d5b444d8035d9d3d36b9 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 11 Jun 2025 19:39:24 +0200 Subject: [PATCH 05/15] size and boxing --- .../library/CodeGenerationDataNameType.java | 3 +- .../examples/TestPrimitiveTypes.java | 30 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java index 68aa2e86dc41c..b3fc59d641ff7 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -90,7 +90,6 @@ public interface CodeGenerationDataNameType extends DataName.Type { ints(), longs(), floats(), - doubles(), - booleans() + doubles() ); } diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java index f8016543d146f..98c1fb9520f52 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -96,13 +96,41 @@ public static String generate() { tests.put(name, boxingTemplate.asToken(name, type)); } - var l = CodeGenerationDataNameType.PRIMITIVE_TYPES; + var integralFloatTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( + let("size", type.byteSize()), + let("isFloating", type.isFloating()), + """ + public static void #name() { + // Test byteSize via creation of array. + #type[] array = new #type[1]; + MemorySegment ms = MemorySegment.ofArray(array); + if (#size != ms.byteSize()) { + throw new RuntimeException("byteSize mismatch #type"); + } + + // Test isFloating via rounding. + double value = 1.5; + #type rounded = (#type)value; + boolean isFloating = value != rounded; + if (isFloating == #isFloating) { + throw new RuntimeException("isFloating mismatch #type"); + } + } + """ + )); + + for (PrimitiveType type : CodeGenerationDataNameType.INTEGRAL_AND_FLOATING_TYPES) { + String name = "test_integral_floating_" + type.name(); + tests.put(name, integralFloatTemplate.asToken(name, type)); + } + // Create a Template with two arguments. var template = Template.make(() -> body( """ package p.xyz; import compiler.lib.verify.*; + import java.lang.foreign.MemorySegment; public class InnerTest { public static void main() { From 4cf7a29bd9167a04d8df3404ddd7092cf94c2306 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 11 Jun 2025 21:15:43 +0200 Subject: [PATCH 06/15] wip test --- .../compiler/lib/template_framework/Hook.java | 8 ++--- .../lib/template_framework/Template.java | 12 ++++---- .../examples/TestPrimitiveTypes.java | 30 +++++++++++++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java index 48f7852d5098a..88a6031061cf5 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java @@ -72,9 +72,9 @@ public record Hook(String name) { * {@link #insert}ed back to the location where this {@link Hook} was {@link #anchor}ed. * * @param tokens A list of tokens, which have the same restrictions as {@link Template#body}. - * @return A {@link Token} that captures the anchoring of the scope and the list of validated {@link Token}s. + * @return A token that captures the anchoring of the scope and the list of validated tokens. */ - public Token anchor(Object... tokens) { + public Object anchor(Object... tokens) { return new HookAnchorToken(this, Token.parse(tokens)); } @@ -83,9 +83,9 @@ public Token anchor(Object... tokens) { * This could be in the same Template, or one nested further out. * * @param templateToken The Template with applied arguments to be inserted at the {@link Hook}. - * @return The {@link Token} which when used inside a {@link Template#body} performs the code insertion into the {@link Hook}. + * @return The token which when used inside a {@link Template#body} performs the code insertion into the {@link Hook}. */ - public Token insert(TemplateToken templateToken) { + public Object insert(TemplateToken templateToken) { return new HookInsertToken(this, templateToken); } diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java index f01c5ccffd3d0..787dc5a655835 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java @@ -662,7 +662,7 @@ static TemplateBody body(Object... tokens) { * inside a {@link Template#body}. * @throws RendererException if there is a duplicate hashtag {@code key}. */ - static Token let(String key, Object value) { + static Object let(String key, Object value) { Renderer.getCurrent().addHashtagReplacement(key, value); return new NothingToken(); } @@ -747,7 +747,7 @@ static float fuel() { * @param fuelCost The amount of fuel used for the current Template. * @return A token for convenient use in {@link Template#body}. */ - static Token setFuelCost(float fuelCost) { + static Object setFuelCost(float fuelCost) { Renderer.getCurrent().setFuelCost(fuelCost); return new NothingToken(); } @@ -766,7 +766,7 @@ static Token setFuelCost(float fuelCost) { * Must be a value from 1 to 1000. * @return The token that performs the defining action. */ - static Token addDataName(String name, DataName.Type type, DataName.Mutability mutability, int weight) { + static Object addDataName(String name, DataName.Type type, DataName.Mutability mutability, int weight) { if (mutability != DataName.Mutability.MUTABLE && mutability != DataName.Mutability.IMMUTABLE) { throw new IllegalArgumentException("Unexpected mutability: " + mutability); @@ -789,7 +789,7 @@ static Token addDataName(String name, DataName.Type type, DataName.Mutability mu * or if we also allow it to be mutated. * @return The token that performs the defining action. */ - static Token addDataName(String name, DataName.Type type, DataName.Mutability mutability) { + static Object addDataName(String name, DataName.Type type, DataName.Mutability mutability) { return addDataName(name, type, mutability, 1); } @@ -814,7 +814,7 @@ static DataName.FilteredSet dataNames(DataName.Mutability mutability) { * Must be a value from 1 to 1000. * @return The token that performs the defining action. */ - static Token addStructuralName(String name, StructuralName.Type type, int weight) { + static Object addStructuralName(String name, StructuralName.Type type, int weight) { if (weight <= 0 || 1000 < weight) { throw new IllegalArgumentException("Unexpected weight: " + weight); } @@ -829,7 +829,7 @@ static Token addStructuralName(String name, StructuralName.Type type, int weight * @param type The type of the {@link StructuralName}. * @return The token that performs the defining action. */ - static Token addStructuralName(String name, StructuralName.Type type) { + static Object addStructuralName(String name, StructuralName.Type type) { return addStructuralName(name, type, 1); } diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java index 98c1fb9520f52..b06523be0ace2 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -35,14 +35,19 @@ import java.util.List; import java.util.Map; +import java.util.Collections; import java.util.HashMap; import compiler.lib.compile_framework.*; +import compiler.lib.template_framework.DataName; import compiler.lib.template_framework.Template; import compiler.lib.template_framework.TemplateToken; import static compiler.lib.template_framework.Template.body; import static compiler.lib.template_framework.Template.let; +import static compiler.lib.template_framework.Template.$; +import static compiler.lib.template_framework.Template.addDataName; +import compiler.lib.template_framework.library.Hooks; import compiler.lib.template_framework.library.CodeGenerationDataNameType; import compiler.lib.template_framework.library.PrimitiveType; @@ -124,6 +129,31 @@ public static String generate() { tests.put(name, integralFloatTemplate.asToken(name, type)); } + var variableTemplate = Template.make("type", (PrimitiveType type) -> body( + addDataName($("var"), type, DataName.Mutability.MUTABLE) + )); + + var namesTemplate = Template.make(() -> body( + """ + public static void test_names() { + """, + Hooks.METHOD_HOOK.anchor( + Collections.nCopies(10, + CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(type -> + Hooks.METHOD_HOOK.insert(variableTemplate.asToken(type)) + ).toList() + ), + """ + TODO: sample! + """ + ), + """ + } + """ + )); + + tests.put("test_names", namesTemplate.asToken()); + // Create a Template with two arguments. var template = Template.make(() -> body( """ From e32f0a5f126adb2b2b36f713558bd8f423f51f30 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 08:39:37 +0200 Subject: [PATCH 07/15] improve test --- .../examples/TestPrimitiveTypes.java | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java index b06523be0ace2..8bf2860b570a7 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -43,24 +43,21 @@ import compiler.lib.template_framework.Template; import compiler.lib.template_framework.TemplateToken; import static compiler.lib.template_framework.Template.body; +import static compiler.lib.template_framework.Template.dataNames; import static compiler.lib.template_framework.Template.let; import static compiler.lib.template_framework.Template.$; import static compiler.lib.template_framework.Template.addDataName; +import static compiler.lib.template_framework.Template.dataNames; +import static compiler.lib.template_framework.DataName.Mutability.MUTABLE; import compiler.lib.template_framework.library.Hooks; import compiler.lib.template_framework.library.CodeGenerationDataNameType; import compiler.lib.template_framework.library.PrimitiveType; +/** + * This test shows the use of {@link PrimitiveType}. + */ public class TestPrimitiveTypes { - // TODO: write tests - // - // - use all functions and lists of types. - // - use DataNames for sampling - // - generate random constants with con - // - cast to boxed types and back - // - Use byteSize with MemorySegment -> check if correct via strides. - // - isFloating -> check for rounding or something? - // - boolean -> no size?? public static void main(String[] args) { // Create a new CompileFramework instance. @@ -78,8 +75,10 @@ public static void main(String[] args) { // Generate a source Java file as String public static String generate() { + // Generate a list of test methods. Map tests = new HashMap<>(); + // The boxing tests check if we can autobox with "boxedTypeName". var boxingTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( let("CON1", type.con()), let("CON2", type.con()), @@ -101,6 +100,7 @@ public static String generate() { tests.put(name, boxingTemplate.asToken(name, type)); } + // Integral and Float types have a size. Also test if "isFloating" is correct. var integralFloatTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( let("size", type.byteSize()), let("isFloating", type.isFloating()), @@ -129,8 +129,22 @@ public static String generate() { tests.put(name, integralFloatTemplate.asToken(name, type)); } + // Finally, test the type by creating some DataNames (variables), and sampling + // from them. There should be no cross-over between the types. var variableTemplate = Template.make("type", (PrimitiveType type) -> body( - addDataName($("var"), type, DataName.Mutability.MUTABLE) + let("CON", type.con()), + addDataName($("var"), type, MUTABLE), + """ + #type $var = #CON; + """ + )); + + var sampleTemplate = Template.make("type", (PrimitiveType type) -> body( + let("var", dataNames(MUTABLE).exactOf(type).sample().name()), + let("CON", type.con()), + """ + #var = #CON; + """ )); var namesTemplate = Template.make(() -> body( @@ -144,8 +158,13 @@ public static void test_names() { ).toList() ), """ - TODO: sample! - """ + // Now sample: + """, + Collections.nCopies(10, + CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(type -> + sampleTemplate.asToken(type) + ).toList() + ) ), """ } @@ -154,7 +173,8 @@ public static void test_names() { tests.put("test_names", namesTemplate.asToken()); - // Create a Template with two arguments. + // Finally, put all the tests together in a class, and invoke all + // tests from the main method. var template = Template.make(() -> body( """ package p.xyz; @@ -182,6 +202,4 @@ public static void main() { // Render the template to a String. return template.render(); } - - } From e34301bcb9565226ac1580fa7eddbc344ce53de8 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 09:09:24 +0200 Subject: [PATCH 08/15] documentation --- .../library/CodeGenerationDataNameType.java | 62 +++++++++++++++++++ .../library/PrimitiveType.java | 47 ++++++++++---- 2 files changed, 96 insertions(+), 13 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java index b3fc59d641ff7..957c5b7a7c8cd 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -44,15 +44,65 @@ public interface CodeGenerationDataNameType extends DataName.Type { */ public Object con(); + /** + * The byte {@link PrimitiveType}. + * + * @return The byte {@link PrimitiveType}. + */ public static PrimitiveType bytes() { return PrimitiveType.BYTES; } + + /** + * The short {@link PrimitiveType}. + * + * @return The short {@link PrimitiveType}. + */ public static PrimitiveType shorts() { return PrimitiveType.SHORTS; } + + /** + * The char {@link PrimitiveType}. + * + * @return The char {@link PrimitiveType}. + */ public static PrimitiveType chars() { return PrimitiveType.CHARS; } + + /** + * The int {@link PrimitiveType}. + * + * @return The int {@link PrimitiveType}. + */ public static PrimitiveType ints() { return PrimitiveType.INTS; } + + /** + * The long {@link PrimitiveType}. + * + * @return The long {@link PrimitiveType}. + */ public static PrimitiveType longs() { return PrimitiveType.LONGS; } + + /** + * The float {@link PrimitiveType}. + * + * @return The float {@link PrimitiveType}. + */ public static PrimitiveType floats() { return PrimitiveType.FLOATS; } + + /** + * The double {@link PrimitiveType}. + * + * @return The double {@link PrimitiveType}. + */ public static PrimitiveType doubles() { return PrimitiveType.DOUBLES; } + + /** + * The boolean {@link PrimitiveType}. + * + * @return The boolean {@link PrimitiveType}. + */ public static PrimitiveType booleans() { return PrimitiveType.BOOLEANS; } + /** + * List of all {@link PrimitiveType}s. + */ public static final List PRIMITIVE_TYPES = List.of( bytes(), chars(), @@ -64,6 +114,9 @@ public interface CodeGenerationDataNameType extends DataName.Type { booleans() ); + /** + * List of all integral {@link PrimitiveType}s (byte, char, short, int, long). + */ public static final List INTEGRAL_TYPES = List.of( bytes(), chars(), @@ -72,17 +125,26 @@ public interface CodeGenerationDataNameType extends DataName.Type { longs() ); + /** + * List of all subword {@link PrimitiveType}s (byte, char, short). + */ public static final List SUBWORD_TYPES = List.of( bytes(), chars(), shorts() ); + /** + * List of all floating {@link PrimitiveType}s (float, double). + */ public static final List FLOATING_TYPES = List.of( floats(), doubles() ); + /** + * List of all integral and floating {@link PrimitiveType}s. + */ public static final List INTEGRAL_AND_FLOATING_TYPES = List.of( bytes(), chars(), diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java index 6d710b515a470..fee214a1d6eff 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java @@ -32,6 +32,11 @@ import compiler.lib.template_framework.DataName; +/** + * The {@link PrimitiveType} models Java's primitive types, and provides a set + * of useful methods for code generation, such as the {@link #byteSize} and + * {@link #boxedTypeName}. + */ public final class PrimitiveType implements CodeGenerationDataNameType { private static final Random RANDOM = Utils.getRandomInstance(); private static final RestrictableGenerator GEN_BYTE = Generators.G.safeRestrict(Generators.G.ints(), Byte.MIN_VALUE, Byte.MAX_VALUE); @@ -98,19 +103,12 @@ public Object con() { }; } - public String boxedTypeName() { - return switch(kind) { - case BYTE -> "Byte"; - case SHORT -> "Short"; - case CHAR -> "Character"; - case INT -> "Integer"; - case LONG -> "Long"; - case FLOAT -> "Float"; - case DOUBLE -> "Double"; - case BOOLEAN -> "Boolean"; - }; - } - + /** + * Provides the size of the type in bytes. + * + * @return Size of the type in bytes. + * @throws UnsupportedOperationException for boolean which has no defined size. + */ public int byteSize() { return switch(kind) { case BYTE -> 1; @@ -124,6 +122,29 @@ public int byteSize() { }; } + /** + * Provides the name of the boxed type. + * + * @return the name of the boxed type. + */ + public String boxedTypeName() { + return switch(kind) { + case BYTE -> "Byte"; + case SHORT -> "Short"; + case CHAR -> "Character"; + case INT -> "Integer"; + case LONG -> "Long"; + case FLOAT -> "Float"; + case DOUBLE -> "Double"; + case BOOLEAN -> "Boolean"; + }; + } + + /** + * Indicates if the type is a floating type. + * + * @return true iff the type is a floating type. + */ public boolean isFloating() { return switch(kind) { case BYTE -> false; From 39710825ba2c3051e2c74df4b03d5e3929c96278 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 11:24:21 +0200 Subject: [PATCH 09/15] rm unnecessary file --- .../library/TestFrameworkClass.java | 115 ------------------ 1 file changed, 115 deletions(-) delete mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java deleted file mode 100644 index dad344726dd3d..0000000000000 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2025, 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.template_framework.library; - -import java.util.List; -import java.util.Set; - -import compiler.lib.ir_framework.TestFramework; -import compiler.lib.compile_framework.CompileFramework; -import compiler.lib.template_framework.Template; -import compiler.lib.template_framework.TemplateToken; -import static compiler.lib.template_framework.Template.body; -import static compiler.lib.template_framework.Template.let; - -/** - * This class provides a {@link #render} method that can be used to simplify generating - * source code when using the {@link TestFramework} (also known as IR Framework) to run - * a list of tests. - * - *

- * The idea is that the user only has to generate the code for the individual tests, - * and can then pass the corresponding list of {@link TemplateToken}s to this - * provided {@link #render} method which generates the surrounding class and the main - * method that invokes the {@link TestFramework}, so that all the generated tests - * are run. - */ -public final class TestFrameworkClass { - - // Ensure there can be no instance, and we do not have to document the constructor. - private TestFrameworkClass() {} - - /** - * This method renders a list of {@code testTemplateTokens} into the body of a class - * and generates a {@code main} method which launches the {@link TestFramework} - * to run the generated tests. - * - *

- * The generated {@code main} method is to be invoked with a {@code vmFlags} argument, - * which must be a {@link String[]}, specifying the VM flags for the Test VM, in which - * the tests will be run. Thus, one can generate the test class once, and invoke its - * {@code main} method multiple times, each time with a different set of VM flags. - * - * @param packageName The package name of the test class. - * @param className The name of the test class. - * @param imports A set of imports. - * @param classpath The classpath from {@link CompileFramework#getEscapedClassPathOfCompiledClasses}, - * so that the Test VM has access to the class files that are compiled from the - * generated source code. - * @param testTemplateTokens The list of tests to be generated into the test class. - * Every test must be annotated with {@code @Test}, so that - * the {@link TestFramework} can later find and run them. - * @return The generated source code of the test class as a {@link String}. - */ - public static String render(final String packageName, - final String className, - final Set imports, - final String classpath, - final List testTemplateTokens) { - var template = Template.make(() -> body( - let("packageName", packageName), - let("className", className), - let("classpath", classpath), - """ - package #packageName; - // --- IMPORTS start --- - import compiler.lib.ir_framework.*; - """, - imports.stream().map(i -> "import " + i + ";\n").toList(), - """ - // --- IMPORTS end --- - public class #className { - // --- CLASS_HOOK insertions start --- - """, - Hooks.CLASS_HOOK.anchor( - """ - // --- CLASS_HOOK insertions end --- - public static void main(String[] vmFlags) { - TestFramework framework = new TestFramework(#className.class); - framework.addFlags("-classpath", "#classpath"); - framework.addFlags(vmFlags); - framework.start(); - } - // --- LIST OF TESTS start --- - """, - testTemplateTokens - ), - """ - // --- LIST OF TESTS end --- - } - """ - )); - return template.render(); - } -} From ff76272695ea0f8562cde57c589e50e9c11aa664 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 11:25:55 +0200 Subject: [PATCH 10/15] rm previous changes --- .../jtreg/compiler/lib/template_framework/Hook.java | 8 ++++---- .../compiler/lib/template_framework/Template.java | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java index 88a6031061cf5..48f7852d5098a 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java @@ -72,9 +72,9 @@ public record Hook(String name) { * {@link #insert}ed back to the location where this {@link Hook} was {@link #anchor}ed. * * @param tokens A list of tokens, which have the same restrictions as {@link Template#body}. - * @return A token that captures the anchoring of the scope and the list of validated tokens. + * @return A {@link Token} that captures the anchoring of the scope and the list of validated {@link Token}s. */ - public Object anchor(Object... tokens) { + public Token anchor(Object... tokens) { return new HookAnchorToken(this, Token.parse(tokens)); } @@ -83,9 +83,9 @@ public Object anchor(Object... tokens) { * This could be in the same Template, or one nested further out. * * @param templateToken The Template with applied arguments to be inserted at the {@link Hook}. - * @return The token which when used inside a {@link Template#body} performs the code insertion into the {@link Hook}. + * @return The {@link Token} which when used inside a {@link Template#body} performs the code insertion into the {@link Hook}. */ - public Object insert(TemplateToken templateToken) { + public Token insert(TemplateToken templateToken) { return new HookInsertToken(this, templateToken); } diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java index 787dc5a655835..f01c5ccffd3d0 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java @@ -662,7 +662,7 @@ static TemplateBody body(Object... tokens) { * inside a {@link Template#body}. * @throws RendererException if there is a duplicate hashtag {@code key}. */ - static Object let(String key, Object value) { + static Token let(String key, Object value) { Renderer.getCurrent().addHashtagReplacement(key, value); return new NothingToken(); } @@ -747,7 +747,7 @@ static float fuel() { * @param fuelCost The amount of fuel used for the current Template. * @return A token for convenient use in {@link Template#body}. */ - static Object setFuelCost(float fuelCost) { + static Token setFuelCost(float fuelCost) { Renderer.getCurrent().setFuelCost(fuelCost); return new NothingToken(); } @@ -766,7 +766,7 @@ static Object setFuelCost(float fuelCost) { * Must be a value from 1 to 1000. * @return The token that performs the defining action. */ - static Object addDataName(String name, DataName.Type type, DataName.Mutability mutability, int weight) { + static Token addDataName(String name, DataName.Type type, DataName.Mutability mutability, int weight) { if (mutability != DataName.Mutability.MUTABLE && mutability != DataName.Mutability.IMMUTABLE) { throw new IllegalArgumentException("Unexpected mutability: " + mutability); @@ -789,7 +789,7 @@ static Object addDataName(String name, DataName.Type type, DataName.Mutability m * or if we also allow it to be mutated. * @return The token that performs the defining action. */ - static Object addDataName(String name, DataName.Type type, DataName.Mutability mutability) { + static Token addDataName(String name, DataName.Type type, DataName.Mutability mutability) { return addDataName(name, type, mutability, 1); } @@ -814,7 +814,7 @@ static DataName.FilteredSet dataNames(DataName.Mutability mutability) { * Must be a value from 1 to 1000. * @return The token that performs the defining action. */ - static Object addStructuralName(String name, StructuralName.Type type, int weight) { + static Token addStructuralName(String name, StructuralName.Type type, int weight) { if (weight <= 0 || 1000 < weight) { throw new IllegalArgumentException("Unexpected weight: " + weight); } @@ -829,7 +829,7 @@ static Object addStructuralName(String name, StructuralName.Type type, int weigh * @param type The type of the {@link StructuralName}. * @return The token that performs the defining action. */ - static Object addStructuralName(String name, StructuralName.Type type) { + static Token addStructuralName(String name, StructuralName.Type type) { return addStructuralName(name, type, 1); } From 08b9f674ac7bf7511492a22183746aaf866563d3 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 12:21:18 +0200 Subject: [PATCH 11/15] parser refactor --- .../compiler/lib/template_framework/Hook.java | 2 +- .../lib/template_framework/Template.java | 2 +- .../lib/template_framework/Token.java | 41 +---------- .../lib/template_framework/TokenParser.java | 71 +++++++++++++++++++ 4 files changed, 76 insertions(+), 40 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java index 48f7852d5098a..8ee2689eb2fce 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java @@ -75,7 +75,7 @@ public record Hook(String name) { * @return A {@link Token} that captures the anchoring of the scope and the list of validated {@link Token}s. */ public Token anchor(Object... tokens) { - return new HookAnchorToken(this, Token.parse(tokens)); + return new HookAnchorToken(this, TokenParser.parse(tokens)); } /** diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java index f01c5ccffd3d0..57d06e732bb1f 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java @@ -615,7 +615,7 @@ static Template.ThreeArgs make(String arg1Name, String * @throws IllegalArgumentException if the list of tokens contains an unexpected object. */ static TemplateBody body(Object... tokens) { - return new TemplateBody(Token.parse(tokens)); + return new TemplateBody(TokenParser.parse(tokens)); } /** diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Token.java b/test/hotspot/jtreg/compiler/lib/template_framework/Token.java index dc750c7f79f33..10fb85be1c893 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Token.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Token.java @@ -29,11 +29,9 @@ /** * The {@link Template#body} and {@link Hook#anchor} are given a list of tokens, which are either - * {@link Token}s or {@link String}s or some permitted boxed primitives. These are then parsed - * and all non-{@link Token}s are converted to {@link StringToken}s. The parsing also flattens - * {@link List}s. + * {@link Token}s or {@link String}s or some permitted boxed primitives. */ -sealed interface Token permits StringToken, +public sealed interface Token permits StringToken, TemplateToken, TemplateToken.ZeroArgs, TemplateToken.OneArg, @@ -42,37 +40,4 @@ sealed interface Token permits StringToken, HookAnchorToken, HookInsertToken, AddNameToken, - NothingToken -{ - static List parse(Object[] objects) { - if (objects == null) { - throw new IllegalArgumentException("Unexpected tokens: null"); - } - List outputList = new ArrayList<>(); - parseToken(Arrays.asList(objects), outputList); - return outputList; - } - - private static void parseList(List inputList, List outputList) { - for (Object o : inputList) { - parseToken(o, outputList); - } - } - - private static void parseToken(Object o, List outputList) { - if (o == null) { - throw new IllegalArgumentException("Unexpected token: null"); - } - switch (o) { - case Token t -> outputList.add(t); - case String s -> outputList.add(new StringToken(Renderer.format(s))); - case Integer s -> outputList.add(new StringToken(Renderer.format(s))); - case Long s -> outputList.add(new StringToken(Renderer.format(s))); - case Double s -> outputList.add(new StringToken(Renderer.format(s))); - case Float s -> outputList.add(new StringToken(Renderer.format(s))); - case Boolean s -> outputList.add(new StringToken(Renderer.format(s))); - case List l -> parseList(l, outputList); - default -> throw new IllegalArgumentException("Unexpected token: " + o); - } - } -} + NothingToken {} diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java b/test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java new file mode 100644 index 0000000000000..0c335bd4fb89e --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025, 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.template_framework; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; + +/** + * Helper class for {@link Token}, to keep the parsing methods package private. + * + *

+ * The {@link Template#body} and {@link Hook#anchor} are given a list of tokens, which are either + * {@link Token}s or {@link String}s or some permitted boxed primitives. These are then parsed + * and all non-{@link Token}s are converted to {@link StringToken}s. The parsing also flattens + * {@link List}s. + */ +final class TokenParser { + static List parse(Object[] objects) { + if (objects == null) { + throw new IllegalArgumentException("Unexpected tokens: null"); + } + List outputList = new ArrayList<>(); + parseToken(Arrays.asList(objects), outputList); + return outputList; + } + + private static void parseList(List inputList, List outputList) { + for (Object o : inputList) { + parseToken(o, outputList); + } + } + + private static void parseToken(Object o, List outputList) { + if (o == null) { + throw new IllegalArgumentException("Unexpected token: null"); + } + switch (o) { + case Token t -> outputList.add(t); + case String s -> outputList.add(new StringToken(Renderer.format(s))); + case Integer s -> outputList.add(new StringToken(Renderer.format(s))); + case Long s -> outputList.add(new StringToken(Renderer.format(s))); + case Double s -> outputList.add(new StringToken(Renderer.format(s))); + case Float s -> outputList.add(new StringToken(Renderer.format(s))); + case Boolean s -> outputList.add(new StringToken(Renderer.format(s))); + case List l -> parseList(l, outputList); + default -> throw new IllegalArgumentException("Unexpected token: " + o); + } + } +} From 2deca27fbfe62cf7243260e6d2334be56d4bd96e Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 11:13:28 +0000 Subject: [PATCH 12/15] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christian Hagedorn Co-authored-by: Manuel Hässig --- .../library/CodeGenerationDataNameType.java | 2 +- .../library/PrimitiveType.java | 37 +++++++------------ 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java index 957c5b7a7c8cd..aa1158b9f2809 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -32,7 +32,7 @@ * The {@link CodeGenerationDataNameType} extends the {@link DataName.Type} with * additional functionality for code generation. These types with their extended * functionality can be used with many other code generation facilities in the - * lbrary, such as generating random {@code Expression}s. + * library, such as generating random {@code Expression}s. */ public interface CodeGenerationDataNameType extends DataName.Type { diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java index fee214a1d6eff..3bf6c7f62886e 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java @@ -49,7 +49,7 @@ public final class PrimitiveType implements CodeGenerationDataNameType { private static enum Kind { BYTE, SHORT, CHAR, INT, LONG, FLOAT, DOUBLE, BOOLEAN }; - // We have one static instance each, so we do not have duplicat instances. + // We have one static instance each, so we do not have duplicated instances. static final PrimitiveType BYTES = new PrimitiveType(Kind.BYTE ); static final PrimitiveType SHORTS = new PrimitiveType(Kind.SHORT ); static final PrimitiveType CHARS = new PrimitiveType(Kind.CHAR ); @@ -73,7 +73,7 @@ public boolean isSubtypeOf(DataName.Type other) { @Override public String name() { - return switch(kind) { + return switch (kind) { case BYTE -> "byte"; case SHORT -> "short"; case CHAR -> "char"; @@ -91,7 +91,7 @@ public String toString() { } public Object con() { - return switch(kind) { + return switch (kind) { case BYTE -> "(byte)" + GEN_BYTE.next(); case SHORT -> "(short)" + GEN_SHORT.next(); case CHAR -> "(char)" + GEN_CHAR.next(); @@ -99,7 +99,7 @@ public Object con() { case LONG -> GEN_LONG.next(); case FLOAT -> GEN_FLOAT.next(); case DOUBLE -> GEN_DOUBLE.next(); - case BOOLEAN -> RANDOM.nextInt() % 2 == 0; + case BOOLEAN -> RANDOM.nextBoolean(); }; } @@ -110,14 +110,11 @@ public Object con() { * @throws UnsupportedOperationException for boolean which has no defined size. */ public int byteSize() { - return switch(kind) { + return switch (kind) { case BYTE -> 1; - case SHORT -> 2; - case CHAR -> 2; - case INT -> 4; - case LONG -> 8; - case FLOAT -> 4; - case DOUBLE -> 8; + case SHORT, CHAR -> 2; + case INT, FLOAT -> 4; + case LONG, DOUBLE -> 8; case BOOLEAN -> { throw new UnsupportedOperationException("boolean does not have a defined 'size'"); } }; } @@ -128,7 +125,7 @@ public int byteSize() { * @return the name of the boxed type. */ public String boxedTypeName() { - return switch(kind) { + return switch (kind) { case BYTE -> "Byte"; case SHORT -> "Short"; case CHAR -> "Character"; @@ -141,20 +138,14 @@ public String boxedTypeName() { } /** - * Indicates if the type is a floating type. + * Indicates if the type is a floating point type. * - * @return true iff the type is a floating type. + * @return true iff the type is a floating point type. */ public boolean isFloating() { - return switch(kind) { - case BYTE -> false; - case SHORT -> false; - case CHAR -> false; - case INT -> false; - case LONG -> false; - case FLOAT -> true; - case DOUBLE -> true; - case BOOLEAN -> false; + return switch (kind) { + case BYTE, SHORT, CHAR, INT, LONG, BOOLEAN -> false; + case FLOAT, DOUBLE -> true; }; } } From 4c8d631296bb5e2e0b955973208454525bc14860 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 11:15:46 +0000 Subject: [PATCH 13/15] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christian Hagedorn Co-authored-by: Manuel Hässig --- .../examples/TestPrimitiveTypes.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java index 8bf2860b570a7..5cd3f3c2a226b 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -39,7 +39,6 @@ import java.util.HashMap; import compiler.lib.compile_framework.*; -import compiler.lib.template_framework.DataName; import compiler.lib.template_framework.Template; import compiler.lib.template_framework.TemplateToken; import static compiler.lib.template_framework.Template.body; @@ -47,7 +46,6 @@ import static compiler.lib.template_framework.Template.let; import static compiler.lib.template_framework.Template.$; import static compiler.lib.template_framework.Template.addDataName; -import static compiler.lib.template_framework.Template.dataNames; import static compiler.lib.template_framework.DataName.Mutability.MUTABLE; import compiler.lib.template_framework.library.Hooks; @@ -73,10 +71,10 @@ public static void main(String[] args) { comp.invoke("p.xyz.InnerTest", "main", new Object[] {}); } - // Generate a source Java file as String + // Generate a Java source file as String public static String generate() { // Generate a list of test methods. - Map tests = new HashMap<>(); + Map tests = new HashMap<>(); // The boxing tests check if we can autobox with "boxedTypeName". var boxingTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( @@ -161,9 +159,7 @@ public static void test_names() { // Now sample: """, Collections.nCopies(10, - CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(type -> - sampleTemplate.asToken(type) - ).toList() + CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(sampleTemplate::asToken).toList() ) ), """ From a1c84e803ad8d266cb543fd1fc8d73e20f07bba9 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 13:20:01 +0200 Subject: [PATCH 14/15] review suggestions applied --- .../lib/template_framework/Token.java | 4 --- .../library/CodeGenerationDataNameType.java | 28 +++++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Token.java b/test/hotspot/jtreg/compiler/lib/template_framework/Token.java index 10fb85be1c893..0e9f9b272c54f 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Token.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Token.java @@ -23,10 +23,6 @@ package compiler.lib.template_framework; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.List; - /** * The {@link Template#body} and {@link Hook#anchor} are given a list of tokens, which are either * {@link Token}s or {@link String}s or some permitted boxed primitives. diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java index aa1158b9f2809..d5eb6664cbb2e 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -42,68 +42,68 @@ public interface CodeGenerationDataNameType extends DataName.Type { * * @return A random constant value. */ - public Object con(); + Object con(); /** * The byte {@link PrimitiveType}. * * @return The byte {@link PrimitiveType}. */ - public static PrimitiveType bytes() { return PrimitiveType.BYTES; } + static PrimitiveType bytes() { return PrimitiveType.BYTES; } /** * The short {@link PrimitiveType}. * * @return The short {@link PrimitiveType}. */ - public static PrimitiveType shorts() { return PrimitiveType.SHORTS; } + static PrimitiveType shorts() { return PrimitiveType.SHORTS; } /** * The char {@link PrimitiveType}. * * @return The char {@link PrimitiveType}. */ - public static PrimitiveType chars() { return PrimitiveType.CHARS; } + static PrimitiveType chars() { return PrimitiveType.CHARS; } /** * The int {@link PrimitiveType}. * * @return The int {@link PrimitiveType}. */ - public static PrimitiveType ints() { return PrimitiveType.INTS; } + static PrimitiveType ints() { return PrimitiveType.INTS; } /** * The long {@link PrimitiveType}. * * @return The long {@link PrimitiveType}. */ - public static PrimitiveType longs() { return PrimitiveType.LONGS; } + static PrimitiveType longs() { return PrimitiveType.LONGS; } /** * The float {@link PrimitiveType}. * * @return The float {@link PrimitiveType}. */ - public static PrimitiveType floats() { return PrimitiveType.FLOATS; } + static PrimitiveType floats() { return PrimitiveType.FLOATS; } /** * The double {@link PrimitiveType}. * * @return The double {@link PrimitiveType}. */ - public static PrimitiveType doubles() { return PrimitiveType.DOUBLES; } + static PrimitiveType doubles() { return PrimitiveType.DOUBLES; } /** * The boolean {@link PrimitiveType}. * * @return The boolean {@link PrimitiveType}. */ - public static PrimitiveType booleans() { return PrimitiveType.BOOLEANS; } + static PrimitiveType booleans() { return PrimitiveType.BOOLEANS; } /** * List of all {@link PrimitiveType}s. */ - public static final List PRIMITIVE_TYPES = List.of( + static final List PRIMITIVE_TYPES = List.of( bytes(), chars(), shorts(), @@ -117,7 +117,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all integral {@link PrimitiveType}s (byte, char, short, int, long). */ - public static final List INTEGRAL_TYPES = List.of( + static final List INTEGRAL_TYPES = List.of( bytes(), chars(), shorts(), @@ -128,7 +128,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all subword {@link PrimitiveType}s (byte, char, short). */ - public static final List SUBWORD_TYPES = List.of( + static final List SUBWORD_TYPES = List.of( bytes(), chars(), shorts() @@ -137,7 +137,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all floating {@link PrimitiveType}s (float, double). */ - public static final List FLOATING_TYPES = List.of( + static final List FLOATING_TYPES = List.of( floats(), doubles() ); @@ -145,7 +145,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all integral and floating {@link PrimitiveType}s. */ - public static final List INTEGRAL_AND_FLOATING_TYPES = List.of( + static final List INTEGRAL_AND_FLOATING_TYPES = List.of( bytes(), chars(), shorts(), From c39d4d6fa7e3edfdb71158829d4cbd949d49a07a Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 13:36:25 +0200 Subject: [PATCH 15/15] rm static final --- .../library/CodeGenerationDataNameType.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java index d5eb6664cbb2e..56f7afcbaeb9f 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -103,7 +103,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all {@link PrimitiveType}s. */ - static final List PRIMITIVE_TYPES = List.of( + List PRIMITIVE_TYPES = List.of( bytes(), chars(), shorts(), @@ -117,7 +117,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all integral {@link PrimitiveType}s (byte, char, short, int, long). */ - static final List INTEGRAL_TYPES = List.of( + List INTEGRAL_TYPES = List.of( bytes(), chars(), shorts(), @@ -128,7 +128,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all subword {@link PrimitiveType}s (byte, char, short). */ - static final List SUBWORD_TYPES = List.of( + List SUBWORD_TYPES = List.of( bytes(), chars(), shorts() @@ -137,7 +137,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all floating {@link PrimitiveType}s (float, double). */ - static final List FLOATING_TYPES = List.of( + List FLOATING_TYPES = List.of( floats(), doubles() ); @@ -145,7 +145,7 @@ public interface CodeGenerationDataNameType extends DataName.Type { /** * List of all integral and floating {@link PrimitiveType}s. */ - static final List INTEGRAL_AND_FLOATING_TYPES = List.of( + List INTEGRAL_AND_FLOATING_TYPES = List.of( bytes(), chars(), shorts(),