Skip to content

Commit 908aca2

Browse files
lahodajBrian GoetzMandy Chung
committed
8262891: Compiler implementation for Pattern Matching for switch (Preview)
Co-authored-by: Brian Goetz <briangoetz@openjdk.org> Co-authored-by: Mandy Chung <mchung@openjdk.org> Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Reviewed-by: mcimadamore, forax, godin, psandoz, mchung
1 parent 3e48244 commit 908aca2

File tree

78 files changed

+4795
-292
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+4795
-292
lines changed

make/CompileInterimLangtools.gmk

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ TARGETS += $(patsubst %, $(BUILDTOOLS_OUTPUTDIR)/gensrc/%/module-info.java, \
4949
$(INTERIM_LANGTOOLS_MODULES))
5050

5151
$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \
52-
FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java, \
52+
FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
53+
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \
5354
DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \
5455
))
5556

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package java.lang.runtime;
27+
28+
import java.lang.invoke.CallSite;
29+
import java.lang.invoke.ConstantCallSite;
30+
import java.lang.invoke.MethodHandle;
31+
import java.lang.invoke.MethodHandles;
32+
import java.lang.invoke.MethodType;
33+
import java.util.Arrays;
34+
import java.util.Objects;
35+
import java.util.stream.Stream;
36+
37+
import jdk.internal.javac.PreviewFeature;
38+
39+
import static java.util.Objects.requireNonNull;
40+
41+
/**
42+
* Bootstrap methods for linking {@code invokedynamic} call sites that implement
43+
* the selection functionality of the {@code switch} statement. The bootstraps
44+
* take additional static arguments corresponding to the {@code case} labels
45+
* of the {@code switch}, implicitly numbered sequentially from {@code [0..N)}.
46+
*
47+
* @since 17
48+
*/
49+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING)
50+
public class SwitchBootstraps {
51+
52+
private SwitchBootstraps() {}
53+
54+
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
55+
56+
private static final MethodHandle DO_SWITCH;
57+
58+
static {
59+
try {
60+
DO_SWITCH = LOOKUP.findStatic(SwitchBootstraps.class, "doSwitch",
61+
MethodType.methodType(int.class, Object.class, int.class, Object[].class));
62+
}
63+
catch (ReflectiveOperationException e) {
64+
throw new ExceptionInInitializerError(e);
65+
}
66+
}
67+
68+
/**
69+
* Bootstrap method for linking an {@code invokedynamic} call site that
70+
* implements a {@code switch} on a target of a reference type. The static
71+
* arguments are an array of case labels which must be non-null and of type
72+
* {@code String} or {@code Integer} or {@code Class}.
73+
* <p>
74+
* The type of the returned {@code CallSite}'s method handle will have
75+
* a return type of {@code int}. It has two parameters: the first argument
76+
* will be an {@code Object} instance ({@code target}) and the second
77+
* will be {@code int} ({@code restart}).
78+
* <p>
79+
* If the {@code target} is {@code null}, then the method of the call site
80+
* returns {@literal -1}.
81+
* <p>
82+
* If the {@code target} is not {@code null}, then the method of the call site
83+
* returns the index of the first element in the {@code labels} array starting from
84+
* the {@code restart} index matching one of the following conditions:
85+
* <ul>
86+
* <li>the element is of type {@code Class} that is assignable
87+
* from the target's class; or</li>
88+
* <li>the element is of type {@code String} or {@code Integer} and
89+
* equals to the target.</li>
90+
* </ul>
91+
* <p>
92+
* If no element in the {@code labels} array matches the target, then
93+
* the method of the call site return the length of the {@code labels} array.
94+
*
95+
* @param lookup Represents a lookup context with the accessibility
96+
* privileges of the caller. When used with {@code invokedynamic},
97+
* this is stacked automatically by the VM.
98+
* @param invocationName unused
99+
* @param invocationType The invocation type of the {@code CallSite} with two parameters,
100+
* a reference type, an {@code int}, and {@code int} as a return type.
101+
* @param labels case labels - {@code String} and {@code Integer} constants
102+
* and {@code Class} instances, in any combination
103+
* @return a {@code CallSite} returning the first matching element as described above
104+
*
105+
* @throws NullPointerException if any argument is {@code null}
106+
* @throws IllegalArgumentException if any element in the labels array is null, if the
107+
* invocation type is not not a method type of first parameter of a reference type,
108+
* second parameter of type {@code int} and with {@code int} as its return type,
109+
* or if {@code labels} contains an element that is not of type {@code String},
110+
* {@code Integer} or {@code Class}.
111+
* @throws Throwable if there is any error linking the call site
112+
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
113+
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
114+
*/
115+
public static CallSite typeSwitch(MethodHandles.Lookup lookup,
116+
String invocationName,
117+
MethodType invocationType,
118+
Object... labels) throws Throwable {
119+
if (invocationType.parameterCount() != 2
120+
|| (!invocationType.returnType().equals(int.class))
121+
|| invocationType.parameterType(0).isPrimitive()
122+
|| !invocationType.parameterType(1).equals(int.class))
123+
throw new IllegalArgumentException("Illegal invocation type " + invocationType);
124+
requireNonNull(labels);
125+
126+
labels = labels.clone();
127+
Stream.of(labels).forEach(SwitchBootstraps::verifyLabel);
128+
129+
MethodHandle target = MethodHandles.insertArguments(DO_SWITCH, 2, (Object) labels);
130+
return new ConstantCallSite(target);
131+
}
132+
133+
private static void verifyLabel(Object label) {
134+
if (label == null) {
135+
throw new IllegalArgumentException("null label found");
136+
}
137+
Class<?> labelClass = label.getClass();
138+
if (labelClass != Class.class &&
139+
labelClass != String.class &&
140+
labelClass != Integer.class) {
141+
throw new IllegalArgumentException("label with illegal type found: " + label.getClass());
142+
}
143+
}
144+
145+
private static int doSwitch(Object target, int startIndex, Object[] labels) {
146+
if (target == null)
147+
return -1;
148+
149+
// Dumbest possible strategy
150+
Class<?> targetClass = target.getClass();
151+
for (int i = startIndex; i < labels.length; i++) {
152+
Object label = labels[i];
153+
if (label instanceof Class<?> c) {
154+
if (c.isAssignableFrom(targetClass))
155+
return i;
156+
} else if (label instanceof Integer constant) {
157+
if (target instanceof Number input && constant.intValue() == input.intValue()) {
158+
return i;
159+
} else if (target instanceof Character input && constant.intValue() == input.charValue()) {
160+
return i;
161+
}
162+
} else if (label.equals(target)) {
163+
return i;
164+
}
165+
}
166+
167+
return labels.length;
168+
}
169+
170+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.internal.javac;
26+
27+
import java.lang.annotation.ElementType;
28+
import java.lang.annotation.Retention;
29+
import java.lang.annotation.RetentionPolicy;
30+
import java.lang.annotation.Target;
31+
32+
/**
33+
* The element annotated with this annotation should not be marked as a preview element.
34+
*/
35+
@Target({ElementType.METHOD,
36+
ElementType.CONSTRUCTOR,
37+
ElementType.FIELD,
38+
ElementType.PACKAGE,
39+
ElementType.MODULE,
40+
ElementType.TYPE})
41+
@Retention(RetentionPolicy.CLASS)
42+
public @interface NoPreview {
43+
}

src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public enum Feature {
5858
* This one can only be removed after JDK 17
5959
*/
6060
SEALED_CLASSES,
61+
SWITCH_PATTERN_MATCHING,
6162
/**
6263
* A key for testing.
6364
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.sun.source.tree;
27+
28+
import jdk.internal.javac.PreviewFeature;
29+
30+
/**
31+
* A marker interface for {@code Tree}s that may be used as {@link CaseTree} labels.
32+
*
33+
* @since 17
34+
*/
35+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
36+
public interface CaseLabelTree extends Tree {}

src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
import java.util.List;
2929

30+
import jdk.internal.javac.PreviewFeature;
31+
3032
/**
3133
* A tree node for a {@code case} in a {@code switch} statement or expression.
3234
*
@@ -65,6 +67,16 @@ public interface CaseTree extends Tree {
6567
*/
6668
List<? extends ExpressionTree> getExpressions();
6769

70+
/**
71+
* Returns the labels for this case.
72+
* For {@code default} case return a list with a single element, {@link DefaultCaseLabelTree}.
73+
*
74+
* @return labels for this case
75+
* @since 17
76+
*/
77+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
78+
List<? extends CaseLabelTree> getLabels();
79+
6880
/**
6981
* For case with kind {@linkplain CaseKind#STATEMENT},
7082
* returns the statements labeled by the case.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.sun.source.tree;
26+
27+
import jdk.internal.javac.PreviewFeature;
28+
29+
/**
30+
* A case label that marks {@code default} in {@code case null, default}.
31+
*
32+
* @since 17
33+
*/
34+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
35+
public interface DefaultCaseLabelTree extends CaseLabelTree {}

src/jdk.compiler/share/classes/com/sun/source/tree/ExpressionTree.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package com.sun.source.tree;
2727

28+
import jdk.internal.javac.NoPreview;
29+
2830
/**
2931
* A tree node used as the base class for the different types of
3032
* expressions.
@@ -35,4 +37,5 @@
3537
* @author Jonathan Gibbons
3638
* @since 1.6
3739
*/
38-
public interface ExpressionTree extends Tree {}
40+
@NoPreview
41+
public interface ExpressionTree extends Tree, CaseLabelTree {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.sun.source.tree;
27+
28+
import jdk.internal.javac.PreviewFeature;
29+
30+
/**
31+
* A guard pattern tree.
32+
*
33+
* @since 17
34+
*/
35+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
36+
public interface GuardedPatternTree extends PatternTree {
37+
38+
/**
39+
* The guarded pattern expression.
40+
* @return the guarded pattern
41+
*/
42+
public PatternTree getPattern();
43+
44+
/**
45+
* The guard expression.
46+
* @return the guard expression
47+
*/
48+
public ExpressionTree getExpression();
49+
50+
}

0 commit comments

Comments
 (0)