This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 166784dddf GROOVY-11872: SC: propagate `STATIC_COMPILE_NODE` metadata
in `Verifier`
166784dddf is described below
commit 166784dddf521f21c26d04a338dbc52040b4da8a
Author: Eric Milles <[email protected]>
AuthorDate: Wed Mar 11 10:39:35 2026 -0500
GROOVY-11872: SC: propagate `STATIC_COMPILE_NODE` metadata in `Verifier`
---
.../org/codehaus/groovy/classgen/Verifier.java | 8 +-
.../sc/CombinedIndyAndStaticCompilationTest.groovy | 160 ++++++++++++++-------
2 files changed, 117 insertions(+), 51 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 9f1d13c74e..4300c57743 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -124,6 +124,8 @@ import static
org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
import static org.codehaus.groovy.ast.tools.GenericsUtils.parameterizeType;
import static
org.codehaus.groovy.ast.tools.PropertyNodeUtils.adjustPropertyModifiersForMethod;
+import static
org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.STATIC_COMPILE_NODE;
+import static
org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
/**
* Verifies the AST node and adds any default AST code before bytecode
generation occurs.
@@ -1020,6 +1022,7 @@ public class Verifier implements GroovyClassVisitor,
Opcodes {
addPropertyMethod(newMethod);
newMethod.putNodeMetaData(DEFAULT_PARAMETER_GENERATED,
Boolean.TRUE);
+ newMethod.putNodeMetaData(STATIC_COMPILE_NODE,
method.getNodeMetaData(STATIC_COMPILE_NODE));
});
}
@@ -1064,7 +1067,9 @@ public class Verifier implements GroovyClassVisitor,
Opcodes {
ConstructorNode old = type.getDeclaredConstructor(params);
if (old == null || isGenerated(old)) { type.removeConstructor(old);
// delegate to original constructor using arguments derived
from defaults
- addConstructor(params, (ConstructorNode) method,
stmt(ctorThisX(arguments)), type);
+ ConstructorCallExpression call = ctorThisX(arguments);
+ call.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, method);
+ addConstructor(params, (ConstructorNode) method, stmt(call),
type);
} else {
String warning = "Default argument(s) specify duplicate
constructor: " +
MethodNodeUtils.methodDescriptor(old,true).replace("<init>",type.getNameWithoutPackage());
@@ -1075,6 +1080,7 @@ public class Verifier implements GroovyClassVisitor,
Opcodes {
protected void addConstructor(final Parameter[] newParams, final
ConstructorNode ctor, final Statement code, final ClassNode type) {
ConstructorNode newConstructor =
type.addConstructor(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
+ newConstructor.putNodeMetaData(STATIC_COMPILE_NODE,
ctor.getNodeMetaData(STATIC_COMPILE_NODE));
newConstructor.putNodeMetaData(DEFAULT_PARAMETER_GENERATED,
Boolean.TRUE);
markAsGenerated(type, newConstructor);
// TODO: Copy annotations, etc.?
diff --git
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CombinedIndyAndStaticCompilationTest.groovy
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CombinedIndyAndStaticCompilationTest.groovy
index def803299d..ffdc43183b 100644
---
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CombinedIndyAndStaticCompilationTest.groovy
+++
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CombinedIndyAndStaticCompilationTest.groovy
@@ -20,73 +20,133 @@ package org.codehaus.groovy.classgen.asm.sc
import org.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase
import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
import static org.codehaus.groovy.control.CompilerConfiguration.DEFAULT as
config
import static org.junit.jupiter.api.Assumptions.assumeTrue
/**
- * Tests for combined static compilation and indy code
+ * Tests for combined static compilation and indy code.
*/
final class CombinedIndyAndStaticCompilationTest extends
AbstractBytecodeTestCase {
+ @ParameterizedTest
+
@ValueSource(strings=['byte','short','int','long','float','double','boolean','char'])
+ void testArrayRead(String type) {
+ assumeTrue config.indyEnabled
+
+ def bytecode = compile method:'test', """
+ @groovy.transform.CompileStatic
+ void test() {
+ ${type}[] array = new ${type}[10]
+ ${type} x = array[0]
+ }
+ """
+ int offset = bytecode.indexOf('--BEGIN--') + 4
+ assert bytecode.indexOf('INVOKEDYNAMIC', offset) > offset
+ assert bytecode.indexOf('INVOKEDYNAMIC', offset) <
bytecode.indexOf('--END--')
+ }
+
+ @ParameterizedTest
+
@ValueSource(strings=['byte','short','int','long','float','double','boolean','char'])
+ void testArrayWrite(String type) {
+ assumeTrue config.indyEnabled
+
+ def bytecode = compile method:'test', """
+ @groovy.transform.CompileStatic
+ void test() {
+ ${type}[] array = new ${type}[10]
+ array[0] = 1
+ }
+ """
+ int offset = bytecode.indexOf('--BEGIN--') + 4
+ assert bytecode.indexOf('INVOKEDYNAMIC', offset) > offset
+ assert bytecode.indexOf('INVOKEDYNAMIC', offset) <
bytecode.indexOf('--END--')
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings=['byte','short','int','long','float','double','char'])
+ void testNegativeIndex(String type) {
+ assertScript """
+ @groovy.transform.CompileStatic
+ void test() {
+ ${type}[] array = [0,1,2]
+ assert array[0] == 0
+ assert array[1] == 1
+ assert array[2] == 2
+ assert array[-1] == 2
+ assert array[-2] == 1
+ array[0] = 9
+ assert array[0] == 9
+ array[-1] = 8
+ assert array[2] == 8
+ }
+ test()
+ """
+ }
+
+ @Test
+ void testNegativeIndexPrimitiveBoolean() {
+ assertScript '''
+ @groovy.transform.CompileStatic
+ void test() {
+ boolean[] array = [false, false, true]
+ assert array[0] == false
+ assert array[1] == false
+ assert array[2] == true
+ assert array[-1] == true
+ assert array[-2] == false
+ array[0] = true
+ assert array[0] == true
+ array[-1] = false
+ assert array[2] == false
+ }
+ test()
+ '''
+ }
+
+ // GROOVY-11872
@Test
- void testArrayAccess() {
- assumeTrue(config.indyEnabled)
- ["byte", "short", "int", "long", "float", "double", "boolean",
"char"].each { type->
- //array get
- compile ("""
+ void testCompileStaticAndMethodWithDefaultParameter() {
+ def bytecode = compile '''
+ class Foo {
@groovy.transform.CompileStatic
- def foo() {
- ${type}[] array = new ${type}[10]
- $type x = array[0]
+ void bar(List list = baz()) {
+ for (item in list) {
+ println item
+ }
}
- """).hasSequence(["INVOKEDYNAMIC"])
- //array set
- compile ("""
- @groovy.transform.CompileStatic
- def foo() {
- ${type}[] array = new ${type}[10]
- array[0] = 1
+ List baz() {
+ ['fizz','buzz']
}
- """).hasSequence(["INVOKEDYNAMIC"])
- }
+ }
+ '''
+ int offset = bytecode.indexOf('public bar()')
+ assert bytecode.indexOf('INVOKEDYNAMIC', offset) < 0
+ assert bytecode.indexOf('INVOKEVIRTUAL', offset) > offset
+ assert bytecode.indexOf('INVOKEVIRTUAL', offset) <
bytecode.indexOf('RETURN', offset)
}
+ // GROOVY-11872
@Test
- void testNegativeAccess() {
- ["byte", "short", "int", "long", "float", "double", "char"].each {
type ->
- assertScript """
+ void testCompileStaticAndConstructorWithDefaultParameter() {
+ def bytecode = compile '''
+ class Foo {
@groovy.transform.CompileStatic
- def foo() {
- ${type}[] array = [0,1,2]
- assert array[0] == 0
- assert array[1] == 1
- assert array[2] == 2
- assert array[-1] == 2
- assert array[-2] == 1
- array[0] = 9
- assert array[0] == 9
- array[-1] = 8
- assert array[2] == 8
+ Foo(List list = bar()) {
+ for (item in list) {
+ println item
+ }
}
- foo()
- """
- }
- assertScript """
- @groovy.transform.CompileStatic
- def foo() {
- boolean[] array = [false, false, true]
- assert array[0] == false
- assert array[1] == false
- assert array[2] == true
- assert array[-1] == true
- assert array[-2] == false
- array[0] = true
- assert array[0] == true
- array[-1] = false
- assert array[2] == false
+ static List bar() {
+ ['fizz','buzz']
}
- foo()
- """
+ }
+ '''
+ int offset = bytecode.indexOf('public <init>()')
+ assert bytecode.indexOf('INVOKEDYNAMIC', offset) < 0
+ assert bytecode.indexOf('INVOKESTATIC ', offset) > offset
+ assert bytecode.indexOf('INVOKESTATIC ', offset) <
bytecode.indexOf('RETURN', offset)
}
}