Experiences using GCJ as an embedded compiler
Jon Olson
olson@mmsi.com
Mon Mar 29 18:43:00 GMT 1999
> // We can do class member testing in constant time adding in each class
> // using a small extra table of all the ancestor classes.
> // (This trick is relatively old.)
> // Note also we do not need to include the java.lang.Object in the table
> // of ancestors, since it is redundant.
> // If we order this table from current classes down by decreasing depth,
> // we can combine the ancestors table with the pointer to the actual classs.
> typedef void *methodptr;
> struct _dispatchTable {
> Class ancestors[CLASS_DEPTH(THIS_CLASS)-1];
> methodptr method[...];
> };
> #define OBJECT_CLASS(OBJ) ((OBJ)->dtable->ancestors[0])
> #define OBJECT_INSTANCEOF_CLASS(OBJ, CLS) \
> CLASS_SUBCLASS_OF(OBJECT_CLASS(OBJ), CLS)
> #define CLASS_SUBCLASS_OF(OCLS, CLS) \
> ((CLS) == &ObjectClass \
> || ((CLASS_DEPTH(OCLS) - CLASS_DEPTH(CLS) >= 0 \
> && (OCLS)->dtable->ancestors[CLASS_DEPTH(OCLS) - CLASS_DEPTH(CLS)] \
> == (CLS))))
Clever, but it makes C++/Java compatibility a bit messy. I suppose that you
could declare the C++ header file with a bunch of dummy virtual functions
to fill in the `ancestors' slots.
BTW, isn't CLASS_DEPTH(OCLS) always 1, since the first element of ancestors
would always be the first subclass of java.lang.Object? Seems that if
`ancestors' contains a vector of all a class's superclasses, then
CLASS_SUBCLASS_OF() should really be:
#define CLASS_SUBCLASS_OF(OCLS, CLS) \
((CLS) == &ObjectClass \
|| ((CLASS_DEPTH(CLS) > CLASS_DEPTH(OCLS) \
&& (CLS)->dtable->ancestors[CLASS_DEPTH(OCLS) - 1] == (OCLS))))
> #define CLASS_IINDEX(CL) ((CL)->ui.cls.iindex)
> #define CLASS_ITABLE(CL) ((CL)->ui.cls.itable)
> #define CLASS_IMAP(CL) ((CL)->ui.iface.imap)
> #define LOOKUP_INTERFACE(CL, IFACE, IMETHODINDEX) \
> (CLASS_ITABLE(CL)[CLASS_IMAP(IFACE)[CLASS_IINDEX(cl)]][IMETHODINDEX])
Looks like a good idea... I think that the CLASS_IINDEX and CLASS_IMAP
assignment should be deferred to class load time, but the compiler must
assign IMETHODINDEX. Seems that the only thing that GCJ should do is:
1) Layout vtables for each interface implemented by a class
2) Assign method indices to all methods in an interface.
My druthers would be to use declaration order, just like
is done for C++ and Java methods now.
This basically is what I was planning on implementing. The additional
idea you present here is to allocate unique class indices and a
back-index to compute an index into the per-class interface table.
This seems like stuff best left to `registerClass()' and won't affect
the compiler at all. We still want the run-time interface between `gcj'
and invoking a method to be the following, no???
jnative
_Jv_LookupInterfaceMethod(jclass cl, jclass xface, int vtableIndex)
{
}
> 1145 classes implement 0 interfaces
> 153 classes implement 1 interface (directly or indirectly)
> 105 classes implement 2 interfaces (directly or indirectly)
> 39 classes implement 3 interfaces (directly or indirectly)
> 10 classes implement 4 interfaces (directly or indirectly)
> 5 classes implement 5 interfaces (directly or indirectly)
> 1 class (java.awt.AWTEventMulticaster) implements 12 interfaces
The run-time can decide whether it wants to allocate the backwards
index if it so desires. Otherwise, it's just a matter of a linear
scan through the interfaces implemented by a class to find the
vtable matching the `xface' class. Since most classes don't implement
very many interfaces (few more than 2 as your statistics show),
even a linear scan through the implemented interfaces would be fast.
--
Jon Olson, Modular Mining Systems
3289 E. Hemisphere Loop
Tucson, AZ 85706
INTERNET: olson@mmsi.com
PHONE: (520)746-9127
FAX: (520)889-5790
More information about the Java
mailing list