Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Vicente Romero
On Thu, 20 Apr 2023 16:54:20 GMT, Jan Lahoda  wrote:

>> could you explain a bit more the relation between `lazyDoEnumSwitch` and 
>> `doEnumSwitch` because my understanding is that `lazyDoEnumSwitch` is 
>> invoking `doEnumSwitch` so to me whenever `lazyDoEnumSwitch` is invoked 
>> there will be an immediate invocation of `doEnumSwitch` that's why I thought 
>> they could be folded together
>
> So, when the `enumSwitch` bootstrap is called, the enum class may or may not 
> be initialized. So, to avoid initialization, we only do lightweight checks, 
> and construct a `MutableCallSite` with `lazyDoEnumSwitch` as a target.
> 
> When the `CallSite` is invoked with an actual selector value, two options may 
> arise:
> a) the selector value is null. The `lazyDoEnumSwitch` itself returns -1.
> b) the selector value is not null. The enum class must already be initialized 
> (I believe). So, we create (hopefully) better structure to do the 
> categorization, based on `doEnumSwitch`, and set that into the `CallSite`. 
> Further calls will use this new `doEnumSwitch` based categorization directly, 
> without calling `lazyDoEnumSwitch`. The current call will manually delegate 
> to the `doEnumSwitch` version, but that should only happen "once" (or a small 
> number of times, due to running in different threads, etc.).

I see, thanks for the explanation, this is nice

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172949033


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Vicente Romero
On Thu, 20 Apr 2023 17:08:10 GMT, Jan Lahoda  wrote:

>> That's in my upcoming update.
>
> The startIndex checks are part of this change:
> https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9
> 
> Thanks for the comment!

Oh I see, thanks!

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172946111


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Tue, 18 Apr 2023 13:43:45 GMT, Maurizio Cimadamore  
wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 915:
> 
>> 913: 
>> 914: for (PatternDescription pdOther : patterns) 
>> {
>> 915: if (pdOther instanceof BindingPattern 
>> bpOther) {
> 
> This code redundantly checks a pattern against itself, which I think we can 
> avoid.

Possibly, but the handling of the binding patterns is getting more complex, so 
I've opted to keep it uniform for now.

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 927:
> 
>> 925: it.remove();
>> 926: reduces = true;
>> 927: continue PERMITTED;
> 
> the label can be dropped here as there's no nested loop

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 953:
> 
>> 951: }
>> 952: 
>> 953: Set cleanedToRemove = new 
>> HashSet<>(toRemove);
> 
> Another way to do this would be to compute the intersection between 
> `toRemove` and `toAdd` (e.g. with `retainAll`), and then remove the 
> intersection from both sets.

The addition and removal of the same binding pattern should be completely 
avoided in the current version of the code.

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1058:
> 
>> 1056: for (int i = 0; i < 
>> rpOne.nested.length; i++) {
>> 1057: if (i != mismatchingCandidate 
>> &&
>> 1058: 
>> !exactlyMatches(rpOne.nested[i], rpOther.nested[i])) {
> 
> should `exactlyMatches` be the implementation of `equals` in the 
> `PatternDescriptor` class?

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java line 
> 847:
> 
>> 845: /** Skip parens and return the enclosed expression
>> 846:  */
>> 847: //XXX: remove??
> 
> What about this?

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172875982
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172876837
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172875031
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877099
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877541


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Tue, 18 Apr 2023 14:31:46 GMT, Maurizio Cimadamore  
wrote:

>> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1021:
>> 
>>> 1019:  *on patterns in the chosen column, as described above
>>> 1020:  */
>>> 1021: var grouppedPerRecordClass =
>> 
>> Suggestion:
>> 
>> var groupedPerRecordClass =
>
> or `patternsByRecordClass`, or `groupByRecordClass` (the latter would be 
> consistent with `groupByHash` which is used below)

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172876875


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Tue, 18 Apr 2023 14:17:02 GMT, Maurizio Cimadamore  
wrote:

>> I've also found an infinite loop with this:
>> 
>> 
>> class Test {
>> sealed interface I0 permits I1, I2 { }
>> sealed interface I00 permits I1, I2 { }
>> 
>> sealed interface I1 extends I0, I00 permits B, C { }
>> sealed interface I2 extends I0, I00 permits B, C { }
>> 
>> static final class B implements I1, I2 { }
>> static final class C implements I1, I2 { }
>> 
>> int test(Object o) {
>> return switch (o) {
>> case B c -> 2;
>> case C d -> 3;
>> };
>> }
>> }
>
>> I've also found an infinite loop with this:
> 
> I believe this has to do with the fact that the list of pattern is not a set 
> - so we can end up adding the same pattern descriptions over and over.

Thanks for the testcase!

I've tried to fix this by (avoiding to add redundant binding patterns):
https://github.com/openjdk/jdk/pull/13074/commits/7e6ed619d89784c49a96984c0f74176a9e0bcf63

Sets might be a good move eventually, but so far it seemed to hide problems, 
which quite probably needed to be solved anyway, so I kept the list impl for 
now.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172874262


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Thu, 20 Apr 2023 16:40:31 GMT, Jan Lahoda  wrote:

>> and regarding checking that `startIndex` should be `>= 0`? shouldn't we 
>> check for that?
>
> That's in my upcoming update.

The startIndex checks are part of this change:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877989


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Tue, 18 Apr 2023 20:24:33 GMT, Vicente Romero  wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 94:
> 
>> 92:  *   the element is of type {@code String} or {@code Integer} and
>> 93:  *   equals to the target.
>> 94:  *   the element is of type {@code EnumDesc}, that describes a 
>> constant that is
> 
> I think that at ~line 76, up in this same javadoc you need to add a reference 
> to EnumDesc in the general description. Where it says:
> 
> 
> The static arguments are an array of case labels which must be non-null and 
> of type
> {@code String} or {@code Integer} or {@code Class}.
> 
> also around line 107, where it says:
> 
> @param labels case labels - {@code String} and {@code Integer} constants
>and {@code Class} instances, in any combination

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 263:
> 
>> 261: private static > void validateEnumLabel(Class 
>> enumClassTemplate, Object label) {
>> 262: if (label == null) {
>> 263: throw new IllegalArgumentException("null label found");
> 
> I think that this one is not hit by any test

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 271:
> 
>> 269:", expected the 
>> provided enum class: " + enumClassTemplate);
>> 270: }
>> 271: } else if (labelClass == String.class) {
> 
> I think that if the condition is changed to `labelClass != String.class` then 
> `throw` we can drop an `else` branch

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 274:
> 
>> 272: //OK
>> 273: } else {
>> 274: throw new IllegalArgumentException("label with illegal type 
>> found: " + labelClass +
> 
> I think that this code is not being tested by any test

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 201:
> 
>> 199: /** Are unconditional patterns in instanceof allowed
>> 200:  */
>> 201: private boolean allowUnconditionalPatternsInstanceOf;
> 
> so I guess this field can be made final now

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 909:
> 
>> 907: 
>> 908: Set permitted = 
>> allPermittedSubTypes(clazz, csym -> {
>> 909: Type instantiated = 
>> infer.instantiatePatternType(selectorType, csym);
> 
> for some cases, when there are no type parameters, this invocation is a 
> no-op, do we really need inference at this point?

Should be resolved by:
https://github.com/openjdk/jdk/pull/13074/commits/bb59254e409821c9b14287c73a35ebe2dd2cbda9

Thanks for the comment!

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877205
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877482
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877294
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172877401
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172878133
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172878329


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Thu, 20 Apr 2023 16:31:33 GMT, Vicente Romero  wrote:

>> yep I found a similar test case triggering this code
>
> could you explain a bit more the relation between `lazyDoEnumSwitch` and 
> `doEnumSwitch` because my understanding is that `lazyDoEnumSwitch` is 
> invoking `doEnumSwitch` so to me whenever `lazyDoEnumSwitch` is invoked there 
> will be an immediate invocation of `doEnumSwitch` that's why I thought they 
> could be folded together

So, when the `enumSwitch` bootstrap is called, the enum class may or may not be 
initialized. So, to avoid initialization, we only do lightweight checks, and 
construct a `MutableCallSite` with `lazyDoEnumSwitch` as a target.

When the `CallSite` is invoked with an actual selector value, two options may 
arise:
a) the selector value is null. The `lazyDoEnumSwitch` itself returns -1.
b) the selector value is not null. The enum class must already be initialized 
(I believe). So, we create (hopefully) better structure to do the 
categorization, based on `doEnumSwitch`, and set that into the `CallSite`. 
Further calls will use this new `doEnumSwitch` based categorization directly, 
without calling `lazyDoEnumSwitch`. The current call will manually delegate to 
the `doEnumSwitch` version, but that should only happen "once" (or a small 
number of times, due to running in different threads, etc.).

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172863795


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Thu, 20 Apr 2023 16:32:33 GMT, Vicente Romero  wrote:

>> I see, thanks
>
> and regarding checking that `startIndex` should be `>= 0`? shouldn't we check 
> for that?

That's in my upcoming update.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172848770


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Vicente Romero
On Thu, 20 Apr 2023 14:07:01 GMT, Vicente Romero  wrote:

>> The intent here is to avoid eager initialization of enums - so, until the 
>> enum is initialized, `lazyDoEnumSwitch` will be used (which, by itself, 
>> won't compute any results, except the result for `null`), which is then 
>> replaced with `doEnumSwitch` using the enum constants directly.
>> 
>> The enum switches support patterns as well, so something like:
>> 
>> enum E {A;}
>> E e = ...;
>> switch (e) {
>>  case E ee -> {}
>> }
>> 
>> is valid, and should trigger the part with Class labels.
>
> yep I found a similar test case triggering this code

could you explain a bit more the relation between `lazyDoEnumSwitch` and 
`doEnumSwitch` because my understanding is that `lazyDoEnumSwitch` is invoking 
`doEnumSwitch` so to me whenever `lazyDoEnumSwitch` is invoked there will be an 
immediate invocation of `doEnumSwitch` that's why I thought they could be 
folded together

>> `startIndex` may be non-0 when there are guards in the switch. In the case 
>> of the `enumSwitch`, something like:
>> 
>> enum E {A, B;}
>> E e = E.B;
>> switch (e) {
>>  case E ee when ee == E.A -> {}
>>  case E ee -> {}
>> }
>> 
>> 
>> the method will be called twice, one with `startIndex == 0` and once with 
>> `startIndex == 1`, after the guard fails/returns `false`.
>
> I see, thanks

and regarding checking that `startIndex` should be `>= 0`? shouldn't we check 
for that?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172839418
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172840817


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Vicente Romero
On Thu, 20 Apr 2023 13:41:05 GMT, Jan Lahoda  wrote:

>> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 279:
>> 
>>> 277: }
>>> 278: 
>>> 279: private static int lazyDoEnumSwitch(Enum target, int 
>>> startIndex, Object[] labels, MethodHandles.Lookup lookup, Class 
>>> enumClass, MutableCallSite callSite) throws Throwable {
>> 
>> out of curiosity, under what conditions the `startIndex` would be different 
>> from `0`? also shouldn't we check that `startIndex` is `>= 0`?
>
> `startIndex` may be non-0 when there are guards in the switch. In the case of 
> the `enumSwitch`, something like:
> 
> enum E {A, B;}
> E e = E.B;
> switch (e) {
>  case E ee when ee == E.A -> {}
>  case E ee -> {}
> }
> 
> 
> the method will be called twice, one with `startIndex == 0` and once with 
> `startIndex == 1`, after the guard fails/returns `false`.

I see, thanks

>> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 279:
>> 
>>> 277: }
>>> 278: 
>>> 279: private static int lazyDoEnumSwitch(Enum target, int 
>>> startIndex, Object[] labels, MethodHandles.Lookup lookup, Class 
>>> enumClass, MutableCallSite callSite) throws Throwable {
>> 
>> can `doEnumSwitch` be folded into `lazyDoEnumSwitch`? just a suggestion, I'm 
>> OK with either way just that now it is not clear that we need two methods 
>> here. Also in `doEnumSwitch` and out of curiosity what example of user code 
>> could hit this section:
>> 
>> 
>> if (label instanceof Class c) {
>> if (c.isAssignableFrom(targetClass))
>> return i;
>> }
>> 
>> EDIT: nvm I found one example
>
> The intent here is to avoid eager initialization of enums - so, until the 
> enum is initialized, `lazyDoEnumSwitch` will be used (which, by itself, won't 
> compute any results, except the result for `null`), which is then replaced 
> with `doEnumSwitch` using the enum constants directly.
> 
> The enum switches support patterns as well, so something like:
> 
> enum E {A;}
> E e = ...;
> switch (e) {
>  case E ee -> {}
> }
> 
> is valid, and should trigger the part with Class labels.

yep I found a similar test case triggering this code

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172646957
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172647746


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Wed, 19 Apr 2023 16:45:06 GMT, Vicente Romero  wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 279:
> 
>> 277: }
>> 278: 
>> 279: private static int lazyDoEnumSwitch(Enum target, int startIndex, 
>> Object[] labels, MethodHandles.Lookup lookup, Class enumClass, 
>> MutableCallSite callSite) throws Throwable {
> 
> can `doEnumSwitch` be folded into `lazyDoEnumSwitch`? just a suggestion, I'm 
> OK with either way just that now it is not clear that we need two methods 
> here. Also in `doEnumSwitch` and out of curiosity what example of user code 
> could hit this section:
> 
> 
> if (label instanceof Class c) {
> if (c.isAssignableFrom(targetClass))
> return i;
> }
> 
> EDIT: nvm I found one example

The intent here is to avoid eager initialization of enums - so, until the enum 
is initialized, `lazyDoEnumSwitch` will be used (which, by itself, won't 
compute any results, except the result for `null`), which is then replaced with 
`doEnumSwitch` using the enum constants directly.

The enum switches support patterns as well, so something like:

enum E {A;}
E e = ...;
switch (e) {
 case E ee -> {}
}

is valid, and should trigger the part with Class labels.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172623143


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Vicente Romero
On Thu, 20 Apr 2023 13:33:17 GMT, Jan Lahoda  wrote:

>> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 170:
>> 
>>> 168: } else if (label instanceof EnumDesc enumDesc) {
>>> 169: if (target.getClass().isEnum() &&
>>> 170: ((Enum) 
>>> target).describeConstable().stream().anyMatch(d -> d.equals(enumDesc))) {
>> 
>> probably a matter of style but isn't it a bit too much to use streams here? 
>> there will be always only one element right?
>
> Technically, one element, but the type is optional, so formally could be no 
> elements. I could use `.get()`, but that feels a bit ugly and against 
> optional?

yep I know, up to you I'm not strong on this, I guess I was thinking about 
performance but probably not using streams won't make a difference in this case

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172609916


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Wed, 19 Apr 2023 15:36:08 GMT, Vicente Romero  wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 279:
> 
>> 277: }
>> 278: 
>> 279: private static int lazyDoEnumSwitch(Enum target, int startIndex, 
>> Object[] labels, MethodHandles.Lookup lookup, Class enumClass, 
>> MutableCallSite callSite) throws Throwable {
> 
> out of curiosity, under what conditions the `startIndex` would be different 
> from `0`? also shouldn't we check that `startIndex` is `>= 0`?

`startIndex` may be non-0 when there are guards in the switch. In the case of 
the `enumSwitch`, something like:

enum E {A, B;}
E e = E.B;
switch (e) {
 case E ee when ee == E.A -> {}
 case E ee -> {}
}


the method will be called twice, one with `startIndex == 0` and once with 
`startIndex == 1`, after the guard fails/returns `false`.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172609212


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-20 Thread Jan Lahoda
On Wed, 19 Apr 2023 04:06:00 GMT, Vicente Romero  wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 170:
> 
>> 168: } else if (label instanceof EnumDesc enumDesc) {
>> 169: if (target.getClass().isEnum() &&
>> 170: ((Enum) 
>> target).describeConstable().stream().anyMatch(d -> d.equals(enumDesc))) {
> 
> probably a matter of style but isn't it a bit too much to use streams here? 
> there will be always only one element right?

Technically, one element, but the type is optional, so formally could be no 
elements. I could use `.get()`, but that feels a bit ugly and against optional?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1172599496


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-19 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 201:

> 199: /** Are unconditional patterns in instanceof allowed
> 200:  */
> 201: private boolean allowUnconditionalPatternsInstanceOf;

so I guess this field can be made final now

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 909:

> 907: 
> 908: Set permitted = 
> allPermittedSubTypes(clazz, csym -> {
> 909: Type instantiated = 
> infer.instantiatePatternType(selectorType, csym);

for some cases, when there are no type parameters, this invocation is a no-op, 
do we really need inference at this point?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1171830887
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1171936405


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-19 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 279:

> 277: }
> 278: 
> 279: private static int lazyDoEnumSwitch(Enum target, int startIndex, 
> Object[] labels, MethodHandles.Lookup lookup, Class enumClass, 
> MutableCallSite callSite) throws Throwable {

can `doEnumSwitch` be folded into `lazyDoEnumSwitch`? just a suggestion, I'm OK 
with either way just that now it is not clear that we need two methods here. 
Also in `doEnumSwitch` and out of curiosity what example of user code could hit 
this section:


if (label instanceof Class c) {
if (c.isAssignableFrom(targetClass))
return i;
}

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1171605248


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-19 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 279:

> 277: }
> 278: 
> 279: private static int lazyDoEnumSwitch(Enum target, int startIndex, 
> Object[] labels, MethodHandles.Lookup lookup, Class enumClass, 
> MutableCallSite callSite) throws Throwable {

out of curiosity, under what conditions the `startIndex` would be different 
from `0`?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1171523963


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-19 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java line 847:

> 845: /** Skip parens and return the enclosed expression
> 846:  */
> 847: //XXX: remove??

What about this?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1171141708


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 263:

> 261: private static > void validateEnumLabel(Class 
> enumClassTemplate, Object label) {
> 262: if (label == null) {
> 263: throw new IllegalArgumentException("null label found");

I think that this one is not hit by any test

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 274:

> 272: //OK
> 273: } else {
> 274: throw new IllegalArgumentException("label with illegal type 
> found: " + labelClass +

I think that this code is not being tested by any test

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170788337
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170786847


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 170:

> 168: } else if (label instanceof EnumDesc enumDesc) {
> 169: if (target.getClass().isEnum() &&
> 170: ((Enum) 
> target).describeConstable().stream().anyMatch(d -> d.equals(enumDesc))) {

probably a matter of style but isn't it a bit too much to use streams here? 
there will be always only one element right?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170784311


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 271:

> 269:", expected the 
> provided enum class: " + enumClassTemplate);
> 270: }
> 271: } else if (labelClass == String.class) {

I think that if the condition is changed to `labelClass != String.class` then 
`throw` we can drop an `else` branch

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170770395


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 149:

> 147: throw new IllegalArgumentException("label with illegal type 
> found: " + label.getClass());
> 148: }
> 149: }

side: are there any cases for which the `startIndex` argument passed to method 
`doTypeSwitch` is not `0`?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170618764


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Vicente Romero
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java line 94:

> 92:  *   the element is of type {@code String} or {@code Integer} and
> 93:  *   equals to the target.
> 94:  *   the element is of type {@code EnumDesc}, that describes a 
> constant that is

I think that at ~line 76, up in this same javadoc you need to add a reference 
to EnumDesc in the general description. Where it says:


The static arguments are an array of case labels which must be non-null and of 
type
{@code String} or {@code Integer} or {@code Class}.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170531849


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 14:31:30 GMT, Maurizio Cimadamore  
wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1021:
> 
>> 1019:  *on patterns in the chosen column, as described above
>> 1020:  */
>> 1021: var grouppedPerRecordClass =
> 
> Suggestion:
> 
> var groupedPerRecordClass =

or `patternsByRecordClass`, or `groupByRecordClass` (the latter would be 
consistent with `groupByHash` which is used below)

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170131872


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1021:

> 1019:  *on patterns in the chosen column, as described above
> 1020:  */
> 1021: var grouppedPerRecordClass =

Suggestion:

var groupedPerRecordClass =

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1058:

> 1056: for (int i = 0; i < 
> rpOne.nested.length; i++) {
> 1057: if (i != mismatchingCandidate &&
> 1058: 
> !exactlyMatches(rpOne.nested[i], rpOther.nested[i])) {

should `exactlyMatches` be the implementation of `equals` in the 
`PatternDescriptor` class?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170131443
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170135800


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 927:

> 925: it.remove();
> 926: reduces = true;
> 927: continue PERMITTED;

the label can be dropped here as there's no nested loop

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170127214


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 13:54:52 GMT, Maurizio Cimadamore  
wrote:

> I've also found an infinite loop with this:

I believe this has to do with the fact that the list of pattern is not a set - 
so we can end up adding the same pattern descriptions over and over.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170110465


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 13:43:17 GMT, Maurizio Cimadamore  
wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 812:
> 
>> 810: if (l instanceof JCPatternCaseLabel patternLabel) {
>> 811: for (Type component : 
>> components(selector.type)) {
>> 812: patterns = 
>> patterns.prepend(PatternDescription.from(types, component, 
>> patternLabel.pat));
> 
> I noted that this code ends up adding redundant pattern descriptions to the 
> list - for instance:
> 
> 
> class Test {
> sealed interface I1 permits B, C { }
> sealed interface I2 permits B, C { }
> 
> static final class B implements I1, I2 { }
> static final class C implements I1, I2 { }
> 
>  int test(Z z) {
> return switch (z) {
> case B c -> 2;
> case C d -> 3;
> };
> }
> }
> 
> 
> In this case the list ends up with 6 elements, [ B, B, B, C, C, C ]. Given 
> that the complexity of the algorithm depends on the number of patterns in the 
> list, it would probably be better to use a set here and try to make the list 
> as small as possible from early on.

I've also found an infinite loop with this:


class Test {
sealed interface I0 permits I1, I2 { }
sealed interface I00 permits I1, I2 { }

sealed interface I1 extends I0, I00 permits B, C { }
sealed interface I2 extends I0, I00 permits B, C { }

static final class B implements I1, I2 { }
static final class C implements I1, I2 { }

int test(Object o) {
return switch (o) {
case B c -> 2;
case C d -> 3;
};
}
}

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170079092


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 812:

> 810: if (l instanceof JCPatternCaseLabel patternLabel) {
> 811: for (Type component : components(selector.type)) 
> {
> 812: patterns = 
> patterns.prepend(PatternDescription.from(types, component, patternLabel.pat));

I noted that this code ends up adding redundant pattern descriptions to the 
list - for instance:


class Test {
sealed interface I1 permits B, C { }
sealed interface I2 permits B, C { }

static final class B implements I1, I2 { }
static final class C implements I1, I2 { }

 int test(Z z) {
return switch (z) {
case B c -> 2;
case C d -> 3;
};
}
}


In this case the list ends up with 6 elements, [ B, B, B, C, C, C ]. Given that 
the complexity of the algorithm depends on the number of patterns in the list, 
it would probably be better to use a set here and try to make the list as small 
as possible from early on.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 915:

> 913: 
> 914: for (PatternDescription pdOther : patterns) {
> 915: if (pdOther instanceof BindingPattern 
> bpOther) {

This code redundantly checks a pattern against itself, which I think we can 
avoid.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170062325
PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1170062982


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Maurizio Cimadamore
On Tue, 18 Apr 2023 09:13:01 GMT, Jan Lahoda  wrote:

>> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
>> 
>>  - the pattern matching for switch and record patterns features are made 
>> final, together with updates to tests.
>>  - parenthesized patterns are removed.
>>  - qualified enum constants are supported for case labels.
>> 
>> This change herein also includes removal record patterns in for each loop, 
>> which may be split into a separate PR in the future.
>
> Jan Lahoda has updated the pull request incrementally with six additional 
> commits since the last revision:
> 
>  - Fixing infinite loop where a binding pattern is replaced with a binding 
> pattern for the same type.
>  - Reflecting review comments.
>  - Fixing exhaustiveness for unsealed supertype pattern.
>  - No need to enable features after error reported.
>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>  - A prototype of avoiding enum initialization.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 953:

> 951: }
> 952: 
> 953: Set cleanedToRemove = new 
> HashSet<>(toRemove);

Another way to do this would be to compute the intersection between `toRemove` 
and `toAdd` (e.g. with `retainAll`), and then remove the intersection from both 
sets.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1169854290


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Jan Lahoda
On Mon, 17 Apr 2023 11:33:56 GMT, Maurizio Cimadamore  
wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 879:
> 
>> 877: }
>> 878: case TYPEVAR -> components(((TypeVar) 
>> seltype).getUpperBound());
>> 879: default -> {
> 
> The block here is redundant

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a70b8d9710a21a7c230fe747af3f4f7ba6a388a

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 890:
> 
>> 888:  * for the sealed supertype.
>> 889:  */
>> 890: private List reduceBindingPatterns(Type 
>> selectorType, List patterns) {
> 
> This method doesn't seem to work for the following case:
> 
> 
> class Test {
> sealed interface I permits A, B, C { }
> sealed interface I3 permits I2 { }
> sealed interface I2 extends I3 permits B, C { }
> final class A implements I {}
> final class B implements I, I2 {}
> final class C implements I, I2 {}
> 
> int m(I i) {
> return switch (i) {
> case A a -> 1;
> case I3 e -> 2;
> };
> }
> }
> 
> 
> There seems to be some ordering issue in the way we visit the patterns.

Hopefully fixed:
https://github.com/openjdk/jdk/pull/13074/commits/857980847e21aee0dee4665f19c1a8a54cff4973

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 901:
> 
>> 899: Type clazzErasure = 
>> types.erasure(clazz.type);
>> 900: if (components(selectorType).stream()
>> 901: .map(c -> 
>> types.erasure(c))
> 
> Suggestion:
> 
> .map(Types::erasure)

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a70b8d9710a21a7c230fe747af3f4f7ba6a388a

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 914:
> 
>> 912: permitted.remove(bpOne.type.tsym);
>> 913: bindings.append(it1.head);
>> 914: for (var it2 = it1.tail; it2.nonEmpty(); 
>> it2 = it2.tail) {
> 
> This could be a for-each loop?

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a70b8d9710a21a7c230fe747af3f4f7ba6a388a

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 971:
> 
>> 969: /* implementation note:
>> 970:  * finding a sub-set of patterns that only differ in a 
>> single
>> 971:  * column is time consuming task, so this method speeds it 
>> up by:
> 
> Suggestion:
> 
>  * column is time-consuming task, so this method speeds it up by:

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a70b8d9710a21a7c230fe747af3f4f7ba6a388a

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 976:
> 
>> 974:  * -- group patterns by their hashs
>> 975:  * -- in each such by-hash group, find sub-sets that only 
>> differ in
>> 976:  *the chosen column, and tcall reduceBindingPatterns 
>> and reduceNestedPatterns
> 
> Suggestion:
> 
>  *the chosen column, and call reduceBindingPatterns and 
> reduceNestedPatterns

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a70b8d9710a21a7c230fe747af3f4f7ba6a388a

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 977:
> 
>> 975:  * -- in each such by-hash group, find sub-sets that only 
>> differ in
>> 976:  *the chosen column, and tcall reduceBindingPatterns 
>> and reduceNestedPatterns
>> 977:  *on patterns in the chosed column, as described above
> 
> Suggestion:
> 
>  *on patterns in the chosen column, as described above

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a70b8d9710a21a7c230fe747af3f4f7ba6a388a

Thanks!

> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 999:
> 
>> 997:  .collect(groupingBy(pd -> 
>> pd.hashCode(mismatchingCandidateFin)));
>> 998: for (var candidates : groupByHashes.values()) {
>> 999: var candidatesArr = candidates.toArray(s -> new 
>> RecordPattern[s]);
> 
> Could this be an array constructor reference? E.g. `RecordPattern[]::new` ?

Fixed:
https://github.com/openjdk/jdk/pull/13074/commits/4a7

Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Jan Lahoda
On Fri, 14 Apr 2023 18:30:56 GMT, Vicente Romero  wrote:

>> Jan Lahoda has updated the pull request incrementally with six additional 
>> commits since the last revision:
>> 
>>  - Fixing infinite loop where a binding pattern is replaced with a binding 
>> pattern for the same type.
>>  - Reflecting review comments.
>>  - Fixing exhaustiveness for unsealed supertype pattern.
>>  - No need to enable features after error reported.
>>  - SwitchBootstraps.typeSwitch should not initialize enum classes.
>>  - A prototype of avoiding enum initialization.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 4092:
> 
>> 4090: log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(),
>> 4091:   
>> Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.error(this.sourceName));
>> 4092: allowUnconditionalPatternsInstanceOf = true;
> 
> sorry not sure why we are doing this. Either the feature should be allowed or 
> not right?

We normally don't produce multiple source level errors, but it is true Log does 
that us by itself, so no need to set the flag, fixed:
https://github.com/openjdk/jdk/pull/13074/commits/bb26b52268c25863ba358843441d4c4352f877fd

Thanks!

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1169907081


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Jan Lahoda
On Fri, 14 Apr 2023 16:45:36 GMT, Roger Riggs  wrote:

>> Well, I'm aware of this, and https://github.com/openjdk/jdk/pull/9779 even 
>> optimizes the case where the `enumSwitch` only gets enum constants as 
>> parameters.
>> 
>> And, overall, it is fairly easy to implement, I think I've had at least one 
>> implementation in the past. But, the last time I was experimenting with 
>> this, there IIRC was a performance hit for using the indy/condy (IIRC it 
>> worked as a condy/ldc for a mapping array - but it could as easily be an 
>> indy doing the mapping as such). So, frankly, to me, simplifying the 
>> compiler slightly (in maybe ~10 years, because we would still need to keep 
>> the current desugaring for targets that don't have the bootstrap) while 
>> slowing down all other code is not a good balance. *If* we can make the 
>> indy/condy at least as fast as the current code, (or faster,) then sure, 
>> this is the right way to go. And, as far as javac is concerned that is not 
>> really difficult.
>
> Is it ever too early in JDK startup (Phase 1) to use #3? But you'll find out 
> pretty quick if the JDK won't start.  But it might constrain where we can use 
> Pattern matching (and it won't be the first feature that can't be used in 
> Phase 1).

FWIW, I've changed the bootstraps to not initialize the enum classes. But, I 
don't think I can promise `ConstantCallSite` will be used.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13074#discussion_r1169905066


Re: RFR: 8300543 Compiler Implementation for Pattern Matching for switch [v2]

2023-04-18 Thread Jan Lahoda
> This is the first draft of a patch for JEP 440 and JEP 441. Changes included:
> 
>  - the pattern matching for switch and record patterns features are made 
> final, together with updates to tests.
>  - parenthesized patterns are removed.
>  - qualified enum constants are supported for case labels.
> 
> This change herein also includes removal record patterns in for each loop, 
> which may be split into a separate PR in the future.

Jan Lahoda has updated the pull request incrementally with six additional 
commits since the last revision:

 - Fixing infinite loop where a binding pattern is replaced with a binding 
pattern for the same type.
 - Reflecting review comments.
 - Fixing exhaustiveness for unsealed supertype pattern.
 - No need to enable features after error reported.
 - SwitchBootstraps.typeSwitch should not initialize enum classes.
 - A prototype of avoiding enum initialization.

-

Changes:
  - all: https://git.openjdk.org/jdk/pull/13074/files
  - new: https://git.openjdk.org/jdk/pull/13074/files/57445212..a6ba602b

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=13074&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=13074&range=00-01

  Stats: 332 lines in 8 files changed: 260 ins; 32 del; 40 mod
  Patch: https://git.openjdk.org/jdk/pull/13074.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/13074/head:pull/13074

PR: https://git.openjdk.org/jdk/pull/13074