Limitations of the Calling Convention Optimization

John Rose john.r.rose at oracle.com
Wed Oct 21 16:34:49 UTC 2020


On Oct 21, 2020, at 5:02 AM, Tobias Hartmann <tobias.hartmann at oracle.com> wrote:
> 
> Also, the VM would need to ensure that the argument/return type is eagerly loaded when the adapters
> are created at method link time (how do we even know eager loading is required for these L-types?).

This is the hard kernel of the problem.  The L in LFoo; means
“Lazy Loading” (among other things); you simply cannot assume
that Foo.class will be loaded when you are setting up layouts and
calling sequences for an LFoo;.  To get that information (and more)
we will always need a signal somewhere in the call site which says,
“do the preload” (which is what I call the “go and look” signal).
The Q in QFooVal; performs this duty.

That said, we might have wiggle room with sealed interfaces.
If there is a “go and look” signal (QFooVal;) nearby that has
forced the loading of an inline type FooVal which has an
interface type FooRef as a super, *and* if FooRef is sealed,
then we can go to work on FooRef calling sequences, if we
think it’s profitable.  (We could substitute in a null flag plus
a FooVal instance, and we can try to merge the null flag into
the “guts” of the FooVal registers, if there is slack.  Or pass
the FooVal on stack by reference.  Or other tricks like that.)

But, back to the hard kernel of the problem, if there is no
mention of QFooVal; near the LFooRef; descriptor, all bets
are off; FooRef.class must be assumed to be unavailable in
the general case when forming calling sequences involving
LFooRef;.

The laziness of LFoo; gives it opaqueness, abstraction.  All you
know is it’s a pointer; you can’t know (in general) what it
points to until Foo.class is loaded and there’s an instance
of Foo running around.  Before that it’s just nulls.  The
opaqueness of LFoo; in turn means that you don’t know
whether it is just a GC heap reference or something special
(a disguised value).  When we try to do special side-heap
treatment for LFoo; values that we discover are disguised
values, we find that it’s difficult to contain the uses of
those values; they are so nondescript they mix with
Object pointers.  This creates a kind of pollution where
suddenly every pointer that might be handed to the GC
has to be checked to see if it’s a side-heap pointer (e.g.,
thread local or on-stack). This possibility of pollution
is introduced by the abstractness of LFoo; and the
result of it is hard-to-control extra expenses wherever
an opaque pointer must be stored in the real GC heap.

Maybe we can slim those expenses down in the future,
using ZGC-like colored pointers.  For now, I think the
good thing to do is buffer on the real GC heap, as we
do now.  Maybe the performance can be increased in
the future by using side-heap tricks, after we figure
out how to prevent side-heap pointers from polluting
the real GC heap.

It’s an odd linkage:  the Lazy Loading LFoo;, by its
nature, has surprising connections to the GC.

— John


More information about the valhalla-dev mailing list