Skip to content

Commit bd58553

Browse files
committed
8290833: Remove ConstantPoolCache::walk_entries_for_initialization()
Reviewed-by: coleenp, ccheung
1 parent 755ecf6 commit bd58553

9 files changed

+124
-85
lines changed

src/hotspot/share/cds/archiveBuilder.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ ArchiveBuilder::ArchiveBuilder() :
159159
_rw_src_objs(),
160160
_ro_src_objs(),
161161
_src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
162+
_dumped_to_src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
162163
_total_closed_heap_region_size(0),
163164
_total_open_heap_region_size(0),
164165
_estimated_metaspaceobj_bytes(0),
@@ -630,6 +631,14 @@ void ArchiveBuilder::make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* s
630631
newtop = dump_region->top();
631632

632633
memcpy(dest, src, bytes);
634+
{
635+
bool created;
636+
_dumped_to_src_obj_table.put_if_absent((address)dest, src, &created);
637+
assert(created, "must be");
638+
if (_dumped_to_src_obj_table.maybe_grow()) {
639+
log_info(cds, hashtables)("Expanded _dumped_to_src_obj_table table to %d", _dumped_to_src_obj_table.table_size());
640+
}
641+
}
633642

634643
intptr_t* archived_vtable = CppVtables::get_archived_vtable(ref->msotype(), (address)dest);
635644
if (archived_vtable != NULL) {
@@ -650,6 +659,13 @@ address ArchiveBuilder::get_dumped_addr(address src_obj) const {
650659
return p->dumped_addr();
651660
}
652661

662+
address ArchiveBuilder::get_src_obj(address dumped_addr) const {
663+
assert(is_in_buffer_space(dumped_addr), "must be");
664+
address* src_obj = _dumped_to_src_obj_table.get(dumped_addr);
665+
assert(src_obj != NULL && *src_obj != NULL, "must be");
666+
return *src_obj;
667+
}
668+
653669
void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) {
654670
for (int i = 0; i < src_objs->objs()->length(); i++) {
655671
src_objs->relocate(i, this);

src/hotspot/share/cds/archiveBuilder.hpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2022, 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
@@ -200,6 +200,7 @@ class ArchiveBuilder : public StackObj {
200200
SourceObjList _rw_src_objs; // objs to put in rw region
201201
SourceObjList _ro_src_objs; // objs to put in ro region
202202
ResizeableResourceHashtable<address, SourceObjInfo, ResourceObj::C_HEAP, mtClassShared> _src_obj_table;
203+
ResizeableResourceHashtable<address, address, ResourceObj::C_HEAP, mtClassShared> _dumped_to_src_obj_table;
203204
GrowableArray<Klass*>* _klasses;
204205
GrowableArray<Symbol*>* _symbols;
205206
GrowableArray<SpecialRefInfo>* _special_refs;
@@ -383,7 +384,17 @@ class ArchiveBuilder : public StackObj {
383384
void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region,
384385
bool read_only, bool allow_exec);
385386

387+
// + When creating a CDS archive, we first load Java classes and create metadata
388+
// objects as usual. These are call "source" objects.
389+
// + We then copy the source objects into the output buffer at "dumped addresses".
390+
//
391+
// The following functions translate between these two (non-overlapping) spaces.
392+
// (The API should be renamed to be less confusing!)
386393
address get_dumped_addr(address src_obj) const;
394+
address get_src_obj(address dumped_addr) const;
395+
template <typename T> T get_src_obj(T dumped_addr) const {
396+
return (T)get_src_obj((address)dumped_addr);
397+
}
387398

388399
// All klasses and symbols that will be copied into the archive
389400
GrowableArray<Klass*>* klasses() const { return _klasses; }

src/hotspot/share/classfile/systemDictionaryShared.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ DumpTimeSharedClassTable* SystemDictionaryShared::_dumptime_table = NULL;
8080
DumpTimeSharedClassTable* SystemDictionaryShared::_cloned_dumptime_table = NULL;
8181
DumpTimeLambdaProxyClassDictionary* SystemDictionaryShared::_dumptime_lambda_proxy_class_dictionary = NULL;
8282
DumpTimeLambdaProxyClassDictionary* SystemDictionaryShared::_cloned_dumptime_lambda_proxy_class_dictionary = NULL;
83+
SystemDictionaryShared::SavedCpCacheEntriesTable* SystemDictionaryShared::_saved_cpcache_entries_table = NULL;
8384

8485
// Used by NoClassLoadingMark
8586
DEBUG_ONLY(bool SystemDictionaryShared::_class_loading_may_happen = true;)
@@ -504,6 +505,7 @@ void SystemDictionaryShared::initialize() {
504505
_dumptime_table = new (ResourceObj::C_HEAP, mtClass) DumpTimeSharedClassTable;
505506
_dumptime_lambda_proxy_class_dictionary =
506507
new (ResourceObj::C_HEAP, mtClass) DumpTimeLambdaProxyClassDictionary;
508+
_saved_cpcache_entries_table = new (ResourceObj::C_HEAP, mtClass) SavedCpCacheEntriesTable;
507509
}
508510
}
509511

@@ -516,6 +518,11 @@ void SystemDictionaryShared::init_dumptime_info(InstanceKlass* k) {
516518
void SystemDictionaryShared::remove_dumptime_info(InstanceKlass* k) {
517519
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
518520
_dumptime_table->remove(k);
521+
522+
ConstantPoolCache* cpc = k->constants()->cache();
523+
if (cpc != NULL) {
524+
remove_saved_cpcache_entries_locked(cpc);
525+
}
519526
}
520527

521528
void SystemDictionaryShared::handle_class_unloading(InstanceKlass* klass) {
@@ -1329,6 +1336,36 @@ void SystemDictionaryShared::update_shared_entry(InstanceKlass* k, int id) {
13291336
info->_id = id;
13301337
}
13311338

1339+
void SystemDictionaryShared::set_saved_cpcache_entries(ConstantPoolCache* cpc, ConstantPoolCacheEntry* entries) {
1340+
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
1341+
bool is_new = _saved_cpcache_entries_table->put(cpc, entries);
1342+
assert(is_new, "saved entries must never changed");
1343+
}
1344+
1345+
ConstantPoolCacheEntry* SystemDictionaryShared::get_saved_cpcache_entries_locked(ConstantPoolCache* cpc) {
1346+
assert_lock_strong(DumpTimeTable_lock);
1347+
ConstantPoolCacheEntry** p = _saved_cpcache_entries_table->get(cpc);
1348+
if (p != nullptr) {
1349+
return *p;
1350+
} else {
1351+
return nullptr;
1352+
}
1353+
}
1354+
1355+
void SystemDictionaryShared::remove_saved_cpcache_entries(ConstantPoolCache* cpc) {
1356+
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
1357+
remove_saved_cpcache_entries_locked(cpc);
1358+
}
1359+
1360+
void SystemDictionaryShared::remove_saved_cpcache_entries_locked(ConstantPoolCache* cpc) {
1361+
assert_lock_strong(DumpTimeTable_lock);
1362+
ConstantPoolCacheEntry** p = _saved_cpcache_entries_table->get(cpc);
1363+
if (p != nullptr) {
1364+
_saved_cpcache_entries_table->remove(cpc);
1365+
FREE_C_HEAP_ARRAY(ConstantPoolCacheEntry, *p);
1366+
}
1367+
}
1368+
13321369
const char* class_loader_name_for_shared(Klass* k) {
13331370
assert(k != nullptr, "Sanity");
13341371
assert(k->is_shared(), "Must be");

src/hotspot/share/classfile/systemDictionaryShared.hpp

+17
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "classfile/systemDictionary.hpp"
3535
#include "oops/klass.hpp"
3636
#include "oops/oopHandle.hpp"
37+
#include "utilities/resourceHash.hpp"
3738

3839

3940
/*===============================================================================
@@ -108,6 +109,8 @@
108109

109110
class BootstrapInfo;
110111
class ClassFileStream;
112+
class ConstantPoolCache;
113+
class ConstantPoolCacheEntry;
111114
class Dictionary;
112115
class DumpTimeClassInfo;
113116
class DumpTimeSharedClassTable;
@@ -165,6 +168,15 @@ class SystemDictionaryShared: public SystemDictionary {
165168
static DumpTimeLambdaProxyClassDictionary* _dumptime_lambda_proxy_class_dictionary;
166169
static DumpTimeLambdaProxyClassDictionary* _cloned_dumptime_lambda_proxy_class_dictionary;
167170

171+
// Doesn't need to be cloned as it's not modified during dump time.
172+
using SavedCpCacheEntriesTable = ResourceHashtable<
173+
ConstantPoolCache*,
174+
ConstantPoolCacheEntry*,
175+
15889, // prime number
176+
ResourceObj::C_HEAP,
177+
mtClassShared>;
178+
static SavedCpCacheEntriesTable* _saved_cpcache_entries_table;
179+
168180
static ArchiveInfo _static_archive;
169181
static ArchiveInfo _dynamic_archive;
170182

@@ -236,6 +248,11 @@ class SystemDictionaryShared: public SystemDictionary {
236248
return ClassLoaderData::the_null_class_loader_data()->dictionary();
237249
}
238250

251+
static void set_saved_cpcache_entries(ConstantPoolCache* cpc, ConstantPoolCacheEntry* entries);
252+
static ConstantPoolCacheEntry* get_saved_cpcache_entries_locked(ConstantPoolCache* k);
253+
static void remove_saved_cpcache_entries(ConstantPoolCache* cpc);
254+
static void remove_saved_cpcache_entries_locked(ConstantPoolCache* cpc);
255+
239256
static void update_shared_entry(InstanceKlass* klass, int id);
240257
static void set_shared_class_misc_info(InstanceKlass* k, ClassFileStream* cfs);
241258

src/hotspot/share/interpreter/rewriter.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2022, 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
@@ -33,6 +33,7 @@
3333
#include "oops/constantPool.hpp"
3434
#include "oops/generateOopMap.hpp"
3535
#include "prims/methodHandles.hpp"
36+
#include "runtime/arguments.hpp"
3637
#include "runtime/fieldDescriptor.inline.hpp"
3738
#include "runtime/handles.inline.hpp"
3839

@@ -116,10 +117,16 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
116117
MetadataFactory::free_metadata(loader_data, cache);
117118
_pool->set_cache(NULL); // so the verifier isn't confused
118119
} else {
119-
DEBUG_ONLY(
120-
if (DumpSharedSpaces) {
121-
cache->verify_just_initialized();
122-
})
120+
if (Arguments::is_dumping_archive()) {
121+
if (_pool->pool_holder()->is_shared()) {
122+
assert(DynamicDumpSharedSpaces, "must be");
123+
// We are linking a shared class from the base archive. This
124+
// class won't be written into the dynamic archive, so there's no
125+
// need to save its CpCaches.
126+
} else {
127+
cache->save_for_archive();
128+
}
129+
}
123130
}
124131
}
125132

src/hotspot/share/oops/constantPool.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ void ConstantPool::remove_unshareable_info() {
423423
}
424424
}
425425
if (cache() != NULL) {
426+
// cache() is NULL if this class is not yet linked.
426427
cache()->remove_unshareable_info();
427428
}
428429
}

src/hotspot/share/oops/cpCache.cpp

+27-73
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "cds/heapShared.hpp"
2727
#include "classfile/resolutionErrors.hpp"
2828
#include "classfile/systemDictionary.hpp"
29+
#include "classfile/systemDictionaryShared.hpp"
2930
#include "classfile/vmClasses.hpp"
3031
#include "interpreter/bytecodeStream.hpp"
3132
#include "interpreter/bytecodes.hpp"
@@ -62,24 +63,6 @@ void ConstantPoolCacheEntry::initialize_entry(int index) {
6263
assert(constant_pool_index() == index, "");
6364
}
6465

65-
void ConstantPoolCacheEntry::verify_just_initialized(bool f2_used) {
66-
assert((_indices & (~cp_index_mask)) == 0, "sanity");
67-
assert(_f1 == NULL, "sanity");
68-
assert(_flags == 0, "sanity");
69-
if (!f2_used) {
70-
assert(_f2 == 0, "sanity");
71-
}
72-
}
73-
74-
void ConstantPoolCacheEntry::reinitialize(bool f2_used) {
75-
_indices &= cp_index_mask;
76-
_f1 = NULL;
77-
_flags = 0;
78-
if (!f2_used) {
79-
_f2 = 0;
80-
}
81-
}
82-
8366
int ConstantPoolCacheEntry::make_flags(TosState state,
8467
int option_bits,
8568
int field_index_or_method_params) {
@@ -700,66 +683,31 @@ void ConstantPoolCache::record_gc_epoch() {
700683
_gc_epoch = Continuations::gc_epoch();
701684
}
702685

703-
void ConstantPoolCache::verify_just_initialized() {
704-
DEBUG_ONLY(walk_entries_for_initialization(/*check_only = */ true));
705-
}
686+
void ConstantPoolCache::save_for_archive() {
687+
#if INCLUDE_CDS
688+
ConstantPoolCacheEntry* copy = NEW_C_HEAP_ARRAY(ConstantPoolCacheEntry, length(), mtClassShared);
689+
for (int i = 0; i < length(); i++) {
690+
copy[i] = *entry_at(i);
691+
}
706692

707-
void ConstantPoolCache::remove_unshareable_info() {
708-
walk_entries_for_initialization(/*check_only = */ false);
693+
SystemDictionaryShared::set_saved_cpcache_entries(this, copy);
694+
#endif
709695
}
710696

711-
void ConstantPoolCache::walk_entries_for_initialization(bool check_only) {
697+
void ConstantPoolCache::remove_unshareable_info() {
698+
#if INCLUDE_CDS
712699
Arguments::assert_is_dumping_archive();
713-
// When dumping the archive, we want to clean up the ConstantPoolCache
714-
// to remove any effect of linking due to the execution of Java code --
715-
// each ConstantPoolCacheEntry will have the same contents as if
716-
// ConstantPoolCache::initialize has just returned:
717-
//
718-
// - We keep the ConstantPoolCache::constant_pool_index() bits for all entries.
719-
// - We keep the "f2" field for entries used by invokedynamic and invokehandle
720-
// - All other bits in the entries are cleared to zero.
721-
ResourceMark rm;
722-
723-
InstanceKlass* ik = constant_pool()->pool_holder();
724-
bool* f2_used = NEW_RESOURCE_ARRAY(bool, length());
725-
memset(f2_used, 0, sizeof(bool) * length());
726-
727-
Thread* current = Thread::current();
728-
729-
// Find all the slots that we need to preserve f2
730-
for (int i = 0; i < ik->methods()->length(); i++) {
731-
Method* m = ik->methods()->at(i);
732-
RawBytecodeStream bcs(methodHandle(current, m));
733-
while (!bcs.is_last_bytecode()) {
734-
Bytecodes::Code opcode = bcs.raw_next();
735-
switch (opcode) {
736-
case Bytecodes::_invokedynamic: {
737-
int index = Bytes::get_native_u4(bcs.bcp() + 1);
738-
int cp_cache_index = constant_pool()->invokedynamic_cp_cache_index(index);
739-
f2_used[cp_cache_index] = 1;
740-
}
741-
break;
742-
case Bytecodes::_invokehandle: {
743-
int cp_cache_index = Bytes::get_native_u2(bcs.bcp() + 1);
744-
f2_used[cp_cache_index] = 1;
745-
}
746-
break;
747-
default:
748-
break;
749-
}
750-
}
751-
}
752-
753-
if (check_only) {
754-
DEBUG_ONLY(
755-
for (int i=0; i<length(); i++) {
756-
entry_at(i)->verify_just_initialized(f2_used[i]);
757-
})
758-
} else {
759-
for (int i=0; i<length(); i++) {
760-
entry_at(i)->reinitialize(f2_used[i]);
761-
}
700+
// <this> is the copy to be written into the archive. It's in
701+
// the ArchiveBuilder's "buffer space". However, the saved_cpcache_entries
702+
// are recorded with the original ConstantPoolCache object.
703+
ConstantPoolCache* orig_cpc = ArchiveBuilder::current()->get_src_obj(this);
704+
ConstantPoolCacheEntry* saved = SystemDictionaryShared::get_saved_cpcache_entries_locked(orig_cpc);
705+
for (int i=0; i<length(); i++) {
706+
// Restore each entry to the initial state -- just after Rewriter::make_constant_pool_cache()
707+
// has finished.
708+
*entry_at(i) = saved[i];
762709
}
710+
#endif
763711
}
764712

765713
void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
@@ -768,6 +716,12 @@ void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
768716
set_resolved_references(OopHandle());
769717
MetadataFactory::free_array<u2>(data, _reference_map);
770718
set_reference_map(NULL);
719+
720+
#if INCLUDE_CDS
721+
if (Arguments::is_dumping_archive()) {
722+
SystemDictionaryShared::remove_saved_cpcache_entries(this);
723+
}
724+
#endif
771725
}
772726

773727
#if INCLUDE_CDS_JAVA_HEAP

src/hotspot/share/oops/cpCache.hpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,6 @@ class ConstantPoolCacheEntry {
386386
// When shifting flags as a 32-bit int, make sure we don't need an extra mask for tos_state:
387387
assert((((u4)-1 >> tos_state_shift) & ~tos_state_mask) == 0, "no need for tos_state mask");
388388
}
389-
390-
void verify_just_initialized(bool f2_used);
391-
void reinitialize(bool f2_used);
392389
};
393390

394391

@@ -457,7 +454,7 @@ class ConstantPoolCache: public MetaspaceObj {
457454

458455
// CDS support
459456
void remove_unshareable_info();
460-
void verify_just_initialized();
457+
void save_for_archive();
461458
private:
462459
void walk_entries_for_initialization(bool check_only);
463460
void set_length(int length) { _length = length; }

src/hotspot/share/oops/instanceKlass.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ void InstanceKlass::deallocate_record_components(ClassLoaderData* loader_data,
576576
// This function deallocates the metadata and C heap pointers that the
577577
// InstanceKlass points to.
578578
void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
579+
SystemDictionaryShared::handle_class_unloading(this);
579580

580581
// Orphan the mirror first, CMS thinks it's still live.
581582
if (java_mirror() != NULL) {
@@ -691,8 +692,6 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
691692
MetadataFactory::free_metadata(loader_data, annotations());
692693
}
693694
set_annotations(NULL);
694-
695-
SystemDictionaryShared::handle_class_unloading(this);
696695
}
697696

698697
bool InstanceKlass::is_record() const {

0 commit comments

Comments
 (0)