--Tobi
> From: Remi Forax <[email protected]>
> To: John Rose <[email protected]>
> Cc: Tobi Ajila <[email protected]>, valhalla-spec-experts
> <[email protected]>
> Date: 2018/07/10 05:44 AM
> Subject: Re: EG help please with getting to LW1 re: Value Types
> Consistency Checking
>
> Hi all,
>
> De: "John Rose" <[email protected]>
> À: "Tobi Ajila" <[email protected]>
> Cc: "valhalla-spec-experts" <[email protected]>
> Envoyé: Samedi 7 Juillet 2018 23:08:27
> Objet: Re: EG help please with getting to LW1 re: Value Types
> Consistency Checking
> Hi Tobi. Thanks for the write-up.
>
> To be brief, your proposed technique will seems to require lazier
> selection of calling
> sequences than what Karen proposed. Argument and return registers
> cannot be assigned
> to values if their size is unknown, which is the case before they
> are loaded. The JVM
> must wait as late as the first actual call (with non-null
> parameters) to determine calling
> sequences.
>
> Karen's proposal allows calling sequences to be determined at
> preparation (v-table pack)
> time, while yours requires them to be chosen much later, by the time
> of the first invocation
> of a given v-table slot. (For JVMs without vtables, a "v-table
> slot" really means an
> equivalence class \u0015of CONSTANT_[I*]Methodrefs equated by the
> transitive closure of
> override relations.) The bytecode instruction just before that
> invocation might have been
> a defaultvalue instruction on a previously unloaded class. This
> means the JVM needs
> to install traps in unused v-table slots, so it can decide calling
sequences.
>
> Karen's proposal, therefore, has the advantage of allowing the JVM
> more lead time
> freedom to set up v-table calling sequences, at preparation time.
> Yours requires
> just-in-time assignment of calling sequences, which seems more difficult.
>
> This leads to the question, what advantage did you find, with Packed
> Objects, from
> making calling sequence setup lazier? (I'm assuming that system
> scalarized arguments
> into multiple registers.) In other words, why is your phasing of
> the checks better than
> Karen's?
>
> — John
>
> P.S. Background:
>
> So we are extending object references (Ljava/lang/Object;) to cover
> references to values
> also, at least in L-world. This gives a simple story for the
> interpreter and a fallback for
> less-optimized JIT-compiled code, but isn't enough to compete with
> statically-compiled
> languages.
>
> So the new requirement here is to make it possible for compiled
> calling sequences
> to use specialized representations for value parameters and returns.
> In particular, we
> often wish to use one or more machine registers to hold scalarized
> fields, and we wish
> to exclude null values (which require an extra encoding and impede
> some optimizations).
>
> A secondary requirement is that we wish to pick the compiled calling
> sequence once
> and not have to revise it. This implies picking the calling
> sequence no later than the first
> execution (compiled or interpreted) of any particular method, and
> getting it right the first
> time.
>
> Deoptimization of calling sequences–across override-trees of
> methods–is a trick we are
> holding in reserve, but it seems a risky research project rather
> than an understood technique.
> I think deoptimization at this scale hasn't been proven efficient
> yet, although it may be.
>
> It seems that in order to flatten, we are obligated to load value
> types more eagerly
> than object types. Value types can't "hide behind" a polymorphic
> reference; any
> user of a value type in its native form (not boxed) needs to "see"
> its complete field
> list, which requires loading the classfile. This is certainly true
> for object layout,
> where an object that contains a value-typed field must load that
> value type to see
> how much space it must reserve for it, in that object's flattened
> and packed layout.
>
> Given that we are going to routinely pre-load value type classfiles,
> it is reasonable
> to apply this technique in other places besides the layout of
> instances and fields.
> In particular, the layout of calling sequences is in many ways
> closely analogous
> to the layout of instances. (There is a deep symmetry between calls
> and objects,
> arising perhaps from the fact that function applications are
> isomorphic to curried
> functions or tuples. In any case, it seems to me that some such
> symmetry crops
> up between the O-O notions of field extension and virtual method
> extension, and
> so in JVM's treatment of object layout vs. its treatment of virtual
> dispatch, both of
> which are examined carefully at loading and preparation time, before
> execution.)
>
> The symmetry is only true for immutable class. The main difference
> is that curried functions usually doesn't expose the value of the
> bounded parameters while tuples let you access to those values.
>
> Anyway, if we are going to preload field classes, it is no great
> additional burden to
> preload argument classes too, if an appropriate signal can be
> defined (the VT list).
> It might even be reasonable to preload *all* VTs mentioned in the
> list, just to make
> the preloading process simpler and more predictable. I'm looking
> for reasons that
> this is a *bad* idea, so we can say in the end, "here's exactly why
> we had to make
> the loading logic for VTs so tricky"–if we must.
>
> I think the answer to the question of lazy loading of method
> parameter types is rooted to the question of what is a value type
> exactly for Java.
> Is it an optimization, a first class concept i.e one that should
> work as if it was integrated in the language from the beginning ?
> The other problem is the more we diverge from the class behavior,
> the harder it will be to allow a class to become a value type.
>
> I firmly believe that value type should be first class because they
> are useless in a lot of scenario if they are not. The main
> limitation of a value type is its immutable characteristic, what
> save them from uselessness is that their creation cost should be
> zero or very close to zero alleviating the burden of think in term
> of object creation and making us, developers, free to use functional
idioms.
> With that in mind, i believe a value type should not be "boxed"
> because it's not loaded yet (it can still be boxed due to separate
> compilation but that's another story) so value type present in
> method descriptor should be loaded eagerly.
>
> About loading all value type of the attribute ValueTypes, from one
> side Java has a strong tradition to not pay for the code you do not
> use. This power today's applications, an average application has an
> hundred jars as dependencies, if all value types are preloaded it's
> at waste of memory and cpu cycles. BTW, it's also what's make jaotc
> useless in its current incarnation because it AOTs things your
> application don't care.
>
> Rémi
>
> On Jul 6, 2018, at 8:38 AM, Tobi Ajila <[email protected]> wrote:
>
> I would like to propose an alternative strategy, one that would
> effectively provide the same consistency checks outlined in http://
> cr.openjdk.java.net/~acorn/value-types-consistency-checking-details.pdf
> without requiring eager loading of value types (VT) in the return/
> args of methods during the preparation phase. This is born out of
> our experience with PackedObjects which took a very similar approach
> to the ValueTypes attribute.
>
> This proposal makes use of the existing ValueTypes attribute. In
> addition, it requires that each classloader keeps a registry of
> ‘expected’ VTs.
>
> Proposal
> --------------------------
> The following steps occur in the loading phase:
>
> 1. Prior to loading the current class each type in the ValueTypes
> attribute is checked see if it is loaded. If it is, the type must be
> a VT or ICCE is thrown. Otherwise, the type is registered with the
> initiating classloaders expected VT registry (EVTR).
>
> 2. Pre-loading of ACC_FLATTENABLE instance fields follow the same
> rules as the ones specified in Karen's proposal.
>
> 3. Prior to loading the current class, if the current class is a VT
> it must be in the classloader's EVTR or ICCE is thrown. If the
> current class is not a VT and does appear in the EVTR, ICCE is thrown.
>
> In link phase prior to preparation:
> - Same as Karen's static field rules, "static fields declared with
> the ACC_FLATTENABLE flag set have their type pre-loaded..."
>
> In preparation phase:
> - Same as Karen's method overriding rules, "any method overriding
> needs to perform value type consistency checking between declarer of
> the overridden method ..."
>
> At resolution time:
> - Same as Karen’s CONSTANT_Class, field and method resolution rules
> ---------------------------
>
> The benefit of this approach is that as soon as anyone believes a
> class is a VT, it must be loaded as a VT or it fails. As a result,
> there is no inconsistency of loaded VTs. This proposal doesn't guard
> against cases where a class was not expecting a method return/arg
> type to be a VT but then later on turned out to be a VT when it was
> resolved. However, I think don’t think Karen’s proposal offered
> these guarantees either.
>
> > Some aspects of the implementation complexity that we have
> identified so far:
> > a) At method resolution time, if there is a mismatch in value type
> consistency
> > between the declaring class and the actual type in the signature,
> then there
> > is also a mismatch in all classes that have overridden the current
method.
> > This is particularly painful with default methods in interfaces.
>
> With this proposal the only possible inconsistency here is:
> Method has a return/arg type that is believed to not be a VT but
> turns out to be a VT. In this case any compiled code is doing pass
> by reference calling convention which works for both VT and non-VT
types.
>
> > b) We need to ensure that we catch all method resolution, through
> all of the
> > alternate accessor paths, including MethodHandles, VarHandles,
> Reflection, JNI,
> > so that we catch both the specification and implementation changes.
>
> All these cases are covered with the class loading consistency checks
(EVTR).
>
> > c) Our favorite, invokespecial ACC_SUPER, needs special handling,
since it
> > performs selection which is not based on overriding, but based on
virtually
> > re-resolving.
>
> same as above
>
> > e) If we modify the specification to allow eager loading, and save
errors
> > to throw at method resolution, we need to work through the JVMS
question
> > of which errors would be saved (e.g. OOME, SOE might be thrown as
part of
> > the implementation vs. saving LinkageError), as well as designing a
new
> > implementation mechanism to repeat exceptions relative to
signatures used
> > for method resolution.
>
> This wouldn’t be required in this proposal
>
> > d) Pass by value calling convention optimizations depend on loading
the
> > actual type. Loading of the parameter types on first method resolution
> > implies that if the caller is compiled, the caller method requires
> > deoptimization/recompilation to pass arguments by value for future
calls,
> > which is a performance cost.
>
> Typically, a method is run a few times before it is compiled
> (perhaps I’m making implementation assumptions?). At this stage, the
> return/arg types are either loaded or they are always null. This
> seems to suggest that deoptimization/recompilation scenario would
> not be a common occurrence.
>
>
> --Tobi
>
> > From: Karen Kinnear <[email protected]>
> > To: valhalla-spec-experts <[email protected]>
> > Date: 2018/06/26 10:32 AM
> > Subject: EG help please with getting to LW1 re: Value Types
> > Consistency Checking
> > Sent by: "valhalla-spec-experts" <valhalla-spec-experts-
> > [email protected]>
> >
> > Summary: Could we please allow eager loading for value types in the
> > locally declared method signatures
> > prior to preparation for LW1?
> >
> > Without that we seriously risk being able to offer an LW1 early
> > access binary for the JVMLS.
> > We believe it is more important to get this into people’s hands for
> > experimentation and feedback than
> > to delay the eager loading at this time.
> >
> > Details:
> > At our EG discussion on June 20, 2018, we discussed the proposal for
> > Value Types Consistency checking
> > at http://cr.openjdk.java.net/~acorn/value-types-consistency-
<http://cr.openjdk.java.net/%7Eacorn/value-types-consistency->
> > checking-details.pdf
> >
> > Part of the proposal for checking value type consistency relative to
> > the actual type
> > was for locally declared methods. The proposal was to check the
> > value types in arguments/return type
> > before preparation of the declaring class.
> >
> > During the meeting, there was a request to explore whether we could
either:
> > 1) delay checking the value type consistency until an attempt to
> > resolve the method for invocation, or
> > 2) write the JVMS is such as way as to allow eager loading, but only
> > throw an error related to the eager loading at method resolution.
> >
> > My understanding is that the goals of this are two-fold:
> > 1) if the method is never called, the rest of the code will
continue to run
> > 2) reduce eager loading
> >
> > We have started this investigation, and there is non-trivial
> > complexity in implementing either of these approaches,
> > and we would like more time to explore how to make this possible,
> > after making LW1 available.
> >
> > Some aspects of the implementation complexity that we have
> identified so far:
> > a) At method resolution time, if there is a mismatch in value type
> > consistency between the declaring class and the actual
> > type in the signature, then there is also a mismatch in all classes
> > that have overridden the current method. This is particularly
> > painful with default methods in interfaces.
> > b) We need to ensure that we catch all method resolution, through
> > all of the alternate accessor paths, including MethodHandles,
VarHandles,
> > Reflection, JNI, so that we catch both the specification and
> > implementation changes.
> > c) Our favorite, invokespecial ACC_SUPER, needs special handling,
> > since it performs selection which is not based on overriding, but
> > based on virtually re-resolving.
> > d) Pass by value calling convention optimizations depend on loading
> > the actual type. Loading of the parameter types on first method
> > resolution implies that if the caller is compiled, the caller method
> > requires deoptimization/recompilation to pass arguments by value for
> > future calls, which is a performance cost.
> > e) If we modify the specification to allow eager loading, and save
> > errors to throw at method resolution, we need to work through the
> > JVMS question of which errors would be saved (e.g. OOME, SOE might
> > be thrown as part of the implementation vs. saving LinkageError), as
> > well as designing a new implementation mechanism to repeat
> > exceptions relative to signatures used for method resolution.
> >
> > thanks,
> > Karen
>