Skip to content

Commit e3a4c28

Browse files
committed
8362657: Make tables used in AOT assembly phase GC-safe
Reviewed-by: shade, dholmes
1 parent 6e4e966 commit e3a4c28

File tree

7 files changed

+86
-24
lines changed

7 files changed

+86
-24
lines changed

src/hotspot/share/cds/aotMetaspace.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ void VM_PopulateDumpSharedSpace::doit() {
720720
_map_info->set_cloned_vtables(CppVtables::vtables_serialized_base());
721721
_map_info->header()->set_class_location_config(cl_config);
722722

723+
HeapShared::delete_tables_with_raw_oops();
723724
CDSConfig::set_is_at_aot_safepoint(false);
724725
}
725726

src/hotspot/share/cds/archiveHeapWriter.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ void ArchiveHeapWriter::init() {
9595
}
9696
}
9797

98+
void ArchiveHeapWriter::delete_tables_with_raw_oops() {
99+
delete _source_objs;
100+
_source_objs = nullptr;
101+
}
102+
98103
void ArchiveHeapWriter::add_source_obj(oop src_obj) {
99104
_source_objs->append(src_obj);
100105
}
@@ -145,7 +150,7 @@ oop ArchiveHeapWriter::requested_obj_from_buffer_offset(size_t offset) {
145150

146151
oop ArchiveHeapWriter::source_obj_to_requested_obj(oop src_obj) {
147152
assert(CDSConfig::is_dumping_heap(), "dump-time only");
148-
HeapShared::CachedOopInfo* p = HeapShared::archived_object_cache()->get(src_obj);
153+
HeapShared::CachedOopInfo* p = HeapShared::get_cached_oop_info(src_obj);
149154
if (p != nullptr) {
150155
return requested_obj_from_buffer_offset(p->buffer_offset());
151156
} else {
@@ -154,9 +159,9 @@ oop ArchiveHeapWriter::source_obj_to_requested_obj(oop src_obj) {
154159
}
155160

156161
oop ArchiveHeapWriter::buffered_addr_to_source_obj(address buffered_addr) {
157-
oop* p = _buffer_offset_to_source_obj_table->get(buffered_address_to_offset(buffered_addr));
158-
if (p != nullptr) {
159-
return *p;
162+
OopHandle* oh = _buffer_offset_to_source_obj_table->get(buffered_address_to_offset(buffered_addr));
163+
if (oh != nullptr) {
164+
return oh->resolve();
160165
} else {
161166
return nullptr;
162167
}
@@ -356,12 +361,13 @@ void ArchiveHeapWriter::copy_source_objs_to_buffer(GrowableArrayCHeap<oop, mtCla
356361
for (int i = 0; i < _source_objs_order->length(); i++) {
357362
int src_obj_index = _source_objs_order->at(i)._index;
358363
oop src_obj = _source_objs->at(src_obj_index);
359-
HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(src_obj);
364+
HeapShared::CachedOopInfo* info = HeapShared::get_cached_oop_info(src_obj);
360365
assert(info != nullptr, "must be");
361366
size_t buffer_offset = copy_one_source_obj_to_buffer(src_obj);
362367
info->set_buffer_offset(buffer_offset);
363368

364-
_buffer_offset_to_source_obj_table->put_when_absent(buffer_offset, src_obj);
369+
OopHandle handle(Universe::vm_global(), src_obj);
370+
_buffer_offset_to_source_obj_table->put_when_absent(buffer_offset, handle);
365371
_buffer_offset_to_source_obj_table->maybe_grow();
366372

367373
if (java_lang_Module::is_instance(src_obj)) {
@@ -696,7 +702,7 @@ void ArchiveHeapWriter::relocate_embedded_oops(GrowableArrayCHeap<oop, mtClassSh
696702
for (int i = 0; i < _source_objs_order->length(); i++) {
697703
int src_obj_index = _source_objs_order->at(i)._index;
698704
oop src_obj = _source_objs->at(src_obj_index);
699-
HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(src_obj);
705+
HeapShared::CachedOopInfo* info = HeapShared::get_cached_oop_info(src_obj);
700706
assert(info != nullptr, "must be");
701707
oop requested_obj = requested_obj_from_buffer_offset(info->buffer_offset());
702708
update_header_for_requested_obj(requested_obj, src_obj, src_obj->klass());
@@ -758,7 +764,7 @@ void ArchiveHeapWriter::compute_ptrmap(ArchiveHeapInfo* heap_info) {
758764
NativePointerInfo info = _native_pointers->at(i);
759765
oop src_obj = info._src_obj;
760766
int field_offset = info._field_offset;
761-
HeapShared::CachedOopInfo* p = HeapShared::archived_object_cache()->get(src_obj);
767+
HeapShared::CachedOopInfo* p = HeapShared::get_cached_oop_info(src_obj);
762768
// requested_field_addr = the address of this field in the requested space
763769
oop requested_obj = requested_obj_from_buffer_offset(p->buffer_offset());
764770
Metadata** requested_field_addr = (Metadata**)(cast_from_oop<address>(requested_obj) + field_offset);

src/hotspot/share/cds/archiveHeapWriter.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class ArchiveHeapWriter : AllStatic {
152152
};
153153
static GrowableArrayCHeap<HeapObjOrder, mtClassShared>* _source_objs_order;
154154

155-
typedef ResizeableHashTable<size_t, oop,
155+
typedef ResizeableHashTable<size_t, OopHandle,
156156
AnyObj::C_HEAP,
157157
mtClassShared> BufferOffsetToSourceObjectTable;
158158
static BufferOffsetToSourceObjectTable* _buffer_offset_to_source_obj_table;
@@ -227,6 +227,7 @@ class ArchiveHeapWriter : AllStatic {
227227

228228
public:
229229
static void init() NOT_CDS_JAVA_HEAP_RETURN;
230+
static void delete_tables_with_raw_oops();
230231
static void add_source_obj(oop src_obj);
231232
static bool is_too_large_to_archive(size_t size);
232233
static bool is_too_large_to_archive(oop obj);

src/hotspot/share/cds/cdsHeapVerifier.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "oops/fieldStreams.inline.hpp"
3737
#include "oops/klass.inline.hpp"
3838
#include "oops/oop.inline.hpp"
39+
#include "oops/oopHandle.inline.hpp"
3940
#include "runtime/fieldDescriptor.inline.hpp"
4041

4142
#if INCLUDE_CDS_JAVA_HEAP
@@ -273,7 +274,8 @@ void CDSHeapVerifier::add_static_obj_field(InstanceKlass* ik, oop field, Symbol*
273274

274275
// This function is called once for every archived heap object. Warn if this object is referenced by
275276
// a static field of a class that's not aot-initialized.
276-
inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value) {
277+
inline bool CDSHeapVerifier::do_entry(OopHandle& orig_obj_handle, HeapShared::CachedOopInfo& value) {
278+
oop orig_obj = orig_obj_handle.resolve();
277279
_archived_objs++;
278280

279281
if (java_lang_String::is_instance(orig_obj) && HeapShared::is_dumped_interned_string(orig_obj)) {
@@ -323,7 +325,7 @@ class CDSHeapVerifier::TraceFields : public FieldClosure {
323325

324326
// Call this function (from gdb, etc) if you want to know why an object is archived.
325327
void CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj) {
326-
HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(orig_obj);
328+
HeapShared::CachedOopInfo* info = HeapShared::get_cached_oop_info(orig_obj);
327329
if (info != nullptr) {
328330
trace_to_root(st, orig_obj, nullptr, info);
329331
} else {
@@ -357,7 +359,7 @@ const char* static_field_name(oop mirror, oop field) {
357359
int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* info) {
358360
int level = 0;
359361
if (info->orig_referrer() != nullptr) {
360-
HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(info->orig_referrer());
362+
HeapShared::CachedOopInfo* ref = HeapShared::get_cached_oop_info(info->orig_referrer());
361363
assert(ref != nullptr, "sanity");
362364
level = trace_to_root(st, info->orig_referrer(), orig_obj, ref) + 1;
363365
} else if (java_lang_String::is_instance(orig_obj)) {

src/hotspot/share/cds/cdsHeapVerifier.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, 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
@@ -27,6 +27,7 @@
2727

2828
#include "cds/heapShared.hpp"
2929
#include "memory/iterator.hpp"
30+
#include "oops/oopHandle.hpp"
3031
#include "utilities/growableArray.hpp"
3132
#include "utilities/hashTable.hpp"
3233

@@ -80,7 +81,7 @@ class CDSHeapVerifier : public KlassClosure {
8081
virtual void do_klass(Klass* k);
8182

8283
// For HashTable::iterate()
83-
inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value);
84+
inline bool do_entry(OopHandle& orig_obj, HeapShared::CachedOopInfo& value);
8485

8586
static void verify();
8687

src/hotspot/share/cds/heapShared.cpp

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "oops/fieldStreams.inline.hpp"
5959
#include "oops/objArrayOop.inline.hpp"
6060
#include "oops/oop.inline.hpp"
61+
#include "oops/oopHandle.inline.hpp"
6162
#include "oops/typeArrayOop.inline.hpp"
6263
#include "prims/jvmtiExport.hpp"
6364
#include "runtime/arguments.hpp"
@@ -159,12 +160,35 @@ bool HeapShared::is_subgraph_root_class(InstanceKlass* ik) {
159160
is_subgraph_root_class_of(fmg_archive_subgraph_entry_fields, ik);
160161
}
161162

163+
oop HeapShared::CachedOopInfo::orig_referrer() const {
164+
return _orig_referrer.resolve();
165+
}
166+
162167
unsigned HeapShared::oop_hash(oop const& p) {
168+
assert(SafepointSynchronize::is_at_safepoint() ||
169+
JavaThread::current()->is_in_no_safepoint_scope(), "sanity");
163170
// Do not call p->identity_hash() as that will update the
164171
// object header.
165172
return primitive_hash(cast_from_oop<intptr_t>(p));
166173
}
167174

175+
unsigned int HeapShared::oop_handle_hash_raw(const OopHandle& oh) {
176+
return oop_hash(oh.resolve());
177+
}
178+
179+
unsigned int HeapShared::oop_handle_hash(const OopHandle& oh) {
180+
oop o = oh.resolve();
181+
if (o == nullptr) {
182+
return 0;
183+
} else {
184+
return o->identity_hash();
185+
}
186+
}
187+
188+
bool HeapShared::oop_handle_equals(const OopHandle& a, const OopHandle& b) {
189+
return a.resolve() == b.resolve();
190+
}
191+
168192
static void reset_states(oop obj, TRAPS) {
169193
Handle h_obj(THREAD, obj);
170194
InstanceKlass* klass = InstanceKlass::cast(obj->klass());
@@ -216,7 +240,8 @@ HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = nullptr;
216240

217241
bool HeapShared::has_been_archived(oop obj) {
218242
assert(CDSConfig::is_dumping_heap(), "dump-time only");
219-
return archived_object_cache()->get(obj) != nullptr;
243+
OopHandle oh(&obj);
244+
return archived_object_cache()->get(oh) != nullptr;
220245
}
221246

222247
int HeapShared::append_root(oop obj) {
@@ -303,7 +328,9 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra
303328
count_allocation(obj->size());
304329
ArchiveHeapWriter::add_source_obj(obj);
305330
CachedOopInfo info = make_cached_oop_info(obj, referrer);
306-
archived_object_cache()->put_when_absent(obj, info);
331+
332+
OopHandle oh(Universe::vm_global(), obj);
333+
archived_object_cache()->put_when_absent(oh, info);
307334
archived_object_cache()->maybe_grow();
308335
mark_native_pointers(obj);
309336

@@ -636,14 +663,16 @@ void HeapShared::mark_native_pointers(oop orig_obj) {
636663
}
637664

638665
void HeapShared::get_pointer_info(oop src_obj, bool& has_oop_pointers, bool& has_native_pointers) {
639-
CachedOopInfo* info = archived_object_cache()->get(src_obj);
666+
OopHandle oh(&src_obj);
667+
CachedOopInfo* info = archived_object_cache()->get(oh);
640668
assert(info != nullptr, "must be");
641669
has_oop_pointers = info->has_oop_pointers();
642670
has_native_pointers = info->has_native_pointers();
643671
}
644672

645673
void HeapShared::set_has_native_pointers(oop src_obj) {
646-
CachedOopInfo* info = archived_object_cache()->get(src_obj);
674+
OopHandle oh(&src_obj);
675+
CachedOopInfo* info = archived_object_cache()->get(oh);
647676
assert(info != nullptr, "must be");
648677
info->set_has_native_pointers();
649678
}
@@ -1453,7 +1482,7 @@ class PointsToOopsChecker : public BasicOopIterateClosure {
14531482
HeapShared::CachedOopInfo HeapShared::make_cached_oop_info(oop obj, oop referrer) {
14541483
PointsToOopsChecker points_to_oops_checker;
14551484
obj->oop_iterate(&points_to_oops_checker);
1456-
return CachedOopInfo(referrer, points_to_oops_checker.result());
1485+
return CachedOopInfo(OopHandle(Universe::vm_global(), referrer), points_to_oops_checker.result());
14571486
}
14581487

14591488
void HeapShared::init_box_classes(TRAPS) {
@@ -2096,6 +2125,18 @@ bool HeapShared::is_dumped_interned_string(oop o) {
20962125
return _dumped_interned_strings->get(o) != nullptr;
20972126
}
20982127

2128+
// These tables should be used only within the CDS safepoint, so
2129+
// delete them before we exit the safepoint. Otherwise the table will
2130+
// contain bad oops after a GC.
2131+
void HeapShared::delete_tables_with_raw_oops() {
2132+
assert(_seen_objects_table == nullptr, "should have been deleted");
2133+
2134+
delete _dumped_interned_strings;
2135+
_dumped_interned_strings = nullptr;
2136+
2137+
ArchiveHeapWriter::delete_tables_with_raw_oops();
2138+
}
2139+
20992140
void HeapShared::debug_trace() {
21002141
ResourceMark rm;
21012142
oop referrer = _object_being_archived.referrer();

src/hotspot/share/cds/heapShared.hpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ class HeapShared: AllStatic {
167167
public:
168168
static void debug_trace();
169169
static unsigned oop_hash(oop const& p);
170+
static unsigned oop_handle_hash(OopHandle const& oh);
171+
static unsigned oop_handle_hash_raw(OopHandle const& oh);
172+
static bool oop_handle_equals(const OopHandle& a, const OopHandle& b);
170173
static unsigned string_oop_hash(oop const& string) {
171174
return java_lang_String::hash_code(string);
172175
}
@@ -175,7 +178,7 @@ class HeapShared: AllStatic {
175178

176179
class CachedOopInfo {
177180
// Used by CDSHeapVerifier.
178-
oop _orig_referrer;
181+
OopHandle _orig_referrer;
179182

180183
// The location of this object inside ArchiveHeapWriter::_buffer
181184
size_t _buffer_offset;
@@ -186,12 +189,12 @@ class HeapShared: AllStatic {
186189
// One or more fields in this object are pointing to MetaspaceObj
187190
bool _has_native_pointers;
188191
public:
189-
CachedOopInfo(oop orig_referrer, bool has_oop_pointers)
192+
CachedOopInfo(OopHandle orig_referrer, bool has_oop_pointers)
190193
: _orig_referrer(orig_referrer),
191194
_buffer_offset(0),
192195
_has_oop_pointers(has_oop_pointers),
193196
_has_native_pointers(false) {}
194-
oop orig_referrer() const { return _orig_referrer; }
197+
oop orig_referrer() const;
195198
void set_buffer_offset(size_t offset) { _buffer_offset = offset; }
196199
size_t buffer_offset() const { return _buffer_offset; }
197200
bool has_oop_pointers() const { return _has_oop_pointers; }
@@ -202,10 +205,11 @@ class HeapShared: AllStatic {
202205
private:
203206
static const int INITIAL_TABLE_SIZE = 15889; // prime number
204207
static const int MAX_TABLE_SIZE = 1000000;
205-
typedef ResizeableHashTable<oop, CachedOopInfo,
208+
typedef ResizeableHashTable<OopHandle, CachedOopInfo,
206209
AnyObj::C_HEAP,
207210
mtClassShared,
208-
HeapShared::oop_hash> ArchivedObjectCache;
211+
HeapShared::oop_handle_hash_raw,
212+
HeapShared::oop_handle_equals> ArchivedObjectCache;
209213
static ArchivedObjectCache* _archived_object_cache;
210214

211215
class DumpTimeKlassSubGraphInfoTable
@@ -378,6 +382,11 @@ class HeapShared: AllStatic {
378382
return _archived_object_cache;
379383
}
380384

385+
static CachedOopInfo* get_cached_oop_info(oop orig_obj) {
386+
OopHandle oh(&orig_obj);
387+
return _archived_object_cache->get(oh);
388+
}
389+
381390
static int archive_exception_instance(oop exception);
382391

383392
static bool archive_reachable_objects_from(int level,
@@ -435,6 +444,7 @@ class HeapShared: AllStatic {
435444
CDS_JAVA_HEAP_ONLY(return (idx == AOTMetaspace::hp);)
436445
NOT_CDS_JAVA_HEAP_RETURN_(false);
437446
}
447+
static void delete_tables_with_raw_oops() NOT_CDS_JAVA_HEAP_RETURN;
438448

439449
static void resolve_classes(JavaThread* current) NOT_CDS_JAVA_HEAP_RETURN;
440450
static void initialize_from_archived_subgraph(JavaThread* current, Klass* k) NOT_CDS_JAVA_HEAP_RETURN;

0 commit comments

Comments
 (0)