Re: RFR: 8262891: Compiler implementation for Pattern Matching for switch (Preview) [v12]

2021-06-05 Thread Evgeny Mandrikov
On Fri, 4 Jun 2021 20:17:43 GMT, Jan Lahoda  wrote:

>> Jan Lahoda has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   Fixing typo.
>
> Thanks a lot for all the feedback. I've tried to do the requested changes in 
> the recent commits.

@lahodaj I also noticed that https://bugs.openjdk.java.net/browse/JDK-8213076 
as well as https://openjdk.java.net/jeps/406 state

> The implementation will likely make use of dynamic constants (JEP 309).

and wondering if this should be changed on

> The implementation will likely make use of invokedynamic.

or maybe even removed?

-

PR: https://git.openjdk.java.net/jdk/pull/3863


Re: RFR: 8262891: Compiler implementation for Pattern Matching for switch (Preview) [v5]

2021-05-27 Thread Evgeny Mandrikov
On Thu, 27 May 2021 18:19:38 GMT, Rémi Forax  wrote:

>  in your example, there is no guard so no backward goto

@forax btw this example is not about switch pattern matching - it is about 
already existing string switch, where indy not involed 😉 


  void example(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: (0x)
Code:
  stack=2, locals=4, args_size=2
 0: aload_1
 1: astore_2
 2: iconst_m1
 3: istore_3
 4: aload_2
 5: invokevirtual #7  // Method 
java/lang/String.hashCode:()I
 8: lookupswitch  { // 1
  97: 28
 default: 39
}
28: aload_2
29: ldc   #13 // String a
31: invokevirtual #15 // Method 
java/lang/String.equals:(Ljava/lang/Object;)Z
34: ifeq  39
37: iconst_0
38: istore_3
39: iload_3
40: lookupswitch  { // 1
   0: 60
 default: 68
}
60: getstatic #19 // Field 
java/lang/System.out:Ljava/io/PrintStream;
63: ldc   #13 // String a
65: invokevirtual #25 // Method 
java/io/PrintStream.println:(Ljava/lang/String;)V
68: return
  LineNumberTable:
line 3: 0
line 5: 60
line 7: 68
  StackMapTable: number_of_entries = 5
frame_type = 253 /* append */
  offset_delta = 4
  locals = [ class java/lang/String, int ]
frame_type = 23 /* same */
frame_type = 10 /* same */
frame_type = 20 /* same */
frame_type = 249 /* chop */
  offset_delta = 7

-

PR: https://git.openjdk.java.net/jdk/pull/3863


Re: RFR: 8262891: Compiler implementation for Pattern Matching for switch (Preview) [v5]

2021-05-27 Thread Evgeny Mandrikov
On Wed, 26 May 2021 17:52:36 GMT, Jan Lahoda  wrote:

>> This is a preview of a patch implementing JEP 406: Pattern Matching for 
>> switch (Preview):
>> https://bugs.openjdk.java.net/browse/JDK-8213076
>> 
>> The current draft of the specification is here:
>> http://cr.openjdk.java.net/~gbierman/jep406/jep406-20210430/specs/patterns-switch-jls.html
>> 
>> A summary of notable parts of the patch:
>> -to support cases expressions and patterns in cases, there is a new common 
>> superinterface for expressions and patterns, `CaseLabelTree`, which 
>> expressions and patterns implement, and a list of case labels is returned 
>> from `CaseTree.getLabels()`.
>> -to support `case default`, there is an implementation of `CaseLabelTree` 
>> that represents it (`DefaultCaseLabelTree`). It is used also to represent 
>> the conventional `default` internally and in the newly added methods.
>> -in the parser, parenthesized patterns and expressions need to be 
>> disambiguated when parsing case labels.
>> -Lower has been enhanced to handle `case null` for ordinary 
>> (boxed-primitive, String, enum) switches. This is a bit tricky for boxed 
>> primitives, as there is no value that is not part of the input domain so 
>> that could be used to represent `case null`. Requires a bit shuffling with 
>> values.
>> -TransPatterns has been enhanced to handle the pattern matching switch. It 
>> produces code that delegates to a new bootstrap method, that will classify 
>> the input value to the switch and return the case number, to which the 
>> switch then jumps. To support guards, the switches (and the bootstrap 
>> method) are restartable. The bootstrap method as such is written very simply 
>> so far, but could be much more optimized later.
>> -nullable type patterns are `case String s, null`/`case null, String 
>> s`/`case null: case String s:`/`case String s: case null:`, handling of 
>> these required a few tricks in `Attr`, `Flow` and `TransPatterns`.
>> 
>> The specdiff for the change is here (to be updated):
>> http://cr.openjdk.java.net/~jlahoda/8265981/specdiff.preview.01/overview-summary.html
>
> Jan Lahoda has updated the pull request with a new target base due to a merge 
> or a rebase. The pull request now contains 12 commits:
> 
>  - Post-merge fix - need to include jdk.internal.javac in the list of 
> packages used by jdk.compiler again, as we now (again) have a preview feature 
> in javac.
>  - Correcting LineNumberTable for rule switches.
>  - Merging master into JDK-8262891
>  - Fixing various error-related bugs.
>  - Avoiding fall-through from the total case to a synthetic default but 
> changing total patterns to default.
>  - Reflecting recent spec changes.
>  - Reflecting review comments.
>  - Reflecting review comments on SwitchBootstraps.
>  - Trailing whitespaces.
>  - Cleanup, reflecting review comments.
>  - ... and 2 more: 
> https://git.openjdk.java.net/jdk/compare/083416d3...fd748501

> I've updated the code to produce better/more useful LineNumberTable for rule 
> switches.

@lahodaj I re-tested previous example and tested few others. Now everything 
seems to be good with `LineNumberTable` entries 👍 



However I also noticed that for


class Example {
void example(String s) {
switch (s) {
case "a":
System.out.println("a");
}
}
}


there is difference in frames before and after this PR


javap -v -p Example.class


diff is


 line 3: 0
 line 5: 60
 line 7: 68
-  StackMapTable: number_of_entries = 4
+  StackMapTable: number_of_entries = 5
 frame_type = 253 /* append */
-  offset_delta = 28
+  offset_delta = 4
   locals = [ class java/lang/String, int ]
+frame_type = 23 /* same */
 frame_type = 10 /* same */
 frame_type = 20 /* same */
 frame_type = 249 /* chop */


and


java -cp asm-util-9.1.jar:asm-9.1.jar org.objectweb.asm.util.Textifier 
Example.class


diff is


+   L1
+   FRAME APPEND [java/lang/String I]
 ALOAD 2
 INVOKEVIRTUAL java/lang/String.hashCode ()I
 LOOKUPSWITCH
-  97: L1
-  default: L2
-   L1
-   FRAME APPEND [java/lang/String I]
+  97: L2
+  default: L3
+   L2
+   FRAME SAME


Don't know about importance of this, and whether this was expected, but decided 
to mention.

-

Marked as reviewed by godin (Author).

PR: https://git.openjdk.java.net/jdk/pull/3863


Re: RFR: 8262891: Compiler implementation for Pattern Matching for switch (Preview) [v4]

2021-05-25 Thread Evgeny Mandrikov
On Tue, 25 May 2021 14:13:55 GMT, Rémi Forax  wrote:

> 7: iconst_0 < this zero

@forax as far as I understood this will be a value of
parameter `startIndex` in `java.lang.runtime. SwitchBootstraps.doSwitch` 😉 
Please correct me @lahodaj if I'm wrong.

-

PR: https://git.openjdk.java.net/jdk/pull/3863


Re: RFR: 8262891: Compiler implementation for Pattern Matching for switch (Preview) [v4]

2021-05-25 Thread Evgeny Mandrikov
On Mon, 17 May 2021 19:01:01 GMT, Jan Lahoda  wrote:

>> Good work. There's a lot to take in here. I think overall, it holds up well 
>> - I like how case labels have been extended to accommodate for patterns. In 
>> the front-end, I think there are some questions over the split between Attr 
>> and Flow - maybe it is unavoidable, but I'm not sure why some control-flow 
>> analysis happens in Attr instead of Flow and I left some questions to make 
>> sure I understand what's happening.
>> 
>> In the backend it's mostly good work - but overall the structure of the 
>> code, both in Lower and in TransPattern is getting very difficult to follow, 
>> given there are many different kind of switches each with its own little 
>> twist attached to it. It would be nice, I think (maybe in a separate 
>> cleanup?) if the code paths serving the different switch kinds could be made 
>> more separate, so that, when reading the code we can worry only about one 
>> possible code shape. That would make the code easier to document as well.
>
> @mcimadamore, @forax, thanks a lot for comments! I tried to apply the 
> requested changes in recent commits 
> (https://github.com/openjdk/jdk/pull/3863/commits/3fc2502a33cec20f39fe571eb25538ee3b459a9b
>  
> https://github.com/openjdk/jdk/pull/3863/commits/aeddb85e65bf77ed62dc7fa1ad00c29646d02c99
>  ).
> 
> I've also tried to update the implementation for the latest spec changes here:
> https://github.com/openjdk/jdk/pull/3863/commits/54ba974e1aac00bbde1c3bd2627f01caaaeda09b
> 
> The spec changes are: total patterns are nullable; pattern matching ("new") 
> statement switches must be complete (as switch expressions).
> 
> Any further feedback is welcome!

Hi @lahodaj  👋 ,

I tried `javac` built from this PR and for the following `Example.java`


class Example {
void example(Object o) {
switch (o) {
case String s && s.length() == 0 ->
System.out.println("1st case");
case String s && s.length() == 1 ->  // line 6
System.out.println("2nd case");  // line 7
case String s -> // line 8
System.out.println("3rd case");  // line 9
default ->   // line 10
System.out.println("default case");  // line 11
}
}
}


execution of


javac --enable-preview --release 17 Example.java
javap -v -p Example.class


produces


  void example(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: (0x)
Code:
  stack=2, locals=7, args_size=2
 0: aload_1
 1: dup
 2: invokestatic  #7  // Method 
java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
 5: pop
 6: astore_2
 7: iconst_0
 8: istore_3
 9: aload_2
10: iload_3
11: invokedynamic #13,  0 // InvokeDynamic 
#0:typeSwitch:(Ljava/lang/Object;I)I
16: tableswitch   { // 0 to 2
   0: 44
   1: 74
   2: 105
 default: 122
}
44: aload_2
45: checkcast #17 // class java/lang/String
48: astore4
50: aload 4
52: invokevirtual #19 // Method 
java/lang/String.length:()I
55: ifeq  63
58: iconst_1
59: istore_3
60: goto  9
63: getstatic #23 // Field 
java/lang/System.out:Ljava/io/PrintStream;
66: ldc   #29 // String 1st case
68: invokevirtual #31 // Method 
java/io/PrintStream.println:(Ljava/lang/String;)V
71: goto  133
74: aload_2
75: checkcast #17 // class java/lang/String
78: astore5
80: aload 5
82: invokevirtual #19 // Method 
java/lang/String.length:()I
85: iconst_1
86: if_icmpeq 94
89: iconst_2
90: istore_3
91: goto  9
94: getstatic #23 // Field 
java/lang/System.out:Ljava/io/PrintStream;
97: ldc   #37 // String 2nd case
99: invokevirtual #31 // Method 
java/io/PrintStream.println:(Ljava/lang/String;)V
   102: goto  133
   105: aload_2
   106: checkcast #17 // class java/lang/String
   109: astore6
   111: getstatic #23 // Field 
java/lang/System.out:Ljava/io/PrintStream;
   114: ldc   #39 // String 3rd case
   116: invokevirtual #31 // Method 
java/io/PrintStream.println:(Ljava/lang/String;)V
   119: goto  133
   122: getstatic #23 //