8341371: CDS cannot load archived heap objects with -XX:+UseSerialGC -XX:-UseCompressedOops
Reviewed-by: ccheung, iklam
This commit is contained in:
parent
120a9357b3
commit
9f6211bcf1
@ -142,15 +142,22 @@ class PatchCompressedEmbeddedPointersQuick: public BitMapClosure {
|
||||
|
||||
class PatchUncompressedEmbeddedPointers: public BitMapClosure {
|
||||
oop* _start;
|
||||
intptr_t _delta;
|
||||
|
||||
public:
|
||||
PatchUncompressedEmbeddedPointers(oop* start) : _start(start) {}
|
||||
PatchUncompressedEmbeddedPointers(oop* start, intx runtime_offset) :
|
||||
_start(start),
|
||||
_delta(runtime_offset) {}
|
||||
|
||||
PatchUncompressedEmbeddedPointers(oop* start) :
|
||||
_start(start),
|
||||
_delta(ArchiveHeapLoader::mapped_heap_delta()) {}
|
||||
|
||||
bool do_bit(size_t offset) {
|
||||
oop* p = _start + offset;
|
||||
intptr_t dumptime_oop = (intptr_t)((void*)*p);
|
||||
assert(dumptime_oop != 0, "null oops should have been filtered out at dump time");
|
||||
intptr_t runtime_oop = dumptime_oop + ArchiveHeapLoader::mapped_heap_delta();
|
||||
intptr_t runtime_oop = dumptime_oop + _delta;
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(runtime_oop));
|
||||
return true;
|
||||
}
|
||||
@ -221,10 +228,6 @@ void ArchiveHeapLoader::init_loaded_heap_relocation(LoadedArchiveHeapRegion* loa
|
||||
}
|
||||
|
||||
bool ArchiveHeapLoader::can_load() {
|
||||
if (!UseCompressedOops) {
|
||||
// Pointer relocation for uncompressed oops is unimplemented.
|
||||
return false;
|
||||
}
|
||||
return Universe::heap()->can_load_archived_objects();
|
||||
}
|
||||
|
||||
@ -312,13 +315,18 @@ bool ArchiveHeapLoader::load_heap_region_impl(FileMapInfo* mapinfo, LoadedArchiv
|
||||
uintptr_t oopmap = bitmap_base + r->oopmap_offset();
|
||||
BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits());
|
||||
|
||||
PatchLoadedRegionPointers patcher((narrowOop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region);
|
||||
bm.iterate(&patcher);
|
||||
if (UseCompressedOops) {
|
||||
PatchLoadedRegionPointers patcher((narrowOop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region);
|
||||
bm.iterate(&patcher);
|
||||
} else {
|
||||
PatchUncompressedEmbeddedPointers patcher((oop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region->_runtime_offset);
|
||||
bm.iterate(&patcher);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArchiveHeapLoader::load_heap_region(FileMapInfo* mapinfo) {
|
||||
assert(UseCompressedOops, "loaded heap for !UseCompressedOops is unimplemented");
|
||||
assert(can_load(), "loaded heap for must be supported");
|
||||
init_narrow_oop_decoding(mapinfo->narrow_oop_base(), mapinfo->narrow_oop_shift());
|
||||
|
||||
LoadedArchiveHeapRegion loaded_region;
|
||||
@ -358,8 +366,12 @@ class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
|
||||
}
|
||||
}
|
||||
virtual void do_oop(oop* p) {
|
||||
// Uncompressed oops are not supported by loaded heaps.
|
||||
Unimplemented();
|
||||
oop v = *p;
|
||||
if(v != nullptr) {
|
||||
uintptr_t u = cast_from_oop<uintptr_t>(v);
|
||||
ArchiveHeapLoader::assert_in_loaded_heap(u);
|
||||
guarantee(_table->contains(u), "must point to beginning of object in loaded archived region");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 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
|
||||
@ -146,6 +146,7 @@ private:
|
||||
inline static oop decode_from_archive_impl(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
|
||||
|
||||
class PatchLoadedRegionPointers;
|
||||
class PatchUncompressedLoadedRegionPointers;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -2054,8 +2054,7 @@ void FileMapInfo::map_or_load_heap_region() {
|
||||
success = ArchiveHeapLoader::load_heap_region(this);
|
||||
} else {
|
||||
if (!UseCompressedOops && !ArchiveHeapLoader::can_map()) {
|
||||
// TODO - remove implicit knowledge of G1
|
||||
log_info(cds)("Cannot use CDS heap data. UseG1GC is required for -XX:-UseCompressedOops");
|
||||
log_info(cds)("Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops");
|
||||
} else {
|
||||
log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC, UseParallelGC, or UseShenandoahGC are required.");
|
||||
}
|
||||
@ -2135,7 +2134,7 @@ address FileMapInfo::heap_region_requested_address() {
|
||||
assert(CDSConfig::is_using_archive(), "runtime only");
|
||||
FileMapRegion* r = region_at(MetaspaceShared::hp);
|
||||
assert(is_aligned(r->mapping_offset(), sizeof(HeapWord)), "must be");
|
||||
assert(ArchiveHeapLoader::can_map(), "cannot be used by ArchiveHeapLoader::can_load() mode");
|
||||
assert(ArchiveHeapLoader::can_use(), "GC must support mapping or loading");
|
||||
if (UseCompressedOops) {
|
||||
// We can avoid relocation if each region's offset from the runtime CompressedOops::base()
|
||||
// is the same as its offset from the CompressedOops::base() during dumptime.
|
||||
|
@ -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.
|
||||
* Copyright (c) 2017, 2022, Red Hat, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -128,7 +128,7 @@ public:
|
||||
bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); }
|
||||
|
||||
// Support for loading objects from CDS archive into the heap
|
||||
bool can_load_archived_objects() const override { return UseCompressedOops; }
|
||||
bool can_load_archived_objects() const override { return true; }
|
||||
HeapWord* allocate_loaded_archive_space(size_t size) override;
|
||||
|
||||
void print_on(outputStream* st) const override;
|
||||
|
@ -246,7 +246,7 @@ public:
|
||||
}
|
||||
|
||||
// Support for loading objects from CDS archive into the heap
|
||||
bool can_load_archived_objects() const override { return UseCompressedOops; }
|
||||
bool can_load_archived_objects() const override { return true; }
|
||||
HeapWord* allocate_loaded_archive_space(size_t size) override;
|
||||
void complete_loaded_archive_space(MemRegion archive_space) override;
|
||||
|
||||
|
@ -291,7 +291,7 @@ public:
|
||||
void safepoint_synchronize_end() override;
|
||||
|
||||
// Support for loading objects from CDS archive into the heap
|
||||
bool can_load_archived_objects() const override { return UseCompressedOops; }
|
||||
bool can_load_archived_objects() const override { return true; }
|
||||
HeapWord* allocate_loaded_archive_space(size_t size) override;
|
||||
void complete_loaded_archive_space(MemRegion archive_space) override;
|
||||
|
||||
|
@ -543,7 +543,7 @@ public:
|
||||
|
||||
// ---------- CDS archive support
|
||||
|
||||
bool can_load_archived_objects() const override { return UseCompressedOops; }
|
||||
bool can_load_archived_objects() const override { return true; }
|
||||
HeapWord* allocate_loaded_archive_space(size_t size) override;
|
||||
void complete_loaded_archive_space(MemRegion archive_space) override;
|
||||
|
||||
|
@ -2159,8 +2159,7 @@ WB_ENTRY(jboolean, WB_IsJVMCISupportedByGC(JNIEnv* env))
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jboolean, WB_CanWriteJavaHeapArchive(JNIEnv* env))
|
||||
return HeapShared::can_write()
|
||||
&& ArchiveHeapLoader::can_use(); // work-around JDK-8341371
|
||||
return HeapShared::can_write();
|
||||
WB_END
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2022, 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
|
||||
@ -37,16 +37,41 @@
|
||||
* @run driver TestEpsilonGCWithCDS
|
||||
*/
|
||||
|
||||
// Below is exactly the same as above, except:
|
||||
// - requires vm.bits == "64"
|
||||
// - extra argument "false"
|
||||
|
||||
/*
|
||||
* @test Loading CDS archived heap objects into EpsilonGC
|
||||
* @bug 8234679 8341371
|
||||
* @requires vm.cds
|
||||
* @requires vm.gc.Epsilon
|
||||
* @requires vm.gc.G1
|
||||
* @requires vm.bits == "64"
|
||||
*
|
||||
* @comment don't run this test if any -XX::+Use???GC options are specified, since they will
|
||||
* interfere with the test.
|
||||
* @requires vm.gc == null
|
||||
*
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||
* @compile test-classes/Hello.java
|
||||
* @run driver TestEpsilonGCWithCDS false
|
||||
*/
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class TestEpsilonGCWithCDS {
|
||||
public final static String HELLO = "Hello World";
|
||||
static String helloJar;
|
||||
static boolean useCompressedOops = true;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
helloJar = JarBuilder.build("hello", "Hello");
|
||||
|
||||
if (args.length > 0 && args[0].equals("false")) {
|
||||
useCompressedOops = false;
|
||||
}
|
||||
|
||||
// Check if we can use EpsilonGC during dump time, or run time, or both.
|
||||
test(false, true);
|
||||
test(true, false);
|
||||
@ -70,6 +95,8 @@ public class TestEpsilonGCWithCDS {
|
||||
String execGC = execWithEpsilon ? Epsilon : G1;
|
||||
String small1 = useSmallRegions ? "-Xmx256m" : "-showversion";
|
||||
String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : "-showversion";
|
||||
String errMsg = "Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops";
|
||||
String coops = useCompressedOops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops";
|
||||
OutputAnalyzer out;
|
||||
|
||||
System.out.println("0. Dump with " + dumpGC);
|
||||
@ -79,6 +106,7 @@ public class TestEpsilonGCWithCDS {
|
||||
dumpGC,
|
||||
small1,
|
||||
small2,
|
||||
coops,
|
||||
"-Xlog:cds");
|
||||
out.shouldContain("Dumping shared data to file:");
|
||||
out.shouldHaveExitValue(0);
|
||||
@ -89,9 +117,11 @@ public class TestEpsilonGCWithCDS {
|
||||
execGC,
|
||||
small1,
|
||||
small2,
|
||||
coops,
|
||||
"-Xlog:cds",
|
||||
"Hello");
|
||||
out.shouldContain(HELLO);
|
||||
out.shouldNotContain(errMsg);
|
||||
out.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
@ -37,16 +37,41 @@
|
||||
* @run driver TestParallelGCWithCDS
|
||||
*/
|
||||
|
||||
// Below is exactly the same as above, except:
|
||||
// - requires vm.bits == "64"
|
||||
// - extra argument "false"
|
||||
|
||||
/*
|
||||
* @test Loading CDS archived heap objects into ParallelGC
|
||||
* @bug 8274788 8341371
|
||||
* @requires vm.cds
|
||||
* @requires vm.gc.Parallel
|
||||
* @requires vm.gc.G1
|
||||
* @requires vm.bits == "64"
|
||||
*
|
||||
* @comment don't run this test if any -XX::+Use???GC options are specified, since they will
|
||||
* interfere with the test.
|
||||
* @requires vm.gc == null
|
||||
*
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||
* @compile test-classes/Hello.java
|
||||
* @run driver TestParallelGCWithCDS false
|
||||
*/
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class TestParallelGCWithCDS {
|
||||
public final static String HELLO = "Hello World";
|
||||
static String helloJar;
|
||||
static boolean useCompressedOops = true;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
helloJar = JarBuilder.build("hello", "Hello");
|
||||
|
||||
if (args.length > 0 && args[0].equals("false")) {
|
||||
useCompressedOops = false;
|
||||
}
|
||||
|
||||
// Check if we can use ParallelGC during dump time, or run time, or both.
|
||||
test(false, true);
|
||||
test(true, false);
|
||||
@ -69,6 +94,8 @@ public class TestParallelGCWithCDS {
|
||||
String execGC = execWithParallel ? Parallel : G1;
|
||||
String small1 = useSmallRegions ? "-Xmx256m" : "-showversion";
|
||||
String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : "-showversion";
|
||||
String errMsg = "Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops";
|
||||
String coops = useCompressedOops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops";
|
||||
OutputAnalyzer out;
|
||||
|
||||
System.out.println("0. Dump with " + dumpGC);
|
||||
@ -77,6 +104,7 @@ public class TestParallelGCWithCDS {
|
||||
dumpGC,
|
||||
small1,
|
||||
small2,
|
||||
coops,
|
||||
"-Xlog:cds");
|
||||
out.shouldContain("Dumping shared data to file:");
|
||||
out.shouldHaveExitValue(0);
|
||||
@ -86,9 +114,11 @@ public class TestParallelGCWithCDS {
|
||||
execGC,
|
||||
small1,
|
||||
small2,
|
||||
coops,
|
||||
"-Xlog:cds",
|
||||
"Hello");
|
||||
out.shouldContain(HELLO);
|
||||
out.shouldNotContain(errMsg);
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
int n = 2;
|
||||
@ -109,10 +139,12 @@ public class TestParallelGCWithCDS {
|
||||
small1,
|
||||
small2,
|
||||
xmx,
|
||||
coops,
|
||||
"-Xlog:cds",
|
||||
"Hello");
|
||||
if (out.getExitValue() == 0) {
|
||||
out.shouldContain(HELLO);
|
||||
out.shouldNotContain(errMsg);
|
||||
} else {
|
||||
String pattern = "((Too small maximum heap)" +
|
||||
"|(GC triggered before VM initialization completed)" +
|
||||
|
@ -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
|
||||
@ -98,6 +98,7 @@ public class TestSerialGCWithCDS {
|
||||
String execGC = execWithSerial ? Serial : G1;
|
||||
String small1 = useSmallRegions ? "-Xmx256m" : DUMMY;
|
||||
String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : DUMMY;
|
||||
String errMsg = "Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops";
|
||||
String coops;
|
||||
if (Platform.is64bit()) {
|
||||
coops = useCompressedOops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops";
|
||||
@ -125,7 +126,7 @@ public class TestSerialGCWithCDS {
|
||||
coops,
|
||||
"-Xlog:cds",
|
||||
"Hello");
|
||||
checkExecOutput(dumpWithSerial, execWithSerial, out);
|
||||
out.shouldNotContain(errMsg);
|
||||
|
||||
System.out.println("2. Exec with " + execGC + " and test ArchiveRelocationMode");
|
||||
out = TestCommon.exec(helloJar,
|
||||
@ -136,7 +137,7 @@ public class TestSerialGCWithCDS {
|
||||
"-Xlog:cds,cds+heap",
|
||||
"-XX:ArchiveRelocationMode=1", // always relocate shared metadata
|
||||
"Hello");
|
||||
checkExecOutput(dumpWithSerial, execWithSerial, out);
|
||||
out.shouldNotContain(errMsg);
|
||||
|
||||
int n = 2;
|
||||
if (dumpWithSerial == false && execWithSerial == true) {
|
||||
@ -160,7 +161,7 @@ public class TestSerialGCWithCDS {
|
||||
"-Xlog:cds",
|
||||
"Hello");
|
||||
if (out.getExitValue() == 0) {
|
||||
checkExecOutput(dumpWithSerial, execWithSerial, out);
|
||||
out.shouldNotContain(errMsg);
|
||||
} else {
|
||||
String output = out.getStdout() + out.getStderr();
|
||||
String exp1 = "Too small maximum heap";
|
||||
@ -173,19 +174,4 @@ public class TestSerialGCWithCDS {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void checkExecOutput(boolean dumpWithSerial, boolean execWithSerial, OutputAnalyzer out) {
|
||||
String errMsg = "Cannot use CDS heap data. UseG1GC is required for -XX:-UseCompressedOops";
|
||||
if (Platform.is64bit() &&
|
||||
!Platform.isWindows() && // archive heap not supported on Windows.
|
||||
!dumpWithSerial && // Dumped with G1, so we have an archived heap
|
||||
execWithSerial && // Running with serial
|
||||
!useCompressedOops) { // ArchiveHeapLoader::can_load() always returns false when COOP is disabled
|
||||
out.shouldContain(errMsg);
|
||||
}
|
||||
if (!execWithSerial) {
|
||||
// We should never see this message with G1
|
||||
out.shouldNotContain(errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,16 +35,38 @@
|
||||
* @run driver TestShenandoahWithCDS
|
||||
*/
|
||||
|
||||
// Below is exactly the same as above, except:
|
||||
// - requires vm.bits == "64"
|
||||
// - extra argument "false"
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8293650 8341371
|
||||
* @requires vm.cds
|
||||
* @requires vm.bits == 64
|
||||
* @requires vm.gc.Shenandoah
|
||||
* @requires vm.gc.G1
|
||||
* @requires vm.gc == null
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
|
||||
* @compile test-classes/Hello.java
|
||||
* @run driver TestShenandoahWithCDS false
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class TestShenandoahWithCDS {
|
||||
public final static String HELLO = "Hello World";
|
||||
static String helloJar;
|
||||
static boolean useCompressedOops = true;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
helloJar = JarBuilder.build("hello", "Hello");
|
||||
|
||||
if (args.length > 0 && args[0].equals("false")) {
|
||||
useCompressedOops = false;
|
||||
}
|
||||
|
||||
// Run with the variety of region sizes, and combinations
|
||||
// of G1/Shenandoah at dump/exec times. "-1" means to use G1.
|
||||
final int[] regionSizes = { -1, 256, 512, 1024, 2048 };
|
||||
@ -62,6 +84,8 @@ public class TestShenandoahWithCDS {
|
||||
String optExecGC = (execRegionSize != -1) ? "-XX:+UseShenandoahGC" : "-XX:+UseG1GC";
|
||||
String optDumpRegionSize = (dumpRegionSize != -1) ? "-XX:ShenandoahRegionSize=" + dumpRegionSize + "K" : exp;
|
||||
String optExecRegionSize = (execRegionSize != -1) ? "-XX:ShenandoahRegionSize=" + execRegionSize + "K" : exp;
|
||||
String errMsg = "Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops";
|
||||
String coops = useCompressedOops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops";
|
||||
OutputAnalyzer out;
|
||||
|
||||
System.out.println("0. Dump with " + optDumpGC + " and " + optDumpRegionSize);
|
||||
@ -71,6 +95,7 @@ public class TestShenandoahWithCDS {
|
||||
"-Xmx1g",
|
||||
optDumpGC,
|
||||
optDumpRegionSize,
|
||||
coops,
|
||||
"-Xlog:cds");
|
||||
out.shouldContain("Dumping shared data to file:");
|
||||
out.shouldHaveExitValue(0);
|
||||
@ -81,9 +106,11 @@ public class TestShenandoahWithCDS {
|
||||
"-Xmx1g",
|
||||
optExecGC,
|
||||
optExecRegionSize,
|
||||
coops,
|
||||
"-Xlog:cds",
|
||||
"Hello");
|
||||
out.shouldContain(HELLO);
|
||||
out.shouldNotContain(errMsg);
|
||||
out.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user