From brian.goetz at oracle.com Fri Jun 1 20:14:18 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 1 Jun 2018 16:14:18 -0400 Subject: LW1 and ValueTypes consistency In-Reply-To: References: Message-ID: <01e1d376-9927-a53f-019a-a7788dd470d5@oracle.com> To add to the LW1 open issues: how we express constructors.? The current model (exposing a __WithField primitive) is adequate for early adopters but will be a distraction (people are simply unable to understand the notion that this is not the permanent model we're proposing.)? I'd like to scope out the costs of exposing a more traditional constructor idiom. On 5/30/2018 1:41 PM, Karen Kinnear wrote: > Details for LW1: > > Goals of LW1: > Support Early Access Binaries ASAP > Support immutable, identity-free value types that are subtypes of java.lang.Object > > Limitations: > No support for value classes as type parameters for generics (enforced by javac) > No migration of value-based classes > > In order to deliver this as quickly as possible, we want to decouple the agreed-upon proposals from > the currently open issues. > > Specifically, we are decoupling adding the ValueTypes attribute for consistently identifying known value types from > the discussion of how we deal with nullability, which allows us to make significant progress and narrows the open design issues. > This email details this initial step. We have done detailed exploration of eager loading requirements. > > ======= > I. Support for ValueTypes attribute and value type consistency > > Javac: > ValueTypes Attribute identifies value types known at compile time > > Verifier: > Ensure specific bytecodes operate on match of value type vs. not: (withfield, defaultvalue vs. new, monitor*) > > Runtime: > Ensure consistency between assumptions of a type being a value type and the actual type?s expectations when loaded. > > Thanks to Frederic: improvement on consistency guarantees for being a Value Type. > Checks for consistency will be performed and throw ICCE on mismatches between ValueTypes attribute and actual loaded class is_value_type. > > Clarification of terms: > ?preloading? means loading before completion of loading for the declaring class. This is only used for flattenable fields. > ?link-time loading? means loading during the link phase for the declaring class, which is used for all other uses of entries in the ValueTypes attribute. > > 1. *1 Flattenable fields: > preload value types used for local flattenable field descriptors listed in the ValueTypes attribute > 2. Local methods: > load value types in method descriptors (parameters/return) at link time, prior to preparation > 3. constant pool resolution: > all constant pool resolution will ensure value type consistency > 4. References to constant pool descriptors: field and method descriptors > at resolution of target field and method descriptors, for all parameters/return, ensure value type consistency > > Interpreter: > specific bytecodes change behavior based on dynamic checks for is_value_type > > JIT: > specific bytecodes change behavior based on dynamic checks for is_value_type > > Open design issues for LW1 > 1. flattenable statics: > http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-May/000699.html > > 2. nullability handling for LW1. > I will send follow-up email exploring trade-offs. > > thanks, > Karen > > > > > > > > > > From karen.kinnear at oracle.com Tue Jun 5 16:49:37 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Tue, 5 Jun 2018 12:49:37 -0400 Subject: LW1 and ValueTypes consistency In-Reply-To: <01e1d376-9927-a53f-019a-a7788dd470d5@oracle.com> References: <01e1d376-9927-a53f-019a-a7788dd470d5@oracle.com> Message-ID: <8CA0566E-E4FA-4E00-81AE-20AB9042A8D4@oracle.com> John also brought up a question about ensuring consistency of the ValueTypes attribute with actual value types for descriptors which refer to an array of value types. For ensuring global consistency, I?d like to propose that we do check ValueTypes consistency for descriptors containing arrays with base elements in the ValueTypes attribute. If at some point we find that there is a reason not to, then we could reconsider. thanks, Karen > On Jun 1, 2018, at 4:14 PM, Brian Goetz wrote: > > To add to the LW1 open issues: how we express constructors. The current model (exposing a __WithField primitive) is adequate for early adopters but will be a distraction (people are simply unable to understand the notion that this is not the permanent model we're proposing.) I'd like to scope out the costs of exposing a more traditional constructor idiom. > > On 5/30/2018 1:41 PM, Karen Kinnear wrote: >> Details for LW1: >> >> Goals of LW1: >> Support Early Access Binaries ASAP >> Support immutable, identity-free value types that are subtypes of java.lang.Object >> >> Limitations: >> No support for value classes as type parameters for generics (enforced by javac) >> No migration of value-based classes >> >> In order to deliver this as quickly as possible, we want to decouple the agreed-upon proposals from >> the currently open issues. >> >> Specifically, we are decoupling adding the ValueTypes attribute for consistently identifying known value types from >> the discussion of how we deal with nullability, which allows us to make significant progress and narrows the open design issues. >> This email details this initial step. We have done detailed exploration of eager loading requirements. >> >> ======= >> I. Support for ValueTypes attribute and value type consistency >> >> Javac: >> ValueTypes Attribute identifies value types known at compile time >> >> Verifier: >> Ensure specific bytecodes operate on match of value type vs. not: (withfield, defaultvalue vs. new, monitor*) >> >> Runtime: >> Ensure consistency between assumptions of a type being a value type and the actual type?s expectations when loaded. >> >> Thanks to Frederic: improvement on consistency guarantees for being a Value Type. >> Checks for consistency will be performed and throw ICCE on mismatches between ValueTypes attribute and actual loaded class is_value_type. >> >> Clarification of terms: >> ?preloading? means loading before completion of loading for the declaring class. This is only used for flattenable fields. >> ?link-time loading? means loading during the link phase for the declaring class, which is used for all other uses of entries in the ValueTypes attribute. >> >> 1. *1 Flattenable fields: >> preload value types used for local flattenable field descriptors listed in the ValueTypes attribute >> 2. Local methods: >> load value types in method descriptors (parameters/return) at link time, prior to preparation >> 3. constant pool resolution: >> all constant pool resolution will ensure value type consistency >> 4. References to constant pool descriptors: field and method descriptors >> at resolution of target field and method descriptors, for all parameters/return, ensure value type consistency >> >> Interpreter: >> specific bytecodes change behavior based on dynamic checks for is_value_type >> >> JIT: >> specific bytecodes change behavior based on dynamic checks for is_value_type >> >> Open design issues for LW1 >> 1. flattenable statics: >> http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-May/000699.html >> >> 2. nullability handling for LW1. >> I will send follow-up email exploring trade-offs. >> >> thanks, >> Karen >> >> >> >> >> >> >> > From karen.kinnear at oracle.com Tue Jun 5 19:22:28 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Tue, 5 Jun 2018 15:22:28 -0400 Subject: Valhalla EG minutes Message-ID: <7CB2D3F2-0A8D-4032-9210-94AD01AD9708@oracle.com> attendees: Tobi, Dan S, Simms, Frederic, Karen corrections welcome. 1. JVMLS talks LWorld - Tobi & Simms Condy - Dan H & Paul Sandoz Nestmates - Just a Small Change -> actual impact: Karen LWorld discussion - multiple folks willing to participate if this is wanted Abstracts (were) due May 25. 2. Nestmates Reviewed and approved David Holmes? update on java doc for java.lang.class::getNestHost() http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-May/000694.html key points: 1. clarified LinkageError vs. e.g. RuntimeError handling 2. clarified primitive and array class handling - member of nest consisting only of itself 3. all nestmates implicitly in same runtime package Remi sent mail that 6.2 ASM is available supporting Nestmates, Condy and preview versioning - many thanks Remi! 3. Value Types Karen described Towards Minimal LWorld discussion and additional thoughts: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-May/000674.html Key messages: 1. We need to phase in the LWorld support LW1: get minimal LWorld/LW1 out as Early Access binaries ASAP - goal pre-JVMLS LW10: initial preview version LW100: we got there and multiple stages in between 2. Scaled back LW1 requirements 1. No support for erased generics: javac disallow value type may not be used for a type argument 2. No requirement for for migration value-based-class to Value Type: nullability issues not yet resolved 3. LW10: 1. support erased generics (but not specialized) 2. preview quality 3. may discuss other requirements, e.g. from feedback from EA users 4. Nullability discussion 1. Agreed on adding ValueTypes attribute Decouple value type consistency checking from nullability discussion. LW1 would disallow any classfiles to not buy in to the global consistency checking of being a value type. Verifier can check value type/non-value type relative to valid bytecodes (defaultvalue/withfield vs. new/monitor*/putfield) ed. note - see follow-on email: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-June/000705.html 2. Nullability direction: Longer-term goal: decouple non-nullability of a type, make this a property of a container could use this for atomicity and immutability Dan H: long-long term: similar to Arrays 2.0, e.g. frozen arrays 3. Nullability handling for LW1 - very much still under discussion Option 1: LW1: all references to value types are non-nullable start with non-nullability as property of a container - specifically fields and arrays in the heap non-nullable fields are marked as ACC_FLATTENABLE (LW1: all fields containing value types from ValueTypes attribute are marked ACC_FLATTENABLE, so remove source keyword) arrays of value types are by default non-nullable/flattenable LW10: will need to evolve to handle nullable references to support erased generics will need to develop model for array handling that allows distinguishing arrays of value types that may contain null Option 2: LW1: all value types are non-nullable - based on type verifier check to ensure static null not stored via putfield, putstatic, withfield, nor passed in invocation/areturn for value type signature - to provide guarantee null is never seen in a value type signature use Object[] if you need an array that may contain null 4. verifier discussion Karen voiced concerns about guarantees that static null checking would ensure no dynamic nulls in value types in the longer term. Dan H: runtime checks would be prohibitive AI: all see if there are holes here ed. note: potential holes: JNI: native method can return null erased generics can return null for a value type, will need a way to support null future: value-based-classes will be value types that allow null note: aastore does no verifier checks, the type-checks are dynamic, the null checks would also need to be dynamic Dan H: worth exploring VT implement interfaces 5. ValueTypes attribute: 5.1 Value-type eager loading ed. note: see same follow-on email: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-June/000705.html 1. value type fields: pre-load (after pre-loading supertypes) only if flattenable (LW1: all in ValueTypes attribute flattenable) 2. eager load for methods: at link time before preparation 3. challenge: initialization of statics before loading type and getting a default value ed. note: see follow-on email on statics: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-May/000699.html 5.2 other uses of default value - must require class initialization e.g. arrays (anewarray, multianewarray) 6. JVMTI implications of ValueTypes attribute agreed: not remove entries, ok to add or reorder 7. Constructor - LW1 will leave alone for LW10 - see email: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-May/000680.html Feedback on ideas above? Dan H: like the idea of something smaller, early, need to study more thanks, Karen From karen.kinnear at oracle.com Tue Jun 5 22:06:54 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Tue, 5 Jun 2018 18:06:54 -0400 Subject: Static value fields initialization In-Reply-To: References: Message-ID: <114AB9CA-B9CF-4DF8-8B11-53C595E3AD17@oracle.com> John, Thank you for the detailed responses. The big remaining issue is the static value field initialization, so I have extracted that to the top here: > In our experiments, I'd like to lift restrictions > on static field types sooner rather than later. (A workaround for Java > coders would be to define a private static inner class to hold the > problematic statics, but I'd rather not have this sharp edge.) So my original email was working on the assumption that we would require pre-loading the value type for all local fields, instance and static. Pre-loading implies risk of class circularity issues. What I am hearing here is that you would like to be able to define a static field of the same type as the defining value class. With the clarifications below, here is a proposal of how we might do that: 1. pre-load value types used in instance field declarations. 2. for static fields declared to contain a value type: JVMS 5.4.2 describes that static fields are created and initialized to their default values at Preparation, without requiring execution of any JVM code. If we were to load the value types for static fields at link time, prior to Preparation, we would have the size information needed to create the default value to fill in the static fields. With link-time loading, the current value type has already been loaded, so there is no risk of circularity. So - it looks like we can lift this restriction on static field types. Minor corrections below - and thanks for those. Karen > On May 30, 2018, at 4:32 PM, John Rose wrote: > > On May 30, 2018, at 1:14 PM, Karen Kinnear > wrote: >> >> John, >> >> Very much like the direction of your proposal, which I summarize as: >> >> 1. preparation: continue no code execution >> VM determines default value via size information from loaded class >> (flattened fields are pre-loaded, so we have that information at preparation time) >> >> 2. pre-: of the containing class requires for all entries >> in the ValueTypes attribute prior to completing its own > > Yes. Point 2 expands slightly to be "ensure VT. before any bytecode > usage of VT.? That is an improvement. > >> >> ---- >> >> I think we could optimize this to pre- for entries in the ValueTypes attribute that >> are referenced by local flattenable fields, static or instance. >> >> Specifically: we have entries in the ValueTypes attribute for: NameAndType Descriptors: >> 1. local fields >> 2. local method signatures >> 3. remote fields >> 4. remote method signatures 5. all CONSTANT_Class_info constant-pool resolution (apologies for missing this) >> >> I think we only need the pre- for #1 > > I agree, and would prefer this. > >> 3. I think we also need to ensure that other bytecodes that can return a default value instance >> of a value type would also require of the value type: >> defaultvalue, anewarray, multianewarray (JVMS draft 4d already includes defaultvalue, but not yet array bytecodes) > > Good catch on defaultvalue (what I meant by "vdefault"). > > The array bytecodes *do* load the array element class, so we are close > already. The missing bit, I think, is to inspect the loaded array class, > see if it is a value type, and run before creating the array. > This will require us to adjust our initialization barriers a little. > >> Still exploring to see if there are any holes in these assumptions, appreciate additional eyes on this. >> So far so good. > > I'm very glad you think so. In our experiments, I'd like to lift restrictions > on static field types sooner rather than later. (A workaround for Java > coders would be to define a private static inner class to hold the > problematic statics, but I'd rather not have this sharp edge.) > > ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From karen.kinnear at oracle.com Fri Jun 15 15:38:44 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Fri, 15 Jun 2018 11:38:44 -0400 Subject: Valhalla EG minutes June 6, 2018 Message-ID: <4E945830-E5E0-42DD-8578-7793BA9C6F01@oracle.com> Attendees: Remi, Tobi, Dan H, Dan S, Frederic, Karen Corrections welcome. AIs: 1. Karen: proposal for value types consistency checking 2. Karen: updated proposal for handling statics No nestmate or condy topics. Value types: 1. ValueTypes attribute Remi: need to ensure that constant pool Constant_Class and Descriptors for fields and arrays all know about value type-ness Checkcast also needs to know Karen: described evolving proposal: There are two kinds of Value Types Consistency checks: checks vs. real loaded value type and caller-callee consistency checks. All mismatches throw ICCE. - instance value fields that are flattenable require pre-loading, i.e. load the value type if it is in the Value Types attribute prior to completion of loading the declaring class, to allow field flattening. Check vs. real. - local methods: any parameter/return in the ValueTypes attribute eagerly loaded during linking, prior to preparation. Check vs. real. - constant pool resolution for CONSTANT_Class always checks consistency vs. real. This covers anewarray, multianewarray, checkcast, new, defaultvalue, ? - resolution of a field or method in another class, caller-callee consistency checks. Dan S asked if a descriptor has a type which is not in the ValueTypes attribute, do we perform consistency checking? For the constant pool resolution, we always check, whether the value type is in the ValueTypes attribute or not. Dan S: If ClassA and ClassB both believe that Point is not a Value Type (not in their ValueTypes attribute) but it actually is, we need to allow the null case. Dan S: expect this to be analogous with class loader constraints Frederic: Agree with class loader constraint checking locations as the places to perform the checks. Storing ALL the expected value types and expected non-value types has too high a cost. Dan H: class loader constraint analogy makes sense AIs: Karen - email proposal for value types consistency checking 2. Flattenable static fields Challenge is allowing a flattenable static field to contain an instance of the declaring class Karen: note: for handling statics, due to class initialization requirements, we need to ensure that any mechanism (bytecodes and otherwise) that expose default value instances trigger class initialization - e.g. need to add anewarray and multianewarray to the specification along with defaultvalue LW1: Plan is to ban flattened fields from statics so we don?t need to deal yet with either circularity issues or fully working out class initialization issues. Current statics proposal exploring: - VM can initialize a default value at preparation time, without executing java code, based on the size and layout information of the type, without requiring that the type yet be initialized - concern about potential leakage of an instance of the value type, i.e the default value prior to the value type class initialization - bytecodes are fine, but we are investigating the alternate accessors: reflection, methodHandles, JNI, JVMTI, ? Remi: Goal in future remove and initialize statics per field - allowing both eager and lazy field initialization - perhaps use indy - Spring problem with startup (also depends on external environment) - let?s not wait very long for this ed. note - bytecode examples are cleaner than the alternate accessors here - which assume a fully initialized class before exposing handles, jmethodID/jfieldID etc. AI: Karen - updated proposal for flattenable static fields for POST-LW1 3. Constructor idiom: Dan S: Problem is a language problem - do we expose withfield? - do we expose something like a constructor - this is not a vm issue - needs further exploration Remi: Need to ensure this handles migration from class to value type Dan S: value-based-classes today which are eligible for migration all require private constructors if other classes migrate - there is a risk of not ensuring binary compatibility if they do not have private constructors VBC assumptions: no identity assumptions, private constructors Javac exploring a lint mode to check identity assumptions of value-based-classes - not for LW1 4. LW10 goals: Support value types as type parameters for erased generics Definition of ?working? - not throwing NPE when e.g. store null when you pass in an array of value types Remi: if erasure is to Object, must accept writing null Karen: agree: must find a way to accept null Remi: If the Type Parameter bound is a Value Type - can we avoid having to accept null? note: you can not extend a Value Type Remi: Also make sure this works for the case in which ClassA type parameter is bound by Object ClassB extends ClassA, bound by Value Type Karen: LW10 supports value types as type parameter for erased generics - goal is working, optimization not required Later LW>10 support for specialized generics - if you have a non-nullable array of ValueTypes, will allow specialization which will provide performance optimization Remi: If you forget the bound (i.e. do not allow a bound to be a VT) and forget specialization for now For erased generics, need to be able to store null At read time, need to cast note: non generics have similar issues with Object/Interface, [Object/[Interface Karen: exploring three possible directions: PlanA: handle nullability at the language level and erase to nonnullable value types or nullable objects at the vm level PlanB: container model, opt-in to nonnullability for heap containers, leave carrier types: local/operand stack/method args null agnostic PlanC: need two different actual types - needing to also change descriptors and carrier types Remi: What if we were able to transform null to a default value? Karen: first challenge is - if you were to write null, record default value and read it back - you don?t get the same answer - this is a source code surprise Second challenge - we don?t have space for a nullability bit to distinguish a null as unset vs. a valid 0 in locals, registers, etc. If you can figure out a way to do this - it would make life much easier Challenges: 1. ensure we have no user visible semantic changes migrating from erased generics to specialized generics - ok if performance improves 2. Arrays - a big challenge - how do we create arrays, how specify if nullable or not? - copying - definitely start with explicit conversions - array covariance - we need to be extremely clear here on what we require and what we can provide Remi: Today when arrays break the type system, we throw ASE Dan S: could build on ASE - e.g. frozen arrays, nullability - may be some leeway here e.g. sam array with different runtime configuration? Frederic: Brian would like javac to warn if you expect a runtime exception Remi: Maybe erase at the vm level to the same array? thanks, Karen From david.holmes at oracle.com Tue Jun 19 10:23:22 2018 From: david.holmes at oracle.com (David Holmes) Date: Tue, 19 Jun 2018 20:23:22 +1000 Subject: [Nestmates] Updates to the java.lang.Class docs in relation to nests Message-ID: Following some extensive discussion on the JEP-181 CSR, Alex proposed a number of changes to the way we described nests and the new nest related methods in java.lang.Class. There is no normative change to the new reflection API that was added, just a change in how things are presented and described. A new overview was added to the class-level javadoc. For reference the latest version can be seen here: http://cr.openjdk.java.net/~dholmes/8010319-JEP181/specs/ The updated RFR for these changes was posted here: http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-June/053913.html Thanks, David From karen.kinnear at oracle.com Tue Jun 19 15:48:18 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Tue, 19 Jun 2018 11:48:18 -0400 Subject: ValueTypes attribute consistency checking and static fields Message-ID: <59DF1DB5-BA13-466A-991E-3729D57533D8@oracle.com> Frederic and I have worked on a set of proposals for ValueTypes consistency checking. http://cr.openjdk.java.net/~acorn/value-types-consistency-checking-details.pdf The first part contains the proposal. The second walks through details of the consistency checking in the case of a value type missing from the ValueTypes attribute. The third walks the details in the case of a non-value type in the ValueTypes attribute. The goal is to implement the consistency checking for LW1. Reviews appreciated. Suggestions on simpler ways to express the details are also welcome. The proposal also walks through a possible (post-LW1) approach for handling static fields that can contain an instance of the same type. I did not explore Value-Based-Class migration here yet, since that adds significant complexity. thanks, Karen From forax at univ-mlv.fr Wed Jun 20 21:00:23 2018 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 20 Jun 2018 23:00:23 +0200 (CEST) Subject: toString/equals/hashCode implemented using method handles Message-ID: <631112271.1232649.1529528423344.JavaMail.zimbra@u-pem.fr> As discussed during our today meeting, here is an implementation of toString, equals and hashCode that can be used as default implementation of these methods for value types. toString use the ConcatMetafactory so the code is simple, for equals(), it first sort the fields to have the primitive type at the end of the array and the reference type at the beginning, given that the tree is constructed by adding equals tests in front of the previous equals tests, the constructed method handle tree will test the fields that stores primitive types first, for hashCode(), it's just a reduction using foldArguments, it creates big mh trees but the code should be fast (not loop combinator). The code tries to cache every primitive method handles and doesn't cache method handles that come from methods in user-defined classes. Currently the code retrieves the fields using the reflection, making the code hard to test because the order of the fields returned by getDeclaredFields() is not specified, perhaps the list of the fields should be stored in a Constant Dynamic as an array of MethodHandle (we can use MethodHandleInfo if we want the name of a method) and pass as a boostrap argument of the indy call inside toString, equals and hashCode. cheers, R?mi --- package fr.umlv.valuetype; import static java.lang.invoke.MethodHandles.constant; import static java.lang.invoke.MethodHandles.dropArguments; import static java.lang.invoke.MethodHandles.filterArguments; import static java.lang.invoke.MethodHandles.filterReturnValue; import static java.lang.invoke.MethodHandles.foldArguments; import static java.lang.invoke.MethodHandles.guardWithTest; import static java.lang.invoke.MethodHandles.insertArguments; import static java.lang.invoke.MethodHandles.lookup; import static java.lang.invoke.MethodHandles.permuteArguments; import static java.lang.invoke.MethodHandles.publicLookup; import static java.lang.invoke.MethodHandles.zero; import static java.lang.invoke.MethodType.methodType; import static java.lang.invoke.StringConcatFactory.makeConcatWithConstants; import java.lang.invoke.CallSite; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import java.lang.invoke.StringConcatException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Objects; import java.util.stream.IntStream; public class ValueTypeBSM { public static CallSite makeBootstrapMethod(Lookup lookup, String name, MethodType type) { Field[] fields = Arrays.stream(lookup.lookupClass().getDeclaredFields()) .filter(field -> !Modifier.isStatic(field.getModifiers())) .toArray(Field[]::new); return createCallSite(lookup, name, fields); } private static CallSite createCallSite(Lookup lookup, String name, Field[] fields) { switch(name) { case "toString": return createToStringCallSite(lookup, fields); case "equals": return createEqualsCallSite(lookup, fields); case "hashCode": return createHashCodeCallSite(lookup, fields); default: throw new LinkageError("unknown method " + name); } } private static MethodHandle[] findGetters(Lookup lookup, Field[] fields) { MethodHandle[] mhs = new MethodHandle[fields.length]; for(int i = 0; i type) { switch(type.getName()) { case "boolean": return 0; case "byte": return 1; case "char": return 2; case "short": return 3; case "int": return 4; case "long": return 5; case "float": return 6; case "double": return 7; default: throw new AssertionError(); } } static LinkageError newLinkageError(Throwable e) { return (LinkageError)new LinkageError().initCause(e); } static class ArrayToString { // the code that access this array is racy but this is a cache, so that's not an issue private static final MethodHandle[] ADAPTER_CACHE = new MethodHandle[PRIMITIVE_COUNT + 1]; private static final int OBJECT_INDEX = PRIMITIVE_COUNT; static MethodHandle adapter(Class arrayType) { Class componentType = arrayType.getComponentType(); int index = componentType.isPrimitive()? projection(componentType): OBJECT_INDEX; MethodHandle mh = ADAPTER_CACHE[index]; if (mh != null) { return mh; } Class erasedType = componentType.isPrimitive()? arrayType: Object[].class; try { mh = publicLookup().findStatic(Arrays.class, "toString", methodType(String.class, erasedType)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } MethodHandle concurrentMh = ADAPTER_CACHE[index]; if (concurrentMh != null) { return concurrentMh; } ADAPTER_CACHE[index] = mh; return mh; } } private static CallSite createToStringCallSite(Lookup lookup, Field[] fields) { int length = fields.length; StringBuilder format = new StringBuilder(); String separator = ""; Class[] parameterTypes = new Class[length]; MethodHandle[] getters = new MethodHandle[length]; for(int i = 0; i < length; i++) { Field field = fields[i]; format.append(separator).append(field.getName()).append("=\1"); separator = " "; MethodHandle getter; try { getter = lookup.unreflectGetter(field); } catch (IllegalAccessException e) { throw newLinkageError(e); } Class type = field.getType(); if (type.isArray()) { MethodHandle adapter = ArrayToString.adapter(type).asType(methodType(String.class, type)); getter = filterReturnValue(getter, adapter); type = String.class; } getters[i] = getter; parameterTypes[i] = type; } // ask for a MethodHandle that will do the concatenation MethodHandle target; try { target = makeConcatWithConstants(lookup, "toString", methodType(String.class, parameterTypes), format.toString()).dynamicInvoker(); } catch (StringConcatException e) { throw newLinkageError(e); } // apply all getters target = filterArguments(target, 0, getters); // duplicate the first argument (this) target = permuteArguments(target, methodType(String.class, lookup.lookupClass()), new int[length]); return new ConstantCallSite(target); } static class Equality { @SuppressWarnings("unused") private static boolean same(boolean b1, boolean b2) { return b1 == b2; } @SuppressWarnings("unused") private static boolean same(byte b1, byte b2) { return b1 == b2; } @SuppressWarnings("unused") private static boolean same(short s1, short s2) { return s1 == s2; } @SuppressWarnings("unused") private static boolean same(char c1, char c2) { return c1 == c2; } @SuppressWarnings("unused") private static boolean same(int i1, int i2) { return i1 == i2; } @SuppressWarnings("unused") private static boolean same(long l1, long l2) { return l1 == l2; } @SuppressWarnings("unused") private static boolean same(float f1, float f2) { return f1 == f2; } @SuppressWarnings("unused") private static boolean same(double d1, double d2) { return d1 == d2; } @SuppressWarnings("unused") private static boolean same(Object o1, Object o2) { return o1 == o2; } // the code that access this array is racy but this is a cache, so that's not an issue private static final MethodHandle[] SAME_CACHE = new MethodHandle[PRIMITIVE_COUNT]; private static MethodHandle primitiveEquals(Class primitiveType) { int index = projection(primitiveType); MethodHandle mh = SAME_CACHE[index]; if (mh != null) { return mh; } mh = findSameMH(primitiveType); MethodHandle concurrentMh = SAME_CACHE[index]; if (concurrentMh != null) { return concurrentMh; } SAME_CACHE[index] = mh; return mh; } private static MethodHandle findSameMH(Class type) { try { return lookup().findStatic(Equality.class, "same", methodType(boolean.class, type, type)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } } private static final MethodHandle SAME_OBJECT, NULL_CHECK, TRUE, FALSE, IS_INSTANCE; static { MethodHandle mh = findSameMH(Object.class); SAME_OBJECT = mh; NULL_CHECK = dropArguments(insertArguments(mh, 1, (Object)null), 1, Object.class); TRUE = dropArguments(constant(boolean.class, true), 0, Object.class, Object.class); FALSE = dropArguments(constant(boolean.class, false), 0, Object.class, Object.class); try { IS_INSTANCE = publicLookup().findVirtual(Class.class, "isInstance", methodType(boolean.class, Object.class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } } private static MethodHandle objectEquals(Lookup lookup, Class type) { MethodHandle equals; try { equals = lookup.findVirtual(type, "equals", methodType(boolean.class, Object.class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } // equivalent to (a == b)? true: (a == null)? false: a.equals(b) return guardWithTest(SAME_OBJECT.asType(methodType(boolean.class, type, type)), TRUE.asType(methodType(boolean.class, type, type)), guardWithTest(NULL_CHECK.asType(methodType(boolean.class, type, type)), FALSE.asType(methodType(boolean.class, type, type)), equals.asType(methodType(boolean.class, type, type)))); } private static MethodHandle equals(Lookup lookup, Class type) { return type.isPrimitive()? primitiveEquals(type): objectEquals(lookup, type); } private static MethodHandle equalsAll(Lookup lookup, Class declaredType, MethodHandle[] getters) { MethodHandle _false = FALSE.asType(methodType(boolean.class, declaredType, declaredType)); MethodHandle target = TRUE.asType(methodType(boolean.class, declaredType, declaredType)); for(MethodHandle getter: getters) { MethodHandle test = filterArguments(equals(lookup, getter.type().returnType()), 0, getter, getter); target = guardWithTest(test, target, _false); } return target; } static MethodHandle createEquals(Lookup lookup, MethodHandle[] getters) { Class declaredType = lookup.lookupClass(); MethodHandle test = dropArguments(IS_INSTANCE.bindTo(declaredType), 0, declaredType); return guardWithTest(test, equalsAll(lookup, declaredType, getters).asType(methodType(boolean.class, declaredType, Object.class)), FALSE.asType(methodType(boolean.class, declaredType, Object.class))); } } private static CallSite createEqualsCallSite(Lookup lookup, Field[] fields) { // move primitives at the end of the array, so they will be tested first (createEquals creates equals tests from the last to the first) Integer[] orders = IntStream.range(0, fields.length).boxed().toArray(Integer[]::new); Arrays.sort(orders, (index1, index2) -> { Class t1 = fields[index1].getType(); Class t2 = fields[index2].getType(); if (t1.isPrimitive()) { if (!t2.isPrimitive()) { return 1; } } else { if (t2.isPrimitive()) { return -1; } } // for both references and primitives, move them in the array so the first in fields is the last in sortedFields return Integer.compare(index2, index1); }); Field[] sortedFields = new Field[fields.length]; Arrays.setAll(sortedFields, i -> fields[orders[i]]); return new ConstantCallSite(Equality.createEquals(lookup, findGetters(lookup, sortedFields))); } static class HashCode { // the code that access this array is racy but this is a cache, so that's not an issue private static final MethodHandle[] HASH_CODE_CACHE = new MethodHandle[PRIMITIVE_COUNT]; private static final Class[] WRAPPERS = new Class[] { Boolean.class, Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class }; private static Class wrapper(Class primitiveType) { return WRAPPERS[projection(primitiveType)]; } private static MethodHandle primitiveHashCode(Class primitiveType) { int index = projection(primitiveType); MethodHandle mh = HASH_CODE_CACHE[index]; if (mh != null) { return mh; } try { mh = publicLookup().findStatic(wrapper(primitiveType), "hashCode", methodType(int.class, primitiveType)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } MethodHandle concurrentMh = HASH_CODE_CACHE[index]; if (concurrentMh != null) { return concurrentMh; } HASH_CODE_CACHE[index] = mh; return mh; } private static MethodHandle NULL_CHECK, ZERO, REDUCE; static { Lookup lookup = lookup(); try { NULL_CHECK = lookup.findStatic(Objects.class, "isNull", methodType(boolean.class, Object.class)); REDUCE = lookup.findStatic(HashCode.class, "reduce", methodType(int.class, int.class, int.class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } ZERO = dropArguments(zero(int.class), 0, Object.class); } @SuppressWarnings("unused") private static int reduce(int value, int accumulator) { return value + accumulator * 31; } private static MethodHandle objectHashCode(Lookup lookup, Class type) { MethodHandle hashCode; try { hashCode = lookup.findVirtual(type, "hashCode", methodType(int.class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw newLinkageError(e); } return guardWithTest(NULL_CHECK.asType(methodType(boolean.class, type)), ZERO.asType(methodType(int.class, type)), hashCode); } private static MethodHandle hashCode(Lookup lookup, Class type) { return type.isPrimitive()? primitiveHashCode(type): objectHashCode(lookup, type); } static MethodHandle hashCodeAll(Lookup lookup, Class declaredType, MethodHandle[] getters) { MethodHandle target = dropArguments(constant(int.class, 1), 0, declaredType); for(MethodHandle getter: getters) { MethodHandle hashField = filterReturnValue(getter, hashCode(lookup, getter.type().returnType())); target = foldArguments( foldArguments(dropArguments(REDUCE, 2, declaredType), dropArguments(hashField, 0, int.class)), target); } return target; } } private static CallSite createHashCodeCallSite(Lookup lookup, Field[] fields) { return new ConstantCallSite(HashCode.hashCodeAll(lookup, lookup.lookupClass(), findGetters(lookup, fields))); } } From mandy.chung at oracle.com Wed Jun 20 22:00:39 2018 From: mandy.chung at oracle.com (mandy chung) Date: Wed, 20 Jun 2018 15:00:39 -0700 Subject: toString/equals/hashCode implemented using method handles In-Reply-To: <631112271.1232649.1529528423344.JavaMail.zimbra@u-pem.fr> References: <631112271.1232649.1529528423344.JavaMail.zimbra@u-pem.fr> Message-ID: Hi Remi, Thanks for this. I will look into it and gladly update the implementation (the current implementation was just an initial version to enable javac to generate the indy). Mandy On 6/20/18 2:00 PM, Remi Forax wrote: > As discussed during our today meeting, here is an implementation of > toString, equals and hashCode that can be used as default > implementation of these methods for value types. > > toString use the ConcatMetafactory so the code is simple, for > equals(), it first sort the fields to have the primitive type at the > end of the array and the reference type at the beginning, given that > the tree is constructed by adding equals tests in front of the > previous equals tests, the constructed method handle tree will test > the fields that stores primitive types first, for hashCode(), it's > just a reduction using foldArguments, it creates big mh trees but the > code should be fast (not loop combinator). > > The code tries to cache every primitive method handles and doesn't > cache method handles that come from methods in user-defined classes. > > Currently the code retrieves the fields using the reflection, making > the code hard to test because the order of the fields returned by > getDeclaredFields() is not specified, perhaps the list of the fields > should be stored in a Constant Dynamic as an array of MethodHandle > (we can use MethodHandleInfo if we want the name of a method) and > pass as a boostrap argument of the indy call inside toString, equals > and hashCode. > > cheers, R?mi From karen.kinnear at oracle.com Thu Jun 21 17:03:04 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Thu, 21 Jun 2018 13:03:04 -0400 Subject: [Nestmates] Updates to the java.lang.Class docs in relation to nests In-Reply-To: References: Message-ID: Folks - if you could review the changes in the java.lang.Class descriptions please. thanks, Karen David, The changes look good and the meaning has not changed from what we discussed. I actually reviewed all the changes and they also still look good. One minor nit - JDWP canUnrestrictedly RedefineClasses: you might add a space between ?classes? and ?in? thank you, Karen > On Jun 19, 2018, at 6:23 AM, David Holmes wrote: > > Following some extensive discussion on the JEP-181 CSR, Alex proposed a number of changes to the way we described nests and the new nest related methods in java.lang.Class. There is no normative change to the new reflection API that was added, just a change in how things are presented and described. A new overview was added to the class-level javadoc. > > For reference the latest version can be seen here: > > http://cr.openjdk.java.net/~dholmes/8010319-JEP181/specs/ > > The updated RFR for these changes was posted here: > > http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-June/053913.html > > Thanks, > David From brian.goetz at oracle.com Thu Jun 21 20:53:57 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 21 Jun 2018 16:53:57 -0400 Subject: toString/equals/hashCode implemented using method handles In-Reply-To: <631112271.1232649.1529528423344.JavaMail.zimbra@u-pem.fr> References: <631112271.1232649.1529528423344.JavaMail.zimbra@u-pem.fr> Message-ID: > As discussed during our today meeting, > here is an implementation of toString, equals and hashCode that can be used as default implementation of these methods for value types. There is also similar code in the Amber repo for records.? At some point, we should have a bake-off and pick the best implementation; surely we should only have one. From forax at univ-mlv.fr Thu Jun 21 21:41:35 2018 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 21 Jun 2018 23:41:35 +0200 (CEST) Subject: toString/equals/hashCode implemented using method handles In-Reply-To: References: <631112271.1232649.1529528423344.JavaMail.zimbra@u-pem.fr> Message-ID: <1726047884.1635313.1529617295715.JavaMail.zimbra@u-pem.fr> yes, the meta-protocols used are not the same (currently ?), - For records, the BSM is called with an array of method handles because a record defined an order (the order of the primary constructor) - For value type, the BSM doesn't use any supplementary constants (yet ?) Note that means that because the method handles are resolved eagerly (at least now *), a record can not reference a non existing class that will have it's field initialized with null. Note2: the implementation i've provided will not resolved the classes of the field too eagerly but it will still try to load the field class even if the field is null. I'm not sure these small differences are enough to justify to have two implementations, but the requirements are not exactly the same. regards, R?mi * we should restart our discussions about how to lazy resolved bootstrap constant soon. ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" , "valhalla-spec-experts" > Cc: "mandy chung" > Envoy?: Jeudi 21 Juin 2018 22:53:57 > Objet: Re: toString/equals/hashCode implemented using method handles >> As discussed during our today meeting, >> here is an implementation of toString, equals and hashCode that can be used as >> default implementation of these methods for value types. > > There is also similar code in the Amber repo for records.? At some > point, we should have a bake-off and pick the best implementation; > surely we should only have one. From karen.kinnear at oracle.com Tue Jun 26 14:30:39 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Tue, 26 Jun 2018 10:30:39 -0400 Subject: EG help please with getting to LW1 re: Value Types Consistency Checking Message-ID: <58F4AAFF-77D4-4CB4-A296-6620BDE75CA7@oracle.com> 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: From karen.kinnear at oracle.com Fri Jun 29 22:36:11 2018 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Fri, 29 Jun 2018 18:36:11 -0400 Subject: Valhalla EG Notes June 20, 2018 Message-ID: <4521AAF1-AA57-425E-8A0E-24080E107441@oracle.com> NO meeting July 4th, 2018 - US Independence day holiday. Next Meeting July 18th. Karen will be on vacation week of July 18th - looking for a volunteer to run the meeting please. AIs: All: review Nestmates GetNestHost minor rewording of javadoc All: review Value Type Consistency Checking proposal: http://cr.openjdk.java.net/~acorn/value-types-consistency-checking-details.pdf All: see follow-up request - please approve LW1 temporary static method consistency checking before preparation, to be revisited: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-June/000717.html Karen: update Value Types Consistency Checking proposal with BootStrapMethod info attendees: John, Dan S, Tobias, Dan H, Frederic, Remi, Karen I. Nestmates: Please review GetNestHost minor javadoc request II. Condy Remi: when will javac use condy for constant lambdas? Dan S: some experiments have been done, would like to do this, no timeframe yet Condy next step: not require Looking and Name&Type argument Remi: ElasticSearch guy: indy metafactory not do all the needed casting - works for java but not for scala and other languages - will dig and find III. Value Types 1. Equals/Hashcode/toString Remi - saw initial prototype implementation - two different approaches - Records in Amber vs. Valhalla Remi has a version he could clean up and offer for all us to use - weave custom MethodHandles for each type John: using loop combinators? Remi - try not to John: good - love to see it ** follow-on email (many thanks Remi!) 2. Value Types Consistency Checking proposal Karen walked through overview Summary: Two types of checks 1. Value Types attribute vs. reality 2. Value Types attribute of two different classes - e.g. caller-callee Users of Value Types attribute: 1. verifier (with no loading) - catching mismatched bytecode usage 2. optimizations Goal: avoid eager loading Terminology: pre-load: load before completing load of containing class - analogous to supertype handling - only proposed for flattenable instance fields, information needed for layout - risk of circularity eager loading: loading at other times - e.g. linking, preparation, etc. Proposed checking against reality: 1. instance fields (all flattenable in LW1) - pre-loaded: test vs. real 2. flattenable static fields - link phase, prior to preparation (post-LW1): test vs. real 3. local methods: prior to preparation check all (in ValueTypes attribute or not) parameters/return vs. real 4. CONSTANT_Class resolution: for all classes (in ValueTypes attribute or not)test vs. real Proposed checking inter-class consistency 5. Preparation (selection cache creation): method declarer vs. method overrider consistency 6. Field or Method Resolution: For all types in signatures, check caller-callee consistency Note: these checks should essentially match where loader constraint checks are performed today. Note: all the inter-class consistency checks check all the signature types, whether or not they are in the Value Types attribute Remi: if a method is never called, why load parameters? Tobi: why not load one first invocation? John: if load before call - add a new barrier. - challenge with overriding hierarchy - deopt - sudden unpredictable performance drop - preparation is better than 1st call Karen: note: if there is a null on the stack, they might not have loaded a parameter at first call Frederic: Overriding example A.m, B.m, C.m if A is correct, B is incorrect, C is maybe wrong - body of the local method may be incorrect Remi: if the super type is correct but the subtype is not Karen: preparation checks are NOT vs. the real type - they just check overrider/overridden - they could both be wrong and pass that check Frederic: This is more complex with interfaces Dan H: if never call method, want to continue to run, throw an exception when realize inconsistency Dan S: alternative - hotspot implementation could perform the check early and cache and throw the exception at first invocation AI: Karen - investigate possibilities including either delaying checking or offering the option to check earlier but delay throwing any exceptions ed. note - sent follow-up email: started the exploration - too complex for LW1 timeframe - asked for approval to keep proposal for now and revisit after we get early access binaries into people?s hands John: Constant_Class resolution - need to also check BootStrapMethod evaluation for indy and condy - spec says ?as if by ldc?. Karen: Issue 1: Note that it is possible for class A to declare a field of V, not know it is a value type, and class C to also not know and to store null in the field, because field resolution only checks between the caller-callee, not reality. Folks were ok with letting this work. III. Static fields - flattenability Karen summarized some of the issues and options outlined in the Value Types Consistency Checking: - risk of circularity errors if we pre-load static fields that are (flattenable) value types. Since there is a requirement to allow a static field to contain an instance of the container type, we obviously can not pre-load. - Preparation time issues: - Preparation is prior to class initialization - challenge in creating a default value instance of a class which has not yet been initialized - theory is that you can?t actually get to the static without initializing the class choices: 1. trigger class initialization early 2. prevent a leak John: bytecodes and MH-like bytecodes know how to make a default instance before class initialization Note: there is a risk of the default value instance escaping prior to initialization ? e.g. JVMTI - maybe spec bug - getFieldIDs/getMethodIDs - require a class to be prepared - should require a class to be initialized (since the jfieldIDs/jmethodIDs will be used by JNI which requires the class to be initialized, and the getField/getStatic etc. JNI methods do NOT ensure this for performance). This is a bug. ? JLS is explicit about hole during that allows the initializer to create an instance of itself and publish it for external view - this is an actual problem - Note that once the instance escapes - there are no class initialization barriers on bytecodes for instances - it is assumed that these are caught at ?new? or ?defaultvalue? Remi: agree with John - go ahead and initialize during preparation to a default value and do not trigger class initialization Dan S: prefer get static trigger class initialization rather than preparation John: concern about circularities for class initialization Karen: circularities - only for class loading, not for initialization - logic explicitly allows same thread to ?successfully? initialize if already in initialization Karen: class initialization of a container should trigger class initialization of all flattenable fields John: any additional class initialization barriers for hiding default - e.g. anewarray Preparation essentially creates storage, AI: Karen - double check potential JVMTI bug Corrections welcome, thanks, Karen From john.r.rose at oracle.com Sat Jun 30 00:31:15 2018 From: john.r.rose at oracle.com (John Rose) Date: Fri, 29 Jun 2018 17:31:15 -0700 Subject: EG help please with getting to LW1 re: Value Types Consistency Checking In-Reply-To: <58F4AAFF-77D4-4CB4-A296-6620BDE75CA7@oracle.com> References: <58F4AAFF-77D4-4CB4-A296-6620BDE75CA7@oracle.com> Message-ID: <780F9992-6CEA-4141-BC9B-0C737F7B755F@oracle.com> On Jun 26, 2018, at 7:30 AM, Karen Kinnear 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 > 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: