RFR: 8262891: Compiler implementation for Pattern Matching for switch (Preview) [v4]
Jan Lahoda
jlahoda at openjdk.java.net
Tue May 25 16:17:59 UTC 2021
On Tue, 25 May 2021 16:00:43 GMT, Rémi Forax <forax at 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
More information about the compiler-dev
mailing list