Inline Record

forax at univ-mlv.fr forax at univ-mlv.fr
Mon May 11 21:31:47 UTC 2020


----- Mail original -----
> De: "John Rose" <john.r.rose at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "Brian Goetz" <brian.goetz at oracle.com>, "Srikanth" <srikanth.adayapalam at oracle.com>, "amber-dev"
> <amber-dev at openjdk.java.net>
> Envoyé: Dimanche 10 Mai 2020 00:34:56
> Objet: Re: Inline Record

> On May 8, 2020, at 1:16 PM, forax at univ-mlv.fr wrote:
>> 
>> Conceptually a ClassValue is like a vtable, so you want the JIT to build a kind
>> of inlining cache (apart if the class is a constant) to avoid to hit the
>> ClassValue if a callsite is monomorphic.
> 
> That’s the thrust of this bit of engineering:
>  https://bugs.openjdk.java.net/browse/JDK-8238260
> 
> The most important optimization is not v-table packing
> but rather devirtualization.  When JDK-8238260 then
> the JIT’s aggressive type propagation will allow CV.get.invoke
> chains to be devirtualized.  Adding a v-table-like mechanism
> would be dessert to the main course of devirtualization.
> 
> (Sketch of dessert:  Detect methods that contain CV.get.invoke
> chains based on this.getClass.  They probably already have v-table
> slots.  Ask the JIT to spin customized method versions for such
> slots in subclasses.  This technique could be triggered as part of
> specialized-generic method instantiation, or it could be triggered
> by counter-driven hotspot detection.)
> 

yes, this is how i believe the specialization of generics should be done,
there is no bytecode specialization, it's the same bytecode for all species thus they all share the same Class,
the type arguments are stored in the species (as an overlay of the constant pool ?),
so the interpreter run the same bytecode but with a different species, a different set of constants,
at JIT time, you can fill the slot of the vtable with a specific JITed code.

For me, it's a mechanism more generic than using ClassValue, it's more like you tag a specific method in the bytecode, let say with an attribute/annotation,
it means that
- it should have a proper index in the vtable, even if it's a private or a static method
- the same method should have different profile depending on the subclass
- species are seen as subclasses from the vtable POV
 

> If we had JDK-8238260 today we wouldn’t need the indy technique,
> nor would we need the strange weasel words in the javadoc for Record,
> that talk about “default methods” instead of the behavior of the
> method inherited from Record.
> 
>> Building this kind of inline cache is far easier with an indy.
> 
> Today it is, on grounds of current performance engineering status
> of the various existing features of the JVM.  But it leads to bad javadoc,
> which is a widely visible wart.

I was thinking about having indy at caller site, not inside equals/hashcode/toString,
which is the dual way of using the vtable patching. Instead of trying to optimize each subclasses,
and consider a generic instantiation as fake subclass (from the vtable POV),
the VM can rewrite the invoke* to those special method to use indy instead,
it's the mjolnir approach. The sharing comes from the fact that several callsites can share the same MethodHandle (like the verified entry point do).

> 
>> So if you want a method equals/hashCode and toString inside java.lang.Record, we
>> need "classy", another mechanism that using a BSM but that time when a vtable
>> slot is derived, when a record ask for the equals/hashCode/toString of
>> java.lang.Record.
> 
> No new feature needed, just optimizing an existing feature which is
> the right tool for the job.  (There’s a reason I added ClassValue at the
> same time as indy:  It does a complementary set of jobs.)
> 
>> It's also not dissimilar to the Bridge-o-matic of Brian, the Forward attribute,
>> equals/hashCode and toString being bridge declaration in j.l.Record and the VM
>> creating the equivalent of an indy calls when building the vtable.
> 
> I like this sort of thinking; I summarize it for myself as “bootstrap
> methods everywhere”.  Multiply that by symbolic mode bootstraps,
> and you can account for a large range of hardwired JVM behaviors
> in terms of “as if this BSM were present”, at each specification point.
> 
> — John

Rémi


More information about the amber-dev mailing list