Interpreter / GFFI

Kresten Krab Thorup krab@gnu.org
Tue Jul 6 07:10:00 GMT 1999


Hi there,
I've been considering the issue of the interpreter some. The first
problem that appears to me, is that we need to produce objects and
vtables making behaving like C++ objects.
To this end, I've been rewriting mframe (GLGP'd), some objective-c
specific code used in the gnustep project. Since it's heavily
rewritten and generalized I've taken the liberty to rename it GFFI,
for Generalized Foreign Function Interface, pronounced Jiffy.
This may be a first step towards being able to produce C++ objects at
runtime. 
With this library, you can:
 - Invoke foreign function calls (as with FFI)
 - Dissect function calls
 - Create generic stubs
Basically, this is a high-level interface to GCC's __builtin_apply and
friends, and quite easy to port.
Here is an example, of how to build a stub, which is perhaps the most
interesting feature for now. First, we build a data structure to
represent the prototype of the function we want:
 gffi_formals_t *formals;
 formals = gffi_build_formals (gffi_double_type, /* return type */
				 2, /* no. of args */
				 gffi_double_type, /* arg1 type */
				 gffi_double_type); /* arg2 type */
So, now formals represent " double(*)(double, double) ". Then, we do
the "magic" and create the stub:
 void (*fun)() = gffi_build_stub (&callback, formals, 0);
His will create a trampoline, which will in turn call the function
"callback" with some specific arguments. We can call FUN directly,
like this:
 double (*fun_2) (double, double) = fun;
 double res = (*fun_2) (2.0, 3.0);
And thus calling fun_2, will in turn call the CALLBACK via a
trampoline.
Now, the function "callback" must have the prototype
 void callback (gffi_actuals_t *actuals,
	 	 gffi_formals_t *formals,
	 void *data)
In which FORMALS and DATA will be the same values originally passed to
gffi_build_stub. (DATA is 0 in this concrete example). 
ACTUALS is an abstraction of the concrete arguments. FORMALS
describes how to interpret the ACTUALS, so we can now write the
callback function for instance like this:
 void
 callback (gffi_actuals_t *actuals,
	 gffi_formals_t *formals,
	 void *data)
 {
 double d1, d2, res;
 
 /* prototype is " double foo(double, double) ". */
 assert (formals->arg[0].type == gffi_double_type);
 assert (formals->arg[1].type == gffi_double_type);
 assert (formals->return_type == gffi_double_type);
 
 gffi_get_actual (actuals, formals, 0, &d1);
 gffi_get_actual (actuals, formals, 1, &d2);
 
 res = d1 * d2;
 
 gffi_set_result (actuals, formals, &res);
 }
HOW ABOUT JAVA?
In the case of GNU Java, the CALLBACK function should be the
interpreter, and DATA would point to the method to be interpreted.
The STUB should be put in the vtable, being perfectly callable from C
or C++. 
SOME DETAILS
The implementation relies on the gcc-builtins, __builtin_apply and
friends. Thus, it only works with GCC. GFFI supports structure
arguments and structure return as well as all the scalar types. 
The entire source code is 500 l.o.c. + 100 l.o.c. per architecture
supported. The machine dependent part includes a rewrite of
FUNCTION_ARG and INITIALIZE_TRAMPOLINE macros from the gcc machine
descriptions to use the datastructures specific to GFFI. The MFRAME
stuff originally supported sparc/i386/m68k/hppa/powerpc in a number of
settings. Right now GFFI only supports sparc-solaris and i386-linux,
but adding support for the other would be rather easy since most of
the work was done in MFRAME.
The overhead? The memory overhead is not too bad. A STUB function
uses the space required for a gcc-trampoline plus 3 words. FORMALS do
not take much space either, and they could reasonably hashed and
reused when identical.
The time-overhead is slightly worse. Calling a STUB function costs
approximately 40 instructions on a Sparc. Hereto, add the cost of the
utility routines like gffi_get_actual, gffi_set_result. These are not
too expensive, since the information they need is stored (precomputed)
in the FORMALS structure.
All in all, I think this is not so bad. Especially, since it avoids
runtime-generated code (except for trampolines). 
-- 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-3812-2111 ext 4118
 Mobile: +81-(0)90-3693-5715


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /