From daniel.smith at oracle.com Wed Sep 6 15:10:12 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 6 Sep 2023 15:10:12 +0000 Subject: EG meeting *canceled* 2023-09-06 Message-ID: <275C2258-F2D9-438D-8F81-4951620CF161@oracle.com> No new email traffic, so we'll cancel today's meeting. We've been working on some details regarding methods internally at Oracle, should have a solid plan to discuss next time. From daniel.smith at oracle.com Wed Sep 20 00:24:38 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 20 Sep 2023 00:24:38 +0000 Subject: Rules for larval value object construction Message-ID: We've spent some time investigating the idea of larval value object construction, and are enthusiastic about this change. Here are some details. 1) In the JVM, we no longer need the special methods or the 'aconst_init' and 'withfield' instructions. Drop them. 2) Value objects are constructed just like identity objects, via field mutation. However, the "object" being mutated is in a larval state and we want to give implementations a lot of flexibility in how these larval objects are implemented. Thus, the language and JVM must ensure that a larval object is never observable?it can be written to but not read. 3) New language concept/modifier: a 'regulated' constructor. (Trying a name out here, haven't put a ton of thought into naming. Feel free to bikeshed.) The 'regulated' keyword can be applied to any constructor in any class. 4) A 'regulated' constructor promises not to make any use of 'this'. An error occurs if this promise is violated in any of a number of different ways: direct reference, instance field access (except for assignment targets), instance method invocation, implicit use as an enclosing instance, any of these occurring in an initializer expression/block, and, importantly, a 'super()' or 'this()' call to a different non-regulated constructor. These checks are very similar to the longstanding rules for "pre-construction contexts" clarified by JEP 447. 5) The no-arg constructor of 'Object' is 'regulated'. The default constructor of any other class (the one you get if you declare no constructor) is implicitly 'regulated' if the superclass's no-arg constructor is 'regulated'. (A slight incompatibility here that I think we can tolerate: if you have an implicit constructor but also an initializer that depends on 'this', an error occurs.) 6) Every constructor of a value class is implicitly 'regulated'. (Similar to the rule that says every instance field of a value class is 'final'.) 7) In the class file, there's an ACC_REGULATED flag for methods, only allowed to be applied to methods. 8) At class loading, an ACC_VALUE class requires that its constructors all be ACC_REGULATED. 9) Verification ensures that 'this' is never read from or passed out of an ACC_REGULATED method. Specifically, in such a method, the type of 'this' is 'uninitializedThis' even after the invokespecial super/this call. Verification also ensures that the target of an invokespecial super/this call is ACC_REGULATED. (See detailed rules below.) 10) The point at which control returns to a invokespecial of an method that *doesn't* represent a super/this call is the point at which a larval object becomes promoted to a "real" value object and the verification type can be 'LValueClass;'. No spec changes here, other than conveying that concept. ----- Some benefits of this approach: - Garbage collecting special new opcodes and the methods, a big simplification - Full binary compatibility when a class is refactored from identity to new, or vice versa - (I think) ability to translate an identity class to a value class by simply flipping a flag bit - Surfacing of a useful general-purpose concept: constructors that can be counted on not to leak 'this' - Fewer restrictions on value objects' superclass constructors: allow code, access control, and checked exceptions - Support for instance fields in superclasses of value objects (!)* (*We can logically allow for superclass fields, anyway. It's possible we'll decide there are implementation constraints that prevent implementing this immediately.) One risk is that ACC_REGULATED methods must not be instrumented in ways that make use of 'this'. This restriction applies to the constructor of Object. What are the chances this breaks somebody's tooling? ----- Suggested verification rule revisions: rewrittenUninitializedType(uninitializedThis, Environment, MethodClass, **Descriptor,** MethodClass) :- MethodClass = class(MethodClassName, CurrentLoader), thisClass(Environment, MethodClass), **Environment = (_, CurrentMethod, _, _, _, _),** **\+ isRegulated(CurrentMethod).** rewrittenUninitializedType(uninitializedThis, Environment, MethodClass, **Descriptor,** uninitializedThis) :- MethodClass = class(MethodClassName, CurrentLoader), thisClass(Environment, MethodClass), **Environment = (_, CurrentMethod, _, _, _, _),** **isRegulated(CurrentMethod),** **isRegulatedTarget(MethodClass, Descriptor).** rewrittenUninitializedType(uninitializedThis, Environment, MethodClass, **Descriptor,** MethodClass) :- MethodClass = class(MethodClassName, CurrentLoader), thisClass(Environment, class(thisClassName, thisLoader)), superclassChain(thisClassName, thisLoader, [MethodClass | Rest]), **Environment = (_, CurrentMethod, _, _, _, _),** **\+ isRegulated(CurrentMethod).** rewrittenUninitializedType(uninitializedThis, Environment, MethodClass, **Descriptor,** uninitializedThis) :- MethodClass = class(MethodClassName, CurrentLoader), thisClass(Environment, class(thisClassName, thisLoader)), superclassChain(thisClassName, thisLoader, [MethodClass | Rest]), **Environment = (_, CurrentMethod, _, _, _, _),** **isRegulated(CurrentMethod),** **isRegulatedTarget(MethodClass, Descriptor).** **isRegulatedTarget(MethodClass, Descriptor) :-** **declaredMethod(MethodClass, '', Descriptor, TargetMethod),** **isRegulated(TargetMethod).** **isRegulatedTarget(MethodClass, Descriptor) :-** **\+ declaredMethod(MethodClass, '', Descriptor, TargetMethod).** // target method is missing, verification can proceed but resolution will cause NSME ----- Some observations made from a corpus analysis of constructor declarations: - About ? of abstract classes are stateless, and almost 80% of these have implicit constructors, so could be automatically converted to get a 'regulated' constructor (conditional on the superclass becoming 'regulated' as well). Almost all of the remaining 20% could be made 'regulated' by applying a keyword?'this' dependency is very rare (<0.3% of value candidates, rarer in other cases). - Among the stateful abstract classes, most are mutable, but 22% are potential value superclasses (about half as many, by raw count, as the stateless abstract value candidates). Around 20% of abstract stateful classes have implicit constructors. There's a fairly high rate of 'this' dependency?around 17%, both overall and among value candidates. Per some spot checking, I imagine most of these can be easily refactored, if it's worth the trouble to make the stateful class value-compatible. - Summarizing: among abstract classes intended to be subclassed, 56% are disqualified from being a value class super (based on mutability/concrete super), 23% can be made value-compatible with recompilation, 18% can be made value-compatible with source modifier opt-in, and 3% would require some refactoring. - Standard concrete stateless classes tend to be things like singletons. 95% appear to be migratable to value classes without any source changes except the 'value' modifier (assuming they don't get subclassed and are okay with being made 'final'). - Mutable classes dominate the space of standard concrete stateful classes, but around ? of standard stateful classes are value candidates, and 93% of these appear to be migratable to value classes without any source changes except the 'value' modifier. Again, the remaining 7% will tend to be classes with constructors that can be easily refactored, plus a few with 'this' dependencies that can't be easily removed. From daniel.smith at oracle.com Wed Sep 20 14:42:17 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 20 Sep 2023 14:42:17 +0000 Subject: EG meeting 2023-09-20 Message-ID: An EG meeting will be held today, September 20, at 4pm UTC (9am PDT, 12pm EDT). To discuss: - "Rules for larval value object construction", describing how we can implement value class construction via methods From jf.mend at gmail.com Mon Sep 25 00:57:35 2023 From: jf.mend at gmail.com (=?UTF-8?B?Sm/Do28gTWVuZG9uw6dh?=) Date: Mon, 25 Sep 2023 01:57:35 +0100 Subject: Synchronized blocks in value constructors Message-ID: I would like to propose a new syntax to specify that, in a value class, some fields must be assigned atomically together: *** synchronized blocks in value class constructors. *** Advantages: - granularity - only the specific fields involved in an invariant need to be assigned in the same synchronized block. Multiple blocks can be used for independent invariants. Tearing is allowed between blocks and between fields assigned outside blocks. VMs could take advantage of this to perform optimizations. - economy - no new keyword/annotation/interface needed. - compatibility - synchronized blocks are currently illegal in constructors. - safety - just like with identity classes, the absence of a synchronized block in a constructor means that the whole constructor is synchronized, i.e. all fields are written atomically. - safety - an empty synchronized block is required to indicate that tearing is allowed between any fields. - clarity - "A synchronized block of field assignments" is a very intuitive description of the semantics involved, given the meaning of the word "synchronized" in english. Disadvantages: - aesthetics - an empty synchronized block is required to indicate that tearing is allowed between any fields. - safety - a user of a value class has no automatic way to be informed of if/where tearing may occur (can be fixed with an update to the generation of java docs). - clarity - synchronized blocks (?14.18.) have two meanings: - The old meaning in regular methods: only one thread may be running inside of a block for the object given in the expression clause - The new meaning in constructors: all assignments in a block are written atomically (no expression clause) Example: value class Range { long start, end; public Range(long start, long end) { if (start > end) throw new IllegalArgumentException(); synchronized { this.start = start; this.end = end; } } } Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: value class Range { long start, end; public Range(long start, long end) { if (start > end) throw new IllegalArgumentException(); this.start = start; this.end = end; } } Another example: value class Point { double x, y; public Point(double x, double y) { synchronized {} this.x = x; this.y = y; } } Jo?o Mendon?a -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Mon Sep 25 01:07:47 2023 From: liangchenblue at gmail.com (-) Date: Mon, 25 Sep 2023 09:07:47 +0800 Subject: Synchronized blocks in value constructors In-Reply-To: References: Message-ID: Hello Joao, I believe the synchronized block proposal is fragile and isn't a good hint to the VM. Each constructor can declare its own synchronization groups, which makes behaviorally-correct optimization harder. For your purpose where you only need to declare some of the properties of the value class atomically together, you can group those properties in an atomic (regular) value class. Then, you can include these regular value classes in a non-atomic value class. Say you have this: value class Container { int a, b, c; Container(int a, int b, int c) { synchronized { this.a = a; this.b = b; } this.c = c; } } Why not this instead: nonatomic value class Container { value class Constraint { int a, b; Constraint(int a, int b) { this.a = a; this.b = b; } } Constraint ab; int c; Container(int a, int b, int c) { this.ab = new Constraint(a, b); this.c = c; } } Chen Liang On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: > I would like to propose a new syntax to specify that, in a value class, > some fields must be assigned atomically together: > > *** synchronized blocks in value class constructors. *** > > > Advantages: > > - granularity - only the specific fields involved in an invariant > need to be assigned in the same synchronized block. Multiple blocks can be > used for independent invariants. Tearing is allowed between blocks and > between fields assigned outside blocks. VMs could take advantage of this to > perform optimizations. > - economy - no new keyword/annotation/interface needed. > - compatibility - synchronized blocks are currently illegal in > constructors. > - safety - just like with identity classes, the absence of a > synchronized block in a constructor means that the whole constructor is > synchronized, i.e. all fields are written atomically. > - safety - an empty synchronized block is required to indicate that > tearing is allowed between any fields. > - clarity - "A synchronized block of field assignments" is a very > intuitive description of the semantics involved, given the meaning of the > word "synchronized" in english. > > > Disadvantages: > > - aesthetics - an empty synchronized block is required to indicate > that tearing is allowed between any fields. > - safety - a user of a value class has no automatic way to be informed > of if/where tearing may occur (can be fixed with an update to the > generation of java docs). > - clarity - synchronized blocks (?14.18.) have two meanings: > - The old meaning in regular methods: only one thread may be > running inside of a block for the object given in the expression clause > - The new meaning in constructors: all assignments in a block are > written atomically (no expression clause) > > Example: > > value class Range { > long start, end; > public Range(long start, long end) { > if (start > end) throw new IllegalArgumentException(); > synchronized { > this.start = start; > this.end = end; > } > } } > > Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: > > value class Range { > long start, end; > > public Range(long start, long end) { > if (start > end) throw new IllegalArgumentException(); > this.start = start; > this.end = end; > } } > > > Another example: > > value class Point { > double x, y; > public Point(double x, double y) { > synchronized {} > this.x = x; this.y = y; > } } > > > > Jo?o Mendon?a > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Mon Sep 25 01:07:47 2023 From: liangchenblue at gmail.com (-) Date: Mon, 25 Sep 2023 09:07:47 +0800 Subject: Synchronized blocks in value constructors In-Reply-To: References: Message-ID: Hello Joao, I believe the synchronized block proposal is fragile and isn't a good hint to the VM. Each constructor can declare its own synchronization groups, which makes behaviorally-correct optimization harder. For your purpose where you only need to declare some of the properties of the value class atomically together, you can group those properties in an atomic (regular) value class. Then, you can include these regular value classes in a non-atomic value class. Say you have this: value class Container { int a, b, c; Container(int a, int b, int c) { synchronized { this.a = a; this.b = b; } this.c = c; } } Why not this instead: nonatomic value class Container { value class Constraint { int a, b; Constraint(int a, int b) { this.a = a; this.b = b; } } Constraint ab; int c; Container(int a, int b, int c) { this.ab = new Constraint(a, b); this.c = c; } } Chen Liang On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: > I would like to propose a new syntax to specify that, in a value class, > some fields must be assigned atomically together: > > *** synchronized blocks in value class constructors. *** > > > Advantages: > > - granularity - only the specific fields involved in an invariant > need to be assigned in the same synchronized block. Multiple blocks can be > used for independent invariants. Tearing is allowed between blocks and > between fields assigned outside blocks. VMs could take advantage of this to > perform optimizations. > - economy - no new keyword/annotation/interface needed. > - compatibility - synchronized blocks are currently illegal in > constructors. > - safety - just like with identity classes, the absence of a > synchronized block in a constructor means that the whole constructor is > synchronized, i.e. all fields are written atomically. > - safety - an empty synchronized block is required to indicate that > tearing is allowed between any fields. > - clarity - "A synchronized block of field assignments" is a very > intuitive description of the semantics involved, given the meaning of the > word "synchronized" in english. > > > Disadvantages: > > - aesthetics - an empty synchronized block is required to indicate > that tearing is allowed between any fields. > - safety - a user of a value class has no automatic way to be informed > of if/where tearing may occur (can be fixed with an update to the > generation of java docs). > - clarity - synchronized blocks (?14.18.) have two meanings: > - The old meaning in regular methods: only one thread may be > running inside of a block for the object given in the expression clause > - The new meaning in constructors: all assignments in a block are > written atomically (no expression clause) > > Example: > > value class Range { > long start, end; > public Range(long start, long end) { > if (start > end) throw new IllegalArgumentException(); > synchronized { > this.start = start; > this.end = end; > } > } } > > Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: > > value class Range { > long start, end; > > public Range(long start, long end) { > if (start > end) throw new IllegalArgumentException(); > this.start = start; > this.end = end; > } } > > > Another example: > > value class Point { > double x, y; > public Point(double x, double y) { > synchronized {} > this.x = x; this.y = y; > } } > > > > Jo?o Mendon?a > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Mon Sep 25 01:17:07 2023 From: liangchenblue at gmail.com (-) Date: Mon, 25 Sep 2023 09:17:07 +0800 Subject: Synchronized blocks in value constructors In-Reply-To: References: Message-ID: Removed expert group comments and added valhalla-dev to the recipient list. This topic should go to valhalla-dev. On Mon, Sep 25, 2023 at 9:07?AM - wrote: > Hello Joao, > I believe the synchronized block proposal is fragile and isn't a good hint > to the VM. Each constructor can declare its own synchronization groups, > which makes behaviorally-correct optimization harder. > For your purpose where you only need to declare some of the properties of > the value class atomically together, you can group those properties in an > atomic (regular) value class. Then, you can include these regular value > classes in a non-atomic value class. > > Say you have this: > value class Container { > int a, b, c; > Container(int a, int b, int c) { > synchronized { this.a = a; this.b = b; } > this.c = c; > } > } > > Why not this instead: > nonatomic value class Container { > value class Constraint { > int a, b; > Constraint(int a, int b) { this.a = a; this.b = b; } > } > Constraint ab; int c; > Container(int a, int b, int c) { > this.ab = new Constraint(a, b); > this.c = c; > } > } > > Chen Liang > > On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: > >> I would like to propose a new syntax to specify that, in a value class, >> some fields must be assigned atomically together: >> >> *** synchronized blocks in value class constructors. *** >> >> >> Advantages: >> >> - granularity - only the specific fields involved in an invariant >> need to be assigned in the same synchronized block. Multiple blocks can be >> used for independent invariants. Tearing is allowed between blocks and >> between fields assigned outside blocks. VMs could take advantage of this to >> perform optimizations. >> - economy - no new keyword/annotation/interface needed. >> - compatibility - synchronized blocks are currently illegal in >> constructors. >> - safety - just like with identity classes, the absence of a >> synchronized block in a constructor means that the whole constructor is >> synchronized, i.e. all fields are written atomically. >> - safety - an empty synchronized block is required to indicate that >> tearing is allowed between any fields. >> - clarity - "A synchronized block of field assignments" is a very >> intuitive description of the semantics involved, given the meaning of the >> word "synchronized" in english. >> >> >> Disadvantages: >> >> - aesthetics - an empty synchronized block is required to indicate >> that tearing is allowed between any fields. >> - safety - a user of a value class has no automatic way to be >> informed of if/where tearing may occur (can be fixed with an update to >> the generation of java docs). >> - clarity - synchronized blocks (?14.18.) have two meanings: >> - The old meaning in regular methods: only one thread may be >> running inside of a block for the object given in the expression clause >> - The new meaning in constructors: all assignments in a block >> are written atomically (no expression clause) >> >> Example: >> >> value class Range { >> long start, end; >> public Range(long start, long end) { >> if (start > end) throw new IllegalArgumentException(); >> synchronized { >> this.start = start; >> this.end = end; >> } >> } } >> >> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >> >> value class Range { >> long start, end; >> >> public Range(long start, long end) { >> if (start > end) throw new IllegalArgumentException(); >> this.start = start; >> this.end = end; >> } } >> >> >> Another example: >> >> value class Point { >> double x, y; >> public Point(double x, double y) { >> synchronized {} >> this.x = x; this.y = y; >> } } >> >> >> >> Jo?o Mendon?a >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From jf.mend at gmail.com Mon Sep 25 09:00:37 2023 From: jf.mend at gmail.com (=?UTF-8?B?Sm/Do28gTWVuZG9uw6dh?=) Date: Mon, 25 Sep 2023 10:00:37 +0100 Subject: Synchronized blocks in value constructors In-Reply-To: References: Message-ID: Hello Chen, Thank you very much for your response. To address the fragility issue you raised, I would modify the new syntax proposal to: *** synchronized blocks in value class field declarations. *** To your very good point on granularity, I think that synchronized blocks could still be considered more readable than having to segregate fields in separate value classes and using some other class modifier/keyword to indicate non-atomicity. All the other advantages/disadvantages would remain the same. Your example would become: value class Container { synchronized {int a, b;} int c; Container(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } } Jo?o Mendon?a On Mon, Sep 25, 2023 at 2:08?AM - wrote: > Hello Joao, > I believe the synchronized block proposal is fragile and isn't a good hint > to the VM. Each constructor can declare its own synchronization groups, > which makes behaviorally-correct optimization harder. > For your purpose where you only need to declare some of the properties of > the value class atomically together, you can group those properties in an > atomic (regular) value class. Then, you can include these regular value > classes in a non-atomic value class. > > Say you have this: > value class Container { > int a, b, c; > Container(int a, int b, int c) { > synchronized { this.a = a; this.b = b; } > this.c = c; > } > } > > Why not this instead: > nonatomic value class Container { > value class Constraint { > int a, b; > Constraint(int a, int b) { this.a = a; this.b = b; } > } > Constraint ab; int c; > Container(int a, int b, int c) { > this.ab = new Constraint(a, b); > this.c = c; > } > } > > Chen Liang > > On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: > >> I would like to propose a new syntax to specify that, in a value class, >> some fields must be assigned atomically together: >> >> *** synchronized blocks in value class constructors. *** >> >> >> Advantages: >> >> - granularity - only the specific fields involved in an invariant >> need to be assigned in the same synchronized block. Multiple blocks can be >> used for independent invariants. Tearing is allowed between blocks and >> between fields assigned outside blocks. VMs could take advantage of this to >> perform optimizations. >> - economy - no new keyword/annotation/interface needed. >> - compatibility - synchronized blocks are currently illegal in >> constructors. >> - safety - just like with identity classes, the absence of a >> synchronized block in a constructor means that the whole constructor is >> synchronized, i.e. all fields are written atomically. >> - safety - an empty synchronized block is required to indicate that >> tearing is allowed between any fields. >> - clarity - "A synchronized block of field assignments" is a very >> intuitive description of the semantics involved, given the meaning of the >> word "synchronized" in english. >> >> >> Disadvantages: >> >> - aesthetics - an empty synchronized block is required to indicate >> that tearing is allowed between any fields. >> - safety - a user of a value class has no automatic way to be >> informed of if/where tearing may occur (can be fixed with an update to >> the generation of java docs). >> - clarity - synchronized blocks (?14.18.) have two meanings: >> - The old meaning in regular methods: only one thread may be >> running inside of a block for the object given in the expression clause >> - The new meaning in constructors: all assignments in a block >> are written atomically (no expression clause) >> >> Example: >> >> value class Range { >> long start, end; >> public Range(long start, long end) { >> if (start > end) throw new IllegalArgumentException(); >> synchronized { >> this.start = start; >> this.end = end; >> } >> } } >> >> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >> >> value class Range { >> long start, end; >> >> public Range(long start, long end) { >> if (start > end) throw new IllegalArgumentException(); >> this.start = start; >> this.end = end; >> } } >> >> >> Another example: >> >> value class Point { >> double x, y; >> public Point(double x, double y) { >> synchronized {} >> this.x = x; this.y = y; >> } } >> >> >> >> Jo?o Mendon?a >> >> On Mon, Sep 25, 2023 at 2:08?AM - wrote: > Hello Joao, > I believe the synchronized block proposal is fragile and isn't a good hint > to the VM. Each constructor can declare its own synchronization groups, > which makes behaviorally-correct optimization harder. > For your purpose where you only need to declare some of the properties of > the value class atomically together, you can group those properties in an > atomic (regular) value class. Then, you can include these regular value > classes in a non-atomic value class. > > Say you have this: > value class Container { > int a, b, c; > Container(int a, int b, int c) { > synchronized { this.a = a; this.b = b; } > this.c = c; > } > } > > Why not this instead: > nonatomic value class Container { > value class Constraint { > int a, b; > Constraint(int a, int b) { this.a = a; this.b = b; } > } > Constraint ab; int c; > Container(int a, int b, int c) { > this.ab = new Constraint(a, b); > this.c = c; > } > } > > Chen Liang > > On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: > >> I would like to propose a new syntax to specify that, in a value class, >> some fields must be assigned atomically together: >> >> *** synchronized blocks in value class constructors. *** >> >> >> Advantages: >> >> - granularity - only the specific fields involved in an invariant >> need to be assigned in the same synchronized block. Multiple blocks can be >> used for independent invariants. Tearing is allowed between blocks and >> between fields assigned outside blocks. VMs could take advantage of this to >> perform optimizations. >> - economy - no new keyword/annotation/interface needed. >> - compatibility - synchronized blocks are currently illegal in >> constructors. >> - safety - just like with identity classes, the absence of a >> synchronized block in a constructor means that the whole constructor is >> synchronized, i.e. all fields are written atomically. >> - safety - an empty synchronized block is required to indicate that >> tearing is allowed between any fields. >> - clarity - "A synchronized block of field assignments" is a very >> intuitive description of the semantics involved, given the meaning of the >> word "synchronized" in english. >> >> >> Disadvantages: >> >> - aesthetics - an empty synchronized block is required to indicate >> that tearing is allowed between any fields. >> - safety - a user of a value class has no automatic way to be >> informed of if/where tearing may occur (can be fixed with an update to >> the generation of java docs). >> - clarity - synchronized blocks (?14.18.) have two meanings: >> - The old meaning in regular methods: only one thread may be >> running inside of a block for the object given in the expression clause >> - The new meaning in constructors: all assignments in a block >> are written atomically (no expression clause) >> >> Example: >> >> value class Range { >> long start, end; >> public Range(long start, long end) { >> if (start > end) throw new IllegalArgumentException(); >> synchronized { >> this.start = start; >> this.end = end; >> } >> } } >> >> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >> >> value class Range { >> long start, end; >> >> public Range(long start, long end) { >> if (start > end) throw new IllegalArgumentException(); >> this.start = start; >> this.end = end; >> } } >> >> >> Another example: >> >> value class Point { >> double x, y; >> public Point(double x, double y) { >> synchronized {} >> this.x = x; this.y = y; >> } } >> >> >> >> Jo?o Mendon?a >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Mon Sep 25 09:37:57 2023 From: liangchenblue at gmail.com (-) Date: Mon, 25 Sep 2023 17:37:57 +0800 Subject: Synchronized blocks in value constructors In-Reply-To: References: Message-ID: Honestly, I don't understand why you propose this, for synchronized is ALREADY the default behavior of Value Classes per JEP 401. By default, all fields in a value class are synchronized (non-atomic), so you won't see a Range where min > max. The current proposed syntax asks users to opt-in into non-atomic (or non-synchronized in your words) for being non-atomic is bug-prone. Chen Liang On Mon, Sep 25, 2023 at 5:01?PM Jo?o Mendon?a wrote: > Hello Chen, > > > Thank you very much for your response. > To address the fragility issue you raised, I would modify the new syntax > proposal to: > > *** synchronized blocks in value class field declarations. *** > > To your very good point on granularity, I think that synchronized blocks > could still be considered more readable than having to segregate fields in > separate value classes and using some other class modifier/keyword to > indicate non-atomicity. > All the other advantages/disadvantages would remain the same. > Your example would become: > > value class Container { > synchronized {int a, b;} > int c; > Container(int a, int b, int c) { > this.a = a; > this.b = b; > this.c = c; > } > } > > > Jo?o Mendon?a > > > On Mon, Sep 25, 2023 at 2:08?AM - wrote: > >> Hello Joao, >> I believe the synchronized block proposal is fragile and isn't a good >> hint to the VM. Each constructor can declare its own synchronization >> groups, which makes behaviorally-correct optimization harder. >> For your purpose where you only need to declare some of the properties of >> the value class atomically together, you can group those properties in an >> atomic (regular) value class. Then, you can include these regular value >> classes in a non-atomic value class. >> >> Say you have this: >> value class Container { >> int a, b, c; >> Container(int a, int b, int c) { >> synchronized { this.a = a; this.b = b; } >> this.c = c; >> } >> } >> >> Why not this instead: >> nonatomic value class Container { >> value class Constraint { >> int a, b; >> Constraint(int a, int b) { this.a = a; this.b = b; } >> } >> Constraint ab; int c; >> Container(int a, int b, int c) { >> this.ab = new Constraint(a, b); >> this.c = c; >> } >> } >> >> Chen Liang >> >> On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: >> >>> I would like to propose a new syntax to specify that, in a value class, >>> some fields must be assigned atomically together: >>> >>> *** synchronized blocks in value class constructors. *** >>> >>> >>> Advantages: >>> >>> - granularity - only the specific fields involved in an invariant >>> need to be assigned in the same synchronized block. Multiple blocks can be >>> used for independent invariants. Tearing is allowed between blocks and >>> between fields assigned outside blocks. VMs could take advantage of this to >>> perform optimizations. >>> - economy - no new keyword/annotation/interface needed. >>> - compatibility - synchronized blocks are currently illegal in >>> constructors. >>> - safety - just like with identity classes, the absence of a >>> synchronized block in a constructor means that the whole constructor is >>> synchronized, i.e. all fields are written atomically. >>> - safety - an empty synchronized block is required to indicate that >>> tearing is allowed between any fields. >>> - clarity - "A synchronized block of field assignments" is a very >>> intuitive description of the semantics involved, given the meaning of the >>> word "synchronized" in english. >>> >>> >>> Disadvantages: >>> >>> - aesthetics - an empty synchronized block is required to indicate >>> that tearing is allowed between any fields. >>> - safety - a user of a value class has no automatic way to be >>> informed of if/where tearing may occur (can be fixed with an update to >>> the generation of java docs). >>> - clarity - synchronized blocks (?14.18.) have two meanings: >>> - The old meaning in regular methods: only one thread may be >>> running inside of a block for the object given in the expression clause >>> - The new meaning in constructors: all assignments in a block >>> are written atomically (no expression clause) >>> >>> Example: >>> >>> value class Range { >>> long start, end; >>> public Range(long start, long end) { >>> if (start > end) throw new IllegalArgumentException(); >>> synchronized { >>> this.start = start; >>> this.end = end; >>> } >>> } } >>> >>> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >>> >>> value class Range { >>> long start, end; >>> >>> public Range(long start, long end) { >>> if (start > end) throw new IllegalArgumentException(); >>> this.start = start; >>> this.end = end; >>> } } >>> >>> >>> Another example: >>> >>> value class Point { >>> double x, y; >>> public Point(double x, double y) { >>> synchronized {} >>> this.x = x; this.y = y; >>> } } >>> >>> >>> >>> Jo?o Mendon?a >>> >>> > > On Mon, Sep 25, 2023 at 2:08?AM - wrote: > >> Hello Joao, >> I believe the synchronized block proposal is fragile and isn't a good >> hint to the VM. Each constructor can declare its own synchronization >> groups, which makes behaviorally-correct optimization harder. >> For your purpose where you only need to declare some of the properties of >> the value class atomically together, you can group those properties in an >> atomic (regular) value class. Then, you can include these regular value >> classes in a non-atomic value class. >> >> Say you have this: >> value class Container { >> int a, b, c; >> Container(int a, int b, int c) { >> synchronized { this.a = a; this.b = b; } >> this.c = c; >> } >> } >> >> Why not this instead: >> nonatomic value class Container { >> value class Constraint { >> int a, b; >> Constraint(int a, int b) { this.a = a; this.b = b; } >> } >> Constraint ab; int c; >> Container(int a, int b, int c) { >> this.ab = new Constraint(a, b); >> this.c = c; >> } >> } >> >> Chen Liang >> >> On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: >> >>> I would like to propose a new syntax to specify that, in a value class, >>> some fields must be assigned atomically together: >>> >>> *** synchronized blocks in value class constructors. *** >>> >>> >>> Advantages: >>> >>> - granularity - only the specific fields involved in an invariant >>> need to be assigned in the same synchronized block. Multiple blocks can be >>> used for independent invariants. Tearing is allowed between blocks and >>> between fields assigned outside blocks. VMs could take advantage of this to >>> perform optimizations. >>> - economy - no new keyword/annotation/interface needed. >>> - compatibility - synchronized blocks are currently illegal in >>> constructors. >>> - safety - just like with identity classes, the absence of a >>> synchronized block in a constructor means that the whole constructor is >>> synchronized, i.e. all fields are written atomically. >>> - safety - an empty synchronized block is required to indicate that >>> tearing is allowed between any fields. >>> - clarity - "A synchronized block of field assignments" is a very >>> intuitive description of the semantics involved, given the meaning of the >>> word "synchronized" in english. >>> >>> >>> Disadvantages: >>> >>> - aesthetics - an empty synchronized block is required to indicate >>> that tearing is allowed between any fields. >>> - safety - a user of a value class has no automatic way to be >>> informed of if/where tearing may occur (can be fixed with an update to >>> the generation of java docs). >>> - clarity - synchronized blocks (?14.18.) have two meanings: >>> - The old meaning in regular methods: only one thread may be >>> running inside of a block for the object given in the expression clause >>> - The new meaning in constructors: all assignments in a block >>> are written atomically (no expression clause) >>> >>> Example: >>> >>> value class Range { >>> long start, end; >>> public Range(long start, long end) { >>> if (start > end) throw new IllegalArgumentException(); >>> synchronized { >>> this.start = start; >>> this.end = end; >>> } >>> } } >>> >>> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >>> >>> value class Range { >>> long start, end; >>> >>> public Range(long start, long end) { >>> if (start > end) throw new IllegalArgumentException(); >>> this.start = start; >>> this.end = end; >>> } } >>> >>> >>> Another example: >>> >>> value class Point { >>> double x, y; >>> public Point(double x, double y) { >>> synchronized {} >>> this.x = x; this.y = y; >>> } } >>> >>> >>> >>> Jo?o Mendon?a >>> >>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From jf.mend at gmail.com Mon Sep 25 10:52:07 2023 From: jf.mend at gmail.com (=?UTF-8?B?Sm/Do28gTWVuZG9uw6dh?=) Date: Mon, 25 Sep 2023 11:52:07 +0100 Subject: Synchronized blocks in value constructors In-Reply-To: References: Message-ID: Yes, I am aware that declaring a value class with a marker interface such as "LooselyConsistentValue" does the same thing. ...for being non-atomic is bug-prone. > I agree that this is crucial. The two safety advantages I mentioned are precisely about this. To reiterate: in my proposal, users must opt-out of atomicity by writing a synchronized block that does not include all field declarations. I'm proposing this syntax for these reasons: - this particular syntax, as far as I know, has not been analyzed yet - for the advantages I wrote comparing with the current proposal - I feel like we are in the syntax-bikeshedding-phase of this particular issue On Mon, Sep 25, 2023 at 10:39?AM - wrote: > Honestly, I don't understand why you propose this, for synchronized is > ALREADY the default behavior of Value Classes per JEP 401. By default, all > fields in a value class are synchronized (non-atomic), so you won't see a > Range where min > max. The current proposed syntax asks users to opt-in > into non-atomic (or non-synchronized in your words) for being non-atomic > is bug-prone. > > Chen Liang > > On Mon, Sep 25, 2023 at 5:01?PM Jo?o Mendon?a wrote: > >> Hello Chen, >> >> >> Thank you very much for your response. >> To address the fragility issue you raised, I would modify the new syntax >> proposal to: >> >> *** synchronized blocks in value class field declarations. *** >> >> To your very good point on granularity, I think that synchronized blocks >> could still be considered more readable than having to segregate fields in >> separate value classes and using some other class modifier/keyword to >> indicate non-atomicity. >> All the other advantages/disadvantages would remain the same. >> Your example would become: >> >> value class Container { >> synchronized {int a, b;} >> int c; >> Container(int a, int b, int c) { >> this.a = a; >> this.b = b; >> this.c = c; >> } >> } >> >> >> Jo?o Mendon?a >> >> >> On Mon, Sep 25, 2023 at 2:08?AM - wrote: >> >>> Hello Joao, >>> I believe the synchronized block proposal is fragile and isn't a good >>> hint to the VM. Each constructor can declare its own synchronization >>> groups, which makes behaviorally-correct optimization harder. >>> For your purpose where you only need to declare some of the properties >>> of the value class atomically together, you can group those properties in >>> an atomic (regular) value class. Then, you can include these regular value >>> classes in a non-atomic value class. >>> >>> Say you have this: >>> value class Container { >>> int a, b, c; >>> Container(int a, int b, int c) { >>> synchronized { this.a = a; this.b = b; } >>> this.c = c; >>> } >>> } >>> >>> Why not this instead: >>> nonatomic value class Container { >>> value class Constraint { >>> int a, b; >>> Constraint(int a, int b) { this.a = a; this.b = b; } >>> } >>> Constraint ab; int c; >>> Container(int a, int b, int c) { >>> this.ab = new Constraint(a, b); >>> this.c = c; >>> } >>> } >>> >>> Chen Liang >>> >>> On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: >>> >>>> I would like to propose a new syntax to specify that, in a value class, >>>> some fields must be assigned atomically together: >>>> >>>> *** synchronized blocks in value class constructors. *** >>>> >>>> >>>> Advantages: >>>> >>>> - granularity - only the specific fields involved in an invariant >>>> need to be assigned in the same synchronized block. Multiple blocks can be >>>> used for independent invariants. Tearing is allowed between blocks and >>>> between fields assigned outside blocks. VMs could take advantage of this to >>>> perform optimizations. >>>> - economy - no new keyword/annotation/interface needed. >>>> - compatibility - synchronized blocks are currently illegal in >>>> constructors. >>>> - safety - just like with identity classes, the absence of a >>>> synchronized block in a constructor means that the whole constructor is >>>> synchronized, i.e. all fields are written atomically. >>>> - safety - an empty synchronized block is required to indicate >>>> that tearing is allowed between any fields. >>>> - clarity - "A synchronized block of field assignments" is a very >>>> intuitive description of the semantics involved, given the meaning of the >>>> word "synchronized" in english. >>>> >>>> >>>> Disadvantages: >>>> >>>> - aesthetics - an empty synchronized block is required to indicate >>>> that tearing is allowed between any fields. >>>> - safety - a user of a value class has no automatic way to be >>>> informed of if/where tearing may occur (can be fixed with an update to >>>> the generation of java docs). >>>> - clarity - synchronized blocks (?14.18.) have two meanings: >>>> - The old meaning in regular methods: only one thread may be >>>> running inside of a block for the object given in the expression clause >>>> - The new meaning in constructors: all assignments in a block >>>> are written atomically (no expression clause) >>>> >>>> Example: >>>> >>>> value class Range { >>>> long start, end; >>>> public Range(long start, long end) { >>>> if (start > end) throw new IllegalArgumentException(); >>>> synchronized { >>>> this.start = start; >>>> this.end = end; >>>> } >>>> } } >>>> >>>> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >>>> >>>> value class Range { >>>> long start, end; >>>> >>>> public Range(long start, long end) { >>>> if (start > end) throw new IllegalArgumentException(); >>>> this.start = start; >>>> this.end = end; >>>> } } >>>> >>>> >>>> Another example: >>>> >>>> value class Point { >>>> double x, y; >>>> public Point(double x, double y) { >>>> synchronized {} >>>> this.x = x; this.y = y; >>>> } } >>>> >>>> >>>> >>>> Jo?o Mendon?a >>>> >>>> >> >> On Mon, Sep 25, 2023 at 2:08?AM - wrote: >> >>> Hello Joao, >>> I believe the synchronized block proposal is fragile and isn't a good >>> hint to the VM. Each constructor can declare its own synchronization >>> groups, which makes behaviorally-correct optimization harder. >>> For your purpose where you only need to declare some of the properties >>> of the value class atomically together, you can group those properties in >>> an atomic (regular) value class. Then, you can include these regular value >>> classes in a non-atomic value class. >>> >>> Say you have this: >>> value class Container { >>> int a, b, c; >>> Container(int a, int b, int c) { >>> synchronized { this.a = a; this.b = b; } >>> this.c = c; >>> } >>> } >>> >>> Why not this instead: >>> nonatomic value class Container { >>> value class Constraint { >>> int a, b; >>> Constraint(int a, int b) { this.a = a; this.b = b; } >>> } >>> Constraint ab; int c; >>> Container(int a, int b, int c) { >>> this.ab = new Constraint(a, b); >>> this.c = c; >>> } >>> } >>> >>> Chen Liang >>> >>> On Mon, Sep 25, 2023 at 8:58?AM Jo?o Mendon?a wrote: >>> >>>> I would like to propose a new syntax to specify that, in a value class, >>>> some fields must be assigned atomically together: >>>> >>>> *** synchronized blocks in value class constructors. *** >>>> >>>> >>>> Advantages: >>>> >>>> - granularity - only the specific fields involved in an invariant >>>> need to be assigned in the same synchronized block. Multiple blocks can be >>>> used for independent invariants. Tearing is allowed between blocks and >>>> between fields assigned outside blocks. VMs could take advantage of this to >>>> perform optimizations. >>>> - economy - no new keyword/annotation/interface needed. >>>> - compatibility - synchronized blocks are currently illegal in >>>> constructors. >>>> - safety - just like with identity classes, the absence of a >>>> synchronized block in a constructor means that the whole constructor is >>>> synchronized, i.e. all fields are written atomically. >>>> - safety - an empty synchronized block is required to indicate >>>> that tearing is allowed between any fields. >>>> - clarity - "A synchronized block of field assignments" is a very >>>> intuitive description of the semantics involved, given the meaning of the >>>> word "synchronized" in english. >>>> >>>> >>>> Disadvantages: >>>> >>>> - aesthetics - an empty synchronized block is required to indicate >>>> that tearing is allowed between any fields. >>>> - safety - a user of a value class has no automatic way to be >>>> informed of if/where tearing may occur (can be fixed with an update to >>>> the generation of java docs). >>>> - clarity - synchronized blocks (?14.18.) have two meanings: >>>> - The old meaning in regular methods: only one thread may be >>>> running inside of a block for the object given in the expression clause >>>> - The new meaning in constructors: all assignments in a block >>>> are written atomically (no expression clause) >>>> >>>> Example: >>>> >>>> value class Range { >>>> long start, end; >>>> public Range(long start, long end) { >>>> if (start > end) throw new IllegalArgumentException(); >>>> synchronized { >>>> this.start = start; >>>> this.end = end; >>>> } >>>> } } >>>> >>>> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks: >>>> >>>> value class Range { >>>> long start, end; >>>> >>>> public Range(long start, long end) { >>>> if (start > end) throw new IllegalArgumentException(); >>>> this.start = start; >>>> this.end = end; >>>> } } >>>> >>>> >>>> Another example: >>>> >>>> value class Point { >>>> double x, y; >>>> public Point(double x, double y) { >>>> synchronized {} >>>> this.x = x; this.y = y; >>>> } } >>>> >>>> >>>> >>>> Jo?o Mendon?a >>>> >>>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From livedinsquares at gmail.com Mon Sep 25 12:14:53 2023 From: livedinsquares at gmail.com (Jonathan F) Date: Mon, 25 Sep 2023 05:14:53 -0700 Subject: Regulated constructors Message-ID: This idea is great! Dan Smith invited alternatives to the ?regulated? keyword. What about simply ?write-only? (AFAIK hyphenated keywords are on the way in). It?s fairly self-explanatory, and also gives a rationale to the poor developer (for what otherwise looks like a grab-bag of restrictions). Dan nearly used this term in his explanation. FWIW in documentation, maybe ?larval? should be changed to match the keyword, to minimise the vocab to understand. best wishes, Jonathan Jonathan Finn -------------- next part -------------- An HTML attachment was scrubbed... URL: