This is the mail archive of the
java-discuss@sourceware.cygnus.com
mailing list for the Java project.
Re: Interpreter progress...
Per Bothner <per@bothner.com> writes:
> Kresten Krab Thorup <krab@gnu.org> 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