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