Status fields:
creation_ts: | 2008-05-23 15:17 |
---|---|
component: | jit |
version: | unspecified |
rep_platform: | i386 |
op_sys: | Linux |
bug_status: | RESOLVED |
resolution: | FIXED |
reporter: | stefan@complang.tuwien.ac.at |
After updating to Fedora 9 (and getting rid of the mmap problem I posted to the mailing list), I noticed that dacapo had stopped working in a very peculiar way - it could not create files during unzipping because of the non-existent directory "scratch/antlr" which it should have created with File.mkdir(). But it had not. After lots of poking around, I found out that gcc 4.3 only uses 8 bits (al) to return a boolean value. But cacao expects the whole register to be set. The following line appeared in a +TraceJavaCalls output. java.io.File.exists()Z->135257088 (0x080fdc00) It means that the file does not exist (the lower 8 bits are zero). CACAO, however, interprets it as non-zero and thus doesn't execute the subsequent mkdir, causing the file extraction to fail. I don't know what the official ABI says, and I couldn't find an obvious easy way to fix it, so I'm reporting it here. On x86_64, in contrast, I didn't have this problem. Maybe the calling convention is different there, maybe gcc didn't change its behavior or maybe it was just bad luck...
Is there even such a thing as an official ABI? If there is, it's not easily discoverable...
Found it: http://www.sco.com/developers/devspecs/abi386-4.pdf Not very helpful though - "A function that returns an integral or pointer value places its result in register %eax." This can mean anything, although I would probably interpret it the way CACAO does.
Stefan, I assign this bug to you.
Created an attachment (id=41) hg export of fix This should fix it (for i386). I cannot commit (thank you Debian), so I'm posting it here. I'm not sure about x86_64 anymore. Theoretically, it should be affected too. Maybe I haven't noticed because I haven't rebuilt classpath yet...
twisti, what's with that "XXX does not work, because of nibbles" comment? It works fine for <REG_RESULT, REG_RESULT> at least...
Yes, it works for register number 0 (EAX == AX == AL), but not for others. So enabling this one is not a good idea.
With what optimization are you compiling? Have you tried to change that?
(In reply to comment #7) > With what optimization are you compiling? Have you tried to change that? > Yeah, it doesn't make a difference. The function "exists" compiles to the code shown below (I used -fomit-frame-pointer for brevity) char exists(int a) { return a > 0; } 0000007d <exists>: 7d: 83 7c 24 04 00 cmpl $0x0,0x4(%esp) 82: 0f 9f c0 setg %al 85: c3 ret
Yes, you're right. I just tried it on my Debian box: $ gcc-4.2 -S -m32 -fomit-frame-pointer -O2 test.c $ cat test.s <snip> exists: xorl %eax, %eax cmpl $0, 4(%esp) setg %al ret $ gcc-4.3 -S -m32 -fomit-frame-pointer -O2 test.c $ cat test.s <snip> exists: movl 4(%esp), %eax testl %eax, %eax setg %al ret See the missing register clear? Same applies to x86_64: $ gcc-4.2 -S -m64 -fomit-frame-pointer -O2 test.c $ cat test.s <snip> exists: .LFB2: xorl %eax, %eax testl %edi, %edi setg %al ret $ gcc-4.3 -S -m64 -fomit-frame-pointer -O2 test.c $ cat test.s <snip> exists: .LFB2: testl %edi, %edi setg %al ret I don't know if this is indented or a bug.
I cannot imagine this being a bug. I think I remember a somewhat similar change a few years ago when gcc changed the point in time at which it forced (C++) bools to 0/1. Before, bools always contained only 0/1, so a cast to char was a nop. They changed it so that bools can contain any value, and only upon casting to a numeric value is it interpreted as false/true and set to 0/1 resp. The change might have been the other way round but I'm sure it happened at some time.
I just tried Sun Studio compiler and it produces the same code as GCC 4.2. Should we ask the GCC list?
Intel 10.0 does the same (like GCC 4.2). It happened somewhere between the gcc-4.3-20070707 and gcc-4.3-20070713 snapshots. No idea which changeset exactly. It does interoperate well with older code, however, because apparently, compiled code has never assumed the upper part of the register to contain anything useful.
See http://gcc.gnu.org/ml/gcc/2008-01/msg00052.html (and followups)
Hmm, OK. So it seems we have to add a "workaround".
Interestingly, Visual C++ 2003 (the only version I tried) produces code like gcc 4.3. In a way, I like the change. Before, the expansion has always been done twice - once before returning and once when interpreting the return value. Now that redundancy is gone. And this is a good thing. It's very similar to that whole cld issue <http://lwn.net/Articles/272048/>, except that the ABI specification is crystal clear for the direction flag, something which cannot be said about the return value issue.
Created an attachment (id=43) pr72-i386 First part (i386). Now I know what you meant with that nibbles comment...
Created an attachment (id=44) pr72-x86_64 This should do it for x86_64...
Committed.
Thanks for fixing this one.
date: | 2008-06-09 18:38 |
---|---|
desc: | hg export of fix |
type: | text/plain |
download: | bug72 |
date: | 2008-06-11 23:21 |
---|---|
desc: | pr72-i386 |
type: | text/plain |
download: | pr72 |
date: | 2008-06-11 23:34 |
---|---|
desc: | pr72-x86_64 |
type: | text/plain |
download: | pr72-x86_64 |