EG help please with getting to LW1 re: Value Types Consistency Checking
Frederic Parain
frederic.parain at oracle.com
Tue Jul 24 13:10:03 UTC 2018
On 07/12/2018 02:41 PM, Tobi Ajila wrote:
> > 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.
This is already the case for flattened value fields: even if the
application never use them, they can cause failures if their
pre-loading fails.
Fred
>
> --Tobi
>
> > From: Remi Forax <forax at univ-mlv.fr>
> > To: John Rose <john.r.rose at oracle.com>
> > Cc: Tobi Ajila <Tobi_Ajila at ca.ibm.com>, valhalla-spec-experts
> > <valhalla-spec-experts at 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.rose at oracle.com>
> > À: "Tobi Ajila" <Tobi_Ajila at ca.ibm.com>
> > Cc: "valhalla-spec-experts" <valhalla-spec-experts at 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_Ajila at 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.kinnear at oracle.com>
> > > To: valhalla-spec-experts <valhalla-spec-experts at 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-
> > > bounces at 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-
> <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
> >
>
More information about the valhalla-spec-experts
mailing list