This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]