class initialization check overhead

C. van Reeuwijk C.vanReeuwijk@its.tudelft.nl
Thu Oct 24 02:10:00 GMT 2002


> How about using a pattern such as:
> 
> ----------------------
> // file-scope
> int _init_gnu_foo_MyClass  __attribute__((common));
> extern _JvClass _gnu_foo_MyClass;
> 
> // inside method code
> {
>    ...
>    if (!_initialized_org_gnu_foo_MyClass) {
>       _Jv_InitClass(&_gnu_foo_MyClass, &_init_gnu_foo_MyClass;);
>    }
>    ...
> }
> 
> 
> 
> -----------------------
> 
> The _init_xxx variables could be defined as "common" so multiple 
> occurrences would turn into one (and default to a 0 value).  [yes, I 
> know there is no such attribute defined, I just put it there to 
> illustrate my point] Or we can use some other linker trick the platform 
> supports for obtaining this effect.
> 
> The implementation of _Jv_InitClass would then do something like this:
> 
> ------------------------
> void _Jv_InitClass(_JvClass* clazz, int *callee_class_initialized)
> {
>    if (!clazz->isInitialized) {
>       .. do the normal initialization ...
>       clazz->isInitialized = TRUE;
>    }
>    *callee_class_initialized = TRUE;
> }
> -----------------------
> 
> This way, we would also avoid spilling registers if the class is in fact 
> already initialized.
> 
> It seems to me that this would be more portable than using traps.

That's what I use in my static Java compiler (see
www.pds.twi.tudelft.nl/timber), except that I don't maintain a
clazz->isInitialized variable (what's the point?), or pass any
parameters to _Jv_InitClass, since it only will access global variables.

Moreover, I use a fairly aggressive strategy to optimize initializations:

- If a class has an empty init, change it to a superclass init (repeat).
- Eliminate inits of java.lang.Object (since it's empty).
- Within a method, keep track of the classes already initialized,
and don't initialize a class again if you know for sure that it, or a
subclass, has already been initialized.
- Inline small inits.

I guess gcj does something similar, but part of this only works
because my compiler does whole-program optimization.

I cannot easily determine the impact of these optimizations, but in
my benchmarks static class initialization is never dominant.
If it were, the next step would be to do inter-procedural analysis.

A trick that sadly doesn't work (for me at least) is to declare the
test as an unlikely if() (after all, the then part will only
be executed once over the entire program). Since I generate c++ code, I've
used the g++ 3.1 branch probability pragma on such tests, but the only
noticable effect is that the resulting program is *slower*. Sigh.
Ditto for a couple of other places with similar circumstances.

Oh, and yes, I've also annotated it with the reverse, since it's very
easy to have such an annotation backwards. Again, the resulting program
is *slower*.

-- 
Kees van Reeuwijk, Delft University of Technology
http://www.pds.twi.tudelft.nl/~reeuwijk



More information about the Java mailing list