On Jun 26, 2018, at 7:30 AM, Karen Kinnear <karen.kinn...@oracle.com> wrote: > > Summary: Could we please allow eager loading for value types in the locally > declared method signatures > prior to preparation for LW1?
My answer would be "yes, if said types are mentioned in the ValueTypes attribute". Otherwise, it seems impractical to do eager loading of type names that appear in descriptors, on the off chance that they might be value types. > 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 > > <http://cr.openjdk.java.net/~acorn/value-types-consistency-checking-details.pdf> > The value-types-consistency-checking-details document should probably lead off by describing the ValueTypes attribute, before giving the four bullet points about instance fields, static fields, descriptor types, and cross-call consistency. Otherwise, I get totally lost in the third bullet, when it claims "these types are eagerly loaded" but without saying exactly what triggers this loading. Looking at the Valhalla prototype (which not all spec experts can do) I see that the 'is_declared_value_type' function is queried when method adapters are created, so we can agree that ValueTypes is the source of truth for method arguments and return values. (Given ValueTypes, we don't need ACC_FLATTENABLE, as has been discussed. AFAIK, we are using ACC_FLATTENABLE in LW1 because we don't want to destabilize the system with a cleanup, and because we might want it later, but I'm arguing that we don't want it at all in the long run. Reason: Any such marking of fields is *also* a desirable marking of method descriptor components. Thus, an ACC_FLATTENABLE, applicable only to fields, is not sufficient for our needs, while ValueTypes is both necessary and sufficient. For nullability in particular, what we really need is a marker for both field and method descriptors, along the lines of Fred's N-types. By JVMLS, I expect I will have a concrete proposal in this space that is a side effect of supporting reified type parameters.) (But as long as ACC_FLATTENABLE is in the mix, perhaps the consistency checking rules should *also* insist that the field types of fields so marked must also be mentioned in the ValueTypes attribute?) > 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. Yep, I am not surprised that this is hard to do. So for the LW1 term I say "yes" to both eager loading and method consistency checking. If we can find a way to be explicit about nullability in value type descriptors, then I think we can keep the rest of the L-world descriptor design. The conversation (post LW1) which I see queuing up is whether to go back to Q-types (or some analog) as explicitly non-nullable value type descriptors, or whether to use some other "channel" to convey the nullness information when it differs from some defined background setting. I think that conversation hinges, in part, on how useful it is to change the meaning of LFoo; to be contextually determined as a value type, vs. just being plain with QFoo;. Our experiments with a live LW1 prototype will help us scope this out. > 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. For LW1 we can insist that all the methods agree. This is a brittle state of affairs which we will (almost certainly) need to make more flexible with on-the-fly adapter generation. One key question post LW1 is what design choices will make adapter generation less pervasive. Personally, I hope we'll find a way to require adapters for a small minority of calls, all related to partially executed migrations. This is one reason I'm eager to avoid going back to Q-types, since those seem to require a relatively large number of adapters. > 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. Yes. > 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. Charming. > 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. I don't think it will pan out. It's less invasive than deferred loading of field types, but it's still invasive to change the calling sequence of a v-table slot. One design heuristic here is that fields and v-table slots are often subject to parallel constraints. This is true when binding physical variables (memory locations, argument registers), and also true when creating specializations (in our future template classes). > 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. I hope that if there is a need to telegraph a failure from loading or preparation phases to the resolution phase, then a simple bit will do, rather than a saved exception. Except, of course, for quality of service concerns; in that case a resolution-time error that stems from a deferred value-type check could be given a getCause of the earlier exception. But, yes, this may require JVMS work. — John