Skip to content

Commit 73166a2

Browse files
committed
JDK-8262891: Compiler implementation for Pattern Matching for switch
1 parent ee5bba0 commit 73166a2

File tree

68 files changed

+3748
-239
lines changed

Some content is hidden

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

68 files changed

+3748
-239
lines changed

make/CompileInterimLangtools.gmk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ 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 $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \
5353
DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \
5454
))
5555

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
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+
* <p>The bootstrap call site accepts a single parameter of the type of the
48+
* operand of the {@code switch}, and return an {@code int} that is the index of
49+
* the matched {@code case} label, {@code -1} if the target is {@code null},
50+
* or {@code N} if the target is not null but matches no {@code case} label.
51+
*
52+
* @since 17
53+
*/
54+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING)
55+
public class SwitchBootstraps {
56+
57+
private SwitchBootstraps() {}
58+
59+
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
60+
61+
//typeSwitch implementation:
62+
private static final MethodHandle TYPE_INIT_HOOK;
63+
private static final MethodHandle TYPE_SWITCH_METHOD;
64+
65+
static {
66+
try {
67+
TYPE_INIT_HOOK = LOOKUP.findStatic(SwitchBootstraps.class, "typeInitHook",
68+
MethodType.methodType(MethodHandle.class, CallSite.class));
69+
TYPE_SWITCH_METHOD = LOOKUP.findVirtual(TypeSwitchCallSite.class, "doSwitch",
70+
MethodType.methodType(int.class, Object.class, int.class));
71+
}
72+
catch (ReflectiveOperationException e) {
73+
throw new ExceptionInInitializerError(e);
74+
}
75+
}
76+
77+
private static<T extends CallSite> MethodHandle typeInitHook(T receiver) {
78+
return TYPE_SWITCH_METHOD.bindTo(receiver);
79+
}
80+
81+
/**
82+
* Bootstrap method for linking an {@code invokedynamic} call site that
83+
* implements a {@code switch} on a reference-typed target. The static
84+
* arguments are a varargs array of case labels. Constants of type {@code String} or
85+
* {@code Integer} and {@code Class} instances are accepted.
86+
*
87+
* @param lookup Represents a lookup context with the accessibility
88+
* privileges of the caller. When used with {@code invokedynamic},
89+
* this is stacked automatically by the VM.
90+
* @param invocationName The invocation name, which is ignored. When used with
91+
* {@code invokedynamic}, this is provided by the
92+
* {@code NameAndType} of the {@code InvokeDynamic}
93+
* structure and is stacked automatically by the VM.
94+
* @param invocationType The invocation type of the {@code CallSite}. This
95+
* method type should have a single parameter of
96+
* a reference type, and return {@code int}. When
97+
* used with {@code invokedynamic}, this is provided by
98+
* the {@code NameAndType} of the {@code InvokeDynamic}
99+
* structure and is stacked automatically by the VM.
100+
* @param labels non-null case labels - {@code String} and {@code Integer} constants
101+
* and {@code Class} instances
102+
* @return the index into {@code labels} of the target value, if the target
103+
* is an instance of any of the types, {@literal -1} if the target
104+
* value is {@code null}, or {@code types.length} if the target value
105+
* is not an instance of any of the types
106+
* @throws NullPointerException if any required argument is null
107+
* @throws IllegalArgumentException if any labels are null, or if the
108+
* invocation type is not {@code (T)int for some reference type {@code T}}
109+
* @throws Throwable if there is any error linking the call site
110+
*/
111+
public static CallSite typeSwitch(MethodHandles.Lookup lookup,
112+
String invocationName,
113+
MethodType invocationType,
114+
Object... labels) throws Throwable {
115+
if (invocationType.parameterCount() != 2
116+
|| (!invocationType.returnType().equals(int.class))
117+
|| invocationType.parameterType(0).isPrimitive())
118+
throw new IllegalArgumentException("Illegal invocation type " + invocationType);
119+
requireNonNull(labels);
120+
121+
labels = labels.clone();
122+
Stream.of(labels).forEach(SwitchBootstraps::verifyLabel);
123+
124+
return new TypeSwitchCallSite(invocationType, labels);
125+
}
126+
127+
private static void verifyLabel(Object label) {
128+
if (Objects.isNull(label)) {
129+
throw new IllegalArgumentException("null label found");
130+
}
131+
if (label.getClass() != Class.class &&
132+
label.getClass() != String.class &&
133+
label.getClass() != Integer.class) {
134+
throw new IllegalArgumentException("label with illegal type found: " + label.getClass());
135+
}
136+
}
137+
138+
static class TypeSwitchCallSite extends ConstantCallSite {
139+
private final Object[] labels;
140+
141+
TypeSwitchCallSite(MethodType targetType,
142+
Object[] labels) throws Throwable {
143+
super(targetType, TYPE_INIT_HOOK);
144+
this.labels = labels;
145+
}
146+
147+
int doSwitch(Object target, int startIndex) {
148+
if (target == null)
149+
return -1;
150+
151+
// Dumbest possible strategy
152+
Class<?> targetClass = target.getClass();
153+
for (int i = startIndex; i < labels.length; i++) {
154+
if (labels[i] instanceof Class<?>) {
155+
Class<?> c = (Class<?>) labels[i];
156+
if (c.isAssignableFrom(targetClass))
157+
return i;
158+
} else {
159+
if (labels[i] instanceof Integer constant) {
160+
if (target instanceof Number input && constant.intValue() == input.intValue()) {
161+
return i;
162+
}
163+
if (target instanceof Character input && constant.intValue() == input.charValue()) {
164+
return i;
165+
}
166+
} else if (labels[i].equals(target)) {
167+
return i;
168+
}
169+
}
170+
}
171+
172+
return labels.length;
173+
}
174+
}
175+
176+
}
Lines changed: 43 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
public enum Feature {
5757
SEALED_CLASSES,
58+
SWITCH_PATTERN_MATCHING,
5859
/**
5960
* A key for testing.
6061
*/
Lines changed: 35 additions & 0 deletions
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+
26+
package com.sun.source.tree;
27+
28+
import jdk.internal.javac.PreviewFeature;
29+
30+
/**A marker interface for {@code Tree}s that may be used as {@link CaseTree} labels.
31+
*
32+
* @since 17
33+
*/
34+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
35+
public interface CaseLabelTree extends Tree {}

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

Lines changed: 12 additions & 0 deletions
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.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
/** A case label that marks {@code default} in {@code case null, default}.
30+
* @since 17
31+
*/
32+
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
33+
public interface DefaultCaseLabelTree extends CaseLabelTree {}

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

Lines changed: 4 additions & 1 deletion
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 {}

0 commit comments

Comments
 (0)