On Tue, 25 May 2021 16:00:43 GMT, Rémi Forax <fo...@openjdk.org> wrote:

> > The reason for this integer (which is not a constant in the case of this 
> > switch) is to restart the matching in case guards fail to "match". 
> > Considering the example here:
> > ```
> > 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
> >                 }
> >         }
> > }
> > ```
> > 
> > 
> >     
> >       
> >     
> > 
> >       
> >     
> > 
> >     
> >   
> > If `o` is `String`, then the first call to indy will be `indy[...](o, 0)`, 
> > returning `0`. Then the guard will be evaluated `s.length() == 0`. If the 
> > length is not zero, the local variable 3 will be reassigned to `1`(bytecode 
> > index 58, 59) and the whole switch is restarted - just this time, the 
> > matching in the indy will start at index `1`, not `0`, i.e. `indy[...](o, 
> > 1)`. And so on. I believe there is a text explaining the meaning of the 
> > parameter in the javadoc of the bootstrap, and in TransPatterns in javac.
> 
> The problem with this design is that calling example("foo") forces the VM 
> will do 6 checkcast String on "foo", and it doesn't work with sub-patterns. 
> Desugaring the guards as static method like with lambdas seems more 
> promising, indy can be called with the pairs [String, MethodHandle(s -> 
> s.length() == 0)], [String, MethodHandle(s -> s.length() == 0)] and [_,_] 
> (with the guards passed as a constant method handles again like lambdas are 
> desugared).
> It means that the indy needs to capture all local variables that are used in 
> the guards, instead of passing an int.
> 
> I believe that a translation using constant method handles for guards is far 
> more efficient than using an int and a backward branch but it has a higher 
> cost in term of runtime data structures.

I'd like to note this is a preview feature - we can change the desugaring. At 
the same time, I don't think this does not work with sub-patterns (those can be 
easily desugared to guards, I think). Regarding efficiency, it may be a balance 
between classfile overhead (which will be higher if we need to desugar every 
guard to a separate method), and the possibility to tweak the matching at 
runtime.

-------------

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

Reply via email to