Limitations of the Calling Convention Optimization

Tobias Hartmann tobias.hartmann at oracle.com
Fri Oct 23 13:07:21 UTC 2020


On 23.10.20 14:42, Brian Goetz wrote:
> So, confirming: we can have multiple calling conventions for a given method, but for a given _call
> site_, we choose a CC at linkage time and we have to stick with that.  Correct?

Not quite. A method always supports the "default" calling convention (all arguments/returns passed
as pointers) but if the type of an argument/return is known to be an inline type at *method* link
time (i.e. when the method holder is loaded by the VM), we can optimize that default calling
convention by adding a scalarized calling convention.

Now whenever a call site to such a method is C2 compiled, that scalarized calling convention can be
used if available. C1 and the interpreter will only use the default calling convention anyway.

> An "easy" case in Maurizio's library is something like this:
> 
>     sealed interface X permits Val { }
>     primitive class Val implements X { }
> 
>     X makeVal() { return new Val(); }
> 
> Here, we are always returning a non-null Val.  So ideally, we'd like invocations
> 
>     Val v = makeVal()
> 
> to scalarize.  But the method descriptor is `()LX;`, and, at linkage time, we can't guarantee `X`
> has been loaded, which means we can't observe that Val is the only subtype of X.  So what you need is:
> 
>  - X and Val have to have been loaded at linkage time;
>  - we need some confidence that `makeVal()` always returns a non-null value.
> 
> Does this capture what you're saying?

Yes, that is correct but we don't need that information at linkage time of the call but at linkage
time of the method holder ('InstanceKlass::link_methods' -> 'Method::link_method' in the HotSpot
implementation). This is a technical limitation of how things work internally (adapters to jump
between interpreted and compiled code need to be created eagerly).

Best regards,
Tobias



More information about the valhalla-dev mailing list