hg: valhalla/valhalla: Scanner, parser, semantic analysis and attribution support for value types
srikanth.adayapalam at oracle.com
Wed Jan 31 05:43:11 UTC 2018
Thanks for your comments - There is no need for apologizing and such ! I
am not looking for a fully evolved specification and am happy to
accommodate any changes you require or address any misunderstandings on
my part that you call out :)
Some of the issues you raise though require further discussion and I am
pulling up and enumerating these below:
(In summary ATM (1) through (6) below look as though they don't call for
a change - But I will wait for any contrary opinions.
I'll study (7) and (8) and follow up suitably.)
(1) Branch to use:
I have asked David Simms for clarification, but I based my decision to
push to "exp"
After hearing from David, I'll take suitable follow up actions
(2) Value types may not declare a super class not even j.l.O:
Please note: In the commit I pushed, value classes *do* extend j.l.O, it
is just that they can't explicitly
declare an extends clause even if that only mentions j.l.O
This is consistent with
(a) How in the original valhalla prototype, value types extend
java.lang.__Value, but cannot mention
an explicit super type in the extends clause.
(b) This is also consistent with how all annotation types automatically
implement java.lang.annotation.Annotation but are not allowed to specify
an implements clause in the annotation type declaration site.
(c) This is also consistent with how all enum types implicitly
automatically extend java.lang.Enum, but
cannot expressly extend it.
(d) Also consistent with how all interfaces have j.l.O as a super type
but this cannot be expressed in
For these reasons I am inclined to think we should leave this matter as
is, but can be convinced if I am found to overlook some points.
(3) "Values have no instance lock and so may not be synchronized upon"
(a) A value type may not declare an instance method that has the
modifier synchronized AND
(b) A value instance may not be used to furnish the mutual exclusion
lock for a synchronized statement.
(Already done in the prototype)
(4) Values have no identity and consequently the method
java.lang.System.identityHashCode may not be invoked on them:
I had assumed that java.lang.System.identityHashCode() would be revised to throw an exception at runtime for values, not that javac would catch this
Certainly a runtime check and throw would be required at
j.l.S.identityHashCode(), but it would feel very "unlike Java" to NOT
catch this error statically where possible. I agree not all cases could
be caught at compile time and so a second line defense would be required
(5) The following methods from j.l.O are not allowed on value
receivers: clone(), finalize(), wait(), wait(long), wait(long, int),
Actually they all are - we will be rewriting the j.l.O methods to throw runtime errors if this happens,
so we do not need javac to disallow this
(we will run into this at runtime due to inheritance when passing an Object or interface and the
receiver is a value instance - so we have to do a runtime check anyway)
I understand how values may "leak" into places where they cannot be
discerned to be values statically and hence the rationale for doing a
runtime check anyway and rewriting j.l.O methods to throw runtime errors
when the receiver happens to be a value instance - but not diagnosing
this where it is possible to do so statically in javac would again
similar to (4) above be very unlike Java - That is to defer errors to
runtime where they can be caught and reported right away at compile time.
(6) Clarification: I expect Javac would issue a withfield instruction
only from the static value factory associated with the value type and
nowhere else. As a matter of fact attempt to assign to an instance field
of a value type anywhere else would trigger a compile time error about
final field being modified,
(7) Null assignment to values, casting null to values and null
comparison against values:
Thanks for your comments and the pointer to recent discussion. I'll
study these in detail and make suitable changes or follow up with
requests for additional clarifications.
(8) Value instances may not be compared with == or !=
The proposal was that value instances MAY be compared with if_acmpeq/if_acmp_ne,
and the bytecode will return FALSE if either argument is a value type
This presupposes a model in which “most” code uses a check of ==/!=, null check, .equals() check
Is this true for source code where it can be discerned by the compiler
that one or both of the operands of == or != is a value type ???
http://cr.openjdk.java.net/~jrose/values/values-0.html does foresee
different semantics for == and != on values, including component-wise ==
comparison or invoking equals method, but I am not sure where we stand.
On Tuesday 30 January 2018 10:58 PM, Karen Kinnear wrote:
> I have not yet had a time to look through the code, but I wanted to get back to you right away.
> First - many many thanks for doing this so quickly and for asking for feedback at this
> early phase.
> Some clarifications to the list below. My apologies if I incorrectly specified some to you.
> Thank you for your understanding A we have been evolving some key issues such as how to
> deal with signatures and nullability. So this is a good time to touch base.
> Also - can you touch base with Mr Simms on the repos - my understanding was that
> the “exp” branch was for independent performance experiments based on JDK 11
> without value types support, and he was going to create a new branch ?name TBD? for our joint
>> On Jan 30, 2018, at 4:21 AM, Srikanth <srikanth.adayapalam at oracle.com> wrote:
>> The commit below is the record of the change set I pushed to valhalla "exp" branch
>> that contains the javac changes for scanner, parser, semantic analysis and attribution
>> support for value types. Most of this is leveraged from the existing prototype
>> and tweaked for the present work.
>> No code generation support exists at the moment. I will look into it now.
>> See below for the summary of changes and a couple of questions.
>> Summary of changes:
>> - Tag a type declaration as being a value type with __ByValue modifier (>= JDK11)
>> - Value types may not declare a super class not even j.l.O
> current proposal is that a value type must explicitly declare j.l.O as the super class
>> - Value class declarations and their instance fields must be final.
>> - Value types may not declare fields of their own types either directly or indirectly.
>> - Null cannot be assigned to value types
> This is a very new proposal - still in discussion
> Proposal is to add in the classfile the ACC_NON_NULLABLE flag for FieldInfo
> — I do not know what the language support should be for a prototype?
> — keyword? annotation? Needs a langtools team discussion, perhaps
> before that all gets sorted out stick with the keywords like the rest of the prototype,
> e.g. __NonNullable
> If the field is declared with the ACC_NON_NULLABLE, then writing to this field
> at runtime with throw and NPE.
> Given that it is illegal to use this flag for an object class (vs. a value class)
> javac could catch both the use of this class for an object class, and catch
> assigning these fields to null.
> Let us know if you see a problem with this approach for prototyping
>> - Null cannot be casted to or compared with value types.
> Changed: null can be cast to a value type or compared with a value type
> (we left the semantics of checkcast and instanceof unchanged)
> (see below for comparison discussion)
>> - Support for static value factories and value instance creation via __MakeDefault()
>> - Values have no instance lock and so may not be synchronized upon.
> clarify: it is illegal to declare a non-static synchronized method for a value class
>> - Values have no identity and consequently the method java.lang.System.identityHashCode
>> may not be invoked on them and
> I had assumed that java.lang.System.identityHashCode() would be revised to throw an exception at runtime for values, not that javac would catch this
>> - The following methods from j.l.O are not allowed on value receivers:
>> - clone()
>> - finalize()
>> - wait()
>> - wait(long),
>> - wait(long, int)
>> - notify
>> - notifyAll
> Actually they all are - we will be rewriting the j.l.O methods to throw runtime errors if this happens,
> so we do not need javac to disallow this
> (we will run into this at runtime due to inheritance when passing an Object or interface and the
> receiver is a value instance - so we have to do a runtime check anyway)
>> - Value instances may not be compared with == or !=
> The proposal was that value instances MAY be compared with if_acmpeq/if_acmp_ne,
> and the bytecode will return FALSE if either argument is a value type
> This presupposes a model in which “most” code uses a check of ==/!=, null check, .equals() check
>> - Tests for the above restrictions.
>> 1. ATM, javac forbids comparison of values using != or ==. This behavior is simply
>> brought forward from the original valhalla implementation. Is this what we want in
>> the present prototype ? (in the context of acmp performance characterization ?)
>> 2. The support in the parser allows inner class to be declared as __ByValue. Do we want
>> to restrict values to top level classes ? I seem to recall this being suggested a while
>> ago - but I am unable to dig up the context.
> I added this to the list of open design questions - I think that is a language choice, I don’t
> know why the JVM would care since today it knows nothing really about top level vs
> inner classes.
> Also brings up the question of withfield (renamed) and where it is legal to call it -
> explicit factories, any method in the value class itself, nestmates?
> thanks so much,
>> On Tuesday 30 January 2018 02:49 PM, srikanth.adayapalam at oracle.com wrote:
>>> Changeset: 8d76e47a91e7
>>> Author: sadayapalam
>>> Date: 2018-01-30 14:45 +0530
>>> URL: http://hg.openjdk.java.net/valhalla/valhalla/rev/8d76e47a91e7
>>> Scanner, parser, semantic analysis and attribution support for value types
>>> ! src/java.compiler/share/classes/javax/lang/model/element/Modifier.java
>>> ! src/jdk.compiler/share/classes/com/sun/source/tree/NewClassTree.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
>>> ! src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
>>> ! src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
>>> ! src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java
>>> ! test/langtools/tools/javac/diags/examples.not-yet.txt
>>> + test/langtools/tools/javac/diags/examples/ValuesNotSupported.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckClone.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckClone.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckCyclicMembership.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckCyclicMembership.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckEquals.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckEquals.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckExtends.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckExtends.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckFinal.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckFinal.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckFinalize.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckFinalize.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckIdentityHash.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckIdentityHash.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckIdentityHash01.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckIdentityHash01.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckMakeDefault.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckNullAssign.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckNullAssign.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckNullCastable.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckNullCastable.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckStaticValueFactory.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckStaticValueFactory.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckSuperCompileOnly.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckSync.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckSync.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckSynchronized.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckSynchronized.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckValueFactoryWithReference.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckValueModifier.java
>>> + test/langtools/tools/javac/valhalla/lworld-values/CheckValueModifier.out
>>> + test/langtools/tools/javac/valhalla/lworld-values/Point.java
More information about the valhalla-dev