Bug 129323
Summary: | ecj produces bad bytecode on x86_64 | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | Gary Benson <gbenson> | ||||||
Component: | gcc | Assignee: | Andrew Haley <aph> | ||||||
Status: | CLOSED RAWHIDE | QA Contact: | |||||||
Severity: | medium | Docs Contact: | |||||||
Priority: | medium | ||||||||
Version: | rawhide | ||||||||
Target Milestone: | --- | ||||||||
Target Release: | --- | ||||||||
Hardware: | x86_64 | ||||||||
OS: | Linux | ||||||||
Whiteboard: | |||||||||
Fixed In Version: | Doc Type: | Bug Fix | |||||||
Doc Text: | Story Points: | --- | |||||||
Clone Of: | Environment: | ||||||||
Last Closed: | 2006-01-24 17:23:09 UTC | Type: | --- | ||||||
Regression: | --- | Mount Type: | --- | ||||||
Documentation: | --- | CRM: | |||||||
Verified Versions: | Category: | --- | |||||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||
Cloudforms Team: | --- | Target Upstream Version: | |||||||
Embargoed: | |||||||||
Attachments: |
|
Description
Gary Benson
2004-08-06 13:42:00 UTC
The tarball was too big to attach to this bug. Replace step one above with 'Download http://people.redhat.com/gbenson/ecj-fail.tar.bz2'. This bug does not occur on i386 boxes. Furthermore, the bug only occurs on x86_64 if the bad class is compiled on x86_64, so it looks like the problem is in the execution of ecj on x86_64. Created attachment 102513 [details]
jcf-dump of the class compiled correctly on i386
Created attachment 102514 [details]
jcf-dump of the class incorrectly compiled on x86_64
The only difference in the compiled classes is at the end of getClearToolCommand(): the x86_64 version has a pair of extra dup instructions. 34 34 ldc #101=<String "/"> 36 36 invokevirtual #117=<Method java.lang.StringBuffer.append...> 39 39 invokevirtual #120=<Method java.lang.StringBuffer.toString...> -- 42 dup 42 43 astore_1 43 44 new #107=<Class java.lang.StringBuffer> 46 47 dup 47 48 aload_1 48 49 invokestatic #111=<Method java.lang.String.valueOf...> 51 52 invokespecial #113=<Method java.lang.StringBuffer.<init>...> 54 55 ldc #16=<String "cleartool"> 56 57 invokevirtual #117=<Method java.lang.StringBuffer.append...> 59 60 invokevirtual #120=<Method java.lang.StringBuffer.toString...> -- 63 dup 62 64 astore_1 63 65 aload_1 64 66 areturn For the record there is no difference between the ecj bytecode generated on i386 and x86_64 machines. The extra dup instruction is coming from here: File org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java: 372: case T_String : 373: codeStream.generateStringAppend(currentScope, this, expression); 374: if (valueRequired) { 375: codeStream.dup(); 376: } 377: codeStream.store(localBinding, false); 378: return; Hi Gary, I dont see a tarball attached to the bug. Does this occur when running ecj as bytecode only (ie ecj in gij) or also when ecj is compiled to native? If it occurs only as bytecode, is the same bytecode being run on both platforms? IIRC there are cases where "gcj -C" will generate different bytecode on i386 vs x86_64. I looked into this a little. Problems like this are very ugly since it is hard to debug interpreted code. I dug around in ecj a little. The extra dup is probably coming from SingleNameReference.generateCompoundAssignment; there is some code in here for String assignments. In this case the "+=" generating incorrect code is a statement expression, so we can be pretty sure that this method is being called (indirectly) from Expression.generateCode(); look for the phrase "expression statement". (See also CompoundAssignment.generateCode()) I added some debugging prints to various methods, and from what I can tell it looks like the "valueRequired" parameter is being set incorrectly. Given that this is passed around and not really mucked with, at the moment I suspect a libffi bug. A simple test case didn't show it though. Here's what my prints show; I added them to CompoundAssignment and SingleNameReference: in generateCode: false type is: org.eclipse.jdt.internal.compiler.ast.SingleNameReference got to generateCompoundAssignment: true value now: true duping in generateCode: false type is: org.eclipse.jdt.internal.compiler.ast.SingleNameReference got to generateCompoundAssignment: true value now: true duping This simple test program shows the bug: public class t { protected final String getClearToolCommand(Object a, Object b, Object c, Object d, int e, int f, boolean x) { return x ? "hi" : "byte"; } public static void main(String[] args) { System.out.println(new t().getClearToolCommand(null, null, null, null, 0, 0, false)); } } For me, on x86-64, with gcc 3.4 from the RH 3.4 branch, this prints "hi" when it should print "byte". If I remove one of the Object or int arguments, it prints the correct answer. This suggests a libffi bug to me. 3.5 doesn't have this problem. So, one solution would be to back-port the 3.5 x86-64 libffi changes to our 3.4 branch. From: Andrew Haley <aph> To: java-patches.org Subject: libffi patch: x86_64 stack args incorrectly aligned Date: Tue, 10 Aug 2004 15:24:02 +0100 Thanks to Gary Benson and Tom tromey for finding this. On the x86_64, we weren't 8-aligning args on the stack that weren't register allocated. I'm not really surprised we never noticed this before, because it requires a lot of method arguments to show the problem. I committed this, and an accompanying test case. Andrew. 2004-08-10 Andrew Haley <aph> * src/x86/ffi64.c (ffi_prep_args ): 8-align all stack arguments. Index: ffi64.c =================================================================== RCS file: /cvs/gcc/gcc/libffi/src/x86/ffi64.c,v retrieving revision 1.6 diff -u -r1.6 ffi64.c --- ffi64.c 21 Jan 2004 06:11:08 -0000 1.6 +++ ffi64.c 10 Aug 2004 13:32:32 -0000 @@ -341,6 +341,8 @@ { /* Pass this argument in memory. */ argp = (void *)ALIGN(argp, (*p_arg)->alignment); + /* Stack arguments are *always* at least 8 byte aligned. */ + argp = (void *)ALIGN(argp, 8); memcpy (argp, *p_argv, (*p_arg)->size); argp += (*p_arg)->size; } 2004-08-10 Andrew Haley <aph> * testsuite/libjava.lang/err14.java: New file. * testsuite/libjava.lang/err14.out: New file. Index: libjava.lang/err14.java =================================================================== RCS file: libjava.lang/err14.java diff -N libjava.lang/err14.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libjava.lang/err14.java 10 Aug 2004 14:18:27 -0000 @@ -0,0 +1,20 @@ +/* Check for incorrectly aligned byte args. */ + +public class err14 +{ + protected final String getClearToolCommand(Object a, Object b, + Object c, Object d, + int e, int f, boolean x) + { + return x ? "hi" : "byte"; + } + + + public static void main(String[] args) + { + System.out.println(new err14().getClearToolCommand(null, null, + null, null, 0, 0, false)); + System.out.println(new err14().getClearToolCommand(null, null, + null, null, 0, 0, true)); + } +} Index: libjava.lang/err14.out =================================================================== RCS file: libjava.lang/err14.out diff -N libjava.lang/err14.out --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libjava.lang/err14.out 10 Aug 2004 14:18:27 -0000 @@ -0,0 +1,2 @@ +byte +hi |