8332934: Do loop with continue with subsequent switch leads to incorrect stack maps

Reviewed-by: vromero
This commit is contained in:
Chen Liang 2025-05-07 18:09:23 +00:00
parent cb02158090
commit 3f6b17777f
5 changed files with 87 additions and 21 deletions

View File

@ -1192,11 +1192,7 @@ public class Gen extends JCTree.Visitor {
code.resolve(c.falseJumps);
}
}
Chain exit = loopEnv.info.exit;
if (exit != null) {
code.resolve(exit);
exit.state.defined.excludeFrom(code.nextreg);
}
code.resolve(loopEnv.info.exit);
}
public void visitForeachLoop(JCEnhancedForLoop tree) {
@ -1206,11 +1202,7 @@ public class Gen extends JCTree.Visitor {
public void visitLabelled(JCLabeledStatement tree) {
Env<GenContext> localEnv = env.dup(tree, new GenContext());
genStat(tree.body, localEnv, CRT_STATEMENT);
Chain exit = localEnv.info.exit;
if (exit != null) {
code.resolve(exit);
exit.state.defined.excludeFrom(code.nextreg);
}
code.resolve(localEnv.info.exit);
}
public void visitSwitch(JCSwitch tree) {
@ -1413,11 +1405,7 @@ public class Gen extends JCTree.Visitor {
}
// Resolve all breaks.
Chain exit = switchEnv.info.exit;
if (exit != null) {
code.resolve(exit);
exit.state.defined.excludeFrom(limit);
}
code.resolve(switchEnv.info.exit);
// If we have not set the default offset, we do so now.
if (code.get4(tableBase) == -1) {
@ -2537,7 +2525,14 @@ public class Gen extends JCTree.Visitor {
/** code generation contexts,
* to be used as type parameter for environments.
*/
static class GenContext {
final class GenContext {
/**
* The top defined local variables for exit or continue branches to merge into.
* It may contain uninitialized variables to be initialized by branched code,
* so we cannot use Code.State.defined bits.
*/
final int limit;
/** A chain for all unresolved jumps that exit the current environment.
*/
@ -2563,15 +2558,26 @@ public class Gen extends JCTree.Visitor {
*/
ListBuffer<Integer> gaps = null;
GenContext() {
var code = Gen.this.code;
this.limit = code == null ? 0 : code.nextreg;
}
/** Add given chain to exit chain.
*/
void addExit(Chain c) {
if (c != null) {
c.state.defined.excludeFrom(limit);
}
exit = Code.mergeChains(c, exit);
}
/** Add given chain to cont chain.
*/
void addCont(Chain c) {
if (c != null) {
c.state.defined.excludeFrom(limit);
}
cont = Code.mergeChains(c, cont);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2025, 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
@ -157,6 +157,7 @@ public class LVTHarness {
if (i < infoFromRanges.size()) {
error(infoFromLVT, infoFromRanges, method.methodName().stringValue());
System.err.println(method.toDebugString());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8067429
* @bug 8067429 8332934
* @summary java.lang.VerifyError: Inconsistent stackmap frames at branch target
* @author srikanth
*

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2025, 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.
*
* 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.
*/
/*
* @test
* @bug 8332934
* @summary Incorrect defined locals escaped from continue in do loop
* @library /tools/lib /test/lib
* @run main DoLoopLocalEscapeThroughContinueTest
*/
import jdk.test.lib.ByteCodeLoader;
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import java.lang.classfile.ClassFile;
import java.lang.invoke.MethodHandles;
public class DoLoopLocalEscapeThroughContinueTest {
public static void main(String... args) throws Throwable {
String source = """
static void main(String[] k) {
do {
int b = 1;
continue;
} while (Math.random() > 0.5D) ;
switch (2) {
case 3:
double d;
case 4:
k.toString();
}
}
""";
var bytes = InMemoryJavaCompiler.compile("Test", source, "-XDdebug.code");
System.out.println(ClassFile.of().parse(bytes).toDebugString());
var clz = ByteCodeLoader.load("Test", bytes);
MethodHandles.privateLookupIn(clz, MethodHandles.lookup()).ensureInitialized(clz); // force verification
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2025, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8160699
* @bug 8160699 8332934
* @summary Verify that having finished executing a switch statement live locals are exactly the same as it was upon entry of the switch.
* @run main SwitchExitStateTest
*/