This is the mail archive of the 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]

Re: Interpreter progress...

Per Bothner <> writes:

> Kresten Krab Thorup <> writes:
> > I'm beginning to think, that maybe interpreted classes should have an
> > extra vtable that the interpreter can use to call other interpreted
> > methods in an efficient way.
> I don't think that is the right thing to do. 

Having thought some more about it I agree.  In fact, I've started to
think that this is becoming a non-issue, at least for some machines.

I added closures (what I called stubs before) to libffi/i386, with the
API I suggested the other day.  Then I realized, that the
interpreter's stack representation is amazingly close to the ABI on
i386, sparc and m68k. ... and I started to see things clearer.

1) In the interpreter, all small integers are allways being kept in
   "promoted to int" mode, and everything is internally word aligned.

2) Doing an ffi-call from interpreter to interpreter involves four
   conversions: (value->ptr, ptr->stack, stack->ptr, ptr->value).
   Each of these conversions has to consider promotion/demotion.

Considering that the original input is "already promoted", and that
values will be promoted when coming out in the other end, this is a
terrible waste.  Doing a call from the interpreter should be just a
matter of copying the arguments from the internal stack-representation
onto a freshly allocated area on the real stack, and doing a call.
Similarly for incoming calls.

With this insight, I've added an experimental new API to libffi-2.0.
For now, this is called the "raw api".  In the raw api:

   1) the user of the library is responsible for promoting integer
      values to word-size.  Similarily, the receiving end of a closure
      will receive the arguments in their promoted variants.

   2) arguments are passed "inline", instead of indirected via
      pointers.  This is defined to be an array of the following type:

        typedef union {
	    PROMOTED_SINT  sint;
	    PROMOTED_UINT  uint;
	    float          flt;
	    void          *ptr;
	  } ffi_raw;

      PROMOTED_{S,U}INT is then reasonably defined to whatever the
      machine's promotion is for integers.

   3) The "raw api" further defines that structures are always passed
      by reference.  Also, double, long double and long long values
      are stored directly, i.e. using memcpy, taking up as many
      entries in the table "as needed" to provide space.

I'm still experimenting with the exact API, especially how to define
the rules in (3) above.  It's hard to define such an API which works
equally well on both 32 and 64-bit machines, ... alas, the bottom line
is that it is quite fast.

Using the "raw api" in the interpreter, my ever-servant verifier now
runs almost twice (x 1.8) as fast as compared to "normal ffi".  And I
am sure that there are still some instructions to be shaved off there.

-- Kresten

 Kresten Krab Thorup, Ph.D. Candidate
 c/o Yonezawa Laboratory
 Department of Information Science   
 The University of Tokyo             
 7-3-1 Hongo, Bunkyo-ku, Tokyo 113 Japan
 Fax: +81-(0)3-5689-4365	 
 Phone: +81-(0)3-5841-4118
 Mobile: +81-(0)90-3693-5715

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