diff --git a/make/Images.gmk b/make/Images.gmk index 5703a74afa5..10fc8041325 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -132,10 +132,16 @@ CDS_DUMP_FLAGS = -Xmx128M -Xms128M # Helper function for creating the CDS archives for the JDK and JRE # # Param1 - VM variant (e.g., server, client, zero, ...) -# Param2 - _nocoops, or empty +# Param2 - _nocoops, _coh, _nocoops_coh, or empty define CreateCDSArchive - $1_$2_DUMP_EXTRA_ARG := $(if $(filter _nocoops, $2), -XX:-UseCompressedOops, ) - $1_$2_DUMP_TYPE := $(if $(filter _nocoops, $2), -NOCOOPS, ) + $1_$2_COOPS_OPTION := $(if $(findstring _nocoops, $2),-XX:-UseCompressedOops) + # enable and also explicitly disable coh as needed. + ifeq ($(call isTargetCpuBits, 64), true) + $1_$2_COH_OPTION := -XX:+UnlockExperimentalVMOptions \ + $(if $(findstring _coh, $2),-XX:+UseCompactObjectHeaders,-XX:-UseCompactObjectHeaders) + endif + $1_$2_DUMP_EXTRA_ARG := $$($1_$2_COOPS_OPTION) $$($1_$2_COH_OPTION) + $1_$2_DUMP_TYPE := $(if $(findstring _nocoops, $2),-NOCOOPS,)$(if $(findstring _coh, $2),-COH,) # Only G1 supports dumping the shared heap, so explicitly use G1 if the JVM supports it. $1_$2_CDS_DUMP_FLAGS := $(CDS_DUMP_FLAGS) $(if $(filter g1gc, $(JVM_FEATURES_$1)), -XX:+UseG1GC) @@ -190,6 +196,14 @@ ifeq ($(BUILD_CDS_ARCHIVE), true) $(foreach v, $(JVM_VARIANTS), \ $(eval $(call CreateCDSArchive,$v,_nocoops)) \ ) + ifeq ($(BUILD_CDS_ARCHIVE_COH), true) + $(foreach v, $(JVM_VARIANTS), \ + $(eval $(call CreateCDSArchive,$v,_coh)) \ + ) + $(foreach v, $(JVM_VARIANTS), \ + $(eval $(call CreateCDSArchive,$v,_nocoops_coh)) \ + ) + endif endif endif diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 21bf61a3fa1..66809127a75 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -261,6 +261,7 @@ JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST JDKOPT_EXCLUDE_TRANSLATIONS JDKOPT_ENABLE_DISABLE_MANPAGES JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE +JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT JDKOPT_SETUP_MACOSX_SIGNING diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 597fd74cc39..eb23f8760ec 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -666,6 +666,37 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE], AC_SUBST(BUILD_CDS_ARCHIVE) ]) +################################################################################ +# +# Enable or disable the default CDS archive generation for Compact Object Headers +# +AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE_COH], +[ + UTIL_ARG_ENABLE(NAME: cds-archive-coh, DEFAULT: auto, RESULT: BUILD_CDS_ARCHIVE_COH, + DESC: [enable generation of default CDS archives for compact object headers (requires --enable-cds-archive)], + DEFAULT_DESC: [auto], + CHECKING_MSG: [if default CDS archives for compact object headers should be generated], + CHECK_AVAILABLE: [ + AC_MSG_CHECKING([if CDS archive with compact object headers is available]) + if test "x$BUILD_CDS_ARCHIVE" = "xfalse"; then + AC_MSG_RESULT([no (CDS default archive generation is disabled)]) + AVAILABLE=false + elif test "x$OPENJDK_TARGET_CPU" != "xx86_64" && + test "x$OPENJDK_TARGET_CPU" != "xaarch64" && + test "x$OPENJDK_TARGET_CPU" != "xppc64" && + test "x$OPENJDK_TARGET_CPU" != "xppc64le" && + test "x$OPENJDK_TARGET_CPU" != "xriscv64" && + test "x$OPENJDK_TARGET_CPU" != "xs390x"; then + AC_MSG_RESULT([no (compact object headers not supported for this platform)]) + AVAILABLE=false + else + AC_MSG_RESULT([yes]) + AVAILABLE=true + fi + ]) + AC_SUBST(BUILD_CDS_ARCHIVE_COH) +]) + ################################################################################ # # Enable the alternative CDS core region alignment diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template index 96b799f0bfe..9b4402b7a26 100644 --- a/make/autoconf/spec.gmk.template +++ b/make/autoconf/spec.gmk.template @@ -370,6 +370,7 @@ EXCLUDE_TRANSLATIONS := @EXCLUDE_TRANSLATIONS@ BUILD_MANPAGES := @BUILD_MANPAGES@ BUILD_CDS_ARCHIVE := @BUILD_CDS_ARCHIVE@ +BUILD_CDS_ARCHIVE_COH := @BUILD_CDS_ARCHIVE_COH@ ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@ diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 6634306636b..23040aa1dcd 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -419,7 +419,7 @@ JVM_FindPrimitiveClass(JNIEnv *env, const char *utf); /* - * Find a class from a boot class loader. Returns NULL if class not found. + * Find a class from a boot class loader. Returns null if class not found. */ JNIEXPORT jclass JNICALL JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); diff --git a/src/java.base/macosx/native/libjli/java_md_macosx.m b/src/java.base/macosx/native/libjli/java_md_macosx.m index 354efc69769..c836ae903e5 100644 --- a/src/java.base/macosx/native/libjli/java_md_macosx.m +++ b/src/java.base/macosx/native/libjli/java_md_macosx.m @@ -415,6 +415,8 @@ static void MacOSXStartup(int argc, char *argv[]) { { char libjava[MAXPATHLEN]; + JLI_TraceLauncher("Attempt to get JDK installation root from launcher executable path\n"); + if (GetApplicationHome(path, pathsize)) { /* Is the JDK co-located with the application? */ if (JLI_IsStaticallyLinked()) { @@ -429,18 +431,6 @@ static void MacOSXStartup(int argc, char *argv[]) { return JNI_TRUE; } } - /* ensure storage for path + /jre + NULL */ - if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) { - JLI_TraceLauncher("Insufficient space to store JRE path\n"); - return JNI_FALSE; - } - /* Does the app ship a private JRE in /jre directory? */ - JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/" JAVA_DLL, path); - if (access(libjava, F_OK) == 0) { - JLI_StrCat(path, "/jre"); - JLI_TraceLauncher("JRE path is %s\n", path); - return JNI_TRUE; - } } /* try to find ourselves instead */ diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index ccb82c84c92..cbcc61e332c 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -63,6 +63,7 @@ import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; +import java.util.TimeZone; import java.util.TreeSet; import java.util.function.Function; import java.util.jar.Attributes; @@ -318,6 +319,8 @@ private static void printLocale(boolean verbose) { Locale.getDefault(Category.DISPLAY).getDisplayName()); ostream.println(INDENT + "default format locale = " + Locale.getDefault(Category.FORMAT).getDisplayName()); + ostream.println(INDENT + "default timezone = " + + TimeZone.getDefault().getID()); ostream.println(INDENT + "tzdata version = " + ZoneInfoFile.getVersion()); if (verbose) { diff --git a/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java b/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java index 7ea1e485869..f15c416f296 100644 --- a/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java +++ b/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java @@ -169,7 +169,7 @@ public void removeNotificationListener(ObjectName name, } catch (Exception e) { // Give back the first exception // - if (re != null) { + if (re == null) { re = e; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index e35ecbdc956..3545ebcc278 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1672,6 +1672,12 @@ public boolean isCastable(Type t, Type s, Warner warn) { // where class DisjointChecker { Set> pairsSeen = new HashSet<>(); + /* there are three cases for ts and ss: + * - one is a class and the other one is an interface (case I) + * - both are classes (case II) + * - both are interfaces (case III) + * all those cases are covered in JLS 23, section: "5.1.6.1 Allowed Narrowing Reference Conversion" + */ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) { Pair newPair = new Pair<>(ts, ss); /* if we are seeing the same pair again then there is an issue with the sealed hierarchy @@ -1679,32 +1685,38 @@ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) { */ if (!pairsSeen.add(newPair)) return false; - if (isSubtype(erasure(ts.type), erasure(ss.type))) { - return false; - } - // if both are classes or both are interfaces, shortcut - if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) { - return false; - } - if (ts.isInterface() && !ss.isInterface()) { - /* so ts is interface but ss is a class - * an interface is disjoint from a class if the class is disjoint form the interface - */ - return areDisjoint(ss, ts); - } - // a final class that is not subtype of ss is disjoint - if (!ts.isInterface() && ts.isFinal()) { - return true; - } - // if at least one is sealed - if (ts.isSealed() || ss.isSealed()) { - // permitted subtypes have to be disjoint with the other symbol - ClassSymbol sealedOne = ts.isSealed() ? ts : ss; - ClassSymbol other = sealedOne == ts ? ss : ts; - return sealedOne.getPermittedSubclasses().stream().allMatch(type -> areDisjoint((ClassSymbol)type.tsym, other)); + + if (ts.isInterface() != ss.isInterface()) { // case I: one is a class and the other one is an interface + ClassSymbol isym = ts.isInterface() ? ts : ss; // isym is the interface and csym the class + ClassSymbol csym = isym == ts ? ss : ts; + if (!isSubtype(erasure(csym.type), erasure(isym.type))) { + if (csym.isFinal()) { + return true; + } else if (csym.isSealed()) { + return areDisjoint(isym, csym.getPermittedSubclasses()); + } else if (isym.isSealed()) { + // if the class is not final and not sealed then it has to be freely extensible + return areDisjoint(csym, isym.getPermittedSubclasses()); + } + } // now both are classes or both are interfaces + } else if (!ts.isInterface()) { // case II: both are classes + return !isSubtype(erasure(ss.type), erasure(ts.type)) && !isSubtype(erasure(ts.type), erasure(ss.type)); + } else { // case III: both are interfaces + if (!isSubtype(erasure(ts.type), erasure(ss.type)) && !isSubtype(erasure(ss.type), erasure(ts.type))) { + if (ts.isSealed()) { + return areDisjoint(ss, ts.getPermittedSubclasses()); + } else if (ss.isSealed()) { + return areDisjoint(ts, ss.getPermittedSubclasses()); + } + } } + // at this point we haven't been able to statically prove that the classes or interfaces are disjoint return false; } + + boolean areDisjoint(ClassSymbol csym, List permittedSubtypes) { + return permittedSubtypes.stream().allMatch(psubtype -> areDisjoint(csym, (ClassSymbol) psubtype.tsym)); + } } private TypeRelation isCastable = new TypeRelation() { diff --git a/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp b/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp index 5f9a361105e..0b438572b2d 100644 --- a/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp +++ b/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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,59 +23,48 @@ #include "precompiled.hpp" #include "gc/shared/preservedMarks.inline.hpp" +#include "gc/shared/fullGCForwarding.inline.hpp" #include "oops/oop.inline.hpp" #include "unittest.hpp" -// Class to create a "fake" oop with a mark that will -// return true for calls to must_be_preserved(). -class FakeOop { - oopDesc _oop; - -public: - FakeOop() : _oop() { _oop.set_mark(originalMark()); } - - oop get_oop() { return &_oop; } - markWord mark() { return _oop.mark(); } - void set_mark(markWord m) { _oop.set_mark(m); } - void forward_to(oop obj) { - markWord m = markWord::encode_pointer_as_mark(obj); - _oop.set_mark(m); - } - - static markWord originalMark() { return markWord(markWord::lock_mask_in_place); } - static markWord changedMark() { return markWord(0x4711); } -}; +static markWord originalMark() { return markWord(markWord::lock_mask_in_place); } +static markWord changedMark() { return markWord(0x4711); } #define ASSERT_MARK_WORD_EQ(a, b) ASSERT_EQ((a).value(), (b).value()) TEST_VM(PreservedMarks, iterate_and_restore) { PreservedMarks pm; - FakeOop o1; - FakeOop o2; - FakeOop o3; - FakeOop o4; + + HeapWord fakeheap[32] = { nullptr }; + HeapWord* heap = align_up(fakeheap, 8 * sizeof(HeapWord)); + FullGCForwarding::initialize(MemRegion(&heap[0], &heap[16])); + + oop o1 = cast_to_oop(&heap[0]); o1->set_mark(originalMark()); + oop o2 = cast_to_oop(&heap[2]); o2->set_mark(originalMark()); + oop o3 = cast_to_oop(&heap[4]); o3->set_mark(originalMark()); + oop o4 = cast_to_oop(&heap[6]); o4->set_mark(originalMark()); // Make sure initial marks are correct. - ASSERT_MARK_WORD_EQ(o1.mark(), FakeOop::originalMark()); - ASSERT_MARK_WORD_EQ(o2.mark(), FakeOop::originalMark()); - ASSERT_MARK_WORD_EQ(o3.mark(), FakeOop::originalMark()); - ASSERT_MARK_WORD_EQ(o4.mark(), FakeOop::originalMark()); + ASSERT_MARK_WORD_EQ(o1->mark(), originalMark()); + ASSERT_MARK_WORD_EQ(o2->mark(), originalMark()); + ASSERT_MARK_WORD_EQ(o3->mark(), originalMark()); + ASSERT_MARK_WORD_EQ(o4->mark(), originalMark()); // Change the marks and verify change. - o1.set_mark(FakeOop::changedMark()); - o2.set_mark(FakeOop::changedMark()); - ASSERT_MARK_WORD_EQ(o1.mark(), FakeOop::changedMark()); - ASSERT_MARK_WORD_EQ(o2.mark(), FakeOop::changedMark()); + o1->set_mark(changedMark()); + o2->set_mark(changedMark()); + ASSERT_MARK_WORD_EQ(o1->mark(), changedMark()); + ASSERT_MARK_WORD_EQ(o2->mark(), changedMark()); // Push o1 and o2 to have their marks preserved. - pm.push_if_necessary(o1.get_oop(), o1.mark()); - pm.push_if_necessary(o2.get_oop(), o2.mark()); + pm.push_if_necessary(o1, o1->mark()); + pm.push_if_necessary(o2, o2->mark()); // Fake a move from o1->o3 and o2->o4. - o1.forward_to(o3.get_oop()); - o2.forward_to(o4.get_oop()); - ASSERT_EQ(o1.get_oop()->forwardee(), o3.get_oop()); - ASSERT_EQ(o2.get_oop()->forwardee(), o4.get_oop()); + FullGCForwarding::forward_to(o1, o3); + FullGCForwarding::forward_to(o2, o4); + ASSERT_EQ(FullGCForwarding::forwardee(o1), o3); + ASSERT_EQ(FullGCForwarding::forwardee(o2), o4); // Adjust will update the PreservedMarks stack to // make sure the mark is updated at the new location. pm.adjust_during_full_gc(); @@ -83,6 +72,6 @@ TEST_VM(PreservedMarks, iterate_and_restore) { // Restore all preserved and verify that the changed // mark is now present at o3 and o4. pm.restore(); - ASSERT_MARK_WORD_EQ(o3.mark(), FakeOop::changedMark()); - ASSERT_MARK_WORD_EQ(o4.mark(), FakeOop::changedMark()); + ASSERT_MARK_WORD_EQ(o3->mark(), changedMark()); + ASSERT_MARK_WORD_EQ(o4->mark(), changedMark()); } diff --git a/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp b/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp index f1a3ac0141a..8a5aabf6cec 100644 --- a/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp +++ b/test/hotspot/gtest/metaspace/metaspaceGtestContexts.hpp @@ -37,10 +37,14 @@ using metaspace::chunklevel_t; using namespace metaspace::chunklevel; class MetaspaceGtestContext : public metaspace::MetaspaceTestContext { + int _num_arenas_created; public: MetaspaceGtestContext(size_t commit_limit = 0, size_t reserve_limit = 0) : - metaspace::MetaspaceTestContext("gtest-metaspace-context", commit_limit, reserve_limit) - {} + metaspace::MetaspaceTestContext("gtest-metaspace-context", commit_limit, reserve_limit), + _num_arenas_created(0) {} + + int num_arenas_created() const { return _num_arenas_created; } + void inc_num_arenas_created() { _num_arenas_created ++; } }; class ChunkGtestContext : public MetaspaceGtestContext { diff --git a/test/hotspot/gtest/metaspace/test_binlist.cpp b/test/hotspot/gtest/metaspace/test_binlist.cpp index dd26d858e24..df12b40c30f 100644 --- a/test/hotspot/gtest/metaspace/test_binlist.cpp +++ b/test/hotspot/gtest/metaspace/test_binlist.cpp @@ -26,12 +26,14 @@ #include "precompiled.hpp" #include "memory/metaspace/binList.hpp" #include "memory/metaspace/counters.hpp" +#include "memory/metaspace/metablock.hpp" //#define LOG_PLEASE #include "metaspaceGtestCommon.hpp" using metaspace::BinList32; using metaspace::BinListImpl; using metaspace::MemRangeCounter; +using metaspace::MetaBlock; #define CHECK_BL_CONTENT(bl, expected_num, expected_size) { \ EXPECT_EQ(bl.count(), (unsigned)expected_num); \ @@ -43,6 +45,19 @@ using metaspace::MemRangeCounter; } \ } +template +struct TestedBinList : public BinListImpl { + typedef BinListImpl ListType; + void add_block(MetaWord* p, size_t word_size) { + ListType::add_block(MetaBlock(p, word_size)); + } + MetaWord* remove_block(size_t requested_size, size_t* real_size) { + MetaBlock result = ListType::remove_block(requested_size); + (*real_size) = result.word_size(); + return result.base(); + } +}; + template struct BinListBasicTest { @@ -206,14 +221,14 @@ struct BinListBasicTest { template const size_t BinListBasicTest::maxws = BINLISTTYPE::MaxWordSize; -TEST_VM(metaspace, BinList_basic_1) { BinListBasicTest< BinListImpl<1> >::basic_test(); } -TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< BinListImpl<8> >::basic_test(); } -TEST_VM(metaspace, BinList_basic_32) { BinListBasicTest::basic_test(); } +TEST_VM(metaspace, BinList_basic_1) { BinListBasicTest< TestedBinList<1> >::basic_test(); } +TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< TestedBinList<8> >::basic_test(); } +TEST_VM(metaspace, BinList_basic_32) { BinListBasicTest< TestedBinList<32> >::basic_test(); } -TEST_VM(metaspace, BinList_basic_2_1) { BinListBasicTest< BinListImpl<1> >::basic_test_2(); } -TEST_VM(metaspace, BinList_basic_2_8) { BinListBasicTest< BinListImpl<8> >::basic_test_2(); } -TEST_VM(metaspace, BinList_basic_2_32) { BinListBasicTest::basic_test_2(); } +TEST_VM(metaspace, BinList_basic_2_1) { BinListBasicTest< TestedBinList<1> >::basic_test_2(); } +TEST_VM(metaspace, BinList_basic_2_8) { BinListBasicTest< TestedBinList<8> >::basic_test_2(); } +TEST_VM(metaspace, BinList_basic_2_32) { BinListBasicTest< TestedBinList<32> >::basic_test_2(); } -TEST_VM(metaspace, BinList_basic_rand_1) { BinListBasicTest< BinListImpl<1> >::random_test(); } -TEST_VM(metaspace, BinList_basic_rand_8) { BinListBasicTest< BinListImpl<8> >::random_test(); } -TEST_VM(metaspace, BinList_basic_rand_32) { BinListBasicTest::random_test(); } +TEST_VM(metaspace, BinList_basic_rand_1) { BinListBasicTest< TestedBinList<1> >::random_test(); } +TEST_VM(metaspace, BinList_basic_rand_8) { BinListBasicTest< TestedBinList<8> >::random_test(); } +TEST_VM(metaspace, BinList_basic_rand_32) { BinListBasicTest< TestedBinList<32> >::random_test(); } diff --git a/test/hotspot/gtest/metaspace/test_blocktree.cpp b/test/hotspot/gtest/metaspace/test_blocktree.cpp index 50ec021ec11..05a3025f529 100644 --- a/test/hotspot/gtest/metaspace/test_blocktree.cpp +++ b/test/hotspot/gtest/metaspace/test_blocktree.cpp @@ -26,16 +26,29 @@ #include "precompiled.hpp" #include "memory/metaspace/blockTree.hpp" #include "memory/metaspace/counters.hpp" +#include "memory/metaspace/metablock.hpp" #include "memory/resourceArea.hpp" // #define LOG_PLEASE #include "metaspaceGtestCommon.hpp" using metaspace::BlockTree; using metaspace::MemRangeCounter; +using metaspace::MetaBlock; + +struct TestedBlockTree : public BlockTree { + void add_block(MetaWord* p, size_t word_size) { + BlockTree::add_block(MetaBlock(p, word_size)); + } + MetaWord* remove_block(size_t requested_size, size_t* real_size) { + MetaBlock result = BlockTree::remove_block(requested_size); + (*real_size) = result.word_size(); + return result.base(); + } +}; // Small helper. Given a 0-terminated array of sizes, a feeder buffer and a tree, // add blocks of these sizes to the tree in the order they appear in the array. -static void create_nodes(const size_t sizes[], FeederBuffer& fb, BlockTree& bt) { +static void create_nodes(const size_t sizes[], FeederBuffer& fb, TestedBlockTree& bt) { for (int i = 0; sizes[i] > 0; i ++) { size_t s = sizes[i]; MetaWord* p = fb.get(s); @@ -55,7 +68,7 @@ static void create_nodes(const size_t sizes[], FeederBuffer& fb, BlockTree& bt) TEST_VM(metaspace, BlockTree_basic) { - BlockTree bt; + TestedBlockTree bt; CHECK_BT_CONTENT(bt, 0, 0); size_t real_size = 0; @@ -112,7 +125,7 @@ static size_t helper_find_nearest_fit(const size_t sizes[], size_t request_size) // for a request size and check that it is the expected result. static void test_find_nearest_fit_with_tree(const size_t sizes[], size_t request_size) { - BlockTree bt; + TestedBlockTree bt; FeederBuffer fb(4 * K); create_nodes(sizes, fb, bt); @@ -155,7 +168,7 @@ TEST_VM(metaspace, BlockTree_find_nearest_fit) { 0 // stop }; - BlockTree bt; + TestedBlockTree bt; FeederBuffer fb(4 * K); create_nodes(sizes, fb, bt); @@ -170,7 +183,7 @@ TEST_VM(metaspace, BlockTree_find_nearest_fit) { // should exercise the list-part of the tree. TEST_VM(metaspace, BlockTree_basic_siblings) { - BlockTree bt; + TestedBlockTree bt; FeederBuffer fb(4 * K); CHECK_BT_CONTENT(bt, 0, 0); @@ -204,7 +217,7 @@ TEST_VM(metaspace, BlockTree_print_test) { 0 // stop }; - BlockTree bt; + TestedBlockTree bt; FeederBuffer fb(4 * K); create_nodes(sizes, fb, bt); @@ -222,7 +235,7 @@ TEST_VM_ASSERT_MSG(metaspace, BlockTree_overwriter_test, ".*failed: Invalid node static const size_t sizes1[] = { 30, 17, 0 }; static const size_t sizes2[] = { 12, 12, 0 }; - BlockTree bt; + TestedBlockTree bt; FeederBuffer fb(4 * K); // some nodes... @@ -249,7 +262,7 @@ class BlockTreeTest { FeederBuffer _fb; - BlockTree _bt[2]; + TestedBlockTree _bt[2]; MemRangeCounter _cnt[2]; RandSizeGenerator _rgen; @@ -356,7 +369,7 @@ class BlockTreeTest { void drain_all() { for (int which = 0; which < 2; which++) { - BlockTree* bt = _bt + which; + TestedBlockTree* bt = _bt + which; size_t last_size = 0; while (!bt->is_empty()) { diff --git a/test/hotspot/gtest/metaspace/test_clms.cpp b/test/hotspot/gtest/metaspace/test_clms.cpp new file mode 100644 index 00000000000..efe83c415e0 --- /dev/null +++ b/test/hotspot/gtest/metaspace/test_clms.cpp @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2024 Red Hat, Inc. All rights reserved. + * Copyright (c) 2024, 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. + * + */ + +#include "precompiled.hpp" +#include "memory/classLoaderMetaspace.hpp" +#include "memory/metaspace/freeBlocks.hpp" +#include "memory/metaspace/metablock.inline.hpp" +#include "memory/metaspace/metaspaceArena.hpp" +#include "memory/metaspace/metaspaceSettings.hpp" +#include "memory/metaspace/metaspaceStatistics.hpp" +#include "memory/metaspace.hpp" +#include "oops/klass.hpp" +#include "runtime/mutex.hpp" +#include "utilities/debug.hpp" +#include "utilities/align.hpp" +#include "utilities/globalDefinitions.hpp" + +#ifdef _LP64 + +#define LOG_PLEASE +#include "metaspaceGtestCommon.hpp" +#include "metaspaceGtestContexts.hpp" +#include "metaspaceGtestRangeHelpers.hpp" +#include "metaspaceGtestSparseArray.hpp" + +#define HANDLE_FAILURE \ + if (testing::Test::HasFailure()) { \ + return; \ + } + +namespace metaspace { + +class ClmsTester { + + Mutex _lock; + MetaspaceContext* _class_context; + MetaspaceContext* _nonclass_context; + ClassLoaderMetaspace* _clms; + const size_t _klass_arena_alignment_words; + unsigned _num_allocations; + + struct Deltas { + int num_chunks_delta; + ssize_t used_words_delta; + int num_freeblocks_delta; + ssize_t freeblocks_words_delta; + }; + + Deltas calc_deltas(const ArenaStats& before, const ArenaStats& after) { + Deltas d; + d.num_chunks_delta = after.totals()._num - before.totals()._num; + d.used_words_delta = after.totals()._used_words - before.totals()._used_words; + d.num_freeblocks_delta = (int)after._free_blocks_num - (int)before._free_blocks_num; + d.freeblocks_words_delta = after._free_blocks_word_size - before._free_blocks_word_size; + return d; + } + +public: + + ClmsTester(size_t klass_alignment_words, Metaspace::MetaspaceType space_type, + MetaspaceContext* class_context, MetaspaceContext* nonclass_context) + : _lock(Monitor::nosafepoint, "CLMSTest_lock"), + _class_context(class_context), _nonclass_context(nonclass_context), + _clms(nullptr), _klass_arena_alignment_words(klass_alignment_words), _num_allocations(0) { + _clms = new ClassLoaderMetaspace(&_lock, space_type, nonclass_context, class_context, klass_alignment_words); + } + + ~ClmsTester() { + delete _clms; + EXPECT_EQ(_class_context->used_words(), (size_t)0); + EXPECT_EQ(_nonclass_context->used_words(), (size_t)0); + } + + MetaBlock allocate_and_check(size_t word_size, bool is_class) { + + // take stats before allocation + ClmsStats stats_before; + _clms->add_to_statistics(&stats_before); + + // allocate + MetaWord* p = _clms->allocate(word_size, is_class ? Metaspace::ClassType : Metaspace::NonClassType); + _num_allocations ++; + + // take stats after allocation + ClmsStats stats_after; + _clms->add_to_statistics(&stats_after); + + // for less verbose testing: + const ArenaStats& ca_before = stats_before._arena_stats_class; + const ArenaStats& ca_after = stats_after._arena_stats_class; + const ArenaStats& nca_before = stats_before._arena_stats_nonclass; + const ArenaStats& nca_after = stats_after._arena_stats_nonclass; + + // deltas + const Deltas d_ca = calc_deltas(ca_before, ca_after); + const Deltas d_nca = calc_deltas(nca_before, nca_after); + +#define EXPECT_FREEBLOCKS_UNCHANGED(arena_prefix) \ + EXPECT_EQ(d_##arena_prefix.num_freeblocks_delta, 0); \ + EXPECT_EQ(d_##arena_prefix.freeblocks_words_delta, (ssize_t)0); + +#define EXPECT_ARENA_UNCHANGED(arena_prefix) \ + EXPECT_EQ(d_##arena_prefix.num_chunks_delta, 0); \ + EXPECT_EQ(d_##arena_prefix.used_words_delta, (ssize_t)0); + + if (p != nullptr) { + + MetaBlock bl(p, word_size); + + if (is_class) { + + EXPECT_TRUE(bl.is_aligned_base(_klass_arena_alignment_words)); + + if (_num_allocations == 1) { + // first allocation: nonclass arena unchanged, class arena grows by 1 chunk and wordsize, + // class arena freeblocks unchanged + EXPECT_ARENA_UNCHANGED(nca); + EXPECT_FREEBLOCKS_UNCHANGED(nca); + EXPECT_EQ(d_ca.num_chunks_delta, 1); + EXPECT_EQ((size_t)d_ca.used_words_delta, word_size); + EXPECT_FREEBLOCKS_UNCHANGED(ca); + return bl; + } + + // Had this been taken from class arena freeblocks? + if (d_ca.num_freeblocks_delta == -1) { + // the class arena freeblocks should have gone down, and the non-class arena freeblocks may have gone + // up in case the block was larger than required + const size_t wordsize_block_taken = (size_t)(-d_ca.freeblocks_words_delta); + EXPECT_GE(wordsize_block_taken, word_size); // the block we took must be at least allocation size + const size_t expected_freeblock_remainder = wordsize_block_taken - word_size; + if (expected_freeblock_remainder > 0) { + // the remainder, if it existed, should have been added to nonclass freeblocks + EXPECT_EQ(d_nca.num_freeblocks_delta, 1); + EXPECT_EQ((size_t)d_nca.freeblocks_words_delta, expected_freeblock_remainder); + } + // finally, nothing should have happened in the arenas proper. + EXPECT_ARENA_UNCHANGED(ca); + EXPECT_ARENA_UNCHANGED(nca); + return bl; + } + + // block was taken from class arena proper + + // We expect allocation waste due to alignment, should have been added to the freeblocks + // of nonclass arena. Allocation waste can be 0. If no chunk turnover happened, it must be + // smaller than klass alignment, otherwise it can get as large as a commit granule. + const size_t max_expected_allocation_waste = + d_ca.num_chunks_delta == 0 ? (_klass_arena_alignment_words - 1) : Settings::commit_granule_words(); + EXPECT_GE(d_ca.num_chunks_delta, 0); + EXPECT_LE(d_ca.num_chunks_delta, 1); + EXPECT_GE((size_t)d_ca.used_words_delta, word_size); + EXPECT_LE((size_t)d_ca.used_words_delta, word_size + max_expected_allocation_waste); + EXPECT_FREEBLOCKS_UNCHANGED(ca); + EXPECT_ARENA_UNCHANGED(nca); + if (max_expected_allocation_waste > 0) { + EXPECT_GE(d_nca.num_freeblocks_delta, 0); + EXPECT_LE(d_nca.num_freeblocks_delta, 1); + EXPECT_GE(d_nca.freeblocks_words_delta, 0); + EXPECT_LE((size_t)d_nca.freeblocks_words_delta, max_expected_allocation_waste); + } else { + EXPECT_FREEBLOCKS_UNCHANGED(nca); + } + return bl; + // end: is_class + } else { + // Nonclass arena allocation. + // Allocation waste can happen: + // - if we allocate from nonclass freeblocks, the block remainder + // - if we allocate from arena proper, by chunk turnover + + if (d_nca.freeblocks_words_delta < 0) { + // We allocated a block from the nonclass arena freeblocks. + const size_t wordsize_block_taken = (size_t)(-d_nca.freeblocks_words_delta); + EXPECT_EQ(wordsize_block_taken, word_size); + // The number of blocks may or may not have decreased (depending on whether there + // was a wastage block) + EXPECT_GE(d_nca.num_chunks_delta, -1); + EXPECT_LE(d_nca.num_chunks_delta, 0); + EXPECT_ARENA_UNCHANGED(nca); + EXPECT_ARENA_UNCHANGED(ca); + EXPECT_FREEBLOCKS_UNCHANGED(ca); + return bl; + } + + // We don't expect alignment waste. Only wastage happens at chunk turnover. + const size_t max_expected_allocation_waste = + d_nca.num_chunks_delta == 0 ? 0 : Settings::commit_granule_words(); + EXPECT_ARENA_UNCHANGED(ca); + EXPECT_FREEBLOCKS_UNCHANGED(ca); + EXPECT_GE(d_nca.num_chunks_delta, 0); + EXPECT_LE(d_nca.num_chunks_delta, 1); + EXPECT_GE((size_t)d_nca.used_words_delta, word_size); + EXPECT_LE((size_t)d_nca.used_words_delta, word_size + max_expected_allocation_waste); + if (max_expected_allocation_waste == 0) { + EXPECT_FREEBLOCKS_UNCHANGED(nca); + } + } + return bl; + + } // end: allocation successful + + // allocation failed. + EXPECT_ARENA_UNCHANGED(ca); + EXPECT_FREEBLOCKS_UNCHANGED(ca); + EXPECT_ARENA_UNCHANGED(nca); + EXPECT_FREEBLOCKS_UNCHANGED(nca); + + return MetaBlock(); + } + + MetaBlock allocate_expect_success(size_t word_size, bool is_class) { + MetaBlock bl = allocate_and_check(word_size, is_class); + EXPECT_TRUE(bl.is_nonempty()); + return bl; + } + + MetaBlock allocate_expect_failure(size_t word_size, bool is_class) { + MetaBlock bl = allocate_and_check(word_size, is_class); + EXPECT_TRUE(bl.is_empty()); + return bl; + } + + void deallocate_and_check(MetaBlock bl) { + + // take stats before deallocation + ClmsStats stats_before; + _clms->add_to_statistics(&stats_before); + + // allocate + _clms->deallocate(bl.base(), bl.word_size()); + + // take stats after deallocation + ClmsStats stats_after; + _clms->add_to_statistics(&stats_after); + + // for less verbose testing: + const ArenaStats& ca_before = stats_before._arena_stats_class; + const ArenaStats& ca_after = stats_after._arena_stats_class; + const ArenaStats& nca_before = stats_before._arena_stats_nonclass; + const ArenaStats& nca_after = stats_after._arena_stats_nonclass; + + // deltas + // deltas + const Deltas d_ca = calc_deltas(ca_before, ca_after); + const Deltas d_nca = calc_deltas(nca_before, nca_after); + + EXPECT_ARENA_UNCHANGED(ca); + EXPECT_ARENA_UNCHANGED(nca); + // Depending on whether the returned block was suitable for Klass, + // it may have gone to either the non-class freelist or the class freelist + if (d_ca.num_freeblocks_delta == 1) { + EXPECT_EQ(d_ca.num_freeblocks_delta, 1); + EXPECT_EQ((size_t)d_ca.freeblocks_words_delta, bl.word_size()); + EXPECT_FREEBLOCKS_UNCHANGED(nca); + } else { + EXPECT_EQ(d_nca.num_freeblocks_delta, 1); + EXPECT_EQ((size_t)d_nca.freeblocks_words_delta, bl.word_size()); + EXPECT_FREEBLOCKS_UNCHANGED(ca); + } + } +}; + +static constexpr size_t klass_size = sizeof(Klass) / BytesPerWord; + +static void basic_test(size_t klass_arena_alignment) { + MetaspaceGtestContext class_context, nonclass_context; + { + ClmsTester tester(klass_arena_alignment, Metaspace::StandardMetaspaceType, class_context.context(), nonclass_context.context()); + + MetaBlock bl1 = tester.allocate_expect_success(klass_size, true); + HANDLE_FAILURE; + + MetaBlock bl2 = tester.allocate_expect_success(klass_size, true); + HANDLE_FAILURE; + + tester.deallocate_and_check(bl1); + HANDLE_FAILURE; + + MetaBlock bl3 = tester.allocate_expect_success(klass_size, true); + HANDLE_FAILURE; + + MetaBlock bl4 = tester.allocate_expect_success(Metaspace::min_allocation_word_size, false); + HANDLE_FAILURE; + + MetaBlock bl5 = tester.allocate_expect_success(K, false); + HANDLE_FAILURE; + + tester.deallocate_and_check(bl5); + HANDLE_FAILURE; + + MetaBlock bl6 = tester.allocate_expect_success(K, false); + HANDLE_FAILURE; + + EXPECT_EQ(bl5, bl6); // should have gotten the same block back from freelist + } + EXPECT_EQ(class_context.used_words(), (size_t)0); + EXPECT_EQ(nonclass_context.used_words(), (size_t)0); + // we should have used exactly one commit granule (64K), not more, for each context + EXPECT_EQ(class_context.committed_words(), Settings::commit_granule_words()); + EXPECT_EQ(nonclass_context.committed_words(), Settings::commit_granule_words()); +} + +#define TEST_BASIC_N(n) \ +TEST_VM(metaspace, CLMS_basics_##n) { \ + basic_test(n); \ +} + +TEST_BASIC_N(1) +TEST_BASIC_N(4) +TEST_BASIC_N(16) +TEST_BASIC_N(32) +TEST_BASIC_N(128) + +static void test_random(size_t klass_arena_alignment) { + MetaspaceGtestContext class_context, nonclass_context; + constexpr int max_allocations = 1024; + const SizeRange nonclass_alloc_range(Metaspace::min_allocation_alignment_words, 1024); + const SizeRange class_alloc_range(klass_size, 1024); + const IntRange one_out_of_ten(0, 10); + for (int runs = 9; runs >= 0; runs--) { + { + ClmsTester tester(64, Metaspace::StandardMetaspaceType, class_context.context(), nonclass_context.context()); + struct LifeBlock { + MetaBlock bl; + bool is_class; + }; + LifeBlock life_allocations[max_allocations]; + for (int i = 0; i < max_allocations; i++) { + life_allocations[i].bl.reset(); + } + + unsigned num_class_allocs = 0, num_nonclass_allocs = 0, num_class_deallocs = 0, num_nonclass_deallocs = 0; + for (int i = 0; i < 5000; i ++) { + const int slot = IntRange(0, max_allocations).random_value(); + if (life_allocations[slot].bl.is_empty()) { + const bool is_class = one_out_of_ten.random_value() == 0; + const size_t word_size = + is_class ? class_alloc_range.random_value() : nonclass_alloc_range.random_value(); + MetaBlock bl = tester.allocate_expect_success(word_size, is_class); + HANDLE_FAILURE; + life_allocations[slot].bl = bl; + life_allocations[slot].is_class = is_class; + if (is_class) { + num_class_allocs ++; + } else { + num_nonclass_allocs ++; + } + } else { + tester.deallocate_and_check(life_allocations[slot].bl); + HANDLE_FAILURE; + life_allocations[slot].bl.reset(); + if (life_allocations[slot].is_class) { + num_class_deallocs ++; + } else { + num_nonclass_deallocs ++; + } + } + } + LOG("num class allocs: %u, num nonclass allocs: %u, num class deallocs: %u, num nonclass deallocs: %u", + num_class_allocs, num_nonclass_allocs, num_class_deallocs, num_nonclass_deallocs); + } + EXPECT_EQ(class_context.used_words(), (size_t)0); + EXPECT_EQ(nonclass_context.used_words(), (size_t)0); + constexpr float fragmentation_factor = 3.0f; + const size_t max_expected_nonclass_committed = max_allocations * nonclass_alloc_range.highest() * fragmentation_factor; + const size_t max_expected_class_committed = max_allocations * class_alloc_range.highest() * fragmentation_factor; + // we should have used exactly one commit granule (64K), not more, for each context + EXPECT_LT(class_context.committed_words(), max_expected_class_committed); + EXPECT_LT(nonclass_context.committed_words(), max_expected_nonclass_committed); + } +} + +#define TEST_RANDOM_N(n) \ +TEST_VM(metaspace, CLMS_random_##n) { \ + test_random(n); \ +} + +TEST_RANDOM_N(1) +TEST_RANDOM_N(4) +TEST_RANDOM_N(16) +TEST_RANDOM_N(32) +TEST_RANDOM_N(128) + +} // namespace metaspace + +#endif // _LP64 diff --git a/test/hotspot/gtest/metaspace/test_freeblocks.cpp b/test/hotspot/gtest/metaspace/test_freeblocks.cpp index fbf2e822c11..239729bc696 100644 --- a/test/hotspot/gtest/metaspace/test_freeblocks.cpp +++ b/test/hotspot/gtest/metaspace/test_freeblocks.cpp @@ -26,10 +26,13 @@ #include "precompiled.hpp" #include "memory/metaspace/counters.hpp" #include "memory/metaspace/freeBlocks.hpp" +#include "memory/metaspace/metablock.hpp" + //#define LOG_PLEASE #include "metaspaceGtestCommon.hpp" using metaspace::FreeBlocks; +using metaspace::MetaBlock; using metaspace::SizeCounter; #define CHECK_CONTENT(fb, num_blocks_expected, word_size_expected) \ @@ -43,199 +46,21 @@ using metaspace::SizeCounter; EXPECT_EQ(fb.count(), (int)num_blocks_expected); \ } -class FreeBlocksTest { - - FeederBuffer _fb; - FreeBlocks _freeblocks; - - // random generator for block feeding - RandSizeGenerator _rgen_feeding; - - // random generator for allocations (and, hence, deallocations) - RandSizeGenerator _rgen_allocations; - - SizeCounter _allocated_words; - - struct allocation_t { - allocation_t* next; - size_t word_size; - MetaWord* p; - }; - - // Array of the same size as the pool max capacity; holds the allocated elements. - allocation_t* _allocations; - - int _num_allocs; - int _num_deallocs; - int _num_feeds; - - bool feed_some() { - size_t word_size = _rgen_feeding.get(); - MetaWord* p = _fb.get(word_size); - if (p != nullptr) { - _freeblocks.add_block(p, word_size); - return true; - } - return false; - } - - bool deallocate_top() { - - allocation_t* a = _allocations; - if (a != nullptr) { - _allocations = a->next; - check_marked_range(a->p, a->word_size); - _freeblocks.add_block(a->p, a->word_size); - delete a; - DEBUG_ONLY(_freeblocks.verify();) - return true; - } - return false; - } - - void deallocate_all() { - while (deallocate_top()); - } - - bool allocate() { - - size_t word_size = MAX2(_rgen_allocations.get(), _freeblocks.MinWordSize); - MetaWord* p = _freeblocks.remove_block(word_size); - if (p != nullptr) { - _allocated_words.increment_by(word_size); - allocation_t* a = new allocation_t; - a->p = p; a->word_size = word_size; - a->next = _allocations; - _allocations = a; - DEBUG_ONLY(_freeblocks.verify();) - mark_range(p, word_size); - return true; - } - return false; - } - - void test_all_marked_ranges() { - for (allocation_t* a = _allocations; a != nullptr; a = a->next) { - check_marked_range(a->p, a->word_size); - } - } - - void test_loop() { - // We loop and in each iteration execute one of three operations: - // - allocation from fbl - // - deallocation to fbl of a previously allocated block - // - feeding a new larger block into the fbl (mimicks chunk retiring) - // When we have fed all large blocks into the fbl (feedbuffer empty), we - // switch to draining the fbl completely (only allocs) - bool forcefeed = false; - bool draining = false; - bool stop = false; - int iter = 25000; // safety stop - while (!stop && iter > 0) { - iter --; - int surprise = (int)os::random() % 10; - if (!draining && (surprise >= 7 || forcefeed)) { - forcefeed = false; - if (feed_some()) { - _num_feeds++; - } else { - // We fed all input memory into the fbl. Now lets proceed until the fbl is drained. - draining = true; - } - } else if (!draining && surprise < 1) { - deallocate_top(); - _num_deallocs++; - } else { - if (allocate()) { - _num_allocs++; - } else { - if (draining) { - stop = _freeblocks.total_size() < 512; - } else { - forcefeed = true; - } - } - } - if ((iter % 1000) == 0) { - DEBUG_ONLY(_freeblocks.verify();) - test_all_marked_ranges(); - LOG("a %d (" SIZE_FORMAT "), d %d, f %d", _num_allocs, _allocated_words.get(), _num_deallocs, _num_feeds); -#ifdef LOG_PLEASE - _freeblocks.print(tty, true); - tty->cr(); -#endif - } - } - - // Drain - - } - -public: - - FreeBlocksTest(size_t avg_alloc_size) : - _fb(512 * K), _freeblocks(), - _rgen_feeding(128, 4096), - _rgen_allocations(avg_alloc_size / 4, avg_alloc_size * 2, 0.01f, avg_alloc_size / 3, avg_alloc_size * 30), - _allocations(nullptr), - _num_allocs(0), - _num_deallocs(0), - _num_feeds(0) - { - CHECK_CONTENT(_freeblocks, 0, 0); - // some initial feeding - _freeblocks.add_block(_fb.get(1024), 1024); - CHECK_CONTENT(_freeblocks, 1, 1024); - } - - ~FreeBlocksTest() { - deallocate_all(); - } - - static void test_small_allocations() { - FreeBlocksTest test(10); - test.test_loop(); - } - - static void test_medium_allocations() { - FreeBlocksTest test(30); - test.test_loop(); - } - - static void test_large_allocations() { - FreeBlocksTest test(150); - test.test_loop(); - } - -}; - TEST_VM(metaspace, freeblocks_basics) { FreeBlocks fbl; MetaWord tmp[1024]; CHECK_CONTENT(fbl, 0, 0); - fbl.add_block(tmp, 1024); + MetaBlock bl(tmp, 1024); + fbl.add_block(bl); DEBUG_ONLY(fbl.verify();) ASSERT_FALSE(fbl.is_empty()); CHECK_CONTENT(fbl, 1, 1024); - MetaWord* p = fbl.remove_block(1024); - EXPECT_EQ(p, tmp); + MetaBlock bl2 = fbl.remove_block(1024); + ASSERT_EQ(bl, bl2); DEBUG_ONLY(fbl.verify();) CHECK_CONTENT(fbl, 0, 0); } - -TEST_VM(metaspace, freeblocks_small) { - FreeBlocksTest::test_small_allocations(); -} - -TEST_VM(metaspace, freeblocks_medium) { - FreeBlocksTest::test_medium_allocations(); -} - -TEST_VM(metaspace, freeblocks_large) { - FreeBlocksTest::test_large_allocations(); -} - diff --git a/test/hotspot/gtest/metaspace/test_metablock.cpp b/test/hotspot/gtest/metaspace/test_metablock.cpp new file mode 100644 index 00000000000..af103a2b462 --- /dev/null +++ b/test/hotspot/gtest/metaspace/test_metablock.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020 SAP SE. 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. + * + */ + +#include "precompiled.hpp" +#include "memory/metaspace/metablock.inline.hpp" +//#define LOG_PLEASE +#include "metaspaceGtestCommon.hpp" + +using metaspace::MetaBlock; + + +#define CHECK_BLOCK_EMPTY(block) { \ + EXPECT_TRUE(block.is_empty()); \ + DEBUG_ONLY(block.verify()); \ +} + +#define CHECK_BLOCK(block, expected_base, expected_size) { \ + EXPECT_EQ(block.base(), (MetaWord*)expected_base); \ + EXPECT_EQ((size_t)expected_size, block.word_size()); \ + EXPECT_EQ(block.end(), expected_base + expected_size); \ + DEBUG_ONLY(block.verify()); \ +} + +static constexpr uintptr_t large_pointer = NOT_LP64(0x99999990) LP64_ONLY(0x9999999999999990ULL); + +TEST(metaspace, MetaBlock_1) { + MetaBlock bl; + CHECK_BLOCK_EMPTY(bl); +} + +TEST(metaspace, MetaBlock_2) { + MetaWord* const p = (MetaWord*)large_pointer; + constexpr size_t s = G; + MetaBlock bl(p, s); + CHECK_BLOCK(bl, p, s); +} + +TEST(metaspace, MetaBlock_3) { + MetaWord* const p = (MetaWord*)large_pointer; + MetaBlock bl(p, 0); + CHECK_BLOCK_EMPTY(bl); +} + +TEST_VM(metaspace, MetaBlock_4) { + MetaWord* const p = (MetaWord*)large_pointer; + MetaBlock bl(p, G); + CHECK_BLOCK(bl, p, G); + + MetaBlock bl_copy = bl, bl2; + + bl2 = bl.split_off_tail(M); + CHECK_BLOCK(bl, p, G - M); + CHECK_BLOCK(bl2, p + G - M, M); + + bl = bl_copy; + +bl.print_on(tty); +bl2.print_on(tty); + bl2 = bl.split_off_tail(G); + bl.print_on(tty); + bl2.print_on(tty); + + ASSERT_EQ(bl2, bl_copy); + ASSERT_TRUE(bl.is_empty()); + + bl = bl_copy; + + bl2 = bl.split_off_tail(0); + ASSERT_EQ(bl, bl_copy); + ASSERT_TRUE(bl2.is_empty()); + + MetaBlock empty; + bl = empty.split_off_tail(0); + ASSERT_TRUE(bl.is_empty()); +} diff --git a/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp b/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp index 9f6ac9e988a..8a46f71be5d 100644 --- a/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp +++ b/test/hotspot/gtest/metaspace/test_metaspaceUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,7 +28,7 @@ #include "memory/metaspaceUtils.hpp" #include "unittest.hpp" -TEST_VM(MetaspaceUtils, reserved) { +TEST_VM(metaspace, MetaspaceUtils_reserved) { size_t reserved = MetaspaceUtils::reserved_bytes(); EXPECT_GT(reserved, 0UL); @@ -37,7 +37,7 @@ TEST_VM(MetaspaceUtils, reserved) { EXPECT_LE(reserved_metadata, reserved); } -TEST_VM(MetaspaceUtils, reserved_compressed_class_pointers) { +TEST_VM(metaspace, MetaspaceUtils_reserved_compressed_class_pointers) { if (!UseCompressedClassPointers) { return; } @@ -49,7 +49,7 @@ TEST_VM(MetaspaceUtils, reserved_compressed_class_pointers) { EXPECT_LE(reserved_class, reserved); } -TEST_VM(MetaspaceUtils, committed) { +TEST_VM(metaspace, MetaspaceUtils_committed) { size_t committed = MetaspaceUtils::committed_bytes(); EXPECT_GT(committed, 0UL); @@ -61,7 +61,7 @@ TEST_VM(MetaspaceUtils, committed) { EXPECT_LE(committed_metadata, committed); } -TEST_VM(MetaspaceUtils, committed_compressed_class_pointers) { +TEST_VM(metaspace, MetaspaceUtils_committed_compressed_class_pointers) { if (!UseCompressedClassPointers) { return; } @@ -73,7 +73,7 @@ TEST_VM(MetaspaceUtils, committed_compressed_class_pointers) { EXPECT_LE(committed_class, committed); } -TEST_VM(MetaspaceUtils, non_compressed_class_pointers) { +TEST_VM(metaspace, MetaspaceUtils_non_compressed_class_pointers) { if (UseCompressedClassPointers) { return; } @@ -99,7 +99,7 @@ static void check_metaspace_stats_are_not_null(const MetaspaceStats& stats) { EXPECT_GT(stats.used(), 0UL); } -TEST_VM(MetaspaceUtils, get_statistics) { +TEST_VM(MetaspaceUtils, MetaspaceUtils_get_statistics) { MetaspaceCombinedStats combined_stats = MetaspaceUtils::get_combined_statistics(); check_metaspace_stats_are_not_null(combined_stats); check_metaspace_stats_are_consistent(combined_stats); diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp index 2e5a6d40ce7..2f7627ccffe 100644 --- a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp +++ b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023 SAP SE. All rights reserved. + * Copyright (c) 2023 Red Hat, Inc. 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 @@ -28,98 +29,125 @@ #include "memory/metaspace/commitLimiter.hpp" #include "memory/metaspace/counters.hpp" #include "memory/metaspace/internalStats.hpp" +#include "memory/metaspace/freeBlocks.hpp" +#include "memory/metaspace/metablock.inline.hpp" #include "memory/metaspace/metaspaceArena.hpp" #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp" +#include "memory/metaspace/metachunkList.hpp" #include "memory/metaspace/metaspaceCommon.hpp" #include "memory/metaspace/metaspaceSettings.hpp" #include "memory/metaspace/metaspaceStatistics.hpp" +#include "memory/metaspace.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -//#define LOG_PLEASE +#define LOG_PLEASE #include "metaspaceGtestCommon.hpp" #include "metaspaceGtestContexts.hpp" #include "metaspaceGtestRangeHelpers.hpp" -using metaspace::AllocationAlignmentByteSize; -using metaspace::ArenaGrowthPolicy; -using metaspace::CommitLimiter; -using metaspace::InternalStats; -using metaspace::MemRangeCounter; -using metaspace::MetaspaceArena; -using metaspace::SizeAtomicCounter; -using metaspace::Settings; -using metaspace::ArenaStats; +#define HANDLE_FAILURE \ + if (testing::Test::HasFailure()) { \ + return; \ + } + +namespace metaspace { + +class MetaspaceArenaTestFriend { + const MetaspaceArena* const _arena; +public: + MetaspaceArenaTestFriend(const MetaspaceArena* arena) : _arena(arena) {} + const MetachunkList& chunks() const { return _arena->_chunks; } + const FreeBlocks* fbl() const { return _arena->_fbl; } +}; class MetaspaceArenaTestHelper { MetaspaceGtestContext& _context; + const ArenaGrowthPolicy* const _growth_policy; - const ArenaGrowthPolicy* _growth_policy; - SizeAtomicCounter _used_words_counter; MetaspaceArena* _arena; - void initialize(const ArenaGrowthPolicy* growth_policy, const char* name = "gtest-MetaspaceArena") { - _growth_policy = growth_policy; - _arena = new MetaspaceArena(&_context.cm(), _growth_policy, &_used_words_counter, name); - DEBUG_ONLY(_arena->verify()); - } - public: - // Create a helper; growth policy for arena is determined by the given spacetype|class tupel - MetaspaceArenaTestHelper(MetaspaceGtestContext& helper, - Metaspace::MetaspaceType space_type, bool is_class, - const char* name = "gtest-MetaspaceArena") : - _context(helper) - { - initialize(ArenaGrowthPolicy::policy_for_space_type(space_type, is_class), name); - } - // Create a helper; growth policy is directly specified MetaspaceArenaTestHelper(MetaspaceGtestContext& helper, const ArenaGrowthPolicy* growth_policy, - const char* name = "gtest-MetaspaceArena") : - _context(helper) + size_t allocation_alignment_words = Metaspace::min_allocation_alignment_words) : + _context(helper), _growth_policy(growth_policy), _arena(nullptr) { - initialize(growth_policy, name); + _arena = new MetaspaceArena(_context.context(), _growth_policy, allocation_alignment_words, "gtest-MetaspaceArena"); + DEBUG_ONLY(_arena->verify()); + _context.inc_num_arenas_created(); } + + // Create a helper; growth policy for arena is determined by the given spacetype|class tupel + MetaspaceArenaTestHelper(MetaspaceGtestContext& helper, + Metaspace::MetaspaceType space_type, bool is_class, + size_t allocation_alignment_words = Metaspace::min_allocation_alignment_words) : + MetaspaceArenaTestHelper(helper, ArenaGrowthPolicy::policy_for_space_type(space_type, is_class), allocation_alignment_words) + {} + ~MetaspaceArenaTestHelper() { delete_arena_with_tests(); } - const CommitLimiter& limiter() const { return _context.commit_limiter(); } MetaspaceArena* arena() const { return _arena; } - SizeAtomicCounter& used_words_counter() { return _used_words_counter; } // Note: all test functions return void due to gtests limitation that we cannot use ASSERT // in non-void returning tests. void delete_arena_with_tests() { if (_arena != nullptr) { - size_t used_words_before = _used_words_counter.get(); - size_t committed_words_before = limiter().committed_words(); + size_t used_words_before = _context.used_words(); + size_t committed_words_before = _context.committed_words(); DEBUG_ONLY(_arena->verify()); delete _arena; _arena = nullptr; - size_t used_words_after = _used_words_counter.get(); - size_t committed_words_after = limiter().committed_words(); - ASSERT_0(used_words_after); + size_t used_words_after = _context.used_words(); + size_t committed_words_after = _context.committed_words(); + assert(_context.num_arenas_created() >= 1, "Sanity"); + if (_context.num_arenas_created() == 1) { + ASSERT_0(used_words_after); + } else { + ASSERT_LE(used_words_after, used_words_before); + } ASSERT_LE(committed_words_after, committed_words_before); } } void usage_numbers_with_test(size_t* p_used, size_t* p_committed, size_t* p_capacity) const { - _arena->usage_numbers(p_used, p_committed, p_capacity); - if (p_used != nullptr) { - if (p_committed != nullptr) { - ASSERT_GE(*p_committed, *p_used); - } - // Since we own the used words counter, it should reflect our usage number 1:1 - ASSERT_EQ(_used_words_counter.get(), *p_used); + size_t arena_used = 0, arena_committed = 0, arena_reserved = 0; + _arena->usage_numbers(&arena_used, &arena_committed, &arena_reserved); + EXPECT_GE(arena_committed, arena_used); + EXPECT_GE(arena_reserved, arena_committed); + + size_t context_used = _context.used_words(); + size_t context_committed = _context.committed_words(); + size_t context_reserved = _context.reserved_words(); + EXPECT_GE(context_committed, context_used); + EXPECT_GE(context_reserved, context_committed); + + // If only one arena uses the context, usage numbers must match. + if (_context.num_arenas_created() == 1) { + EXPECT_EQ(context_used, arena_used); + } else { + assert(_context.num_arenas_created() > 1, "Sanity"); + EXPECT_GE(context_used, arena_used); } - if (p_committed != nullptr && p_capacity != nullptr) { - ASSERT_GE(*p_capacity, *p_committed); + + // commit, reserve numbers don't have to match since free chunks may exist + EXPECT_GE(context_committed, arena_committed); + EXPECT_GE(context_reserved, arena_reserved); + + if (p_used) { + *p_used = arena_used; + } + if (p_committed) { + *p_committed = arena_committed; + } + if (p_capacity) { + *p_capacity = arena_reserved; } } @@ -142,23 +170,33 @@ class MetaspaceArenaTestHelper { ASSERT_NULL(dummy); } - // Allocate; it may or may not work; return value in *p_return_value void allocate_from_arena_with_tests(MetaWord** p_return_value, size_t word_size) { + MetaBlock result, wastage; + allocate_from_arena_with_tests(word_size, result, wastage); + if (wastage.is_nonempty()) { + _arena->deallocate(wastage); + wastage.reset(); + } + (*p_return_value) = result.base(); + } + + // Allocate; it may or may not work; return value in *p_return_value + void allocate_from_arena_with_tests(size_t word_size, MetaBlock& result, MetaBlock& wastage) { // Note: usage_numbers walks all chunks in use and counts. size_t used = 0, committed = 0, capacity = 0; usage_numbers_with_test(&used, &committed, &capacity); - size_t possible_expansion = limiter().possible_expansion_words(); + size_t possible_expansion = _context.commit_limiter().possible_expansion_words(); - MetaWord* p = _arena->allocate(word_size); + result = _arena->allocate(word_size, wastage); SOMETIMES(DEBUG_ONLY(_arena->verify();)) size_t used2 = 0, committed2 = 0, capacity2 = 0; usage_numbers_with_test(&used2, &committed2, &capacity2); - if (p == nullptr) { + if (result.is_empty()) { // Allocation failed. ASSERT_LT(possible_expansion, word_size); ASSERT_EQ(used, used2); @@ -166,7 +204,8 @@ class MetaspaceArenaTestHelper { ASSERT_EQ(capacity, capacity2); } else { // Allocation succeeded. Should be correctly aligned. - ASSERT_TRUE(is_aligned(p, AllocationAlignmentByteSize)); + ASSERT_TRUE(result.is_aligned_base(_arena->allocation_alignment_words())); + // used: may go up or may not (since our request may have been satisfied from the freeblocklist // whose content already counts as used). // committed: may go up, may not @@ -175,8 +214,6 @@ class MetaspaceArenaTestHelper { ASSERT_GE(committed2, committed); ASSERT_GE(capacity2, capacity); } - - *p_return_value = p; } // Allocate; it may or may not work; but caller does not care for the result value @@ -189,7 +226,7 @@ class MetaspaceArenaTestHelper { size_t used = 0, committed = 0, capacity = 0; usage_numbers_with_test(&used, &committed, &capacity); - _arena->deallocate(p, word_size); + _arena->deallocate(MetaBlock(p, word_size)); SOMETIMES(DEBUG_ONLY(_arena->verify();)) @@ -209,9 +246,13 @@ class MetaspaceArenaTestHelper { return stats; } + MetaspaceArenaTestFriend internal_access() const { + return MetaspaceArenaTestFriend (_arena); + } + // Convenience method to return number of chunks in arena (including current chunk) int get_number_of_chunks() const { - return get_arena_statistics().totals()._num; + return internal_access().chunks().count(); } }; @@ -391,23 +432,28 @@ TEST_VM(metaspace, MetaspaceArena_deallocate) { MetaWord* p1 = nullptr; helper.allocate_from_arena_with_tests_expect_success(&p1, s); + ASSERT_FALSE(HasFailure()); size_t used1 = 0, capacity1 = 0; helper.usage_numbers_with_test(&used1, nullptr, &capacity1); + ASSERT_FALSE(HasFailure()); ASSERT_EQ(used1, s); helper.deallocate_with_tests(p1, s); size_t used2 = 0, capacity2 = 0; helper.usage_numbers_with_test(&used2, nullptr, &capacity2); + ASSERT_FALSE(HasFailure()); ASSERT_EQ(used1, used2); ASSERT_EQ(capacity2, capacity2); MetaWord* p2 = nullptr; helper.allocate_from_arena_with_tests_expect_success(&p2, s); + ASSERT_FALSE(HasFailure()); size_t used3 = 0, capacity3 = 0; helper.usage_numbers_with_test(&used3, nullptr, &capacity3); + ASSERT_FALSE(HasFailure()); ASSERT_EQ(used3, used2); ASSERT_EQ(capacity3, capacity2); @@ -450,6 +496,7 @@ static void test_recover_from_commit_limit_hit() { helper1.allocate_from_arena_with_tests_expect_success(1); helper2.allocate_from_arena_with_tests_expect_success(1); allocated_from_1_and_2 += 2; + HANDLE_FAILURE } // Now, allocating from helper3, creep up on the limit @@ -494,11 +541,11 @@ static void test_controlled_growth(Metaspace::MetaspaceType type, bool is_class, // have different initial capacities. MetaspaceGtestContext context; - MetaspaceArenaTestHelper smhelper(context, type, is_class, "Grower"); + MetaspaceArenaTestHelper smhelper(context, type, is_class); const Metaspace::MetaspaceType other_type = (type == Metaspace::StandardMetaspaceType) ? Metaspace::ClassMirrorHolderMetaspaceType : Metaspace::StandardMetaspaceType; - MetaspaceArenaTestHelper smhelper_harrasser(context, other_type, true, "Harasser"); + MetaspaceArenaTestHelper smhelper_harrasser(context, other_type, true); size_t used = 0, committed = 0, capacity = 0; const size_t alloc_words = 16; @@ -561,12 +608,14 @@ static void test_controlled_growth(Metaspace::MetaspaceType type, bool is_class, } smhelper.allocate_from_arena_with_tests_expect_success(alloc_words); + HANDLE_FAILURE words_allocated += metaspace::get_raw_word_size_for_requested_word_size(alloc_words); num_allocated++; size_t used2 = 0, committed2 = 0, capacity2 = 0; smhelper.arena()->usage_numbers(&used2, &committed2, &capacity2); + HANDLE_FAILURE // used should not grow larger than what we allocated, plus possible overhead. ASSERT_GE(used2, used); @@ -608,6 +657,10 @@ static void test_controlled_growth(Metaspace::MetaspaceType type, bool is_class, } + // No FBL should exist, we did not deallocate + ASSERT_EQ(smhelper.internal_access().fbl(), (FreeBlocks*)nullptr); + ASSERT_EQ(smhelper_harrasser.internal_access().fbl(), (FreeBlocks*)nullptr); + // After all this work, we should see an increase in number of chunk-in-place-enlargements // (this especially is vulnerable to regression: the decisions of when to do in-place-enlargements are somewhat // complicated, see MetaspaceArena::attempt_enlarge_current_chunk()) @@ -691,7 +744,8 @@ TEST_VM(metaspace, MetaspaceArena_growth_boot_nc_not_inplace) { // block should be reused by the next allocation). static void test_repeatedly_allocate_and_deallocate(bool is_topmost) { // Test various sizes, including (important) the max. possible block size = 1 root chunk - for (size_t blocksize = Metaspace::max_allocation_word_size(); blocksize >= 1; blocksize /= 2) { + for (size_t blocksize = Metaspace::max_allocation_word_size(); + blocksize >= Metaspace::min_allocation_word_size; blocksize /= 2) { size_t used1 = 0, used2 = 0, committed1 = 0, committed2 = 0; MetaWord* p = nullptr, *p2 = nullptr; @@ -703,6 +757,7 @@ static void test_repeatedly_allocate_and_deallocate(bool is_topmost) { if (!is_topmost) { // another one on top, size does not matter. helper.allocate_from_arena_with_tests_expect_success(0x10); + HANDLE_FAILURE } // Measure @@ -712,6 +767,7 @@ static void test_repeatedly_allocate_and_deallocate(bool is_topmost) { for (int i = 0; i < 5; i ++) { helper.deallocate_with_tests(p, blocksize); helper.allocate_from_arena_with_tests_expect_success(&p2, blocksize); + HANDLE_FAILURE // We should get the same pointer back. EXPECT_EQ(p2, p); } @@ -730,3 +786,120 @@ TEST_VM(metaspace, MetaspaceArena_test_repeatedly_allocate_and_deallocate_top_al TEST_VM(metaspace, MetaspaceArena_test_repeatedly_allocate_and_deallocate_nontop_allocation) { test_repeatedly_allocate_and_deallocate(false); } + +static void test_random_aligned_allocation(size_t arena_alignment_words, SizeRange range) { + // We let the arena use 4K chunks, unless the alloc size is larger. + chunklevel_t level = CHUNK_LEVEL_4K; + const ArenaGrowthPolicy policy (&level, 1); + const size_t chunk_word_size = word_size_for_level(level); + + size_t expected_used = 0; + + MetaspaceGtestContext context; + MetaspaceArenaTestHelper helper(context, &policy, arena_alignment_words); + + size_t last_alloc_size = 0; + unsigned num_allocations = 0; + + const size_t max_used = MIN2(MAX2(chunk_word_size * 10, (range.highest() * 100)), + LP64_ONLY(64) NOT_LP64(16) * M); // word size! + while (expected_used < max_used) { + + const int chunks_before = helper.get_number_of_chunks(); + + MetaBlock result, wastage; + size_t alloc_words = range.random_value(); + NOT_LP64(alloc_words = align_up(alloc_words, Metaspace::min_allocation_alignment_words)); + helper.allocate_from_arena_with_tests(alloc_words, result, wastage); + + ASSERT_TRUE(result.is_nonempty()); + ASSERT_TRUE(result.is_aligned_base(arena_alignment_words)); + ASSERT_EQ(result.word_size(), alloc_words); + + expected_used += alloc_words + wastage.word_size(); + const int chunks_now = helper.get_number_of_chunks(); + ASSERT_GE(chunks_now, chunks_before); + ASSERT_LE(chunks_now, chunks_before + 1); + + // Estimate wastage: + // Guessing at wastage is somewhat simple since we don't expect to ever use the fbl (we + // don't deallocate). Therefore, wastage can only be caused by alignment gap or by + // salvaging an old chunk before a new chunk is added. + const bool expect_alignment_gap = !is_aligned(last_alloc_size, arena_alignment_words); + const bool new_chunk_added = chunks_now > chunks_before; + + if (num_allocations == 0) { + // expect no wastage if its the first allocation in the arena + ASSERT_TRUE(wastage.is_empty()); + } else { + if (expect_alignment_gap) { + // expect wastage if the alignment requires it + ASSERT_TRUE(wastage.is_nonempty()); + } + } + + if (wastage.is_nonempty()) { + // If we have wastage, we expect it to be either too small or unaligned. That would not be true + // for wastage from the fbl, which could have any size; however, in this test we don't deallocate, + // so we don't expect wastage from the fbl. + if (wastage.is_aligned_base(arena_alignment_words)) { + ASSERT_LT(wastage.word_size(), alloc_words); + } + if (new_chunk_added) { + // chunk turnover: no more wastage than size of a commit granule, since we salvage the + // committed remainder of the old chunk. + ASSERT_LT(wastage.word_size(), Settings::commit_granule_words()); + } else { + // No chunk turnover: no more wastage than what alignment requires. + ASSERT_LT(wastage.word_size(), arena_alignment_words); + } + } + + // Check stats too + size_t used, committed, reserved; + helper.usage_numbers_with_test(&used, &committed, &reserved); + ASSERT_EQ(used, expected_used); + + // No FBL should exist, we did not deallocate + ASSERT_EQ(helper.internal_access().fbl(), (FreeBlocks*)nullptr); + + HANDLE_FAILURE + + last_alloc_size = alloc_words; + num_allocations ++; + } + LOG("allocs: %u", num_allocations); +} + +#define TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(al) \ +TEST_VM(metaspace, MetaspaceArena_test_random_small_aligned_allocation_##al) { \ + static const SizeRange range(Metaspace::min_allocation_word_size, 128); \ + test_random_aligned_allocation(al, range); \ +} + +#ifdef _LP64 +TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(1); +#endif +TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(2); +TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(8); +TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(32); +TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(128); +TEST_ARENA_WITH_ALIGNMENT_SMALL_RANGE(MIN_CHUNK_WORD_SIZE); + +#define TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(al) \ +TEST_VM(metaspace, MetaspaceArena_test_random_large_aligned_allocation_##al) { \ + static const SizeRange range(Metaspace::max_allocation_word_size() / 2, \ + Metaspace::max_allocation_word_size()); \ + test_random_aligned_allocation(al, range); \ +} + +#ifdef _LP64 +TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(1); +#endif +TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(2); +TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(8); +TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(32); +TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(128); +TEST_ARENA_WITH_ALIGNMENT_LARGE_RANGE(MIN_CHUNK_WORD_SIZE); + +} // namespace metaspace diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp index bb536dfd0e2..950f21fb92f 100644 --- a/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp +++ b/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp @@ -26,8 +26,10 @@ #include "precompiled.hpp" #include "memory/metaspace/chunkManager.hpp" #include "memory/metaspace/counters.hpp" +#include "memory/metaspace/metablock.hpp" #include "memory/metaspace/metaspaceArena.hpp" #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp" +#include "memory/metaspace/metaspaceContext.hpp" #include "memory/metaspace/metaspaceSettings.hpp" #include "memory/metaspace/metaspaceStatistics.hpp" #include "runtime/mutexLocker.hpp" @@ -43,7 +45,9 @@ using metaspace::ArenaGrowthPolicy; using metaspace::ChunkManager; using metaspace::IntCounter; using metaspace::MemRangeCounter; +using metaspace::MetaBlock; using metaspace::MetaspaceArena; +using metaspace::MetaspaceContext; using metaspace::SizeAtomicCounter; using metaspace::ArenaStats; using metaspace::InUseChunkStats; @@ -124,16 +128,14 @@ class MetaspaceArenaTestBed : public CHeapObj { MetaspaceArena* arena() { return _arena; } - MetaspaceArenaTestBed(ChunkManager* cm, const ArenaGrowthPolicy* alloc_sequence, - SizeAtomicCounter* used_words_counter, SizeRange allocation_range) : - _arena(nullptr), - _allocation_range(allocation_range), - _size_of_last_failed_allocation(0), - _allocations(nullptr), - _alloc_count(), - _dealloc_count() + MetaspaceArenaTestBed(MetaspaceContext* context, const ArenaGrowthPolicy* growth_policy, + size_t allocation_alignment_words, SizeRange allocation_range) + : _arena(nullptr) + , _allocation_range(allocation_range) + , _size_of_last_failed_allocation(0) + , _allocations(nullptr) { - _arena = new MetaspaceArena(cm, alloc_sequence, used_words_counter, "gtest-MetaspaceArenaTestBed-sm"); + _arena = new MetaspaceArena(context, growth_policy, Metaspace::min_allocation_alignment_words, "gtest-MetaspaceArenaTestBed-sm"); } ~MetaspaceArenaTestBed() { @@ -163,13 +165,20 @@ class MetaspaceArenaTestBed : public CHeapObj { // Allocate a random amount. Return false if the allocation failed. bool checked_random_allocate() { size_t word_size = 1 + _allocation_range.random_value(); - MetaWord* p = _arena->allocate(word_size); - if (p != nullptr) { - EXPECT_TRUE(is_aligned(p, AllocationAlignmentByteSize)); + MetaBlock wastage; + MetaBlock bl = _arena->allocate(word_size, wastage); + // We only expect wastage if either alignment was not met or the chunk remainder + // was not large enough. + if (wastage.is_nonempty()) { + _arena->deallocate(wastage); + wastage.reset(); + } + if (bl.is_nonempty()) { + EXPECT_TRUE(is_aligned(bl.base(), AllocationAlignmentByteSize)); allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal); a->word_size = word_size; - a->p = p; + a->p = bl.base(); a->mark(); a->next = _allocations; _allocations = a; @@ -193,7 +202,7 @@ class MetaspaceArenaTestBed : public CHeapObj { } if (a != nullptr && a->p != nullptr) { a->verify(); - _arena->deallocate(a->p, a->word_size); + _arena->deallocate(MetaBlock(a->p, a->word_size)); _dealloc_count.add(a->word_size); a->p = nullptr; a->word_size = 0; if ((_dealloc_count.count() % 20) == 0) { @@ -218,8 +227,8 @@ class MetaspaceArenaTest { void create_new_test_bed_at(int slotindex, const ArenaGrowthPolicy* growth_policy, SizeRange allocation_range) { DEBUG_ONLY(_testbeds.check_slot_is_null(slotindex)); - MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(&_context.cm(), growth_policy, - &_used_words_counter, allocation_range); + MetaspaceArenaTestBed* bed = new MetaspaceArenaTestBed(_context.context(), growth_policy, + Metaspace::min_allocation_alignment_words, allocation_range); _testbeds.set_at(slotindex, bed); _num_beds.increment(); } diff --git a/test/hotspot/gtest/oops/test_arrayOop.cpp b/test/hotspot/gtest/oops/test_arrayOop.cpp index e67e6e6c13b..5670aedafc1 100644 --- a/test/hotspot/gtest/oops/test_arrayOop.cpp +++ b/test/hotspot/gtest/oops/test_arrayOop.cpp @@ -82,7 +82,23 @@ TEST_VM(arrayOopDesc, narrowOop) { TEST_VM(arrayOopDesc, base_offset) { #ifdef _LP64 - if (UseCompressedClassPointers) { + if (UseCompactObjectHeaders) { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_CHAR), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_INT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_LONG), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 16); + if (UseCompressedOops) { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 12); + } else { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 16); + } + } else if (UseCompressedClassPointers) { EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 16); EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 16); diff --git a/test/hotspot/gtest/oops/test_compressedKlass.cpp b/test/hotspot/gtest/oops/test_compressedKlass.cpp index b2fc5064581..48026f46852 100644 --- a/test/hotspot/gtest/oops/test_compressedKlass.cpp +++ b/test/hotspot/gtest/oops/test_compressedKlass.cpp @@ -36,6 +36,7 @@ TEST_VM(CompressedKlass, basics) { ASSERT_LE(CompressedKlassPointers::base(), CompressedKlassPointers::klass_range_start()); ASSERT_LT(CompressedKlassPointers::klass_range_start(), CompressedKlassPointers::klass_range_end()); ASSERT_LE(CompressedKlassPointers::klass_range_end(), CompressedKlassPointers::encoding_range_end()); + switch (CompressedKlassPointers::shift()) { case 0: ASSERT_EQ(CompressedKlassPointers::encoding_range_end() - CompressedKlassPointers::base(), (ptrdiff_t)(4 * G)); @@ -44,10 +45,23 @@ TEST_VM(CompressedKlass, basics) { ASSERT_EQ(CompressedKlassPointers::encoding_range_end() - CompressedKlassPointers::base(), (ptrdiff_t)(32 * G)); break; default: - ShouldNotReachHere(); + const size_t expected_size = nth_bit(CompressedKlassPointers::narrow_klass_pointer_bits() + CompressedKlassPointers::shift()); + ASSERT_EQ(CompressedKlassPointers::encoding_range_end() - CompressedKlassPointers::base(), (ptrdiff_t)expected_size); } } +TEST_VM(CompressedKlass, ccp_off) { + if (UseCompressedClassPointers) { + return; + } + ASSERT_EQ(CompressedKlassPointers::klass_range_start(), (address)nullptr); + ASSERT_EQ(CompressedKlassPointers::klass_range_end(), (address)nullptr); + // We should be able to call CompressedKlassPointers::is_encodable, and it should + // always return false + ASSERT_FALSE(CompressedKlassPointers::is_encodable((address)0x12345)); +} + + TEST_VM(CompressedKlass, test_too_low_address) { if (!UseCompressedClassPointers) { return; @@ -68,12 +82,29 @@ TEST_VM(CompressedKlass, test_too_high_address) { ASSERT_FALSE(CompressedKlassPointers::is_encodable(high)); } +TEST_VM(CompressedKlass, test_unaligned_address) { + if (!UseCompressedClassPointers) { + return; + } + const size_t alignment = CompressedKlassPointers::klass_alignment_in_bytes(); + address addr = CompressedKlassPointers::klass_range_start() + alignment - 1; + ASSERT_FALSE(CompressedKlassPointers::is_encodable(addr)); + // Try word-aligned, but not sufficiently aligned + if (alignment > BytesPerWord) { + addr = CompressedKlassPointers::klass_range_start() + BytesPerWord; + ASSERT_FALSE(CompressedKlassPointers::is_encodable(addr)); + } + addr = CompressedKlassPointers::klass_range_end() - 1; + ASSERT_FALSE(CompressedKlassPointers::is_encodable(addr)); +} + TEST_VM(CompressedKlass, test_good_address) { if (!UseCompressedClassPointers) { return; } + const size_t alignment = CompressedKlassPointers::klass_alignment_in_bytes(); address addr = CompressedKlassPointers::klass_range_start(); ASSERT_TRUE(CompressedKlassPointers::is_encodable(addr)); - addr = CompressedKlassPointers::klass_range_end() - 1; + addr = CompressedKlassPointers::klass_range_end() - alignment; ASSERT_TRUE(CompressedKlassPointers::is_encodable(addr)); } diff --git a/test/hotspot/gtest/oops/test_objArrayOop.cpp b/test/hotspot/gtest/oops/test_objArrayOop.cpp index 60cf6242dd5..deb4919ce46 100644 --- a/test/hotspot/gtest/oops/test_objArrayOop.cpp +++ b/test/hotspot/gtest/oops/test_objArrayOop.cpp @@ -28,29 +28,36 @@ TEST_VM(objArrayOop, osize) { static const struct { - int objal; bool ccp; bool coops; int result; + int objal; bool ccp; bool coops; bool coh; int result; } x[] = { -// ObjAligInB, UseCCP, UseCoops, object size in heap words +// ObjAligInB, UseCCP, UseCoops, UseCOH, object size in heap words #ifdef _LP64 - { 8, false, false, 4 }, // 20 byte header, 8 byte oops - { 8, false, true, 3 }, // 20 byte header, 4 byte oops - { 8, true, false, 3 }, // 16 byte header, 8 byte oops - { 8, true, true, 3 }, // 16 byte header, 4 byte oops - { 16, false, false, 4 }, // 20 byte header, 8 byte oops, 16-byte align - { 16, false, true, 4 }, // 20 byte header, 4 byte oops, 16-byte align - { 16, true, false, 4 }, // 16 byte header, 8 byte oops, 16-byte align - { 16, true, true, 4 }, // 16 byte header, 4 byte oops, 16-byte align - { 256, false, false, 32 }, // 20 byte header, 8 byte oops, 256-byte align - { 256, false, true, 32 }, // 20 byte header, 4 byte oops, 256-byte align - { 256, true, false, 32 }, // 16 byte header, 8 byte oops, 256-byte align - { 256, true, true, 32 }, // 16 byte header, 4 byte oops, 256-byte align + { 8, false, false, false, 4 }, // 20 byte header, 8 byte oops + { 8, false, true, false, 3 }, // 20 byte header, 4 byte oops + { 8, true, false, false, 3 }, // 16 byte header, 8 byte oops + { 8, true, true, false, 3 }, // 16 byte header, 4 byte oops + { 8, true, false, true, 3 }, // 12 byte header, 8 byte oops + { 8, true, true, true, 2 }, // 12 byte header, 4 byte oops + { 16, false, false, false, 4 }, // 20 byte header, 8 byte oops, 16-byte align + { 16, false, true, false, 4 }, // 20 byte header, 4 byte oops, 16-byte align + { 16, true, false, false, 4 }, // 16 byte header, 8 byte oops, 16-byte align + { 16, true, true, false, 4 }, // 16 byte header, 4 byte oops, 16-byte align + { 16, true, false, true, 4 }, // 12 byte header, 8 byte oops, 16-byte align + { 16, true, true, true, 2 }, // 12 byte header, 4 byte oops, 16-byte align + { 256, false, false, false, 32 }, // 20 byte header, 8 byte oops, 256-byte align + { 256, false, true, false, 32 }, // 20 byte header, 4 byte oops, 256-byte align + { 256, true, false, false, 32 }, // 16 byte header, 8 byte oops, 256-byte align + { 256, true, true, false, 32 }, // 16 byte header, 4 byte oops, 256-byte align + { 256, true, false, true, 32 }, // 12 byte header, 8 byte oops, 256-byte align + { 256, true, true, true, 32 }, // 12 byte header, 4 byte oops, 256-byte align #else - { 8, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4 + { 8, false, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4 #endif - { -1, false, false, -1 } + { -1, false, false, false, -1 } }; for (int i = 0; x[i].result != -1; i++) { - if (x[i].objal == (int)ObjectAlignmentInBytes && x[i].ccp == UseCompressedClassPointers && x[i].coops == UseCompressedOops) { + if (x[i].objal == (int)ObjectAlignmentInBytes && x[i].ccp == UseCompressedClassPointers && x[i].coops == UseCompressedOops && + x[i].coh == UseCompactObjectHeaders) { EXPECT_EQ(objArrayOopDesc::object_size(1), (size_t)x[i].result); } } diff --git a/test/hotspot/gtest/oops/test_typeArrayOop.cpp b/test/hotspot/gtest/oops/test_typeArrayOop.cpp index a7565a23d58..b8c55867077 100644 --- a/test/hotspot/gtest/oops/test_typeArrayOop.cpp +++ b/test/hotspot/gtest/oops/test_typeArrayOop.cpp @@ -36,7 +36,11 @@ TEST_VM(typeArrayOopDesc, bool_at_put) { char* addr = align_up(mem, 16); typeArrayOop o = (typeArrayOop) cast_to_oop(addr); - o->set_klass(Universe::boolArrayKlass()); + if (UseCompactObjectHeaders) { + o->set_mark(Universe::boolArrayKlass()->prototype_header()); + } else { + o->set_klass(Universe::boolArrayKlass()); + } o->set_length(10); diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 000f26d71c6..ab4b44c9dd0 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -114,6 +114,10 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 +# Fails with +UseCompactObjectHeaders on aarch64 +runtime/cds/appcds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64 +runtime/cds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64 + applications/jcstress/copy.java 8229852 linux-all containers/docker/TestJcmd.java 8278102 linux-all diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java index 2d17753ba94..b511476bf52 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java @@ -153,6 +153,8 @@ static private void runAndVerify3(Runnable test, int offset) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned). @@ -165,6 +167,8 @@ public static void testByteLong1a(byte[] dest, long[] src) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: address has ConvL2I for cast of long to address, not supported. @@ -176,6 +180,8 @@ public static void testByteLong1b(byte[] dest, long[] src) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}) public static void testByteLong1c(byte[] dest, long[] src) { long base = 64; // make sure it is big enough and 8 byte aligned (required for 32-bit) @@ -186,6 +192,8 @@ public static void testByteLong1c(byte[] dest, long[] src) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: address has ConvL2I for cast of long to address, not supported. @@ -235,6 +243,8 @@ public static void testByteLong2_runner() { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned). @@ -247,6 +257,8 @@ public static void testByteLong3a(byte[] dest, long[] src) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: address has ConvL2I for cast of long to address, not supported. @@ -298,6 +310,8 @@ public static void testByteLong4_runner() { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned). @@ -310,6 +324,8 @@ public static void testByteLong5a(byte[] dest, long[] src, int start, int stop) @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: address has ConvL2I for cast of long to address, not supported. @@ -328,6 +344,8 @@ public static void testByteLong5_runner() { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned). @@ -340,6 +358,8 @@ public static void testByteByte1a(byte[] dest, byte[] src) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: address has ConvL2I for cast of long to address, not supported. @@ -357,6 +377,8 @@ public static void testByteByte1_runner() { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: offsets are badly aligned (UNSAFE.ARRAY_BYTE_BASE_OFFSET is 4 byte aligned, but not 8 byte aligned). @@ -369,6 +391,8 @@ public static void testByteByte2a(byte[] dest, byte[] src) { @Test @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}, applyIfPlatform = {"64-bit", "true"}) // 32-bit: address has ConvL2I for cast of long to address, not supported. diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java index 5968b7221c7..d61b8c658d6 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java @@ -51,7 +51,9 @@ public static void main(String[] args) { static long[] longArray = new long[size]; @Test - @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }) + @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }) public static void test(byte[] dest, long[] src) { for (int i = 0; i < src.length; i++) { if ((i < 0) || (8 > sizeBytes - i)) { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java index 159e471e3fc..b005d767287 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -122,6 +122,10 @@ public static OutputAnalyzer runTest(Class expr, List vmOpts = new LinkedList(); Collections.addAll(vmOpts, additionalVMOpts); + // Hide timestamps from warnings (e.g. due to potential CDS + // saved/runtime state mismatch), to avoid false positives when + // comparing output across runs. + vmOpts.add("-Xlog:all=warning:stdout:level,tags"); //setup mode-specific options switch (testVMMode) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index d477aa44763..caef911f73a 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -142,7 +142,8 @@ public class TestFramework { "UseZbb", "UseRVV", "Xlog", - "LogCompilation" + "LogCompilation", + "UseCompactObjectHeaders" ) ); diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java index c77f4f6fa2e..efd328dc5cc 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java @@ -398,6 +398,7 @@ static Object[] test0(byte[] a, byte[] b, byte mask) { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.AND_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test1(byte[] a, byte[] b, byte mask) { @@ -706,7 +707,7 @@ static Object[] test10c(short[] a, short[] b, short mask) { @IR(counts = {IRNode.LOAD_VECTOR_S, IRNode.VECTOR_SIZE_4, "> 0", IRNode.AND_VS, IRNode.VECTOR_SIZE_4, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIf = {"MaxVectorSize", ">=16"}, + applyIfAnd = {"MaxVectorSize", ">=16", "UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test10d(short[] a, short[] b, short mask) { @@ -1001,6 +1002,7 @@ static Object[] test13aIL(int[] a, long[] b) { IRNode.ADD_VB, "> 0", IRNode.ADD_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test13aIB(int[] a, byte[] b) { @@ -1017,6 +1019,7 @@ static Object[] test13aIB(int[] a, byte[] b) { IRNode.ADD_VI, "> 0", IRNode.ADD_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test13aIS(int[] a, short[] b) { @@ -1037,6 +1040,7 @@ static Object[] test13aIS(int[] a, short[] b) { IRNode.ADD_VI, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test13aBSIL(byte[] a, short[] b, int[] c, long[] d) { @@ -1072,6 +1076,7 @@ static Object[] test13bIL(int[] a, long[] b) { IRNode.ADD_VB, "> 0", IRNode.ADD_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test13bIB(int[] a, byte[] b) { @@ -1088,6 +1093,7 @@ static Object[] test13bIB(int[] a, byte[] b) { IRNode.ADD_VI, "> 0", IRNode.ADD_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test13bIS(int[] a, short[] b) { @@ -1108,6 +1114,7 @@ static Object[] test13bIS(int[] a, short[] b) { IRNode.ADD_VI, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"UseCompactObjectHeaders", "false"}, applyIfPlatform = {"64-bit", "true"}, applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) static Object[] test13bBSIL(byte[] a, short[] b, int[] c, long[] d) { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java index fb99fc5983a..9aaa7cdd8a9 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java @@ -163,11 +163,13 @@ public static int[] testc(int[] out) { @Test @IR(applyIfCPUFeature = {"sse2", "true"}, applyIfPlatform = {"64-bit", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"asimd", "true"}, - applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false"}, // AD file requires vector_length = 16 counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) public static int[] testd(int[] out) { for (int i = 0; i < ITER-2; i+=2) { @@ -181,11 +183,13 @@ public static int[] testd(int[] out) { @Test @IR(applyIfCPUFeature = {"sse2", "true"}, applyIfPlatform = {"64-bit", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"asimd", "true"}, - applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16 counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) public static int[] teste(int[] out) { for (int i = 0; i < ITER-2; i+=2) { @@ -199,11 +203,13 @@ public static int[] teste(int[] out) { @Test @IR(applyIfCPUFeature = {"sse2", "true"}, applyIfPlatform = {"64-bit", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"asimd", "true"}, - applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16 counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) public static int[] testf(int[] out) { for (int i = 0; i < ITER-2; i+=2) { @@ -217,11 +223,13 @@ public static int[] testf(int[] out) { @Test @IR(applyIfCPUFeature = {"sse2", "true"}, applyIfPlatform = {"64-bit", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"asimd", "true"}, - applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16 counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) public static int[] testg(int[] out) { for (int i = 0; i < ITER-2; i+=2) { @@ -235,11 +243,13 @@ public static int[] testg(int[] out) { @Test @IR(applyIfCPUFeature = {"sse2", "true"}, applyIfPlatform = {"64-bit", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"asimd", "true"}, - applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + applyIfAnd = {"MaxVectorSize", "16", "UseCompactObjectHeaders", "false" }, // AD file requires vector_length = 16 counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) public static int[] testh(int[] out) { for (int i = 0; i < ITER-2; i+=2) { diff --git a/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java b/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java new file mode 100644 index 00000000000..371c0fb2bc5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/TestIdenticalDominatingCLE.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, Red Hat, Inc. 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 8340532 + * @summary C2: assert(is_OuterStripMinedLoop()) failed: invalid node class: IfTrue + * @requires vm.compiler2.enabled + * @run main/othervm -XX:CompileOnly=TestIdenticalDominatingCLE::* -XX:CompileThreshold=100 -Xcomp -XX:-TieredCompilation + * -XX:-RangeCheckElimination -XX:LoopMaxUnroll=0 TestIdenticalDominatingCLE + * + */ + + +public class TestIdenticalDominatingCLE { + boolean bFld; + long lFld; + float[][] fArr = new float[6][6]; + + public static void main(String[] var0) { + TestIdenticalDominatingCLE t = new TestIdenticalDominatingCLE(); + t.test(); + } + + void test() { + int i = 0; + do { + for (int j = 0; j < 2; j++) { + float f = fArr[j][3] / Float.valueOf((float)1.318095814E9); + switch (i) { + case 1: + if (bFld ^ bFld) { + } else { + for (int k = 0; k < 600; k++) { + } + } + break; + default: + if (bFld) { + } + } + } + lFld = ++i; + } while (i < 6); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java index cddc5207d42..16d04102082 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopCombinedOpTest.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -223,6 +223,8 @@ public int[] multipleOpsWith2DifferentTypesAndConstant() { @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.STORE_VECTOR, ">0"}) public int[] multipleOpsWith2DifferentTypesAndInvariant() { short[] res1 = new short[SIZE]; @@ -236,6 +238,8 @@ public int[] multipleOpsWith2DifferentTypesAndInvariant() { @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "sse2", "true"}, + // This test fails with compact headers, but only with UseSSE<=3. + applyIf = { "UseCompactObjectHeaders", "false" }, counts = {IRNode.STORE_VECTOR, ">0"}) public int[] multipleOpsWith2DifferentTypesAndComplexExpression() { short[] res1 = new short[SIZE]; diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index d37bf567381..2a7886a2106 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -259,7 +259,6 @@ private void testConcurrentRefinementLogs() throws Exception { LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] { new LogMessageWithLevel("Recalculate Used Memory \\(ms\\):", Level.DEBUG), - new LogMessageWithLevel("Restore Preserved Marks \\(ms\\):", Level.DEBUG), new LogMessageWithLevel("Restore Evacuation Failed Regions \\(ms\\):", Level.DEBUG), new LogMessageWithLevel("Process Evacuation Failed Regions \\(ms\\):", Level.DEBUG), new LogMessageWithLevel("Evacuation Failed Regions:", Level.DEBUG), diff --git a/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java b/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java index 2e7ebc2370f..88d11c10fa0 100644 --- a/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java +++ b/test/hotspot/jtreg/gc/g1/plab/TestPLABPromotion.java @@ -32,7 +32,7 @@ * @modules java.management * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/timeout=240 gc.g1.plab.TestPLABPromotion + * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.g1.plab.TestPLABPromotion */ package gc.g1.plab; @@ -48,12 +48,15 @@ import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; /** * Test checks PLAB promotion of different size objects. */ public class TestPLABPromotion { + private static final boolean COMPACT_HEADERS = Platform.is64bit() && WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompactObjectHeaders"); + // GC ID with survivor PLAB statistics private final static long GC_ID_SURVIVOR_STATS = 1l; // GC ID with old PLAB statistics @@ -74,7 +77,7 @@ public class TestPLABPromotion { private static final int PLAB_SIZE_HIGH = 65536; private static final int OBJECT_SIZE_SMALL = 10 * HEAP_WORD_SIZE; private static final int OBJECT_SIZE_MEDIUM = 128 * HEAP_WORD_SIZE; - private static final int OBJECT_SIZE_HIGH = 3072 * HEAP_WORD_SIZE; + private static final int OBJECT_SIZE_HIGH = (COMPACT_HEADERS ? 3266 : 3250) * HEAP_WORD_SIZE; private static final int GC_NUM_SMALL = 1; private static final int GC_NUM_MEDIUM = 3; private static final int GC_NUM_HIGH = 7; diff --git a/test/hotspot/jtreg/gtest/CompressedKlassGtest.java b/test/hotspot/jtreg/gtest/CompressedKlassGtest.java index e6377a8570d..fce30285312 100644 --- a/test/hotspot/jtreg/gtest/CompressedKlassGtest.java +++ b/test/hotspot/jtreg/gtest/CompressedKlassGtest.java @@ -35,5 +35,26 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.xml - * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m + * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:+UnlockExperimentalVMOptions -XX:-UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m + */ + +/* @test id=ccp_off + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:-UseCompressedClassPointers -Xlog:metaspace* -Xmx6g -Xms128m + */ + +/* @test id=use-zero-based-encoding-coh + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=128m + */ + +/* @test id=use-zero-based-encoding-coh-large-class-space + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=CompressedKlass* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders -Xlog:metaspace* -Xmx6g -Xms128m -Xshare:off -XX:CompressedClassSpaceSize=4g */ diff --git a/test/hotspot/jtreg/gtest/MetaspaceGtests.java b/test/hotspot/jtreg/gtest/MetaspaceGtests.java index f1f811d6a71..fac88588e31 100644 --- a/test/hotspot/jtreg/gtest/MetaspaceGtests.java +++ b/test/hotspot/jtreg/gtest/MetaspaceGtests.java @@ -49,3 +49,14 @@ * @requires vm.flagless * @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockDiagnosticVMOptions -XX:-UseCompressedClassPointers */ + +/* @test id=UseCompactObjectHeaders + * @summary Run metaspace-related gtests with tiny classpointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @requires vm.bits == 64 + * @requires vm.flagless + * @requires vm.debug + * @run main/native GTestWrapper --gtest_filter=metaspace* -XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders + */ diff --git a/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java b/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java index 7a9b1c8dfb3..e69de29bb2d 100644 --- a/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java +++ b/test/hotspot/jtreg/gtest/MetaspaceUtilsGtests.java @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2021 THL A29 Limited, a Tencent company. 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. - * - */ - -/* - * Note: This runs the metaspace utils related parts of gtest in configurations which - * are not tested explicitly in the standard gtests. - * - */ - -/* @test - * @bug 8264008 - * @summary Run metaspace utils related gtests with compressed class pointers off - * @requires vm.bits == 64 - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=MetaspaceUtils* -XX:-UseCompressedClassPointers - */ diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java index f1b4c7143b4..574a680aceb 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -56,6 +56,7 @@ private static void do_test(boolean CDS) throws IOException { "-Xshare:" + (CDS ? "on" : "off"), "-Xmx128m", "-XX:CompressedClassSpaceSize=128m", + "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-Xlog:metaspace*", "-Xlog:metaspace+map=trace", "-Xlog:os+map=trace", "-XX:+SimulateFullAddressSpace", // So that no resevation attempt will succeed "-version"); diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java index 4feadfb5565..e4b6f2a0548 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -46,6 +46,7 @@ public class CompressedClassPointers { static final String logging_option = "-Xlog:gc+metaspace=trace,metaspace=info,cds=trace"; static final String reserveCCSAnywhere = "Reserving compressed class space anywhere"; + static final String usesCompactObjectHeadersPat = "UseCompactObjectHeaders 1"; // Returns true if we are to test the narrow klass base; we only do this on // platforms where we can be reasonably shure that we get reproducable placement). @@ -57,6 +58,11 @@ static boolean testNarrowKlassBase() { } + // Returns true if the output indicates that the VM uses compact object headers + static boolean usesCompactObjectHeaders(OutputAnalyzer output) { + return output.getOutput().contains(usesCompactObjectHeadersPat); + } + // Returns true if the output indicates that the ccs is reserved anywhere. static boolean isCCSReservedAnywhere(OutputAnalyzer output) { if (output.getOutput().contains(reserveCCSAnywhere)) { @@ -221,7 +227,7 @@ public static void smallHeapTestNoCoop() throws Exception { "-Xlog:cds=trace", "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - if (!isCCSReservedAnywhere(output)) { + if (!isCCSReservedAnywhere(output) && !usesCompactObjectHeaders(output)) { output.shouldContain("Narrow klass base: 0x0000000000000000"); } output.shouldHaveExitValue(0); @@ -239,10 +245,10 @@ public static void smallHeapTestWith1GNoCoop() throws Exception { "-Xlog:cds=trace", "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - if (!isCCSReservedAnywhere(output)) { + if (!isCCSReservedAnywhere(output) && !usesCompactObjectHeaders(output)) { output.shouldContain("Narrow klass base: 0x0000000000000000"); } - if (!Platform.isAArch64() && !Platform.isPPC()) { + if (!Platform.isAArch64() && !usesCompactObjectHeaders(output) && !Platform.isPPC()) { // Currently relax this test for Aarch64 and ppc. output.shouldContain("Narrow klass shift: 0"); } @@ -261,10 +267,10 @@ public static void largeHeapTestNoCoop() throws Exception { "-Xlog:cds=trace", "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - if (!isCCSReservedAnywhere(output)) { + if (!isCCSReservedAnywhere(output) && !usesCompactObjectHeaders(output)) { output.shouldContain("Narrow klass base: 0x0000000000000000"); } - if (!Platform.isAArch64() && !Platform.isPPC()) { + if (!Platform.isAArch64() && !usesCompactObjectHeaders(output) && !Platform.isPPC()) { // Currently relax this test for Aarch64 and ppc. output.shouldContain("Narrow klass shift: 0"); } diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java index 070c856a322..665c4cb8b9f 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointersEncodingScheme.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -42,13 +42,16 @@ public class CompressedClassPointersEncodingScheme { - private static void test(long forceAddress, long classSpaceSize, long expectedEncodingBase, int expectedEncodingShift) throws IOException { + private static void test(long forceAddress, boolean COH, long classSpaceSize, long expectedEncodingBase, int expectedEncodingShift) throws IOException { String forceAddressString = String.format("0x%016X", forceAddress).toLowerCase(); String expectedEncodingBaseString = String.format("0x%016X", expectedEncodingBase).toLowerCase(); ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "-Xshare:off", // to make CompressedClassSpaceBaseAddress work "-XX:+UnlockDiagnosticVMOptions", "-XX:-UseCompressedOops", // keep VM from optimizing heap location + "-XX:+UnlockExperimentalVMOptions", + "-XX:" + (COH ? "+" : "-") + "UseCompactObjectHeaders", + "-XX:" + (COH ? "+" : "-") + "UseObjectMonitorTable", "-XX:CompressedClassSpaceBaseAddress=" + forceAddress, "-XX:CompressedClassSpaceSize=" + classSpaceSize, "-Xmx128m", @@ -60,7 +63,8 @@ private static void test(long forceAddress, long classSpaceSize, long expectedEn // We ignore cases where we were not able to map at the force address if (output.contains("reserving class space failed")) { - throw new SkippedException("Skipping because we cannot force ccs to " + forceAddressString); + System.out.println("Skipping because we cannot force ccs to " + forceAddressString); + return; } output.shouldHaveExitValue(0); @@ -73,9 +77,51 @@ private static void test(long forceAddress, long classSpaceSize, long expectedEn public static void main(String[] args) throws Exception { // Test ccs nestling right at the end of the 4G range // Expecting base=0, shift=0 - test(4 * G - 128 * M, 128 * M, 0, 0); + test(4 * G - 128 * M, false, 128 * M, 0, 0); + // Test ccs nestling right at the end of the 32G range + // Expecting: + // - non-aarch64: base=0, shift=3 + // - aarch64: base to start of class range, shift 0 + if (Platform.isAArch64()) { + // The best we can do on aarch64 is to be *near* the end of the 32g range, since a valid encoding base + // on aarch64 must be 4G aligned, and the max. class space size is 3G. + long forceAddress = 0x7_0000_0000L; // 28g, and also a valid EOR immediate + test(forceAddress, false, 3 * G, forceAddress, 0); + } else { + test(32 * G - 128 * M, false, 128 * M, 0, 3); + } + + // Test ccs starting *below* 4G, but extending upwards beyond 4G. All platforms except aarch64 should pick + // zero based encoding. On aarch64, this test is excluded since the only valid mode would be XOR, but bit + // pattern for base and bit pattern would overlap. + if (!Platform.isAArch64()) { + test(4 * G - 128 * M, false, 2 * 128 * M, 0, 3); + } // add more... + // Compact Object Header Mode: + // On aarch64 and x64 we expect the VM to chose the smallest possible shift value needed to cover + // the encoding range. We expect the encoding Base to start at the class space start - but to enforce that, + // we choose a high address. + if (Platform.isAArch64() || Platform.isX64() || Platform.isRISCV64()) { + long forceAddress = 32 * G; + + long ccsSize = 128 * M; + int expectedShift = 6; + test(forceAddress, true, ccsSize, forceAddress, expectedShift); + + ccsSize = 512 * M; + expectedShift = 8; + test(forceAddress, true, ccsSize, forceAddress, expectedShift); + + ccsSize = G; + expectedShift = 9; + test(forceAddress, true, ccsSize, forceAddress, expectedShift); + + ccsSize = 3 * G; + expectedShift = 10; + test(forceAddress, true, ccsSize, forceAddress, expectedShift); + } } } diff --git a/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java b/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java index b679e866ac8..e69de29bb2d 100644 --- a/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java +++ b/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java @@ -1,113 +0,0 @@ -/* - * Copyright Amazon.com Inc. 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 id=with-coops-no-ccp - * @library /test/lib - * @requires vm.bits == "64" - * @modules java.base/jdk.internal.misc - * @run main/othervm -XX:+UseCompressedOops -XX:-UseCompressedClassPointers ArrayBaseOffsets - */ -/* - * @test id=with-coops-with-ccp - * @library /test/lib - * @requires vm.bits == "64" - * @requires vm.opt.UseCompressedClassPointers != false - * @modules java.base/jdk.internal.misc - * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers ArrayBaseOffsets - */ -/* - * @test id=no-coops-no-ccp - * @library /test/lib - * @requires vm.bits == "64" - * @modules java.base/jdk.internal.misc - * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers ArrayBaseOffsets - */ -/* - * @test id=no-coops-with-ccp - * @library /test/lib - * @requires vm.bits == "64" - * @requires vm.opt.UseCompressedClassPointers != false - * @modules java.base/jdk.internal.misc - * @run main/othervm -XX:-UseCompressedOops -XX:+UseCompressedClassPointers ArrayBaseOffsets - */ -/* - * @test id=32bit - * @library /test/lib - * @requires vm.bits == "32" - * @modules java.base/jdk.internal.misc - * @run main/othervm ArrayBaseOffsets - */ - -import jdk.internal.misc.Unsafe; - -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.util.List; - -import jdk.test.lib.Asserts; -import jdk.test.lib.Platform; - -public class ArrayBaseOffsets { - - private static final boolean COOP; - private static final boolean CCP; - - static { - if (Platform.is64bit()) { - RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); - List vmargs = runtime.getInputArguments(); - CCP = !vmargs.contains("-XX:-UseCompressedClassPointers"); - COOP = System.getProperty("java.vm.compressedOopsMode") != null; - } else { - COOP = CCP = false; - } - } - - static public void main(String[] args) { - Unsafe unsafe = Unsafe.getUnsafe(); - int intOffset, longOffset; - if (Platform.is64bit()) { - if (CCP) { - intOffset = 16; - longOffset = 16; - } else { - intOffset = 20; - longOffset = 24; - } - } else { - intOffset = 12; - longOffset = 16; - } - Asserts.assertEquals(unsafe.arrayBaseOffset(boolean[].class), intOffset, "Misplaced boolean array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(byte[].class), intOffset, "Misplaced byte array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(char[].class), intOffset, "Misplaced char array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(short[].class), intOffset, "Misplaced short array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(int[].class), intOffset, "Misplaced int array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(long[].class), longOffset, "Misplaced long array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(float[].class), intOffset, "Misplaced float array base"); - Asserts.assertEquals(unsafe.arrayBaseOffset(double[].class), longOffset, "Misplaced double array base"); - int expectedObjArrayOffset = (COOP || !Platform.is64bit()) ? intOffset : longOffset; - Asserts.assertEquals(unsafe.arrayBaseOffset(Object[].class), expectedObjArrayOffset, "Misplaced object array base"); - } -} diff --git a/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java b/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java new file mode 100644 index 00000000000..e4f88b5d8d5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/FieldLayout/BaseOffsets.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2022, 2024, 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 id=with-coops-with-ccp + * @library /test/lib / + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * java.management + * @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:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets + */ +/* + * @test id=no-coops-with-ccp + * @library /test/lib / + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * java.management + * @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:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets + */ +/* + * @test id=with-coops-no-ccp + * @library /test/lib / + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * java.management + * @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:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets + */ +/* + * @test id=no-coops-no-ccp + * @library /test/lib / + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * java.management + * @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:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:-UseCompactObjectHeaders BaseOffsets + */ +/* + * @test id=with-coop--with-coh + * @library /test/lib / + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * java.management + * @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:+UnlockExperimentalVMOptions -XX:+UseCompressedOops -XX:+UseCompactObjectHeaders BaseOffsets + */ +/* + * @test id=no-coops-with-coh + * @library /test/lib / + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * java.management + * @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:+UnlockExperimentalVMOptions -XX:-UseCompressedOops -XX:+UseCompactObjectHeaders BaseOffsets + */ +/* + * @test id=32bit + * @library /test/lib / + * @requires vm.bits == "32" + * @modules java.base/jdk.internal.misc + * java.management + * @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 BaseOffsets + */ + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Comparator; +import jdk.internal.misc.Unsafe; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.test.whitebox.WhiteBox; + +public class BaseOffsets { + + static class LIClass { + public int i; + } + + public static final WhiteBox WB = WhiteBox.getWhiteBox(); + + static final long INT_OFFSET; + static final int INT_ARRAY_OFFSET; + static final int LONG_ARRAY_OFFSET; + static { + if (!Platform.is64bit() || WB.getBooleanVMFlag("UseCompactObjectHeaders")) { + INT_OFFSET = 8; + INT_ARRAY_OFFSET = 12; + LONG_ARRAY_OFFSET = 16; + } else if (WB.getBooleanVMFlag("UseCompressedClassPointers")) { + INT_OFFSET = 12; + INT_ARRAY_OFFSET = 16; + LONG_ARRAY_OFFSET = 16; + } else { + INT_OFFSET = 16; + INT_ARRAY_OFFSET = 20; + LONG_ARRAY_OFFSET = 24; + } + } + + static public void main(String[] args) { + Unsafe unsafe = Unsafe.getUnsafe(); + Class c = LIClass.class; + Field[] fields = c.getFields(); + for (int i = 0; i < fields.length; i++) { + long offset = unsafe.objectFieldOffset(fields[i]); + if (fields[i].getType() == int.class) { + Asserts.assertEquals(offset, INT_OFFSET, "Misplaced int field"); + } else { + Asserts.fail("Unexpected field type"); + } + } + + Asserts.assertEquals(unsafe.arrayBaseOffset(boolean[].class), INT_ARRAY_OFFSET, "Misplaced boolean array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(byte[].class), INT_ARRAY_OFFSET, "Misplaced byte array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(char[].class), INT_ARRAY_OFFSET, "Misplaced char array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(short[].class), INT_ARRAY_OFFSET, "Misplaced short array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(int[].class), INT_ARRAY_OFFSET, "Misplaced int array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(long[].class), LONG_ARRAY_OFFSET, "Misplaced long array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(float[].class), INT_ARRAY_OFFSET, "Misplaced float array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(double[].class), LONG_ARRAY_OFFSET, "Misplaced double array base"); + boolean narrowOops = System.getProperty("java.vm.compressedOopsMode") != null || + !Platform.is64bit(); + int expected_objary_offset = narrowOops ? INT_ARRAY_OFFSET : LONG_ARRAY_OFFSET; + Asserts.assertEquals(unsafe.arrayBaseOffset(Object[].class), expected_objary_offset, "Misplaced object array base"); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java new file mode 100644 index 00000000000..590f22feed7 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/TestDefaultArchiveLoading.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Red Hat, Inc. 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 id=nocoops_nocoh + * @summary Test Loading of default archives in all configurations + * @requires vm.cds + * @requires vm.bits == 64 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver TestDefaultArchiveLoading nocoops_nocoh + */ + +/** + * @test id=nocoops_coh + * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) + * @requires vm.cds + * @requires vm.bits == 64 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver TestDefaultArchiveLoading nocoops_coh + */ + +/** + * @test id=coops_nocoh + * @summary Test Loading of default archives in all configurations + * @requires vm.cds + * @requires vm.bits == 64 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver TestDefaultArchiveLoading coops_nocoh + */ + +/** + * @test id=coops_coh + * @summary Test Loading of default archives in all configurations (requires --enable-cds-archive-coh) + * @requires vm.cds + * @requires vm.bits == 64 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run driver TestDefaultArchiveLoading coops_coh + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; + +public class TestDefaultArchiveLoading { + public static void main(String[] args) throws Exception { + + if (args.length != 1) { + throw new RuntimeException("Expected argument"); + } + + String archiveSuffix; + char coh, coops; + + switch (args[0]) { + case "nocoops_nocoh": + coh = coops = '-'; + archiveSuffix = "_nocoops"; + break; + case "nocoops_coh": + coops = '-'; + coh = '+'; + archiveSuffix = "_nocoops_coh"; + break; + case "coops_nocoh": + coops = '+'; + coh = '-'; + archiveSuffix = ""; + break; + case "coops_coh": + coh = coops = '+'; + archiveSuffix = "_coh"; + break; + default: throw new RuntimeException("Invalid argument " + args[0]); + } + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:+UnlockExperimentalVMOptions", + "-XX:" + coh + "UseCompactObjectHeaders", + "-XX:" + coops + "UseCompressedOops", + "-Xlog:cds", + "-Xshare:on", // fail if we cannot load archive + "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + output.shouldContain("classes" + archiveSuffix + ".jsa"); + + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java index 89fc346ffbb..e2e0f1bdf77 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestZGCWithCDS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -42,12 +42,15 @@ public class TestZGCWithCDS { public final static String UNABLE_TO_USE_ARCHIVE = "Unable to use shared archive."; public final static String ERR_MSG = "The saved state of UseCompressedOops and UseCompressedClassPointers is different from runtime, CDS will be disabled."; public static void main(String... args) throws Exception { + String compactHeaders = "-XX:+UseCompactObjectHeaders"; String helloJar = JarBuilder.build("hello", "Hello"); System.out.println("0. Dump with ZGC"); OutputAnalyzer out = TestCommon .dump(helloJar, new String[] {"Hello"}, "-XX:+UseZGC", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds"); out.shouldContain("Dumping shared data to file:"); out.shouldHaveExitValue(0); @@ -56,6 +59,8 @@ public static void main(String... args) throws Exception { out = TestCommon .exec(helloJar, "-XX:+UseZGC", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(HELLO); @@ -67,6 +72,8 @@ public static void main(String... args) throws Exception { "-XX:-UseZGC", "-XX:+UseCompressedOops", // in case turned off by vmoptions "-XX:+UseCompressedClassPointers", // by jtreg + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(UNABLE_TO_USE_ARCHIVE); @@ -79,6 +86,8 @@ public static void main(String... args) throws Exception { "-XX:+UseSerialGC", "-XX:-UseCompressedOops", "-XX:-UseCompressedClassPointers", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(UNABLE_TO_USE_ARCHIVE); @@ -91,6 +100,8 @@ public static void main(String... args) throws Exception { "-XX:+UseSerialGC", "-XX:-UseCompressedOops", "-XX:+UseCompressedClassPointers", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(HELLO); @@ -102,6 +113,8 @@ public static void main(String... args) throws Exception { "-XX:+UseSerialGC", "-XX:+UseCompressedOops", "-XX:-UseCompressedClassPointers", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(UNABLE_TO_USE_ARCHIVE); @@ -114,6 +127,8 @@ public static void main(String... args) throws Exception { "-XX:+UseSerialGC", "-XX:+UseCompressedOops", "-XX:+UseCompressedClassPointers", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(UNABLE_TO_USE_ARCHIVE); @@ -127,6 +142,8 @@ public static void main(String... args) throws Exception { "-XX:+UseSerialGC", "-XX:-UseCompressedOops", "-XX:+UseCompressedClassPointers", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds"); out.shouldContain("Dumping shared data to file:"); out.shouldHaveExitValue(0); @@ -135,6 +152,8 @@ public static void main(String... args) throws Exception { out = TestCommon .exec(helloJar, "-XX:+UseZGC", + "-XX:+UnlockExperimentalVMOptions", + compactHeaders, "-Xlog:cds", "Hello"); out.shouldContain(HELLO); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java index 46e08c7b754..133f44521d5 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -144,6 +144,7 @@ public static void main(String[] args) throws Exception { private static void removeDefaultArchives(String java_home_dst, String variant) { removeDefaultArchive(java_home_dst, variant, ""); removeDefaultArchive(java_home_dst, variant, "_nocoops"); + removeDefaultArchive(java_home_dst, variant, "_coh"); } private static void removeDefaultArchive(String java_home_dst, String variant, String suffix) { diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp index c32b787d578..ad7708ba55d 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/GetMethodDeclaringClass/libTestUnloadedClass.cpp @@ -39,9 +39,9 @@ static std::atomic ring_buffer[BUFFER_SIZE]; void get_method_details(jmethodID method) { jclass method_class; - char *class_name = NULL; + char *class_name = nullptr; if (_jvmti->GetMethodDeclaringClass(method, &method_class) == JVMTI_ERROR_NONE) { - if (_jvmti->GetClassSignature(method_class, &class_name, NULL) == JVMTI_ERROR_NONE) { + if (_jvmti->GetClassSignature(method_class, &class_name, nullptr) == JVMTI_ERROR_NONE) { _jvmti->Deallocate((unsigned char *)class_name); } } @@ -49,14 +49,14 @@ void get_method_details(jmethodID method) { void* read_ringbuffer(void* arg) { JNIEnv *env; - _jvm->AttachCurrentThreadAsDaemon((void **)&env, NULL); + _jvm->AttachCurrentThreadAsDaemon((void **)&env, nullptr); for (;;) { jmethodID id = ring_buffer[rand() % BUFFER_SIZE].load(std::memory_order_relaxed); if (id != (jmethodID)0) { get_method_details(id); } } - return NULL; + return nullptr; } static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env, @@ -66,8 +66,8 @@ static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env, static bool reader_created = false; static int ring_buffer_idx = 0; - char *class_name = NULL; - if (jvmti_env->GetClassSignature(klass, &class_name, NULL) != JVMTI_ERROR_NONE) { + char *class_name = nullptr; + if (jvmti_env->GetClassSignature(klass, &class_name, nullptr) != JVMTI_ERROR_NONE) { return; } // We only care MyClass and only one thread loads it @@ -79,7 +79,7 @@ static void JNICALL ClassPrepareCallback(jvmtiEnv *jvmti_env, if (!reader_created) { pthread_t tid; - pthread_create(&tid, NULL, read_ringbuffer, NULL); + pthread_create(&tid, nullptr, read_ringbuffer, nullptr); reader_created = true; } @@ -119,7 +119,7 @@ JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) } // Enable the ClassPrepare event - error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL); + error = _jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, nullptr); if (error != JVMTI_ERROR_NONE) { fprintf(stderr, "Error enabling ClassPrepare event: %d\n", error); return JNI_ERR; diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp index 477ede9f30a..1e272d0b02d 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/VThreadEventTest/libVThreadEventTest.cpp @@ -123,13 +123,13 @@ Agent_OnAttach(JavaVM *vm, char *options, void *reserved) { } clazz = env->FindClass("VThreadEventTest"); - if (clazz == NULL) { + if (clazz == nullptr) { LOG("FindClass failed\n"); return JNI_ERR; } mid = env->GetStaticMethodID(clazz, "agentStarted", "()V"); - if (mid == NULL) { + if (mid == nullptr) { LOG("GetStaticMethodID failed\n"); return JNI_ERR; } diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java index bcf93498574..1f039eb73b5 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -93,12 +93,12 @@ private static void checkForTruncation(String longConstantOutput) throws Excepti // ... // longConstant VM_Version::CPU_SHA 17179869184 // longConstant markWord::age_shift 3 - // longConstant markWord::hash_mask_in_place 549755813632 + // longConstant markWord::hash_mask_in_place 4398046509056 // ... checkLongValue("markWord::hash_mask_in_place", longConstantOutput, - Platform.is64bit() ? 549755813632L: 4294967168L); + Platform.is64bit() ? 4398046509056L: 4294967168L); String arch = System.getProperty("os.arch"); if (arch.equals("amd64") || arch.equals("i386") || arch.equals("x86")) { diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 5f78fc06abd..1ae9623ef14 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -773,6 +773,7 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all +jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index e7ee8990f94..4ac340ad3a3 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -670,4 +670,4 @@ jdk_core_no_security = \ # Set of tests for `@since` checks in source code documentation jdk_since_checks = \ - tools/sincechecker/modules/java_base/CheckSince_javaBase.java + tools/sincechecker/ diff --git a/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java b/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java index 6a256914527..44487a57200 100644 --- a/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java +++ b/test/jdk/java/awt/Graphics2D/ScaledTransform/ScaledTransform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -21,6 +21,7 @@ * questions. */ import java.awt.Dialog; +import java.awt.EventQueue; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; @@ -29,63 +30,93 @@ import java.awt.GraphicsEnvironment; import java.awt.Panel; import java.awt.geom.AffineTransform; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /* * @test * @bug 8069361 * @key headful * @summary SunGraphics2D.getDefaultTransform() does not include scale factor - * @author Alexander Scherbatiy - * @run main ScaledTransform + * @run main/timeout=300 ScaledTransform */ public class ScaledTransform { - private static volatile boolean passed = false; + private static volatile CountDownLatch painted; + private static volatile boolean passed; + private static volatile Dialog dialog; + private static volatile long startTime; + private static volatile long endTime; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { GraphicsEnvironment ge = GraphicsEnvironment. getLocalGraphicsEnvironment(); - if (ge.isHeadlessInstance()) { - return; - } - for (GraphicsDevice gd : ge.getScreenDevices()) { - for (GraphicsConfiguration gc : gd.getConfigurations()) { - testScaleFactor(gc); + System.out.println("Screen = " + gd); + test(gd.getDefaultConfiguration()); + /* Don't want to run too long. Test the default and up to 10 more */ + GraphicsConfiguration[] configs = gd.getConfigurations(); + for (int c = 0; c < configs.length && c < 10; c++) { + test(configs[c]); } } } - private static void testScaleFactor(final GraphicsConfiguration gc) { - final Dialog dialog = new Dialog((Frame) null, "Test", true, gc); - + static void test(GraphicsConfiguration gc) throws Exception { try { - dialog.setSize(100, 100); - Panel panel = new Panel() { - - @Override - public void paint(Graphics g) { - if (g instanceof Graphics2D) { - AffineTransform gcTx = gc.getDefaultTransform(); - AffineTransform gTx - = ((Graphics2D) g).getTransform(); - passed = gcTx.getScaleX() == gTx.getScaleX() - && gcTx.getScaleY() == gTx.getScaleY(); - } else { - passed = true; - } - dialog.setVisible(false); - } - }; - dialog.add(panel); - dialog.setVisible(true); - + /* reset vars for each run */ + passed = false; + dialog = null; + painted = new CountDownLatch(1); + EventQueue.invokeLater(() -> showDialog(gc)); + startTime = System.currentTimeMillis(); + endTime = startTime; + if (!painted.await(5, TimeUnit.SECONDS)) { + throw new RuntimeException("Panel is not painted!"); + } + System.out.println("Time to paint = " + (endTime - startTime) + "ms."); if (!passed) { throw new RuntimeException("Transform is not scaled!"); } } finally { - dialog.dispose(); + EventQueue.invokeAndWait(() -> disposeDialog()); } } + + private static void showDialog(final GraphicsConfiguration gc) { + System.out.println("Creating dialog for gc=" + gc + " with tx=" + gc.getDefaultTransform()); + dialog = new Dialog((Frame) null, "ScaledTransform", true, gc); + dialog.setSize(300, 100); + + Panel panel = new Panel() { + + @Override + public void paint(Graphics g) { + System.out.println("Painting panel"); + if (g instanceof Graphics2D g2d) { + AffineTransform gcTx = gc.getDefaultTransform(); + AffineTransform gTx = g2d.getTransform(); + System.out.println("GTX = " + gTx); + passed = (gcTx.getScaleX() == gTx.getScaleX()) && + (gcTx.getScaleY() == gTx.getScaleY()); + } else { + passed = true; + } + endTime = System.currentTimeMillis(); + painted.countDown(); + System.out.println("Painted panel"); + } + }; + dialog.add(panel); + dialog.setVisible(true); + } + + private static void disposeDialog() { + if (dialog != null) { + System.out.println("Disposing dialog"); + dialog.setVisible(false); + dialog.dispose(); + } + } } diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index 22c5069f3e7..1e473ccd974 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -301,6 +301,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase { + private static final boolean COMPACT_HEADERS = Platform.is64bit() && WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompactObjectHeaders"); static final Boolean COMPRESSED_OOPS = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedOops"); static final long REF_SIZE = (COMPRESSED_OOPS == null || COMPRESSED_OOPS == true) ? 4 : 8; @@ -374,15 +375,25 @@ private static long roundUp(long v, long a) { return (v + a - 1) / a * a; } + private static long expectedSmallObjSize() { + long size; + if (!Platform.is64bit() || COMPACT_HEADERS) { + size = 8; + } else { + size = 16; + } + return roundUp(size, OBJ_ALIGN); + } + private void testSize_newObject() { - long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); + long expected = expectedSmallObjSize(); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(new Object())); } } private void testSize_localObject() { - long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); + long expected = expectedSmallObjSize(); Object o = new Object(); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(o)); @@ -392,7 +403,7 @@ private void testSize_localObject() { static Object staticO = new Object(); private void testSize_fieldObject() { - long expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN); + long expected = expectedSmallObjSize(); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(staticO)); } diff --git a/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java b/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java index 2a858d32fc2..96bef099da2 100644 --- a/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java +++ b/test/jdk/java/net/HttpURLConnection/HttpURLConnectionExpect100Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -82,9 +82,9 @@ public void expect100ContinueHitCountTest() throws Exception { conn.setRequestProperty("Expect", "100-continue"); sendRequest(conn); getHeaderField(conn); - assertEquals(1, server.getServerHitCount()); // Server rejects the expect 100-continue request with 417 response assertEquals(417, conn.getResponseCode()); + assertEquals(1, server.getServerHitCount()); } @Test @@ -99,12 +99,12 @@ public void defaultRequestHitCountTest() throws Exception { conn.setRequestMethod("PUT"); sendRequest(conn); getHeaderField(conn); - assertEquals(1, server.getServerHitCount()); assertEquals(200, conn.getResponseCode()); try ( InputStream in = conn.getInputStream()) { byte[] data = in.readAllBytes(); assertEquals(RESPONSE.length(), data.length); } + assertEquals(1, server.getServerHitCount()); } private void sendRequest(final HttpURLConnection conn) throws Exception { @@ -116,6 +116,7 @@ private void sendRequest(final HttpURLConnection conn) throws Exception { os.flush(); } catch (IOException e) { // intentional, server will reject the expect 100 + System.err.println("Got expected exception: " + e); } } @@ -179,7 +180,7 @@ void close() { @Override public void run() { Socket client; - try { + try (ss) { while (isRunning) { client = ss.accept(); System.out.println(client.getRemoteSocketAddress().toString()); @@ -191,29 +192,16 @@ public void run() { if (isRunning) { throw new RuntimeException(ex); } - } finally { - if (ss != null && !ss.isClosed()) { - try { - ss.close(); - } catch (IOException ex) { - //ignore - } - } } } private void handleConnection(Socket client) throws IOException { - try ( BufferedReader in = new BufferedReader( + try (client; BufferedReader in = new BufferedReader( new InputStreamReader(client.getInputStream())); PrintStream out = new PrintStream(client.getOutputStream())) { handle_connection(in, out); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - } finally { - try { - client.close(); - } catch (IOException e) { - } } } @@ -230,6 +218,10 @@ private void handle_connection(BufferedReader in, PrintStream out) } else { defaultResponse(out); } + // wait until the client closes the socket + while (line != null) { + line = in.readLine(); + } } private void rejectExpect100Continue(PrintStream out) { diff --git a/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java b/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java index 9a9da43b544..f4ddd726d0c 100644 --- a/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java +++ b/test/jdk/javax/crypto/KDF/KDFDelayedProviderSyncTest.java @@ -60,7 +60,7 @@ public void setUp() throws NoSuchAlgorithmException { kdfUnderTest = KDF.getInstance("HKDF-SHA256"); } - @Test(threadPoolSize = 50, invocationCount = 100, timeOut = 150) + @Test(threadPoolSize = 50, invocationCount = 100) public void testDerive() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException { SecretKey result = kdfUnderTest.deriveKey("Generic", derivationSpec); diff --git a/test/jdk/tools/jlink/plugins/CDSPluginTest.java b/test/jdk/tools/jlink/plugins/CDSPluginTest.java index d50b1c88a21..c9766183297 100644 --- a/test/jdk/tools/jlink/plugins/CDSPluginTest.java +++ b/test/jdk/tools/jlink/plugins/CDSPluginTest.java @@ -26,6 +26,7 @@ import jdk.test.lib.JDKToolFinder; import jdk.test.lib.Platform; import jdk.test.lib.process.*; +import jdk.test.whitebox.WhiteBox; import tests.Helper; @@ -44,11 +45,12 @@ * jdk.jlink/jdk.tools.jimage * jdk.compiler * @build tests.* - * @run main CDSPluginTest + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CDSPluginTest */ public class CDSPluginTest { - public static void main(String[] args) throws Throwable { if (!Platform.isDefaultCDSArchiveSupported()) @@ -75,12 +77,19 @@ public static void main(String[] args) throws Throwable { } subDir += "server" + sep; + WhiteBox wb = WhiteBox.getWhiteBox(); + boolean COMPACT_HEADERS = Platform.is64bit() && + wb.getBooleanVMFlag("UseCompactObjectHeaders") && + wb.isDefaultVMFlag("UseCompactObjectHeaders"); + + String suffix = COMPACT_HEADERS ? "_coh.jsa" : ".jsa"; + if (Platform.isAArch64() || Platform.isX64()) { helper.checkImage(image, module, null, null, - new String[] { subDir + "classes.jsa", subDir + "classes_nocoops.jsa" }); + new String[] { subDir + "classes" + suffix, subDir + "classes_nocoops" + suffix }); } else { helper.checkImage(image, module, null, null, - new String[] { subDir + "classes.jsa" }); + new String[] { subDir + "classes" + suffix }); } } } diff --git a/test/jdk/tools/launcher/Settings.java b/test/jdk/tools/launcher/Settings.java index 2b581be5b26..fe5a9c3b157 100644 --- a/test/jdk/tools/launcher/Settings.java +++ b/test/jdk/tools/launcher/Settings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, 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 @@ -25,7 +25,7 @@ /* * @test - * @bug 6994753 7123582 8305950 8281658 8310201 8311653 + * @bug 6994753 7123582 8305950 8281658 8310201 8311653 8343804 * @summary tests -XshowSettings options * @modules jdk.compiler * jdk.zipfs @@ -80,6 +80,7 @@ static void checkNotContains(TestResult tr, String str) { private static final String SYSTEM_SETTINGS = "Operating System Metrics:"; private static final String METRICS_NOT_AVAILABLE_MSG = "No metrics available for this platform"; private static final String STACKSIZE_SETTINGS = "Stack Size:"; + private static final String TIMEZONE_SETTINGS = "default timezone"; private static final String TZDATA_SETTINGS = "tzdata version"; private static final String ERR_MSG = "Unrecognized showSettings option:"; @@ -96,6 +97,7 @@ static void containsAllOptions(TestResult tr) { checkNotContains(tr, SEC_SUMMARY_PROPS_SETTINGS); checkContains(tr, SEC_PROVIDER_SETTINGS); checkContains(tr, SEC_TLS_SETTINGS); + checkContains(tr, TIMEZONE_SETTINGS); checkContains(tr, TZDATA_SETTINGS); if (System.getProperty("os.name").contains("Linux")) { checkContains(tr, SYSTEM_SETTINGS); @@ -119,6 +121,7 @@ static void containsDefaultOptions(TestResult tr) { checkContains(tr, SEC_SUMMARY_PROPS_SETTINGS); checkContains(tr, SEC_PROVIDER_SETTINGS); checkContains(tr, SEC_TLS_SETTINGS); + checkContains(tr, TIMEZONE_SETTINGS); checkContains(tr, TZDATA_SETTINGS); if (System.getProperty("os.name").contains("Linux")) { checkContains(tr, SYSTEM_SETTINGS); @@ -190,6 +193,7 @@ static void runTestOptionLocale() throws IOException { checkContains(tr, LOCALE_SETTINGS); checkContains(tr, AVAILABLE_LOCALES); checkNotContains(tr, LOCALE_SUMMARY_SETTINGS); + checkContains(tr, TIMEZONE_SETTINGS); checkContains(tr, TZDATA_SETTINGS); } diff --git a/test/jdk/tools/sincechecker/TEST.properties b/test/jdk/tools/sincechecker/TEST.properties new file mode 100644 index 00000000000..27f669ef4ca --- /dev/null +++ b/test/jdk/tools/sincechecker/TEST.properties @@ -0,0 +1,4 @@ +modules = \ + jdk.compiler/com.sun.tools.javac.api \ + jdk.compiler/com.sun.tools.javac.util \ + jdk.compiler/com.sun.tools.javac.code diff --git a/test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java similarity index 81% rename from test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java rename to test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java index 6d0b9d0e932..64d5bf2465f 100644 --- a/test/jdk/tools/sincechecker/modules/java_base/CheckSince_javaBase.java +++ b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java @@ -24,11 +24,7 @@ /* * @test * @bug 8331051 - * @summary Test for `@since` for java.base module - * @library /test/lib - * /test/jdk/tools/sincechecker - * @modules jdk.compiler/com.sun.tools.javac.api - * jdk.compiler/com.sun.tools.javac.util - * jdk.compiler/com.sun.tools.javac.code + * @summary Test for `@since` in java.base module + * @library /test/lib /test/jdk/tools/sincechecker * @run main SinceChecker java.base --exclude java.lang.classfile */ diff --git a/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java new file mode 100644 index 00000000000..c843c962d27 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/java.compiler/JavaCompilerCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8341399 + * @summary Test for `@since` in java.compiler module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker java.compiler + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java new file mode 100644 index 00000000000..5eb819786e9 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8341399 + * @summary Test for `@since` in jdk.compiler module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.compiler + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java new file mode 100644 index 00000000000..0e68d8213e9 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.javadoc/JdkJavadocCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8341399 + * @summary Test for `@since` in jdk.javadoc module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.javadoc + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java new file mode 100644 index 00000000000..68439c49e24 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jdeps/JdkJdepsCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8341399 + * @summary Test for `@since` in jdk.jdeps module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jdeps + */ diff --git a/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java new file mode 100644 index 00000000000..09f762cfeba --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.jshell/JdkJshellCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024, 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 8341399 + * @summary Test for `@since` in jdk.jshell module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.jshell + */ diff --git a/test/langtools/tools/javac/sealed/SealedCompilationTests.java b/test/langtools/tools/javac/sealed/SealedCompilationTests.java index 5ad70d102d6..dee64fd0865 100644 --- a/test/langtools/tools/javac/sealed/SealedCompilationTests.java +++ b/test/langtools/tools/javac/sealed/SealedCompilationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -1178,6 +1178,39 @@ void test () { I[] i = (I[]) c; } } + """, + """ + class Test { + sealed interface I permits C1 {} + non-sealed class C1 implements I {} + class C2 extends C1 {} + class C3 {} + I m(int s, C3 c3) { + I i = (I)c3; + } + } + """, + """ + class Test { + sealed interface I permits C1 {} + non-sealed class C1 implements I {} + class C2 extends C1 {} + class C3 {} + I m(int s, C3 c3) { + I i = (C1)c3; + } + } + """, + """ + class Test { + sealed interface I permits C1 {} + non-sealed class C1 implements I {} + class C2 extends C1 {} + class C3 {} + I m(int s, C3 c3) { + I i = (C2)c3; + } + } """ )) { assertFail("compiler.err.prob.found.req", s); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java index 520c1ad5a9b..b627c4de089 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class AllocFromTest extends CLayouts { Arena arena = Arena.ofConfined(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java index d9b268a1846..a70861a0dda 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -50,7 +50,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class AllocTest extends CLayouts { Arena arena = Arena.ofConfined(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java index f779d52151c..6a1dd05b615 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -51,7 +51,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class BulkOps { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java index 8f758477cbe..a725b427038 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverConstant extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java index d74ac8fbcee..c0d16f9818d 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNew extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java index 94c220292a0..e869a92c4d8 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNewHeap extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java index da7d15483e8..668a6ab8e30 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java @@ -51,7 +51,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstant extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java index 547e3bc298f..e7c08512db3 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantAsType.java @@ -54,7 +54,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgs = { "-XX:-TieredCompilation" }) +@Fork(value = 3, jvmArgs = { "-XX:-TieredCompilation", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantAsType extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java index 4a24512b22d..7bc39f5e372 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantFP { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java index e123e5baf1a..baaa1909718 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -49,7 +49,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantHeap extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java index ee4a4f3c60b..409b837ee8b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -55,7 +55,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantMapped extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java index 9504439bda1..2c1a5672749 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverNonConstantShared extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java index 99cf83b75e5..c9060adc18b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverPollutedBuffer { static final int ELEM_SIZE = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java index 4ad60297a32..b0fddeeb8da 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -46,7 +46,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = { "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" }) public class LoopOverPollutedSegments extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java index 9ee54f8ef6b..392ac6d667b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverRandom.java @@ -46,7 +46,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class LoopOverRandom extends JavaLayouts { static final int SEED = 0; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java index ffdff6e64ef..a0b57b5662c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -45,7 +45,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"}) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MemorySegmentCopyUnsafe { static final Unsafe UNSAFE = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java index 11cb1e98889..b18696a1424 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -50,7 +50,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"}) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MemorySegmentGetUnsafe { static final Unsafe UNSAFE = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java index 72fdded386f..09e5a1e3e77 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentZeroUnsafe.java @@ -44,7 +44,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED"}) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class MemorySegmentZeroUnsafe { static final Unsafe UNSAFE = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java index 3d00674f89e..42c6e481a72 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -52,7 +52,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(3) +@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class ParallelSum extends JavaLayouts { final static int CARRIER_SIZE = 4; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java b/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java index eb19fc56ac2..96cf62cc5f6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/SegmentBulkFill.java @@ -38,6 +38,7 @@ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.concurrent.TimeUnit; @@ -74,6 +75,20 @@ public void arraysFill() { Arrays.fill(array, (byte) 0); } + @Benchmark + public void arraysFillLoop() { + for (int i = 0; i < array.length; i++) { + array[i] = 0; + } + } + + @Benchmark + public void bufferFillLoop() { + for (int i = 0; i < array.length; i++) { + buffer.put(i, (byte)0); + } + } + @Fork(value = 3, jvmArgs = {"-Djava.lang.foreign.native.threshold.power.fill=31"}) @Benchmark public void heapSegmentFillJava() { @@ -86,6 +101,13 @@ public void heapSegmentFillUnsafe() { heapSegment.fill((byte) 0); } + @Benchmark + public void heapSegmentFillLoop() { + for (long i = 0; i < heapSegment.byteSize(); i++) { + heapSegment.set(ValueLayout.JAVA_BYTE, i, (byte) 0); + } + } + @Fork(value = 3, jvmArgs = {"-Djava.lang.foreign.native.threshold.power.fill=31"}) @Benchmark public void nativeSegmentFillJava() { @@ -98,6 +120,13 @@ public void nativeSegmentFillUnsafe() { nativeSegment.fill((byte) 0); } + @Benchmark + public void nativeSegmentFillLoop() { + for (long i = 0; i < nativeSegment.byteSize(); i++) { + nativeSegment.set(ValueLayout.JAVA_BYTE, i, (byte) 0); + } + } + @Fork(value = 3, jvmArgs = {"-Djava.lang.foreign.native.threshold.power.fill=31"}) @Benchmark public void unalignedSegmentFillJava() { @@ -110,4 +139,11 @@ public void unalignedSegmentFillUnsafe() { unalignedSegment.fill((byte) 0); } + @Benchmark + public void unalignedSegmentFillLoop() { + for (long i = 0; i < unalignedSegment.byteSize(); i++) { + unalignedSegment.set(ValueLayout.JAVA_BYTE, i, (byte) 0); + } + } + } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java index 197dcf99e28..a52f9181350 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -40,7 +40,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(value = 3, jvmArgs = { "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgs = {"--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class UnrolledAccess extends JavaLayouts { static final Unsafe U = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java b/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java index 9054c0dbd1e..0b29f925c7c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/xor/GetArrayUnsafeXorOpImpl.java @@ -1,7 +1,31 @@ +/* + * Copyright (c) 2023, 2024, 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. + */ + package org.openjdk.bench.java.lang.foreign.xor; import org.openjdk.bench.java.lang.foreign.Utils; import jdk.internal.misc.Unsafe; +import org.openjdk.jmh.annotations.Fork; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -14,6 +38,7 @@ import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static org.openjdk.bench.java.lang.foreign.CLayouts.*; +@Fork(value = 3, jvmArgs = {"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"}) public class GetArrayUnsafeXorOpImpl implements XorOp { static final Unsafe UNSAFE = Utils.unsafe;