SGI: Development

Firefox 10 Porting Progress - Page 1

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:

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.
Very nice, I was just going to ask about the progress :) .
The problem with Origin200 is that it doesn't even have a video card, so in fact there is no way to test Gtk+ locally - you'd need physical box for that.

Cheers
[click for links to hinv] JP: :Fuel: | :O2: | :Indy: || PL: [ :Fuel: :O2: :O2+: :Indy: ]
Many thanks for your great work!
kubatyszko wrote: Very nice, I was just going to ask about the progress :) .
The problem with Origin200 is that it doesn't even have a video card, so in fact there is no way to test Gtk+ locally - you'd need physical box for that.

Cheers


Couldn't he simply run a VNC Server? That's what I do with my O300.
:Indigo: 33mhz R3k/48mb/XS24 :Indy: 150mhz R4400/256mb/XL24 :Fuel: 600mhz R14kA/2gb/V10 Image 8x1.4ghz Itanium 2/8GB :O3x08R: 32x600mhz R14kA/24GB :Tezro: 4x700mhz R16k/8GB/V12/DCD/SAS/FC/DM5 (2x) :O3x0: 4x700mhz R16k/4GB :PrismDT: 2x1.6ghz 8mb/12gb/SAS/2xFGL
You could look at the Boehm GC ( http://www.hpl.hp.com/personal/Hans_Boehm/gc/ ) for the stack-specific stuff (it has an IRIX port and thread support). It seems like the firefox guys are reinventing the wheel :)
Adrenaline wrote:
kubatyszko wrote: Very nice, I was just going to ask about the progress :) .
The problem with Origin200 is that it doesn't even have a video card, so in fact there is no way to test Gtk+ locally - you'd need physical box for that.

Cheers


Couldn't he simply run a VNC Server? That's what I do with my O300.


There is a VNC Server installed on the box, the rest is up to NCommander.
[click for links to hinv] JP: :Fuel: | :O2: | :Indy: || PL: [ :Fuel: :O2: :O2+: :Indy: ]
So I'm making more progress, fixing random build failures as they pop up. I think the build is more than 75% through roughly (a full build of FF10 on ARM takes about 8 hours just to build the source, excluding the test suite), so processor speed is a bit of an issue here :-) .

I've found out that as part of that Meego work, a Qt backend landed and was accepted and landed (there are nightly builds of firefox-qt from the mozilla-central tree). From reading around, Qt doesn't have the performance issues Gtk+2 does, nor the Xrender issues. If that is the case, I'll look at retargetting Firefox 10 to build its Qt backend instead of Gtk+, which solve nicely solve the issue.

Can anyone comment on the state of Qt apps on IRIX? :-)

EDIT: And **** ...

Code: Select all

../../dist/include/mozilla/layers/ShadowLayerUtilsX11.h:44:36: fatal error: X11/extensions/Xrender.h: No such file or directory


When did firefox start depending on Xrender :-/. This might kill this port right here and there. I'm still a bit confused on support for Xrender in IRIX ...

SON OF EDIT: I got nekoware's Xrender library installed and the build continues, but its not clear to me if the resulting binary would be usable except over X11 forwarding to a box that did Xrendering ...
NCommander wrote: When did firefox start depending on Xrender :-/. ...

Pretty sure that was right about the same time that they stuck their heads firmly up their asses :P
So the build ran for several more hours before failing with this

Code: Select all

g++: error trying to exec '/usr/people/michael/local/gcc/libexec/gcc/mips-sgi-irix6.5/4.6.2/collect2': execv: Arg list too long
gmake[5]: *** [libxul.so] Error 1
gmake[5]: Leaving directory `/usr/people/michael/porting/obj1-mips-sgi-irix6.5/toolkit/library'
gmake[4]: *** [libs_tier_platform] Error 2
gmake[4]: Leaving directory `/usr/people/michael/porting/obj1-mips-sgi-irix6.5'
gmake[3]: *** [tier_platform] Error 2
gmake[3]: Leaving directory `/usr/people/michael/porting/obj1-mips-sgi-irix6.5'
gmake[2]: *** [default] Error 2
gmake[2]: Leaving directory `/usr/people/michael/porting/obj1-mips-sgi-irix6.5'
gmake[1]: *** [realbuild] Error 2
gmake[1]: Leaving directory `/usr/people/michael/porting/mozilla-irix'
gmake: *** [build] Error 2


Currently waiting for my sysadmin to bump the limit (AGAIN).
NCommander wrote: so processor speed is a bit of an issue here :-)


This is where you should be glad I didn't give you 200MHz O2 with 128MB ram :D , O200 with dual 360 is not thaaat bad :P
[click for links to hinv] JP: :Fuel: | :O2: | :Indy: || PL: [ :Fuel: :O2: :O2+: :Indy: ]

Code: Select all

/usr/people/michael/porting/obj1-mips-sgi-irix6.5/config/nsinstall -D ../../dist/sdk/lib
I dunn
ld32: WARNING 15 : Multiply defined:(base::GetCurrentProcId()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::GetCurrentProcessHandle()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::OpenProcessHandle(long, long*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::OpenPrivilegedProcessHandle(long, long*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::CloseProcessHandle(long)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::GetProcId(long)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::KillProcess(long, int, bool)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::CloseSuperfluousFds(std::vector<base::InjectionArc, std::allocator<base::InjectionArc> > const&)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::SetAllFDsToCloseOnExec()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::ProcessMetrics::ProcessMetrics(long)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::ProcessMetrics::CreateProcessMetrics(long)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::ProcessMetrics::ProcessMetrics(long)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::ProcessMetrics::~ProcessMetrics()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::EnableTerminationOnHeapCorruption()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::RaiseProcessToHighPriority()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::DidProcessCrash(bool*, long)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::WaitForExitCode(long, int*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::WaitForSingleProcess(long, int)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::CrashAwareSleep(long, int)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::ProcessMetrics::GetCPUUsage()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::GetAppOutput(CommandLine const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::GetProcessCount(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, base::ProcessFilter const*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::KillProcesses(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, int, base::ProcessFilter const*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::WaitForProcessesToExit(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, int, base::ProcessFilter const*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::CleanupProcesses(std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > const&, int, int, base::ProcessFilter const*)) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 15 : Multiply defined:(base::ProcessMetrics::~ProcessMetrics()) in ../../ipc/chromium/process_util_posix.o and ../../ipc/chromium/process_util_posix.o (2nd definition ignored).
ld32: WARNING 84 : ../../staticlib/libmozreg_s.a is not used for resolving any symbol.
ld32: WARNING 84 : /usr/lib/../lib32/libdl.so is not used for resolving any symbol.
ld32: WARNING 84 : /usr/people/michael/local/lib/libbz2.a is not used for resolving any symbol.
ld32: WARNING 84 : /usr/lib/../lib32/libsocket.so is not used for resolving any symbol.
ld32: ERROR   103: Direct reference to preemptible symbol "sharedstub".
ld32: WARNING 47 : This module (../../layout/base/nsCSSFrameConstructor.o .text) contains branch instruction(s)
that might degrade performance on an older version (rev. 2.2) R4000 processor.
ld32: INFO    171: Multigot invoked. Gp relative region broken up into 25 separate regions.
ld32: mmap'd output file could not grow.
ld32: Not a directory.  Removing output file...
ld32: INFO    152: Output file removed because of error.
collect2: ld returned 32 exit status
gmake[5]: *** [libxul.so] Error 1


So it tried to do one of the final links and crapped out. We *might* have hit an internal limit on the linker which brings us to the point that we simply can't continue. I'll look more into this, but I'm kinda not sure how to continue. Might need to fix binutils GNU ld and pray it can successfullymanage it.

To put this in context, ld ran for over an hour, ate 700 MiB of RAM, and pegged out the processor it was running on.

Monster library is monster ...

EDIT: Cross-compilation might be possible (not to methon faster), but I don't have a local copy of the IRIX core system libs, and GNU ld 2.22 has issues on IRIX. 2.20 is known to be healther though. The idea of trying to cross-compile the lizard though scares me ...
NCommander wrote:

Code: Select all

ld32: mmap'd output file could not grow.


So it tried to do one of the final links and crapped out. We *might* have hit an internal limit on the linker which brings us to the point that we simply can't continue. I'll look more into this, but I'm kinda not sure how to continue. Might need to fix binutils GNU ld and pray it can successfullymanage it.

To put this in context, ld ran for over an hour, ate 700 MiB of RAM, and pegged out the processor it was running on.

Monster library is monster ...

I had the very same problem when attempting to build libwebkit. My par investigation revealed that there was indeed a mmap hard limit at 1GB.
In your case, I simply hope you just ran out of memory/swap.
In my case, I tested with 8GB of ram and tons of swap, with the same result. My (poor) workaround was to strip all objects before linking, to keep the size within the 1GB limit.
:Onyx2: :O2: :O3x0: :O3x0:
From man(1) ld :

Code: Select all

I/O Options
The options affect I/O:

-mmap     Directs the linker to use mmap(2) as its preferred mode for
reading object files.  This usually results in better I/O
performances, except when using NFS mounted files with high
network latencies.  This is enabled by default.

-read     Directs the linker to use the open(2), lseek(2), and read(2)
utilities as its preferred mode for reading object files.
Setting this option when many object files are remotely
mounted with high network latency often improves
performance.


Try to pass the linker option '-read' to work around mmap limitations?
Now this is a deep dark secret, so everybody keep it quiet :)
It turns out that when reset, the WD33C93 defaults to a SCSI ID of 0, and it was simpler to leave it that way... -- Dave Olson, in comp.sys.sgi

Currently in commercial service: Image :Onyx2: (2x) :O3x02L:
In the museum : almost every MIPS/IRIX system.
Wanted : GM1 board for Professional Series GT graphics (030-0076-003, 030-0076-004)
jan-jaap wrote: From man(1) ld :

Code: Select all

I/O Options
The options affect I/O:

-mmap     Directs the linker to use mmap(2) as its preferred mode for
reading object files.  This usually results in better I/O
performances, except when using NFS mounted files with high
network latencies.  This is enabled by default.

-read     Directs the linker to use the open(2), lseek(2), and read(2)
utilities as its preferred mode for reading object files.
Setting this option when many object files are remotely
mounted with high network latency often improves
performance.


Try to pass the linker option '-read' to work around mmap limitations?


Tried passing in -Wl,-read to GCC, no such luck. I *suspect* it might be using mmap to write the file out; none of the input files are over a gigabyte. I suspect binutils will be required though it might not be immune.

IRIX mmap manpage:


ENOMEM zero was passed as the value of addr, and insufficient space was
available in the standard address ranges. This is primarily an
issue for 32 bit programs requesting 1GByte or more, because the
range from 0x30000000 to 0x40000000 is reserved for MAP_FIXED as
described above.

I'm currently debating options; cross-compiliatoin isn't really feasible unless I acquire IRIX hardware and a legal license. I could go hunting through binutils and see if it uses MAP_FIXED + MAP_AUTOGROW, and change it, but I also doubt that will help ...

*grumble*
Would moving you to dual 600Mhz, 4.5G RAM Octane2 help ? :D
That can be arranged pretty quickly, I'd only need a fresh install of 6.5.22.
[click for links to hinv] JP: :Fuel: | :O2: | :Indy: || PL: [ :Fuel: :O2: :O2+: :Indy: ]
NCommander wrote: 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.

*- 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


If you're still looking for a way to get the stack size of the current thread, I've made a new thread with some code: Get current thread stack base

Also, you should take a look at the TenFourFox project if you haven't heard of it before. He's going to great lengths to keep the PowerPC JIT (which I think is based on the older JIT/JS architecture?) working with the latest Firefox for PPC Macs.
:Octane: R12K/300x2, MXE
:1600SW: :ChallengeL:
pip wrote: Also, you should take a look at the TenFourFox project if you haven't heard of it before.

Whoa ! Gotta love it ! Altho i tend more to turning Javascript off rather than making it faster (it's nothing but a rattlesnake hiding under your bed) the rest of the project looks dang good ...

http://www.floodgap.com/software/tenfourfox/

and OS 9, too ...

http://www.floodgap.com/software/classilla/
I've been using TenFourFox for a while on my old 12" G4 PowerBook, and the last couple of releases have been extremely impressive performance-wise. A really great project!
hamei wrote: Whoa ! Gotta love it ! Altho i tend more to turning Javascript off rather than making it faster (it's nothing but a rattlesnake hiding under your bed) the rest of the project looks dang good ...

http://www.floodgap.com/software/tenfourfox/

and OS 9, too ...

http://www.floodgap.com/software/classilla/
hamei wrote:
NCommander wrote: When did firefox start depending on Xrender :-/. ...

Pretty sure that was right about the same time that they stuck their heads firmly up their asses :P


Ugh! I know, right?!

What the heck were they thinking when they started depending on technologies that our beloved IRIX doesn't have?! Don't they know how many IRIX users they have? I can't believe they'd alienate such a huge and important user-base like that. And, doing all of that over the objections of the many IRIX developers who begged and pleaded with them to just not use such a new (from the year 2000!) technology like Xrender.
My computers (incomplete)
mattst88 wrote:
hamei wrote:
NCommander wrote: When did firefox start depending on Xrender :-/. ...

Pretty sure that was right about the same time that they stuck their heads firmly up their asses :P


Ugh! I know, right?!

What the heck were they thinking when they started depending on technologies that our beloved IRIX doesn't have?! Don't they know how many IRIX users they have? I can't believe they'd alienate such a huge and important user-base like that. And, doing all of that over the objections of the many IRIX developers who begged and pleaded with them to just not use such a new (from the year 2000!) technology like Xrender.


One of the nice things about Firefox/Mozilla was that it only used the new fangled technology if (and I stress if) it was available and it could be turned off.

That thinking seemed to have died around FF4.