So since getting access to an IRIX box, I've been making slow but steady progress on bootstrapping Firefox on IRIX. After getting a sane and working toolchain, I went and built Firefox's dependencies cleanly with the new GCC as a stress test (and as some of nekoware's packages were out of date and I don't have root access to the box
).
I figured some might be interested in my progress thus far. Currently, I've got a ton of patches that gets Spidermonkey (Firefox's Javascript Engine) running under IRIX, and its pretty happy, if slow (no JIT on MIPS; see below for more information). I still am having some serious issues getting working executables; the official documentation says that -lpthreads MUST be the last library on the linker line, and I ran into issues with spidermonkey due to this (gdb and dbx both reported SIGSEGV in pthread_key_create in pre-main code). My workaround was to use _RLDN32_LIBS to rewrite the rld's loading order which worked. I found however quite by accident that if I leave -lpthreads off the linking line for the js, I get working binaries! (this may be because the js shell itself doesn't spin any threads directly as far as I can tell; all the voodoo is done in libmozjs.so)
Part of the issue seems to be the order MIPSpro vs. GCC feeds libraries into IRIX's ld, but I haven't quite figured out the voodoo to get a working binary every time. It seems rld only looks at libX.so's library linking list if said libraries aren't already loaded by the initial executable; the pratical upshot of this its working by magic, and is primarily influenced by the library load order of the calling executable :-/. I got a lead in #nekoware for someone who might be able to explain the deep-voodoo going on, but as best I can tell, libpthread replaces many symbols in libc.so which is why the linking order is so flighty.
Making life more difficult is dbx has no support for pthreads, and can't properly put breakpoints in g++ compiled code. gdb on the otherhand can find and place breakpoints, but crashes whenever one is it (I guess its more literal on 'break' point ). I haven't built a more recent gdb to see if it helps, that's next on the TODO.
Firefox itself has also lost a lot of its cross-platform magic; i.e., there's a configure check looking for MAP_ANON(YMOUS), and then doesn't use it or any replacement mmap to wrap the function call. In one place, a file did "#define MAP_ANONYMOUS 0" if its undefined, which lead to a silent failure, which required considerable fprintf debugging to find and fix. Another headache is that the garbage collector wants access to a threads stack and stacksize. On most platforms, this is handled by a non-POSIX pthread extension that can grab a running threads attributes, and report the base/stacksize. I couldn't find an equivelent function on IRIX that worked*, so I modified NSPR to include such information in the PRThread structure, and then added a function that I could pull it on the fly; my implementation is not 100% correct as it doesn't account properly for the NSPR thread wrapper function and stack size its using, but its "good enough" for the time being; fixing it is pretty trivial, I just haven't done it yet.
Javascript performance was unusable in a debugging build, but with gcc -O3 -march=mips4, I got pretty good performances out of it. It should be noted that the YARR interperer (which replaced PRCE for non-JIT archs) is known to be upwards of %50 percent slower. Also, please don't take the time into account, python appears to have deadlocked on the final test, and hung until I manually killed it. To run all tests up to this point took 2649 seconds (44 minutes); on a modern dual-core amd64 machine, I've been quoted runtimes between 8 and 12 minutes. Most tests ran extremely fast, but a few (mostly the stress tests) ran slowly and took awhile. Considering we've got no JIT, and I'm not on the fastest box in the world, its not that bad.
Here's what hinv has to say on my system:
Here's what Spidermonkey's test suite spat out after I killed the hung python process (--no-extensions means only test ECMAScript functionality; do not test XUL (which I have as yet compiled).
EDIT: Just to be clear, this means 2649 tests passed, two failed or timed out, 146 skipped.
A MIPS JIT was written and landed in Firefox 11, but its against O32/LInux. On the plus side, it appears to have been tested and works on big-endian MIPS, so it might be realistically possible to backport to Firefox 10; I will review this once I actually have the browser working!.
If anyone could give some insight into the pthread linking/ordering issues on IRIX, I'd be most appreciative.
*- IRIX's getcontext() suggests it works in threads, but only returned the stack of the base thread as far as I could tell. The same function is used on AIX in jsnativestack.cpp; I suspect it is broken on that platform as well
SON OF EDIT: It should be noted that I was unaware of the Xrender issue with Xsgi when I started this, so the version of Gtk+ I'm building with will not work locally (nor do I have a way to test local output). Firefox should be able to be built with an older Gtk+2 which didn't require Xrender, or relatively easy to backport.
I figured some might be interested in my progress thus far. Currently, I've got a ton of patches that gets Spidermonkey (Firefox's Javascript Engine) running under IRIX, and its pretty happy, if slow (no JIT on MIPS; see below for more information). I still am having some serious issues getting working executables; the official documentation says that -lpthreads MUST be the last library on the linker line, and I ran into issues with spidermonkey due to this (gdb and dbx both reported SIGSEGV in pthread_key_create in pre-main code). My workaround was to use _RLDN32_LIBS to rewrite the rld's loading order which worked. I found however quite by accident that if I leave -lpthreads off the linking line for the js, I get working binaries! (this may be because the js shell itself doesn't spin any threads directly as far as I can tell; all the voodoo is done in libmozjs.so)
Part of the issue seems to be the order MIPSpro vs. GCC feeds libraries into IRIX's ld, but I haven't quite figured out the voodoo to get a working binary every time. It seems rld only looks at libX.so's library linking list if said libraries aren't already loaded by the initial executable; the pratical upshot of this its working by magic, and is primarily influenced by the library load order of the calling executable :-/. I got a lead in #nekoware for someone who might be able to explain the deep-voodoo going on, but as best I can tell, libpthread replaces many symbols in libc.so which is why the linking order is so flighty.
Making life more difficult is dbx has no support for pthreads, and can't properly put breakpoints in g++ compiled code. gdb on the otherhand can find and place breakpoints, but crashes whenever one is it (I guess its more literal on 'break' point ). I haven't built a more recent gdb to see if it helps, that's next on the TODO.
Firefox itself has also lost a lot of its cross-platform magic; i.e., there's a configure check looking for MAP_ANON(YMOUS), and then doesn't use it or any replacement mmap to wrap the function call. In one place, a file did "#define MAP_ANONYMOUS 0" if its undefined, which lead to a silent failure, which required considerable fprintf debugging to find and fix. Another headache is that the garbage collector wants access to a threads stack and stacksize. On most platforms, this is handled by a non-POSIX pthread extension that can grab a running threads attributes, and report the base/stacksize. I couldn't find an equivelent function on IRIX that worked*, so I modified NSPR to include such information in the PRThread structure, and then added a function that I could pull it on the fly; my implementation is not 100% correct as it doesn't account properly for the NSPR thread wrapper function and stack size its using, but its "good enough" for the time being; fixing it is pretty trivial, I just haven't done it yet.
Javascript performance was unusable in a debugging build, but with gcc -O3 -march=mips4, I got pretty good performances out of it. It should be noted that the YARR interperer (which replaced PRCE for non-JIT archs) is known to be upwards of %50 percent slower. Also, please don't take the time into account, python appears to have deadlocked on the final test, and hung until I manually killed it. To run all tests up to this point took 2649 seconds (44 minutes); on a modern dual-core amd64 machine, I've been quoted runtimes between 8 and 12 minutes. Most tests ran extremely fast, but a few (mostly the stress tests) ran slowly and took awhile. Considering we've got no JIT, and I'm not on the fastest box in the world, its not that bad.
Here's what hinv has to say on my system:
Code: Select all
michael@IRIS:~/porting/mozilla-irix/js/src/tests$ hinv
2 360 MHZ IP27 Processors
CPU: MIPS R12000 Processor Chip Revision: 3.5
FPU: MIPS R12010 Floating Point Chip Revision: 3.5
Main memory size: 1536 Mbytes
Instruction cache size: 32 Kbytes
Data cache size: 32 Kbytes
Secondary unified instruction/data cache size: 4 Mbytes
Integral SCSI controller 0: Version QL1040B (rev. 2), single ended
Disk drive: unit 1 on SCSI controller 0
Disk drive: unit 2 on SCSI controller 0
Disk drive: unit 3 on SCSI controller 0
Disk drive: unit 4 on SCSI controller 0
Disk drive: unit 5 on SCSI controller 0
Integral SCSI controller 1: Version QL1040B (rev. 2), single ended
Tape drive: unit 4 on SCSI controller 1: DAT
CDROM: unit 6 on SCSI controller 1
Integral SCSI controller 2: Version Fibre Channel QL2200A
Integral SCSI controller 3: Version Fibre Channel QL2200A
IOC3/IOC4 serial port: tty1
IOC3/IOC4 serial port: tty2
IOC3 parallel port: plp1
Integral Fast Ethernet: ef0, version 1, module 1, slot MotherBoard, pci 2
Gigabit Ethernet: eg0, module 1, PCI slot 7, firmware version 0.0.0
Origin 200 base I/O, module 1 slot 1
IOC3/IOC4 external interrupts: 1
Here's what Spidermonkey's test suite spat out after I killed the hung python process (--no-extensions means only test ECMAScript functionality; do not test XUL (which I have as yet compiled).
Code: Select all
michael@IRIS:~/porting/release-mips-sgi-irix6.5/js/src/shell$ ~/porting/mozilla-irix/js/src/tests/jstests.py --no-extensions ./js
[2649| 2| 146] 100% ===============================================>| 5351.3s
REGRESSIONS
ecma_3/RegExp/perlstress-001.js
TIMEOUTS
ecma/Date/15.9.5.10-2.js
FAIL (partial run -- interrupted by user)
EDIT: Just to be clear, this means 2649 tests passed, two failed or timed out, 146 skipped.
A MIPS JIT was written and landed in Firefox 11, but its against O32/LInux. On the plus side, it appears to have been tested and works on big-endian MIPS, so it might be realistically possible to backport to Firefox 10; I will review this once I actually have the browser working!.
If anyone could give some insight into the pthread linking/ordering issues on IRIX, I'd be most appreciative.
*- IRIX's getcontext() suggests it works in threads, but only returned the stack of the base thread as far as I could tell. The same function is used on AIX in jsnativestack.cpp; I suspect it is broken on that platform as well
SON OF EDIT: It should be noted that I was unaware of the Xrender issue with Xsgi when I started this, so the version of Gtk+ I'm building with will not work locally (nor do I have a way to test local output). Firefox should be able to be built with an older Gtk+2 which didn't require Xrender, or relatively easy to backport.