Skip to content

Commit 2300ed4

Browse files
committedDec 5, 2022
8291769: Translation of switch with record patterns could be improved
Reviewed-by: vromero
1 parent eab0ada commit 2300ed4

File tree

13 files changed

+1373
-164
lines changed

13 files changed

+1373
-164
lines changed
 

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java

+450-130
Large diffs are not rendered by default.

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java

+15
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
package com.sun.tools.javac.comp;
2828

29+
import com.sun.tools.javac.code.Flags;
2930
import com.sun.tools.javac.code.Symbol;
3031
import com.sun.tools.javac.tree.JCTree;
3132
import com.sun.tools.javac.tree.JCTree.JCAnnotatedType;
@@ -44,6 +45,7 @@
4445
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
4546
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
4647
import com.sun.tools.javac.tree.JCTree.JCConditional;
48+
import com.sun.tools.javac.tree.JCTree.JCConstantCaseLabel;
4749
import com.sun.tools.javac.tree.JCTree.JCContinue;
4850
import com.sun.tools.javac.tree.JCTree.JCDefaultCaseLabel;
4951
import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
@@ -69,6 +71,7 @@
6971
import com.sun.tools.javac.tree.JCTree.JCNewClass;
7072
import com.sun.tools.javac.tree.JCTree.JCOpens;
7173
import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
74+
import com.sun.tools.javac.tree.JCTree.JCPatternCaseLabel;
7275
import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
7376
import com.sun.tools.javac.tree.JCTree.JCProvides;
7477
import com.sun.tools.javac.tree.JCTree.JCRecordPattern;
@@ -297,6 +300,18 @@ public void visitCase(JCCase tree) {
297300
result = scan(tree.labels, that.labels) && scan(tree.stats, that.stats);
298301
}
299302

303+
@Override
304+
public void visitConstantCaseLabel(JCConstantCaseLabel tree) {
305+
JCConstantCaseLabel that = (JCConstantCaseLabel) parameter;
306+
result = scan(tree.expr, that.expr);
307+
}
308+
309+
@Override
310+
public void visitPatternCaseLabel(JCPatternCaseLabel tree) {
311+
JCPatternCaseLabel that = (JCPatternCaseLabel) parameter;
312+
result = scan(tree.pat, that.pat) && scan(tree.guard, that.guard);
313+
}
314+
300315
@Override
301316
public void visitDefaultCaseLabel(JCDefaultCaseLabel tree) {
302317
result = true;

‎src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java

+58-11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.util.HashMap;
2929
import java.util.Map;
30+
import java.util.Set;
3031

3132
import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
3233
import com.sun.tools.javac.tree.TreeInfo.PosKind;
@@ -170,6 +171,8 @@ protected Gen(Context context) {
170171
Chain switchExpressionFalseChain;
171172
List<LocalItem> stackBeforeSwitchExpression;
172173
LocalItem switchResult;
174+
Set<JCMethodInvocation> invocationsWithPatternMatchingCatch = Set.of();
175+
ListBuffer<int[]> patternMatchingInvocationRanges;
173176

174177
/** Generate code to load an integer constant.
175178
* @param n The integer to be loaded.
@@ -1049,6 +1052,29 @@ public void visitSkip(JCSkip tree) {
10491052
}
10501053

10511054
public void visitBlock(JCBlock tree) {
1055+
if (tree.patternMatchingCatch != null) {
1056+
Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
1057+
ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
1058+
State startState = code.state.dup();
1059+
try {
1060+
invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
1061+
patternMatchingInvocationRanges = new ListBuffer<>();
1062+
doVisitBlock(tree);
1063+
} finally {
1064+
Chain skipCatch = code.branch(goto_);
1065+
JCCatch handler = tree.patternMatchingCatch.handler();
1066+
code.entryPoint(startState, handler.param.sym.type);
1067+
genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
1068+
code.resolve(skipCatch);
1069+
invocationsWithPatternMatchingCatch = prevInvocationsWithPatternMatchingCatch;
1070+
patternMatchingInvocationRanges = prevRanges;
1071+
}
1072+
} else {
1073+
doVisitBlock(tree);
1074+
}
1075+
}
1076+
1077+
private void doVisitBlock(JCBlock tree) {
10521078
int limit = code.nextreg;
10531079
Env<GenContext> localEnv = env.dup(tree, new GenContext());
10541080
genStats(tree.stats, localEnv);
@@ -1611,18 +1637,33 @@ void genCatch(JCCatch tree,
16111637
}
16121638
}
16131639
}
1614-
VarSymbol exparam = tree.param.sym;
1615-
code.statBegin(tree.pos);
1616-
code.markStatBegin();
1617-
int limit = code.nextreg;
1618-
code.newLocal(exparam);
1619-
items.makeLocalItem(exparam).store();
1620-
code.statBegin(TreeInfo.firstStatPos(tree.body));
1621-
genStat(tree.body, env, CRT_BLOCK);
1622-
code.endScopes(limit);
1623-
code.statBegin(TreeInfo.endPos(tree.body));
1640+
genCatchBlock(tree, env);
16241641
}
16251642
}
1643+
void genPatternMatchingCatch(JCCatch tree,
1644+
Env<GenContext> env,
1645+
List<int[]> ranges) {
1646+
for (int[] range : ranges) {
1647+
JCExpression subCatch = tree.param.vartype;
1648+
int catchType = makeRef(tree.pos(), subCatch.type);
1649+
registerCatch(tree.pos(),
1650+
range[0], range[1], code.curCP(),
1651+
catchType);
1652+
}
1653+
genCatchBlock(tree, env);
1654+
}
1655+
void genCatchBlock(JCCatch tree, Env<GenContext> env) {
1656+
VarSymbol exparam = tree.param.sym;
1657+
code.statBegin(tree.pos);
1658+
code.markStatBegin();
1659+
int limit = code.nextreg;
1660+
code.newLocal(exparam);
1661+
items.makeLocalItem(exparam).store();
1662+
code.statBegin(TreeInfo.firstStatPos(tree.body));
1663+
genStat(tree.body, env, CRT_BLOCK);
1664+
code.endScopes(limit);
1665+
code.statBegin(TreeInfo.endPos(tree.body));
1666+
}
16261667
// where
16271668
List<Pair<List<Attribute.TypeCompound>, JCExpression>> catchTypesWithAnnotations(JCCatch tree) {
16281669
return TreeInfo.isMultiCatch(tree) ?
@@ -1839,7 +1880,13 @@ public void visitApply(JCMethodInvocation tree) {
18391880
if (!msym.isDynamic()) {
18401881
code.statBegin(tree.pos);
18411882
}
1842-
result = m.invoke();
1883+
if (invocationsWithPatternMatchingCatch.contains(tree)) {
1884+
int start = code.curCP();
1885+
result = m.invoke();
1886+
patternMatchingInvocationRanges.add(new int[] {start, code.curCP()});
1887+
} else {
1888+
result = m.invoke();
1889+
}
18431890
}
18441891

18451892
public void visitConditional(JCConditional tree) {

‎src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java

+41-5
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,15 @@
8989

9090
import static com.sun.tools.javac.code.TypeTag.CLASS;
9191
import static com.sun.tools.javac.main.Option.*;
92+
import com.sun.tools.javac.tree.JCTree.JCBindingPattern;
9293
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
9394

9495
import static javax.tools.StandardLocation.CLASS_OUTPUT;
9596

9697
import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
98+
import com.sun.tools.javac.tree.JCTree.JCRecordPattern;
99+
import com.sun.tools.javac.tree.JCTree.JCSwitch;
100+
import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
97101

98102
/** This class could be the main entry point for GJC when GJC is used as a
99103
* component in a larger software system. It provides operations to
@@ -1465,6 +1469,7 @@ protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>,
14651469
class ScanNested extends TreeScanner {
14661470
Set<Env<AttrContext>> dependencies = new LinkedHashSet<>();
14671471
protected boolean hasLambdas;
1472+
protected boolean hasPatterns;
14681473
@Override
14691474
public void visitClassDef(JCClassDecl node) {
14701475
Type st = types.supertype(node.sym.type);
@@ -1475,16 +1480,19 @@ public void visitClassDef(JCClassDecl node) {
14751480
if (stEnv != null && env != stEnv) {
14761481
if (dependencies.add(stEnv)) {
14771482
boolean prevHasLambdas = hasLambdas;
1483+
boolean prevHasPatterns = hasPatterns;
14781484
try {
14791485
scan(stEnv.tree);
14801486
} finally {
14811487
/*
1482-
* ignore any updates to hasLambdas made during
1483-
* the nested scan, this ensures an initialized
1484-
* LambdaToMethod is available only to those
1485-
* classes that contain lambdas
1488+
* ignore any updates to hasLambdas and hasPatterns
1489+
* made during the nested scan, this ensures an
1490+
* initialized LambdaToMethod or TransPatterns is
1491+
* available only to those classes that contain
1492+
* lambdas or patterns, respectivelly
14861493
*/
14871494
hasLambdas = prevHasLambdas;
1495+
hasPatterns = prevHasPatterns;
14881496
}
14891497
}
14901498
envForSuperTypeFound = true;
@@ -1503,6 +1511,31 @@ public void visitReference(JCMemberReference tree) {
15031511
hasLambdas = true;
15041512
super.visitReference(tree);
15051513
}
1514+
@Override
1515+
public void visitBindingPattern(JCBindingPattern tree) {
1516+
hasPatterns = true;
1517+
super.visitBindingPattern(tree);
1518+
}
1519+
@Override
1520+
public void visitRecordPattern(JCRecordPattern that) {
1521+
hasPatterns = true;
1522+
super.visitRecordPattern(that);
1523+
}
1524+
@Override
1525+
public void visitParenthesizedPattern(JCTree.JCParenthesizedPattern tree) {
1526+
hasPatterns = true;
1527+
super.visitParenthesizedPattern(tree);
1528+
}
1529+
@Override
1530+
public void visitSwitch(JCSwitch tree) {
1531+
hasPatterns |= tree.patternSwitch;
1532+
super.visitSwitch(tree);
1533+
}
1534+
@Override
1535+
public void visitSwitchExpression(JCSwitchExpression tree) {
1536+
hasPatterns |= tree.patternSwitch;
1537+
super.visitSwitchExpression(tree);
1538+
}
15061539
}
15071540
ScanNested scanner = new ScanNested();
15081541
scanner.scan(env.tree);
@@ -1551,7 +1584,10 @@ public void visitReference(JCMemberReference tree) {
15511584
if (shouldStop(CompileState.TRANSPATTERNS))
15521585
return;
15531586

1554-
env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake);
1587+
if (scanner.hasPatterns) {
1588+
env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake);
1589+
}
1590+
15551591
compileStates.put(env, CompileState.TRANSPATTERNS);
15561592

15571593
if (scanner.hasLambdas) {

‎src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java

+11
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,12 @@ public static class JCBlock extends JCStatement implements BlockTree {
10741074
public List<JCStatement> stats;
10751075
/** Position of closing brace, optional. */
10761076
public int endpos = Position.NOPOS;
1077+
/** If this block contains record pattern, it is necessary to catch
1078+
* exceptions from the deconstructors and wrap them.
1079+
* The {@code patternMatchingCatch} keeps the list of the deconstructor
1080+
* invocations, and the additional catch block that wraps the exceptions.
1081+
*/
1082+
public PatternMatchingCatch patternMatchingCatch;
10771083
protected JCBlock(long flags, List<JCStatement> stats) {
10781084
this.stats = stats;
10791085
this.flags = flags;
@@ -1098,6 +1104,8 @@ public <R,D> R accept(TreeVisitor<R,D> v, D d) {
10981104
public Tag getTag() {
10991105
return BLOCK;
11001106
}
1107+
1108+
public record PatternMatchingCatch(JCCatch handler, Set<JCMethodInvocation> calls2Handle) {}
11011109
}
11021110

11031111
/**
@@ -2218,6 +2226,9 @@ public Tag getTag() {
22182226
public static class JCInstanceOf extends JCExpression implements InstanceOfTree {
22192227
public JCExpression expr;
22202228
public JCTree pattern;
2229+
/**{@code true} if this instanceof test should have
2230+
* value {@code true} when the {@code expr} is {@code null}.*/
2231+
public boolean allowNull;
22212232
protected JCInstanceOf(JCExpression expr, JCTree pattern) {
22222233
this.expr = expr;
22232234
this.pattern = pattern;

‎src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java

+9
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,15 @@ public static JCTree skipParens(JCTree tree) {
838838
return tree;
839839
}
840840

841+
/** Skip parens and return the enclosed expression
842+
*/
843+
public static JCPattern skipParens(JCPattern tree) {
844+
while (tree.hasTag(PARENTHESIZEDPATTERN)) {
845+
tree = ((JCParenthesizedPattern) tree).pattern;
846+
}
847+
return tree;
848+
}
849+
841850
/** Return the types of a list of trees.
842851
*/
843852
public static List<Type> types(List<? extends JCTree> trees) {

‎test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java

+14-18
Original file line numberDiff line numberDiff line change
@@ -209,27 +209,27 @@ public void runDeconstruction() throws Exception {
209209
descriptor: ()V
210210
flags: (0x0001) ACC_PUBLIC
211211
RuntimeInvisibleTypeAnnotations:
212-
0: #_A_(): LOCAL_VARIABLE, {start_pc=251, length=11, index=2}
212+
0: #_A_(): LOCAL_VARIABLE, {start_pc=316, length=11, index=2}
213213
Patterns$DeconstructionPattern$A
214-
1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=290, length=11, index=3}
214+
1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=359, length=11, index=3}
215215
Patterns$DeconstructionPattern$CA(
216216
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
217217
)
218-
2: #_A_(): LOCAL_VARIABLE, {start_pc=26, length=11, index=1}
218+
2: #_A_(): LOCAL_VARIABLE, {start_pc=30, length=11, index=1}
219219
Patterns$DeconstructionPattern$A
220-
3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=63, length=11, index=1}
220+
3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=1}
221221
Patterns$DeconstructionPattern$CA(
222222
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
223223
)
224-
4: #_A_(): LOCAL_VARIABLE, {start_pc=101, length=11, index=2}
224+
4: #_A_(): LOCAL_VARIABLE, {start_pc=114, length=11, index=2}
225225
Patterns$DeconstructionPattern$A
226-
5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=140, length=11, index=3}
226+
5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=157, length=11, index=3}
227227
Patterns$DeconstructionPattern$CA(
228228
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
229229
)
230-
6: #_A_(): LOCAL_VARIABLE, {start_pc=176, length=11, index=2}
230+
6: #_A_(): LOCAL_VARIABLE, {start_pc=215, length=11, index=2}
231231
Patterns$DeconstructionPattern$A
232-
7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=215, length=11, index=3}
232+
7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=258, length=11, index=3}
233233
Patterns$DeconstructionPattern$CA(
234234
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
235235
)
@@ -238,30 +238,26 @@ public void runDeconstruction() throws Exception {
238238
descriptor: ()V
239239
flags: (0x0000)
240240
RuntimeInvisibleTypeAnnotations:
241-
0: #_A_(): LOCAL_VARIABLE, {start_pc=23, length=11, index=2}
241+
0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=2}
242242
Patterns$DeconstructionPattern$A
243-
1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=11, index=3}
243+
1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=3}
244244
Patterns$DeconstructionPattern$CA(
245245
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
246246
)
247247
248-
private static java.lang.String $proxy$s(Patterns$DeconstructionPattern$R);
249-
descriptor: (LPatterns$DeconstructionPattern$R;)Ljava/lang/String;
250-
flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
251-
252248
static {};
253249
descriptor: ()V
254250
flags: (0x0008) ACC_STATIC
255251
RuntimeInvisibleTypeAnnotations:
256-
0: #_A_(): LOCAL_VARIABLE, {start_pc=26, length=11, index=0}
252+
0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=0}
257253
Patterns$DeconstructionPattern$A
258-
1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=11, index=0}
254+
1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=66, length=11, index=0}
259255
Patterns$DeconstructionPattern$CA(
260256
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
261257
)
262-
2: #_A_(): LOCAL_VARIABLE, {start_pc=98, length=11, index=1}
258+
2: #_A_(): LOCAL_VARIABLE, {start_pc=106, length=11, index=1}
263259
Patterns$DeconstructionPattern$A
264-
3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=134, length=11, index=2}
260+
3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=147, length=11, index=2}
265261
Patterns$DeconstructionPattern$CA(
266262
value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A]
267263
)

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Dec 5, 2022

@openjdk-notifier[bot]
Please sign in to comment.