Skip to content

Commit 3f6b177

Browse files
committed
8332934: Do loop with continue with subsequent switch leads to incorrect stack maps
Reviewed-by: vromero
1 parent cb02158 commit 3f6b177

File tree

5 files changed

+87
-21
lines changed

5 files changed

+87
-21
lines changed

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,11 +1192,7 @@ private void genLoop(JCStatement loop,
11921192
code.resolve(c.falseJumps);
11931193
}
11941194
}
1195-
Chain exit = loopEnv.info.exit;
1196-
if (exit != null) {
1197-
code.resolve(exit);
1198-
exit.state.defined.excludeFrom(code.nextreg);
1199-
}
1195+
code.resolve(loopEnv.info.exit);
12001196
}
12011197

12021198
public void visitForeachLoop(JCEnhancedForLoop tree) {
@@ -1206,11 +1202,7 @@ public void visitForeachLoop(JCEnhancedForLoop tree) {
12061202
public void visitLabelled(JCLabeledStatement tree) {
12071203
Env<GenContext> localEnv = env.dup(tree, new GenContext());
12081204
genStat(tree.body, localEnv, CRT_STATEMENT);
1209-
Chain exit = localEnv.info.exit;
1210-
if (exit != null) {
1211-
code.resolve(exit);
1212-
exit.state.defined.excludeFrom(code.nextreg);
1213-
}
1205+
code.resolve(localEnv.info.exit);
12141206
}
12151207

12161208
public void visitSwitch(JCSwitch tree) {
@@ -1413,11 +1405,7 @@ private void handleSwitch(JCTree swtch, JCExpression selector, List<JCCase> case
14131405
}
14141406

14151407
// Resolve all breaks.
1416-
Chain exit = switchEnv.info.exit;
1417-
if (exit != null) {
1418-
code.resolve(exit);
1419-
exit.state.defined.excludeFrom(limit);
1420-
}
1408+
code.resolve(switchEnv.info.exit);
14211409

14221410
// If we have not set the default offset, we do so now.
14231411
if (code.get4(tableBase) == -1) {
@@ -2537,7 +2525,14 @@ void afterBody() {}
25372525
/** code generation contexts,
25382526
* to be used as type parameter for environments.
25392527
*/
2540-
static class GenContext {
2528+
final class GenContext {
2529+
2530+
/**
2531+
* The top defined local variables for exit or continue branches to merge into.
2532+
* It may contain uninitialized variables to be initialized by branched code,
2533+
* so we cannot use Code.State.defined bits.
2534+
*/
2535+
final int limit;
25412536

25422537
/** A chain for all unresolved jumps that exit the current environment.
25432538
*/
@@ -2563,15 +2558,26 @@ static class GenContext {
25632558
*/
25642559
ListBuffer<Integer> gaps = null;
25652560

2561+
GenContext() {
2562+
var code = Gen.this.code;
2563+
this.limit = code == null ? 0 : code.nextreg;
2564+
}
2565+
25662566
/** Add given chain to exit chain.
25672567
*/
25682568
void addExit(Chain c) {
2569+
if (c != null) {
2570+
c.state.defined.excludeFrom(limit);
2571+
}
25692572
exit = Code.mergeChains(c, exit);
25702573
}
25712574

25722575
/** Add given chain to cont chain.
25732576
*/
25742577
void addCont(Chain c) {
2578+
if (c != null) {
2579+
c.state.defined.excludeFrom(limit);
2580+
}
25752581
cont = Code.mergeChains(c, cont);
25762582
}
25772583
}

test/langtools/tools/javac/flow/LVTHarness.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -157,6 +157,7 @@ void checkMethod(MethodModel method, AliveRanges ranges) {
157157

158158
if (i < infoFromRanges.size()) {
159159
error(infoFromLVT, infoFromRanges, method.methodName().stringValue());
160+
System.err.println(method.toDebugString());
160161
}
161162
}
162163

test/langtools/tools/javac/BranchToFewerDefines.java renamed to test/langtools/tools/javac/stackmap/BranchToFewerDefines.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8067429
26+
* @bug 8067429 8332934
2727
* @summary java.lang.VerifyError: Inconsistent stackmap frames at branch target
2828
* @author srikanth
2929
*
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2025, 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8332934
27+
* @summary Incorrect defined locals escaped from continue in do loop
28+
* @library /tools/lib /test/lib
29+
* @run main DoLoopLocalEscapeThroughContinueTest
30+
*/
31+
32+
import jdk.test.lib.ByteCodeLoader;
33+
import jdk.test.lib.compiler.InMemoryJavaCompiler;
34+
35+
import java.lang.classfile.ClassFile;
36+
import java.lang.invoke.MethodHandles;
37+
38+
public class DoLoopLocalEscapeThroughContinueTest {
39+
public static void main(String... args) throws Throwable {
40+
String source = """
41+
static void main(String[] k) {
42+
do {
43+
int b = 1;
44+
continue;
45+
} while (Math.random() > 0.5D) ;
46+
switch (2) {
47+
case 3:
48+
double d;
49+
case 4:
50+
k.toString();
51+
}
52+
}
53+
""";
54+
var bytes = InMemoryJavaCompiler.compile("Test", source, "-XDdebug.code");
55+
System.out.println(ClassFile.of().parse(bytes).toDebugString());
56+
var clz = ByteCodeLoader.load("Test", bytes);
57+
MethodHandles.privateLookupIn(clz, MethodHandles.lookup()).ensureInitialized(clz); // force verification
58+
}
59+
}

test/langtools/tools/javac/SwitchExitStateTest.java renamed to test/langtools/tools/javac/stackmap/SwitchExitStateTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8160699
26+
* @bug 8160699 8332934
2727
* @summary Verify that having finished executing a switch statement live locals are exactly the same as it was upon entry of the switch.
2828
* @run main SwitchExitStateTest
2929
*/

0 commit comments

Comments
 (0)