-
Bug
-
Resolution: Duplicate
-
P3
-
None
-
7u65
-
x86_64
-
linux
FULL PRODUCT VERSION :
FULL OS VERSION :
Linux ccvmware 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
The static compiler of Groovy generates bytecode which runs perfectly fine if the target bytecode level is set to JDK 6, but the 7+ verifier fails.
The problem is highlighted in https://jira.codehaus.org/browse/GROOVY-6946
Code like this:
class A {
Long id
}
class Foo {
List<Long> ids
Foo(List<Long> ids) { this.ids = ids }
}
def list = [new A(id:1), new A(id:2)]
new Foo(list.id)
uses an optimized path to expand "list.ids" into an ArrayList containing the "id" property of each element. The generated bytecode runs fine if we set the bytecode level to 6, but fails with 7+ with:
Uninitialized object exists on backward branch.
This is likely a duplicate of https://bugs.openjdk.java.net/browse/JDK-8046233 but it's actually critical for us as existing code already produces this bytecode.
I think the bytecode we produce is correct. An example can be found here: http://pastebin.com/raw.php?i=A96D1WRS
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try
REGRESSION. Last worked in version 6u45
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Write this into test.groovy:
---
import org.codehaus.groovy.control.CompilerConfiguration
def config = new CompilerConfiguration()
config.targetBytecode = '1.7'
def shell = new GroovyShell(config)
shell.evaluate '''
class A { String id }
@groovy.transform.CompileStatic
void bug(List<A> response) {
println "${response.id}"
}
bug([])
'''
---
then run the script using:
groovy test.groovy
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Caught: java.lang.VerifyError: Uninitialized object exists on backward branch 32
Exception Details:
Location:
Script1.bug(Ljava/util/List;)V @64: goto
Reason:
Error exists in the bytecode
Bytecode:
0000000: 2abb 0041 5904 bd00 1b59 03bb 0043 592b
0000010: b900 4901 00b7 004c 4d2b b900 5001 004e
0000020: 2db9 0056 0100 9900 1d2d b900 5901 00c0
0000030: 005b 3a04 2c19 04b6 005f b900 6302 0057
0000040: a7ff e02c 5305 bd00 6559 0312 6753 5904
0000050: 1267 53b7 006a b600 6e01 57b1
Stackmap Table:
full_frame(@32,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
full_frame(@67,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
java.lang.VerifyError: Uninitialized object exists on backward branch 32
Exception Details:
Location:
Script1.bug(Ljava/util/List;)V @64: goto
Reason:
Error exists in the bytecode
Bytecode:
0000000: 2abb 0041 5904 bd00 1b59 03bb 0043 592b
0000010: b900 4901 00b7 004c 4d2b b900 5001 004e
0000020: 2db9 0056 0100 9900 1d2d b900 5901 00c0
0000030: 005b 3a04 2c19 04b6 005f b900 6302 0057
0000040: a7ff e02c 5305 bd00 6559 0312 6753 5904
0000050: 1267 53b7 006a b600 6e01 57b1
Stackmap Table:
full_frame(@32,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
full_frame(@67,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
at test.run(test.groovy:5)
REPRODUCIBILITY :
This bug can be reproduced always.
CUSTOMER SUBMITTED WORKAROUND :
We could change the way we generate the bytecode to introduce a local variable for each argument of a constructor call. This is unfortunately very complicated (if not impossible) to do this without major changes to the compiler infrastructure, including breakages in the public API.
FULL OS VERSION :
Linux ccvmware 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
The static compiler of Groovy generates bytecode which runs perfectly fine if the target bytecode level is set to JDK 6, but the 7+ verifier fails.
The problem is highlighted in https://jira.codehaus.org/browse/GROOVY-6946
Code like this:
class A {
Long id
}
class Foo {
List<Long> ids
Foo(List<Long> ids) { this.ids = ids }
}
def list = [new A(id:1), new A(id:2)]
new Foo(list.id)
uses an optimized path to expand "list.ids" into an ArrayList containing the "id" property of each element. The generated bytecode runs fine if we set the bytecode level to 6, but fails with 7+ with:
Uninitialized object exists on backward branch.
This is likely a duplicate of https://bugs.openjdk.java.net/browse/JDK-8046233 but it's actually critical for us as existing code already produces this bytecode.
I think the bytecode we produce is correct. An example can be found here: http://pastebin.com/raw.php?i=A96D1WRS
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try
REGRESSION. Last worked in version 6u45
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Write this into test.groovy:
---
import org.codehaus.groovy.control.CompilerConfiguration
def config = new CompilerConfiguration()
config.targetBytecode = '1.7'
def shell = new GroovyShell(config)
shell.evaluate '''
class A { String id }
@groovy.transform.CompileStatic
void bug(List<A> response) {
println "${response.id}"
}
bug([])
'''
---
then run the script using:
groovy test.groovy
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Caught: java.lang.VerifyError: Uninitialized object exists on backward branch 32
Exception Details:
Location:
Script1.bug(Ljava/util/List;)V @64: goto
Reason:
Error exists in the bytecode
Bytecode:
0000000: 2abb 0041 5904 bd00 1b59 03bb 0043 592b
0000010: b900 4901 00b7 004c 4d2b b900 5001 004e
0000020: 2db9 0056 0100 9900 1d2d b900 5901 00c0
0000030: 005b 3a04 2c19 04b6 005f b900 6302 0057
0000040: a7ff e02c 5305 bd00 6559 0312 6753 5904
0000050: 1267 53b7 006a b600 6e01 57b1
Stackmap Table:
full_frame(@32,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
full_frame(@67,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
java.lang.VerifyError: Uninitialized object exists on backward branch 32
Exception Details:
Location:
Script1.bug(Ljava/util/List;)V @64: goto
Reason:
Error exists in the bytecode
Bytecode:
0000000: 2abb 0041 5904 bd00 1b59 03bb 0043 592b
0000010: b900 4901 00b7 004c 4d2b b900 5001 004e
0000020: 2db9 0056 0100 9900 1d2d b900 5901 00c0
0000030: 005b 3a04 2c19 04b6 005f b900 6302 0057
0000040: a7ff e02c 5305 bd00 6559 0312 6753 5904
0000050: 1267 53b7 006a b600 6e01 57b1
Stackmap Table:
full_frame(@32,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
full_frame(@67,{Object[#2],Object[#69],Object[#67],Object[#82]},{Object[#2],Uninitialized[#1],Uninitialized[#1],Object[#114],Object[#114],Integer})
at test.run(test.groovy:5)
REPRODUCIBILITY :
This bug can be reproduced always.
CUSTOMER SUBMITTED WORKAROUND :
We could change the way we generate the bytecode to introduce a local variable for each argument of a constructor call. This is unfortunately very complicated (if not impossible) to do this without major changes to the compiler infrastructure, including breakages in the public API.