mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-04 15:15:23 +00:00
8389220: Implement JEP 539: Strict Field Initialization in the JVM (Preview) Co-authored-by: David Simms <dsimms@openjdk.org> Co-authored-by: Dan Smith <dlsmith@openjdk.org> Co-authored-by: Frederic Parain <fparain@openjdk.org> Co-authored-by: Tobias Hartmann <thartmann@openjdk.org> Co-authored-by: Roger Riggs <rriggs@openjdk.org> Co-authored-by: Vicente Romero <vromero@openjdk.org> Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org> Co-authored-by: Karen Kinnear <acorn@openjdk.org> Co-authored-by: Alex Menkov <amenkov@openjdk.org> Co-authored-by: Bill Huang <bhuang@openjdk.org> Co-authored-by: Benoît Maillard <bmaillard@openjdk.org> Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org> Co-authored-by: Chris Plummer <cjplummer@openjdk.org> Co-authored-by: Casper Norrbin <cnorrbin@openjdk.org> Co-authored-by: Coleen Phillimore <coleenp@openjdk.org> Co-authored-by: David Beaumont <dbeaumont@openjdk.org> Co-authored-by: Daniel D. Daugherty <dcubed@openjdk.org> Co-authored-by: Damon Fenacci <dfenacci@openjdk.org> Co-authored-by: David Holmes <dholmes@openjdk.org> Co-authored-by: Dmitry Samersoff <dsamersoff@openjdk.org> Co-authored-by: Eric Caspole <ecaspole@openjdk.org> Co-authored-by: Evgeny Nikitin <enikitin@openjdk.org> Co-authored-by: Ekaterina Pavlova <epavlova@openjdk.org> Co-authored-by: Fei Yang <fyang@openjdk.org> Co-authored-by: Dan Heidinga <heidinga@openjdk.org> Co-authored-by: Harold Seigel <hseigel@openjdk.org> Co-authored-by: Ioi Lam <iklam@openjdk.org> Co-authored-by: Ivan Walulya <iwalulya@openjdk.org> Co-authored-by: Jatin Bhateja <jbhateja@openjdk.org> Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Co-authored-by: Jim Laskey <jlaskey@openjdk.org> Co-authored-by: John R Rose <jrose@openjdk.org> Co-authored-by: Joel Sikström <jsikstro@openjdk.org> Co-authored-by: Lois Foltan <lfoltan@openjdk.org> Co-authored-by: Chen Liang <liach@openjdk.org> Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org> Co-authored-by: Matias Saavedra Silva <matsaave@openjdk.org> Co-authored-by: Marc Chevalier <mchevalier@openjdk.org> Co-authored-by: Mandy Chung <mchung@openjdk.org> Co-authored-by: Maurizio Cimadamore <mcimadamore@openjdk.org> Co-authored-by: Markus Grönlund <mgronlun@openjdk.org> Co-authored-by: Manuel Hässig <mhaessig@openjdk.org> Co-authored-by: Nick Gasson <ngasson@openjdk.org> Co-authored-by: Patricio Chilano Mateo <pchilanomate@openjdk.org> Co-authored-by: Paul Hübner <phubner@openjdk.org> Co-authored-by: Paul Sandoz <psandoz@openjdk.org> Co-authored-by: Quan Anh Mai <qamai@openjdk.org> Co-authored-by: Roberto Castañeda Lozano <rcastanedalo@openjdk.org> Co-authored-by: Roland Westrelin <roland@openjdk.org> Co-authored-by: Srikanth Adayapalam <sadayapalam@openjdk.org> Co-authored-by: Aleksey Shipilev <shade@openjdk.org> Co-authored-by: Stefan Johansson <sjohanss@openjdk.org> Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org> Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org> Co-authored-by: Stefan Karlsson <stefank@openjdk.org> Co-authored-by: Thomas Stuefe <stuefe@openjdk.org> Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org> Co-authored-by: Zoltan Majo <zmajo@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Co-authored-by: Jaikiran Pai <jpai@openjdk.org> Co-authored-by: Martin Doerr <mdoerr@openjdk.org> Co-authored-by: Richard Reingruber <rrich@openjdk.org> Co-authored-by: Feilong Jiang <fjiang@openjdk.org> Co-authored-by: Daisuke Yamazaki <dyama@openjdk.org> Reviewed-by: mcimadamore, liach, darcy, dcubed, aboldtch, coleenp, iklam, jlahoda, dlong, jpai, vklang, heidinga, sspitsyn, cjplummer
184 lines
7.3 KiB
Java
184 lines
7.3 KiB
Java
/*
|
|
* Copyright (c) 2026, 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 8375548
|
|
* @enablePreview
|
|
* @library / /test/lib
|
|
* @summary Testing that compiler replay correctly loads sub classes of ObjArrayKlass.
|
|
* @requires vm.flagless & vm.flightRecorder != true & vm.compMode != "Xint" & vm.compMode != "Xcomp" &
|
|
* vm.debug == true & vm.compiler2.enabled
|
|
* @modules java.base/jdk.internal.misc
|
|
* java.base/jdk.internal.value
|
|
* java.base/jdk.internal.vm.annotation
|
|
* @build jdk.test.whitebox.WhiteBox
|
|
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+TieredCompilation
|
|
* compiler.ciReplay.TestValueClassArrays
|
|
*/
|
|
|
|
package compiler.ciReplay;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import jdk.internal.value.ValueClass;
|
|
import jdk.test.lib.Asserts;
|
|
|
|
public class TestValueClassArrays extends DumpReplayBase {
|
|
private static final String LOG_FILE = "hotspot.log";
|
|
private static final String ERROR_FILE = "error.log";
|
|
private final PrintIdeal printIdeal;
|
|
private final String[] defaultReplayRunFlags;
|
|
|
|
public static void main(String[] args) {
|
|
new TestValueClassArrays().runTest("-XX:CompileCommand=dontinline,*::*",
|
|
"--enable-preview",
|
|
"--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED",
|
|
"--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED",
|
|
TIERED_DISABLED_VM_OPTION);
|
|
}
|
|
|
|
private TestValueClassArrays() {
|
|
printIdeal = new PrintIdeal(LOG_FILE);
|
|
defaultReplayRunFlags = defaultReplayRunFlags();
|
|
}
|
|
|
|
|
|
private String[] defaultReplayRunFlags() {
|
|
List<String> vmFlags = printIdeal.vmFlags();
|
|
Collections.addAll(vmFlags,
|
|
"-XX:+ReplayIgnoreInitErrors",
|
|
"-XX:CompileCommand=dontinline,*::*",
|
|
"--enable-preview",
|
|
"--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED",
|
|
"--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED",
|
|
"-XX:ErrorFile=" + ERROR_FILE,
|
|
TIERED_DISABLED_VM_OPTION
|
|
);
|
|
return vmFlags.toArray(new String[0]);
|
|
}
|
|
|
|
@Override
|
|
public void testAction() {
|
|
testArrayAccessSpeculation();
|
|
testNoProfilingNoSpeculation();
|
|
testInvalidArrayProperty();
|
|
remove(LOG_FILE);
|
|
remove(ERROR_FILE);
|
|
}
|
|
|
|
/**
|
|
* Check that we emit traps for speculation on array stores and loads as captured in the profiling.
|
|
*/
|
|
private void testArrayAccessSpeculation() {
|
|
positiveTest(defaultReplayRunFlags);
|
|
printIdeal.parse();
|
|
int countClassCheck = printIdeal.count("class_check");
|
|
Asserts.assertEQ(countClassCheck, 8, "not found all class checks for speculation on array accesses");
|
|
}
|
|
|
|
/**
|
|
* Check that we do not emit traps for speculation on array stores and loads since we disabled array profiling.
|
|
*/
|
|
private void testNoProfilingNoSpeculation() {
|
|
String[] noProfilingFlags = Arrays.copyOf(defaultReplayRunFlags, defaultReplayRunFlags.length + 1);
|
|
noProfilingFlags[defaultReplayRunFlags.length] = "-XX:-UseArrayLoadStoreProfile";
|
|
positiveTest(noProfilingFlags);
|
|
printIdeal.parse();
|
|
String empty = printIdeal.find("class_check");
|
|
Asserts.assertTrue(empty.isEmpty(), "should not find UCTs for speculation without array profiling");
|
|
}
|
|
|
|
/**
|
|
* Replace the "array property" in the "ciMethodData" with an invalid value -1 to make compiler replay fail
|
|
* with an assertion.
|
|
*/
|
|
private void testInvalidArrayProperty() {
|
|
invalidateCiMethodDataInReplayFile();
|
|
negativeTest(defaultReplayRunFlags);
|
|
ErrorFile errorFile = new ErrorFile(ERROR_FILE);
|
|
Asserts.assertTrue(errorFile.find("failed: invalid flags set"));
|
|
}
|
|
|
|
private void invalidateCiMethodDataInReplayFile() {
|
|
ReplayFile replayFile = new ReplayFile(getReplayFileName());
|
|
String ciMethodData = replayFile.findLineStartingWith(
|
|
"ciMethodData compiler/ciReplay/TestValueClassArrays$Test test");
|
|
Pattern pattern = Pattern.compile("(\\[Lcompiler/ciReplay/TestValueClassArrays\\$Test\\$A;) (\\d+)");
|
|
Matcher matcher = pattern.matcher(ciMethodData);
|
|
Asserts.assertTrue(matcher.find(), "must find array_property");
|
|
String replacement = matcher.group(1) + " -1";
|
|
String newCiMethodData = matcher.replaceFirst(Matcher.quoteReplacement(replacement));
|
|
replayFile.replaceLineStartingWith(ciMethodData, newCiMethodData);
|
|
}
|
|
|
|
@Override
|
|
public String getTestClass() {
|
|
return Test.class.getName();
|
|
}
|
|
|
|
|
|
private static class Test {
|
|
static A[] oArrDefault = new A[2];
|
|
static A[] oArrNullableAtomicArray = (A[]) ValueClass.newNullableAtomicArray(A.class, 2);
|
|
static A[] oArrNullRestrictedAtomicArray = (A[]) ValueClass.newNullRestrictedAtomicArray(A.class, 2, new A(1));
|
|
static A[] oArrNullRestrictedNonAtomicArray = (A[]) ValueClass.newNullRestrictedNonAtomicArray(A.class, 2, new A(2));
|
|
|
|
static A o1, o2, o3, o4;
|
|
static A a = new A(10);
|
|
|
|
public static void main(String[] args) {
|
|
oArrDefault[0] = new A(3);
|
|
oArrNullableAtomicArray[0] = new A(4);
|
|
oArrNullRestrictedAtomicArray[0] = new A(5);
|
|
oArrNullRestrictedNonAtomicArray[0] = new A(6);
|
|
for (int i = 0; i < 10000; i++) {
|
|
test();
|
|
}
|
|
}
|
|
|
|
static void test() {
|
|
o1 = oArrDefault[0];
|
|
oArrDefault[1] = a;
|
|
o2 = oArrNullableAtomicArray[0];
|
|
oArrNullableAtomicArray[1] = a;
|
|
o3 = oArrNullRestrictedAtomicArray[0];
|
|
oArrNullRestrictedAtomicArray[1] = a;
|
|
o4 = oArrNullRestrictedNonAtomicArray[0];
|
|
oArrNullRestrictedNonAtomicArray[1] = a;
|
|
}
|
|
|
|
static value class A {
|
|
int x;
|
|
public A(int x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
}
|
|
}
|