Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
73166a2
JDK-8262891: Compiler implementation for Pattern Matching for switch
lahodaj May 4, 2021
c88e3f2
Merge branch 'master' into JDK-8262891
lahodaj May 10, 2021
1a5a424
Cleanup, reflecting review comments.
lahodaj May 10, 2021
5e663d7
Trailing whitespaces.
lahodaj May 10, 2021
3fc2502
Reflecting review comments on SwitchBootstraps.
lahodaj May 11, 2021
aeddb85
Reflecting review comments.
lahodaj May 14, 2021
54ba974
Reflecting recent spec changes.
lahodaj May 17, 2021
5fa8005
Avoiding fall-through from the total case to a synthetic default but …
lahodaj May 18, 2021
0875377
Fixing various error-related bugs.
lahodaj May 18, 2021
25f1b76
Merging master into JDK-8262891
lahodaj May 26, 2021
7d1abc1
Correcting LineNumberTable for rule switches.
lahodaj May 26, 2021
fd74850
Post-merge fix - need to include jdk.internal.javac in the list of pa…
lahodaj May 26, 2021
a57d306
Avoiding unnecessary StackMap point.
lahodaj May 28, 2021
a1b7678
Properly report errors for pattern+default clash.
lahodaj May 31, 2021
4a7dc57
Total pattern dominates the null pattern.
lahodaj May 31, 2021
a49b610
Fixing tests.
lahodaj May 31, 2021
80b1392
Fixing enum switch with patterns with guards.
lahodaj Jun 1, 2021
79e3621
Enhancing tests as suggested.
lahodaj Jun 3, 2021
fa50b5f
Merging master into JDK-8262891
lahodaj Jun 3, 2021
c6204f9
Improving javadoc.
lahodaj Jun 3, 2021
216b87c
Tweaking SwitchBootstraps javadoc, as suggested.
lahodaj Jun 4, 2021
8d4c02b
Fixing typo.
lahodaj Jun 4, 2021
2b7a38d
Tweaking javadoc.
lahodaj Jun 4, 2021
e3c2975
Applying review feedback.
lahodaj Jun 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion make/CompileInterimLangtools.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ TARGETS += $(patsubst %, $(BUILDTOOLS_OUTPUTDIR)/gensrc/%/module-info.java, \
$(INTERIM_LANGTOOLS_MODULES))

$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \
FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java, \
FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \
DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \
))

Expand Down
170 changes: 170 additions & 0 deletions src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package java.lang.runtime;

import java.lang.invoke.CallSite;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Stream;

import jdk.internal.javac.PreviewFeature;

import static java.util.Objects.requireNonNull;

/**
* Bootstrap methods for linking {@code invokedynamic} call sites that implement
* the selection functionality of the {@code switch} statement. The bootstraps
* take additional static arguments corresponding to the {@code case} labels
* of the {@code switch}, implicitly numbered sequentially from {@code [0..N)}.
*
* @since 17
*/
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING)
public class SwitchBootstraps {

private SwitchBootstraps() {}

private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

private static final MethodHandle DO_SWITCH;

static {
try {
DO_SWITCH = LOOKUP.findStatic(SwitchBootstraps.class, "doSwitch",
MethodType.methodType(int.class, Object.class, int.class, Object[].class));
}
catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}

/**
* Bootstrap method for linking an {@code invokedynamic} call site that
* implements a {@code switch} on a target of a reference type. The static
* arguments are an array of case labels which must be non-null and of type
* {@code String} or {@code Integer} or {@code Class}.
* <p>
* The type of the returned {@code CallSite}'s method handle will have
* a return type of {@code int}. It has two parameters: the first argument
* will be an {@code Object} instance ({@code target}) and the second
* will be {@code int} ({@code restart}).
* <p>
* If the {@code target} is {@code null}, then the method of the call site
* returns {@literal -1}.
* <p>
* If the {@code target} is not {@code null}, then the method of the call site
* returns the index of the first element in the {@code labels} array starting from
* the {@code restart} index matching one of the following conditions:
* <ul>
* <li>the element is of type {@code Class} that is assignable
* from the target's class; or</li>
* <li>the element is of type {@code String} or {@code Integer} and
* equals to the target.</li>
* </ul>
* <p>
* If no element in the {@code labels} array matches the target, then
* the method of the call site return the length of the {@code labels} array.
*
* @param lookup Represents a lookup context with the accessibility
* privileges of the caller. When used with {@code invokedynamic},
* this is stacked automatically by the VM.
* @param invocationName unused
* @param invocationType The invocation type of the {@code CallSite} with two parameters,
* a reference type, an {@code int}, and {@code int} as a return type.
* @param labels case labels - {@code String} and {@code Integer} constants
* and {@code Class} instances, in any combination
* @return a {@code CallSite} returning the first matching element as described above
*
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if any element in the labels array is null, if the
* invocation type is not not a method type of first parameter of a reference type,
* second parameter of type {@code int} and with {@code int} as its return type,
* or if {@code labels} contains an element that is not of type {@code String},
* {@code Integer} or {@code Class}.
* @throws Throwable if there is any error linking the call site
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
*/
public static CallSite typeSwitch(MethodHandles.Lookup lookup,
String invocationName,
MethodType invocationType,
Object... labels) throws Throwable {
if (invocationType.parameterCount() != 2
|| (!invocationType.returnType().equals(int.class))
|| invocationType.parameterType(0).isPrimitive()
|| !invocationType.parameterType(1).equals(int.class))
throw new IllegalArgumentException("Illegal invocation type " + invocationType);
requireNonNull(labels);

labels = labels.clone();
Stream.of(labels).forEach(SwitchBootstraps::verifyLabel);

MethodHandle target = MethodHandles.insertArguments(DO_SWITCH, 2, (Object) labels);
return new ConstantCallSite(target);
}

private static void verifyLabel(Object label) {
if (label == null) {
throw new IllegalArgumentException("null label found");
}
Class<?> labelClass = label.getClass();
if (labelClass != Class.class &&
labelClass != String.class &&
labelClass != Integer.class) {
throw new IllegalArgumentException("label with illegal type found: " + label.getClass());
}
}

private static int doSwitch(Object target, int startIndex, Object[] labels) {
if (target == null)
return -1;

// Dumbest possible strategy
Class<?> targetClass = target.getClass();
for (int i = startIndex; i < labels.length; i++) {
Object label = labels[i];
if (label instanceof Class<?> c) {
if (c.isAssignableFrom(targetClass))
return i;
} else if (label instanceof Integer constant) {
if (target instanceof Number input && constant.intValue() == input.intValue()) {
return i;
} else if (target instanceof Character input && constant.intValue() == input.charValue()) {
return i;
}
} else if (label.equals(target)) {
return i;
}
}

return labels.length;
}

}
43 changes: 43 additions & 0 deletions src/java.base/share/classes/jdk/internal/javac/NoPreview.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.javac;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* The element annotated with this annotation should not be marked as a preview element.
*/
@Target({ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.PACKAGE,
ElementType.MODULE,
ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface NoPreview {
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public enum Feature {
* This one can only be removed after JDK 17
*/
SEALED_CLASSES,
SWITCH_PATTERN_MATCHING,
/**
* A key for testing.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.sun.source.tree;

import jdk.internal.javac.PreviewFeature;

/**
* A marker interface for {@code Tree}s that may be used as {@link CaseTree} labels.
*
* @since 17
*/
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
public interface CaseLabelTree extends Tree {}
12 changes: 12 additions & 0 deletions src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import java.util.List;

import jdk.internal.javac.PreviewFeature;

/**
* A tree node for a {@code case} in a {@code switch} statement or expression.
*
Expand Down Expand Up @@ -65,6 +67,16 @@ public interface CaseTree extends Tree {
*/
List<? extends ExpressionTree> getExpressions();

/**
* Returns the labels for this case.
* For {@code default} case return a list with a single element, {@link DefaultCaseLabelTree}.
*
* @return labels for this case
* @since 17
*/
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
List<? extends CaseLabelTree> getLabels();

/**
* For case with kind {@linkplain CaseKind#STATEMENT},
* returns the statements labeled by the case.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.source.tree;

import jdk.internal.javac.PreviewFeature;

/**
* A case label that marks {@code default} in {@code case null, default}.
*
* @since 17
*/
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
public interface DefaultCaseLabelTree extends CaseLabelTree {}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

package com.sun.source.tree;

import jdk.internal.javac.NoPreview;

/**
* A tree node used as the base class for the different types of
* expressions.
Expand All @@ -35,4 +37,5 @@
* @author Jonathan Gibbons
* @since 1.6
*/
public interface ExpressionTree extends Tree {}
@NoPreview
public interface ExpressionTree extends Tree, CaseLabelTree {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.sun.source.tree;

import jdk.internal.javac.PreviewFeature;

/**
* A guard pattern tree.
*
* @since 17
*/
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
public interface GuardedPatternTree extends PatternTree {

/**
* The guarded pattern expression.
* @return the guarded pattern
*/
public PatternTree getPattern();

/**
* The guard expression.
* @return the guard expression
*/
public ExpressionTree getExpression();

}
Loading