This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: class initialization check overhead
- From: Jeff Sturm <jsturm at one-point dot com>
- To: Adam Megacz <adam at megacz dot com>
- Cc: java at gcc dot gnu dot org
- Date: Wed, 23 Oct 2002 19:51:46 -0400 (EDT)
- Subject: Re: class initialization check overhead
On 23 Oct 2002, Adam Megacz wrote:
> I noticed that every static method has a check at the top of the
> method to see if <clinit> needs to be run. Doesn't this incur
> substantial overhead?
A similar check is made when accessing static fields, and each time a
non-array object is allocated. There is certainly significant overhead.
It's hard to say just how much though.
> Could this be eliminated by putting each class (static data and code)
> on its own page and write-protecting the page? Then you could catch
> SIGSEGV and perform the initialization.
How does that work, e.g. in the following:
class Singleton {
static Singleton theInstance = new Singleton();
static getInstance() { return theInstance; }
}
I don't see where the getInstance() method would trigger a write fault.
Or are you suggesting something like PROT_NONE, as in a guard page?
Just this week I tried an experiment on class initialization. I modified
the frontend to call an alternate initialization function, which alters
its caller on i686:
void
_Jv_InitCompiledClass (jclass klass)
{
_Jv_InitClass (klass);
unsigned char *ra = (unsigned char *) __builtin_return_address (0);
mprotect ((void *)(((unsigned long)ra) & ~4095),
4096, PROT_READ | PROT_WRITE | PROT_EXEC);
ra[-5] = 0x90;
ra[-4] = 0x90;
ra[-3] = 0x90;
ra[-2] = 0x90;
ra[-1] = 0x90;
}
This writes NOP instructions over the original call. It did not prove
enormously helpful. The real problem must be the memory and register
clobbers associated with a call, disrupting the instruction pipeline:
movl 32(%esp), %ebx
movl $_ZN3tcl4lang4Util6class$E, (%esp)
movl 36(%esp), %esi
movl 40(%esp), %edi
call _Jv_InitCompiledClass
movl %ebx, 32(%esp)
movl %esi, 36(%esp)
movl %edi, 40(%esp)
These eight instructions would disappear if gcj could optimize the call
away in the first place.
Come to think of it... what if compiled classes were prepared early
instead of at initialization time? In my application of 191 classes, only
36 have a <clinit>. If the frontend knows that a class invokes no
<clinit> method (directly or in a superclass), could the _Jv_InitClass be
dropped entirely?
Jeff