> 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.

Karen's initial post mentions our two biggest concerns. If there is no
guarantee that the VTs in the method descriptors will be used, loading them
is an overhead. We would like to minimize the cost to startup as much as
possible. The other reason is eager loading may trigger failures that would
otherwise never occur if the method wasn't run, which is change from how
the JVM normally behaves.

--Tobi

> From: Remi Forax <fo...@univ-mlv.fr>
> To: John Rose <john.r.r...@oracle.com>
> Cc: Tobi Ajila <tobi_aj...@ca.ibm.com>, valhalla-spec-experts
> <valhalla-spec-experts@openjdk.java.net>
> 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" <john.r.r...@oracle.com>
> À: "Tobi Ajila" <tobi_aj...@ca.ibm.com>
> Cc: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net>
> 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 <tobi_aj...@ca.ibm.com> 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 <karen.kinn...@oracle.com>
> > To: valhalla-spec-experts <valhalla-spec-experts@openjdk.java.net>
> > 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-
> > boun...@openjdk.java.net>
> >
> > 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-
> > 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
>

Reply via email to