Skip to content

Commit 9f6211b

Browse files
author
Matias Saavedra Silva
committed
8341371: CDS cannot load archived heap objects with -XX:+UseSerialGC -XX:-UseCompressedOops
Reviewed-by: ccheung, iklam
1 parent 120a935 commit 9f6211b

File tree

12 files changed

+128
-42
lines changed

12 files changed

+128
-42
lines changed

src/hotspot/share/cds/archiveHeapLoader.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,22 @@ class PatchCompressedEmbeddedPointersQuick: public BitMapClosure {
142142

143143
class PatchUncompressedEmbeddedPointers: public BitMapClosure {
144144
oop* _start;
145+
intptr_t _delta;
145146

146147
public:
147-
PatchUncompressedEmbeddedPointers(oop* start) : _start(start) {}
148+
PatchUncompressedEmbeddedPointers(oop* start, intx runtime_offset) :
149+
_start(start),
150+
_delta(runtime_offset) {}
151+
152+
PatchUncompressedEmbeddedPointers(oop* start) :
153+
_start(start),
154+
_delta(ArchiveHeapLoader::mapped_heap_delta()) {}
148155

149156
bool do_bit(size_t offset) {
150157
oop* p = _start + offset;
151158
intptr_t dumptime_oop = (intptr_t)((void*)*p);
152159
assert(dumptime_oop != 0, "null oops should have been filtered out at dump time");
153-
intptr_t runtime_oop = dumptime_oop + ArchiveHeapLoader::mapped_heap_delta();
160+
intptr_t runtime_oop = dumptime_oop + _delta;
154161
RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(runtime_oop));
155162
return true;
156163
}
@@ -221,10 +228,6 @@ void ArchiveHeapLoader::init_loaded_heap_relocation(LoadedArchiveHeapRegion* loa
221228
}
222229

223230
bool ArchiveHeapLoader::can_load() {
224-
if (!UseCompressedOops) {
225-
// Pointer relocation for uncompressed oops is unimplemented.
226-
return false;
227-
}
228231
return Universe::heap()->can_load_archived_objects();
229232
}
230233

@@ -312,13 +315,18 @@ bool ArchiveHeapLoader::load_heap_region_impl(FileMapInfo* mapinfo, LoadedArchiv
312315
uintptr_t oopmap = bitmap_base + r->oopmap_offset();
313316
BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits());
314317

315-
PatchLoadedRegionPointers patcher((narrowOop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region);
316-
bm.iterate(&patcher);
318+
if (UseCompressedOops) {
319+
PatchLoadedRegionPointers patcher((narrowOop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region);
320+
bm.iterate(&patcher);
321+
} else {
322+
PatchUncompressedEmbeddedPointers patcher((oop*)load_address + FileMapInfo::current_info()->heap_oopmap_start_pos(), loaded_region->_runtime_offset);
323+
bm.iterate(&patcher);
324+
}
317325
return true;
318326
}
319327

320328
bool ArchiveHeapLoader::load_heap_region(FileMapInfo* mapinfo) {
321-
assert(UseCompressedOops, "loaded heap for !UseCompressedOops is unimplemented");
329+
assert(can_load(), "loaded heap for must be supported");
322330
init_narrow_oop_decoding(mapinfo->narrow_oop_base(), mapinfo->narrow_oop_shift());
323331

324332
LoadedArchiveHeapRegion loaded_region;
@@ -358,8 +366,12 @@ class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
358366
}
359367
}
360368
virtual void do_oop(oop* p) {
361-
// Uncompressed oops are not supported by loaded heaps.
362-
Unimplemented();
369+
oop v = *p;
370+
if(v != nullptr) {
371+
uintptr_t u = cast_from_oop<uintptr_t>(v);
372+
ArchiveHeapLoader::assert_in_loaded_heap(u);
373+
guarantee(_table->contains(u), "must point to beginning of object in loaded archived region");
374+
}
363375
}
364376
};
365377

src/hotspot/share/cds/archiveHeapLoader.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -146,6 +146,7 @@ class ArchiveHeapLoader : AllStatic {
146146
inline static oop decode_from_archive_impl(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
147147

148148
class PatchLoadedRegionPointers;
149+
class PatchUncompressedLoadedRegionPointers;
149150

150151
public:
151152

src/hotspot/share/cds/filemap.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,8 +2054,7 @@ void FileMapInfo::map_or_load_heap_region() {
20542054
success = ArchiveHeapLoader::load_heap_region(this);
20552055
} else {
20562056
if (!UseCompressedOops && !ArchiveHeapLoader::can_map()) {
2057-
// TODO - remove implicit knowledge of G1
2058-
log_info(cds)("Cannot use CDS heap data. UseG1GC is required for -XX:-UseCompressedOops");
2057+
log_info(cds)("Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops");
20592058
} else {
20602059
log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC, UseParallelGC, or UseShenandoahGC are required.");
20612060
}
@@ -2135,7 +2134,7 @@ address FileMapInfo::heap_region_requested_address() {
21352134
assert(CDSConfig::is_using_archive(), "runtime only");
21362135
FileMapRegion* r = region_at(MetaspaceShared::hp);
21372136
assert(is_aligned(r->mapping_offset(), sizeof(HeapWord)), "must be");
2138-
assert(ArchiveHeapLoader::can_map(), "cannot be used by ArchiveHeapLoader::can_load() mode");
2137+
assert(ArchiveHeapLoader::can_use(), "GC must support mapping or loading");
21392138
if (UseCompressedOops) {
21402139
// We can avoid relocation if each region's offset from the runtime CompressedOops::base()
21412140
// is the same as its offset from the CompressedOops::base() during dumptime.

src/hotspot/share/gc/epsilon/epsilonHeap.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2017, 2022, Red Hat, Inc. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -128,7 +128,7 @@ class EpsilonHeap : public CollectedHeap {
128128
bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); }
129129

130130
// Support for loading objects from CDS archive into the heap
131-
bool can_load_archived_objects() const override { return UseCompressedOops; }
131+
bool can_load_archived_objects() const override { return true; }
132132
HeapWord* allocate_loaded_archive_space(size_t size) override;
133133

134134
void print_on(outputStream* st) const override;

src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class ParallelScavengeHeap : public CollectedHeap {
246246
}
247247

248248
// Support for loading objects from CDS archive into the heap
249-
bool can_load_archived_objects() const override { return UseCompressedOops; }
249+
bool can_load_archived_objects() const override { return true; }
250250
HeapWord* allocate_loaded_archive_space(size_t size) override;
251251
void complete_loaded_archive_space(MemRegion archive_space) override;
252252

src/hotspot/share/gc/serial/serialHeap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class SerialHeap : public CollectedHeap {
291291
void safepoint_synchronize_end() override;
292292

293293
// Support for loading objects from CDS archive into the heap
294-
bool can_load_archived_objects() const override { return UseCompressedOops; }
294+
bool can_load_archived_objects() const override { return true; }
295295
HeapWord* allocate_loaded_archive_space(size_t size) override;
296296
void complete_loaded_archive_space(MemRegion archive_space) override;
297297

src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ class ShenandoahHeap : public CollectedHeap, public ShenandoahSpaceInfo {
543543

544544
// ---------- CDS archive support
545545

546-
bool can_load_archived_objects() const override { return UseCompressedOops; }
546+
bool can_load_archived_objects() const override { return true; }
547547
HeapWord* allocate_loaded_archive_space(size_t size) override;
548548
void complete_loaded_archive_space(MemRegion archive_space) override;
549549

src/hotspot/share/prims/whitebox.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,8 +2159,7 @@ WB_ENTRY(jboolean, WB_IsJVMCISupportedByGC(JNIEnv* env))
21592159
WB_END
21602160

21612161
WB_ENTRY(jboolean, WB_CanWriteJavaHeapArchive(JNIEnv* env))
2162-
return HeapShared::can_write()
2163-
&& ArchiveHeapLoader::can_use(); // work-around JDK-8341371
2162+
return HeapShared::can_write();
21642163
WB_END
21652164

21662165

test/hotspot/jtreg/runtime/cds/appcds/TestEpsilonGCWithCDS.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -37,16 +37,41 @@
3737
* @run driver TestEpsilonGCWithCDS
3838
*/
3939

40+
// Below is exactly the same as above, except:
41+
// - requires vm.bits == "64"
42+
// - extra argument "false"
43+
44+
/*
45+
* @test Loading CDS archived heap objects into EpsilonGC
46+
* @bug 8234679 8341371
47+
* @requires vm.cds
48+
* @requires vm.gc.Epsilon
49+
* @requires vm.gc.G1
50+
* @requires vm.bits == "64"
51+
*
52+
* @comment don't run this test if any -XX::+Use???GC options are specified, since they will
53+
* interfere with the test.
54+
* @requires vm.gc == null
55+
*
56+
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
57+
* @compile test-classes/Hello.java
58+
* @run driver TestEpsilonGCWithCDS false
59+
*/
4060
import jdk.test.lib.Platform;
4161
import jdk.test.lib.process.OutputAnalyzer;
4262

4363
public class TestEpsilonGCWithCDS {
4464
public final static String HELLO = "Hello World";
4565
static String helloJar;
66+
static boolean useCompressedOops = true;
4667

4768
public static void main(String... args) throws Exception {
4869
helloJar = JarBuilder.build("hello", "Hello");
4970

71+
if (args.length > 0 && args[0].equals("false")) {
72+
useCompressedOops = false;
73+
}
74+
5075
// Check if we can use EpsilonGC during dump time, or run time, or both.
5176
test(false, true);
5277
test(true, false);
@@ -70,6 +95,8 @@ static void test(boolean dumpWithEpsilon, boolean execWithEpsilon, boolean useSm
7095
String execGC = execWithEpsilon ? Epsilon : G1;
7196
String small1 = useSmallRegions ? "-Xmx256m" : "-showversion";
7297
String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : "-showversion";
98+
String errMsg = "Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops";
99+
String coops = useCompressedOops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops";
73100
OutputAnalyzer out;
74101

75102
System.out.println("0. Dump with " + dumpGC);
@@ -79,6 +106,7 @@ static void test(boolean dumpWithEpsilon, boolean execWithEpsilon, boolean useSm
79106
dumpGC,
80107
small1,
81108
small2,
109+
coops,
82110
"-Xlog:cds");
83111
out.shouldContain("Dumping shared data to file:");
84112
out.shouldHaveExitValue(0);
@@ -89,9 +117,11 @@ static void test(boolean dumpWithEpsilon, boolean execWithEpsilon, boolean useSm
89117
execGC,
90118
small1,
91119
small2,
120+
coops,
92121
"-Xlog:cds",
93122
"Hello");
94123
out.shouldContain(HELLO);
124+
out.shouldNotContain(errMsg);
95125
out.shouldHaveExitValue(0);
96126
}
97127
}

test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,41 @@
3737
* @run driver TestParallelGCWithCDS
3838
*/
3939

40+
// Below is exactly the same as above, except:
41+
// - requires vm.bits == "64"
42+
// - extra argument "false"
43+
44+
/*
45+
* @test Loading CDS archived heap objects into ParallelGC
46+
* @bug 8274788 8341371
47+
* @requires vm.cds
48+
* @requires vm.gc.Parallel
49+
* @requires vm.gc.G1
50+
* @requires vm.bits == "64"
51+
*
52+
* @comment don't run this test if any -XX::+Use???GC options are specified, since they will
53+
* interfere with the test.
54+
* @requires vm.gc == null
55+
*
56+
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
57+
* @compile test-classes/Hello.java
58+
* @run driver TestParallelGCWithCDS false
59+
*/
4060
import jdk.test.lib.Platform;
4161
import jdk.test.lib.process.OutputAnalyzer;
4262

4363
public class TestParallelGCWithCDS {
4464
public final static String HELLO = "Hello World";
4565
static String helloJar;
66+
static boolean useCompressedOops = true;
4667

4768
public static void main(String... args) throws Exception {
4869
helloJar = JarBuilder.build("hello", "Hello");
4970

71+
if (args.length > 0 && args[0].equals("false")) {
72+
useCompressedOops = false;
73+
}
74+
5075
// Check if we can use ParallelGC during dump time, or run time, or both.
5176
test(false, true);
5277
test(true, false);
@@ -69,6 +94,8 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use
6994
String execGC = execWithParallel ? Parallel : G1;
7095
String small1 = useSmallRegions ? "-Xmx256m" : "-showversion";
7196
String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : "-showversion";
97+
String errMsg = "Cannot use CDS heap data. Selected GC not compatible -XX:-UseCompressedOops";
98+
String coops = useCompressedOops ? "-XX:+UseCompressedOops" : "-XX:-UseCompressedOops";
7299
OutputAnalyzer out;
73100

74101
System.out.println("0. Dump with " + dumpGC);
@@ -77,6 +104,7 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use
77104
dumpGC,
78105
small1,
79106
small2,
107+
coops,
80108
"-Xlog:cds");
81109
out.shouldContain("Dumping shared data to file:");
82110
out.shouldHaveExitValue(0);
@@ -86,9 +114,11 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use
86114
execGC,
87115
small1,
88116
small2,
117+
coops,
89118
"-Xlog:cds",
90119
"Hello");
91120
out.shouldContain(HELLO);
121+
out.shouldNotContain(errMsg);
92122
out.shouldHaveExitValue(0);
93123

94124
int n = 2;
@@ -109,10 +139,12 @@ static void test(boolean dumpWithParallel, boolean execWithParallel, boolean use
109139
small1,
110140
small2,
111141
xmx,
142+
coops,
112143
"-Xlog:cds",
113144
"Hello");
114145
if (out.getExitValue() == 0) {
115146
out.shouldContain(HELLO);
147+
out.shouldNotContain(errMsg);
116148
} else {
117149
String pattern = "((Too small maximum heap)" +
118150
"|(GC triggered before VM initialization completed)" +

0 commit comments

Comments
 (0)