Skip to content

Commit 166784d

Browse files
committed
GROOVY-11872: SC: propagate STATIC_COMPILE_NODE metadata in Verifier
1 parent a2a7da6 commit 166784d

File tree

2 files changed

+117
-51
lines changed

2 files changed

+117
-51
lines changed

src/main/java/org/codehaus/groovy/classgen/Verifier.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@
124124
import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
125125
import static org.codehaus.groovy.ast.tools.GenericsUtils.parameterizeType;
126126
import static org.codehaus.groovy.ast.tools.PropertyNodeUtils.adjustPropertyModifiersForMethod;
127+
import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.STATIC_COMPILE_NODE;
128+
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
127129

128130
/**
129131
* Verifies the AST node and adds any default AST code before bytecode generation occurs.
@@ -1020,6 +1022,7 @@ public void visitConstructorCallExpression(final ConstructorCallExpression call)
10201022

10211023
addPropertyMethod(newMethod);
10221024
newMethod.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
1025+
newMethod.putNodeMetaData(STATIC_COMPILE_NODE, method.getNodeMetaData(STATIC_COMPILE_NODE));
10231026
});
10241027
}
10251028

@@ -1064,7 +1067,9 @@ public void visitVariableExpression(final VariableExpression e) {
10641067
ConstructorNode old = type.getDeclaredConstructor(params);
10651068
if (old == null || isGenerated(old)) { type.removeConstructor(old);
10661069
// delegate to original constructor using arguments derived from defaults
1067-
addConstructor(params, (ConstructorNode) method, stmt(ctorThisX(arguments)), type);
1070+
ConstructorCallExpression call = ctorThisX(arguments);
1071+
call.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, method);
1072+
addConstructor(params, (ConstructorNode) method, stmt(call), type);
10681073
} else {
10691074
String warning = "Default argument(s) specify duplicate constructor: " +
10701075
MethodNodeUtils.methodDescriptor(old,true).replace("<init>",type.getNameWithoutPackage());
@@ -1075,6 +1080,7 @@ public void visitVariableExpression(final VariableExpression e) {
10751080

10761081
protected void addConstructor(final Parameter[] newParams, final ConstructorNode ctor, final Statement code, final ClassNode type) {
10771082
ConstructorNode newConstructor = type.addConstructor(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
1083+
newConstructor.putNodeMetaData(STATIC_COMPILE_NODE, ctor.getNodeMetaData(STATIC_COMPILE_NODE));
10781084
newConstructor.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
10791085
markAsGenerated(type, newConstructor);
10801086
// TODO: Copy annotations, etc.?

src/test/groovy/org/codehaus/groovy/classgen/asm/sc/CombinedIndyAndStaticCompilationTest.groovy

Lines changed: 110 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,73 +20,133 @@ package org.codehaus.groovy.classgen.asm.sc
2020

2121
import org.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase
2222
import org.junit.jupiter.api.Test
23+
import org.junit.jupiter.params.ParameterizedTest
24+
import org.junit.jupiter.params.provider.ValueSource
2325

2426
import static org.codehaus.groovy.control.CompilerConfiguration.DEFAULT as config
2527
import static org.junit.jupiter.api.Assumptions.assumeTrue
2628

2729
/**
28-
* Tests for combined static compilation and indy code
30+
* Tests for combined static compilation and indy code.
2931
*/
3032
final class CombinedIndyAndStaticCompilationTest extends AbstractBytecodeTestCase {
3133

34+
@ParameterizedTest
35+
@ValueSource(strings=['byte','short','int','long','float','double','boolean','char'])
36+
void testArrayRead(String type) {
37+
assumeTrue config.indyEnabled
38+
39+
def bytecode = compile method:'test', """
40+
@groovy.transform.CompileStatic
41+
void test() {
42+
${type}[] array = new ${type}[10]
43+
${type} x = array[0]
44+
}
45+
"""
46+
int offset = bytecode.indexOf('--BEGIN--') + 4
47+
assert bytecode.indexOf('INVOKEDYNAMIC', offset) > offset
48+
assert bytecode.indexOf('INVOKEDYNAMIC', offset) < bytecode.indexOf('--END--')
49+
}
50+
51+
@ParameterizedTest
52+
@ValueSource(strings=['byte','short','int','long','float','double','boolean','char'])
53+
void testArrayWrite(String type) {
54+
assumeTrue config.indyEnabled
55+
56+
def bytecode = compile method:'test', """
57+
@groovy.transform.CompileStatic
58+
void test() {
59+
${type}[] array = new ${type}[10]
60+
array[0] = 1
61+
}
62+
"""
63+
int offset = bytecode.indexOf('--BEGIN--') + 4
64+
assert bytecode.indexOf('INVOKEDYNAMIC', offset) > offset
65+
assert bytecode.indexOf('INVOKEDYNAMIC', offset) < bytecode.indexOf('--END--')
66+
}
67+
68+
@ParameterizedTest
69+
@ValueSource(strings=['byte','short','int','long','float','double','char'])
70+
void testNegativeIndex(String type) {
71+
assertScript """
72+
@groovy.transform.CompileStatic
73+
void test() {
74+
${type}[] array = [0,1,2]
75+
assert array[0] == 0
76+
assert array[1] == 1
77+
assert array[2] == 2
78+
assert array[-1] == 2
79+
assert array[-2] == 1
80+
array[0] = 9
81+
assert array[0] == 9
82+
array[-1] = 8
83+
assert array[2] == 8
84+
}
85+
test()
86+
"""
87+
}
88+
89+
@Test
90+
void testNegativeIndexPrimitiveBoolean() {
91+
assertScript '''
92+
@groovy.transform.CompileStatic
93+
void test() {
94+
boolean[] array = [false, false, true]
95+
assert array[0] == false
96+
assert array[1] == false
97+
assert array[2] == true
98+
assert array[-1] == true
99+
assert array[-2] == false
100+
array[0] = true
101+
assert array[0] == true
102+
array[-1] = false
103+
assert array[2] == false
104+
}
105+
test()
106+
'''
107+
}
108+
109+
// GROOVY-11872
32110
@Test
33-
void testArrayAccess() {
34-
assumeTrue(config.indyEnabled)
35-
["byte", "short", "int", "long", "float", "double", "boolean", "char"].each { type->
36-
//array get
37-
compile ("""
111+
void testCompileStaticAndMethodWithDefaultParameter() {
112+
def bytecode = compile '''
113+
class Foo {
38114
@groovy.transform.CompileStatic
39-
def foo() {
40-
${type}[] array = new ${type}[10]
41-
$type x = array[0]
115+
void bar(List list = baz()) {
116+
for (item in list) {
117+
println item
118+
}
42119
}
43-
""").hasSequence(["INVOKEDYNAMIC"])
44-
//array set
45-
compile ("""
46-
@groovy.transform.CompileStatic
47-
def foo() {
48-
${type}[] array = new ${type}[10]
49-
array[0] = 1
120+
List baz() {
121+
['fizz','buzz']
50122
}
51-
""").hasSequence(["INVOKEDYNAMIC"])
52-
}
123+
}
124+
'''
125+
int offset = bytecode.indexOf('public bar()')
126+
assert bytecode.indexOf('INVOKEDYNAMIC', offset) < 0
127+
assert bytecode.indexOf('INVOKEVIRTUAL', offset) > offset
128+
assert bytecode.indexOf('INVOKEVIRTUAL', offset) < bytecode.indexOf('RETURN', offset)
53129
}
54130

131+
// GROOVY-11872
55132
@Test
56-
void testNegativeAccess() {
57-
["byte", "short", "int", "long", "float", "double", "char"].each { type ->
58-
assertScript """
133+
void testCompileStaticAndConstructorWithDefaultParameter() {
134+
def bytecode = compile '''
135+
class Foo {
59136
@groovy.transform.CompileStatic
60-
def foo() {
61-
${type}[] array = [0,1,2]
62-
assert array[0] == 0
63-
assert array[1] == 1
64-
assert array[2] == 2
65-
assert array[-1] == 2
66-
assert array[-2] == 1
67-
array[0] = 9
68-
assert array[0] == 9
69-
array[-1] = 8
70-
assert array[2] == 8
137+
Foo(List list = bar()) {
138+
for (item in list) {
139+
println item
140+
}
71141
}
72-
foo()
73-
"""
74-
}
75-
assertScript """
76-
@groovy.transform.CompileStatic
77-
def foo() {
78-
boolean[] array = [false, false, true]
79-
assert array[0] == false
80-
assert array[1] == false
81-
assert array[2] == true
82-
assert array[-1] == true
83-
assert array[-2] == false
84-
array[0] = true
85-
assert array[0] == true
86-
array[-1] = false
87-
assert array[2] == false
142+
static List bar() {
143+
['fizz','buzz']
88144
}
89-
foo()
90-
"""
145+
}
146+
'''
147+
int offset = bytecode.indexOf('public <init>()')
148+
assert bytecode.indexOf('INVOKEDYNAMIC', offset) < 0
149+
assert bytecode.indexOf('INVOKESTATIC ', offset) > offset
150+
assert bytecode.indexOf('INVOKESTATIC ', offset) < bytecode.indexOf('RETURN', offset)
91151
}
92152
}

0 commit comments

Comments
 (0)