There’s something totally awesome about writing assembler and writing the assembler to assemble it.
It actually did work too!
#0 report_unimplemented ( file_name=0xfb3d624 "aztec/hotspot/src/cpu/ppc/vm/icache_ppc.cpp", line_no=65) at aztec/hotspot/src/share/vm/utilities/debug.cpp:241 #1 0xf5b8405c in ?? () #2 0x0f760d84 in AbstractICache::invalidate_range (start=0xf5b86400 "", nbytes=15) at aztec/hotspot/src/share/vm/runtime/icache.cpp:102
Obviously this is like “so what?” for all you JIT guys but I’m kind of stunned here.
Well, my assembler worked, I think:
3c 60 0f b4 lis r3, file@hi 60 63 68 e4 ori r3, r3, file@lo 38 80 00 3a li r4, line 3d 40 0f 6e lis r10, report_unimplemented@hi 61 4a 82 60 ori r10, r10, report_unimplemented@lo 7d 48 03 a6 mtlr r10 4e 80 00 21 blrl 3d 40 0f e5 lis r10, abort@hi 61 4a 7b a0 ori r10, r10, abort@lo 7d 48 03 a6 mtlr r10 4e 80 00 21 blrl
I finally bit the bullet and threw myself into PPC assembly. And what better way to ease you into your first assembly since 1998 than writing an assembler! It’s been a long couple of days but finally — finally! — it compiled and ran:
3c600fb4606368e43880003a3d400f6e614a82607d48 03a64e8000213d400fe5614a7ba07d4803a64e800021
Check back Monday to see if that’s garbage…
I’ve been busy filling in stubs recently, but something didn’t feel right. The stubs all say Unimplemented()
— and that was calling itself. I’d been working towards the short term goal of getting Unimplemented()
to work when I discovered that what lay beneath Unimplemented()
and assert()
was the most complicated error handling and debugging system in the world.
First it scans the command line to see if you told it to ignore the particular error it’s trying to report. Then it prints a message to tell you the command line options to make it skip that particular error. Then it checks to see if this is the first error it’s seen, if any other threads are trying to report errors, if any other threads are trying to report this particular error, whether this particular error is being reported as the first error by another thread, and whether this error is being reported as a result of an error in the error reporting system. Then it prepares messages of varying detail to print to a file if possible and the screen if not. It creates and executes shell scripts (!) to do who knows what. Then it thinks about quitting.
This is great, except that all this wacky stack and thread stuff is calling unimplemented code, and filling in stubs that the error reporting system is calling was getting the error reporting system working — not the VM!
The error reporting system now looks like this:
fprintf(stderr, "error: %s: %s:%d\n", _message, _filename, _lineno); exit(EXIT_FAILURE);
Om Shanti.
I flipped out yesterday and converted my memo-list coping strategy into actual code.
One thing I keep meaning to mention and forgetting. I’m using IcedTea’s bootstrap JDK and plug replacements for my PPC builds:
hg clone http://icedtea.classpath.org/hg/icedtea cd icedtea ./configure make boot plugs
The tricky bit is if you want to build 64-bit. I couldn’t decide on the best way to set the data model — integrating setarch and ARCH_DATA_MODEL and who knows what else — so I deferred that particular decision. I made it so that IcedTea always builds 32-bit on ppc and s390, which means you need to symlink the libraries if you want to build with ARCH_DATA_MODEL=64:
ln -s ppc bootstrap/jdk1.7.0/jre/lib/ppc64
I should figure this out properly but it’s hardly urgent.
Long time no post. I haven’t been sleeping well this past couple of weeks so my brain is like sponge. I’ve been filling in stubs, but somewhat slowly, for I’m tired and keep making stupid mistakes. The stubs just say Unimplemented(), which should be printing little file:line error messages, but what’s happening is the the printing code is itself calling Unimplemented() so it’s segfaulting and I have to run it in the debugger every time to see what’s missing. It’s really boring.
Some of the code I’m writing is really nasty*. Thing is, any one of these stubs could take me a week to write, and I don’t want to spend a week writing this and a week writing that and so on and so on. I’d much rather have a load of hacky awful code so I can say “this and this and this need writing, which will take me X many weeks (maybe)”. I don’t like this whole open-ended thing where there’s no way to gauge how close you are to finishing.
The segfault I was debugging the other day turned out a stack overflow caused by the Unimplemented() in Atomic::cmpxchg_ptr (void *, void *, void *) calling itself to generate the error message for the Unimplemented() in Atomic::xchg (jint, jint *). I guess this means it’s time to start writing assembler.
I had a little tangent yesterday while I tried to figure out what sizes all the different types were. aph and mjw pointed me at some stuff [1, 2 and 3]. Who knew?
ILP32 | LP64 | |
---|---|---|
int | 32 | 32 |
long | 32 | 64 |
void * | 32 | 64 |
jint | 32 | 32 |
jlong | 64 | 64 |
intptr_t | 32 | 64 |
I fixed the build on ppc64 while I was experimenting too.
Here’s a fun thing: all the commands in OpenJDK will execve() themselves to set LD_LIBRARY_PATH if it’s not what they want it to be. This totally unhooks your gdb session.
Here’s another fun thing: setting _JAVA_LAUNCHER_DEBUG=1 prints out a load of stuff so you can see this bit of tomfoolery. I added an extra bit of debugging in my repository, a dump of the environment so I can see what I need to be exporting to keep gdb hooked in.
Om Shanti.