8290833: Remove ConstantPoolCache::walk_entries_for_initialization()
Reviewed-by: coleenp, ccheung
This commit is contained in:
parent
755ecf6b73
commit
bd5855337c
@ -159,6 +159,7 @@ ArchiveBuilder::ArchiveBuilder() :
|
||||
_rw_src_objs(),
|
||||
_ro_src_objs(),
|
||||
_src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
|
||||
_dumped_to_src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
|
||||
_total_closed_heap_region_size(0),
|
||||
_total_open_heap_region_size(0),
|
||||
_estimated_metaspaceobj_bytes(0),
|
||||
@ -630,6 +631,14 @@ void ArchiveBuilder::make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* s
|
||||
newtop = dump_region->top();
|
||||
|
||||
memcpy(dest, src, bytes);
|
||||
{
|
||||
bool created;
|
||||
_dumped_to_src_obj_table.put_if_absent((address)dest, src, &created);
|
||||
assert(created, "must be");
|
||||
if (_dumped_to_src_obj_table.maybe_grow()) {
|
||||
log_info(cds, hashtables)("Expanded _dumped_to_src_obj_table table to %d", _dumped_to_src_obj_table.table_size());
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t* archived_vtable = CppVtables::get_archived_vtable(ref->msotype(), (address)dest);
|
||||
if (archived_vtable != NULL) {
|
||||
@ -650,6 +659,13 @@ address ArchiveBuilder::get_dumped_addr(address src_obj) const {
|
||||
return p->dumped_addr();
|
||||
}
|
||||
|
||||
address ArchiveBuilder::get_src_obj(address dumped_addr) const {
|
||||
assert(is_in_buffer_space(dumped_addr), "must be");
|
||||
address* src_obj = _dumped_to_src_obj_table.get(dumped_addr);
|
||||
assert(src_obj != NULL && *src_obj != NULL, "must be");
|
||||
return *src_obj;
|
||||
}
|
||||
|
||||
void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) {
|
||||
for (int i = 0; i < src_objs->objs()->length(); i++) {
|
||||
src_objs->relocate(i, this);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2022, 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
|
||||
@ -200,6 +200,7 @@ private:
|
||||
SourceObjList _rw_src_objs; // objs to put in rw region
|
||||
SourceObjList _ro_src_objs; // objs to put in ro region
|
||||
ResizeableResourceHashtable<address, SourceObjInfo, ResourceObj::C_HEAP, mtClassShared> _src_obj_table;
|
||||
ResizeableResourceHashtable<address, address, ResourceObj::C_HEAP, mtClassShared> _dumped_to_src_obj_table;
|
||||
GrowableArray<Klass*>* _klasses;
|
||||
GrowableArray<Symbol*>* _symbols;
|
||||
GrowableArray<SpecialRefInfo>* _special_refs;
|
||||
@ -383,7 +384,17 @@ public:
|
||||
void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region,
|
||||
bool read_only, bool allow_exec);
|
||||
|
||||
// + When creating a CDS archive, we first load Java classes and create metadata
|
||||
// objects as usual. These are call "source" objects.
|
||||
// + We then copy the source objects into the output buffer at "dumped addresses".
|
||||
//
|
||||
// The following functions translate between these two (non-overlapping) spaces.
|
||||
// (The API should be renamed to be less confusing!)
|
||||
address get_dumped_addr(address src_obj) const;
|
||||
address get_src_obj(address dumped_addr) const;
|
||||
template <typename T> T get_src_obj(T dumped_addr) const {
|
||||
return (T)get_src_obj((address)dumped_addr);
|
||||
}
|
||||
|
||||
// All klasses and symbols that will be copied into the archive
|
||||
GrowableArray<Klass*>* klasses() const { return _klasses; }
|
||||
|
@ -80,6 +80,7 @@ DumpTimeSharedClassTable* SystemDictionaryShared::_dumptime_table = NULL;
|
||||
DumpTimeSharedClassTable* SystemDictionaryShared::_cloned_dumptime_table = NULL;
|
||||
DumpTimeLambdaProxyClassDictionary* SystemDictionaryShared::_dumptime_lambda_proxy_class_dictionary = NULL;
|
||||
DumpTimeLambdaProxyClassDictionary* SystemDictionaryShared::_cloned_dumptime_lambda_proxy_class_dictionary = NULL;
|
||||
SystemDictionaryShared::SavedCpCacheEntriesTable* SystemDictionaryShared::_saved_cpcache_entries_table = NULL;
|
||||
|
||||
// Used by NoClassLoadingMark
|
||||
DEBUG_ONLY(bool SystemDictionaryShared::_class_loading_may_happen = true;)
|
||||
@ -504,6 +505,7 @@ void SystemDictionaryShared::initialize() {
|
||||
_dumptime_table = new (ResourceObj::C_HEAP, mtClass) DumpTimeSharedClassTable;
|
||||
_dumptime_lambda_proxy_class_dictionary =
|
||||
new (ResourceObj::C_HEAP, mtClass) DumpTimeLambdaProxyClassDictionary;
|
||||
_saved_cpcache_entries_table = new (ResourceObj::C_HEAP, mtClass) SavedCpCacheEntriesTable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,6 +518,11 @@ void SystemDictionaryShared::init_dumptime_info(InstanceKlass* k) {
|
||||
void SystemDictionaryShared::remove_dumptime_info(InstanceKlass* k) {
|
||||
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
|
||||
_dumptime_table->remove(k);
|
||||
|
||||
ConstantPoolCache* cpc = k->constants()->cache();
|
||||
if (cpc != NULL) {
|
||||
remove_saved_cpcache_entries_locked(cpc);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::handle_class_unloading(InstanceKlass* klass) {
|
||||
@ -1329,6 +1336,36 @@ void SystemDictionaryShared::update_shared_entry(InstanceKlass* k, int id) {
|
||||
info->_id = id;
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::set_saved_cpcache_entries(ConstantPoolCache* cpc, ConstantPoolCacheEntry* entries) {
|
||||
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
|
||||
bool is_new = _saved_cpcache_entries_table->put(cpc, entries);
|
||||
assert(is_new, "saved entries must never changed");
|
||||
}
|
||||
|
||||
ConstantPoolCacheEntry* SystemDictionaryShared::get_saved_cpcache_entries_locked(ConstantPoolCache* cpc) {
|
||||
assert_lock_strong(DumpTimeTable_lock);
|
||||
ConstantPoolCacheEntry** p = _saved_cpcache_entries_table->get(cpc);
|
||||
if (p != nullptr) {
|
||||
return *p;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::remove_saved_cpcache_entries(ConstantPoolCache* cpc) {
|
||||
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
|
||||
remove_saved_cpcache_entries_locked(cpc);
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::remove_saved_cpcache_entries_locked(ConstantPoolCache* cpc) {
|
||||
assert_lock_strong(DumpTimeTable_lock);
|
||||
ConstantPoolCacheEntry** p = _saved_cpcache_entries_table->get(cpc);
|
||||
if (p != nullptr) {
|
||||
_saved_cpcache_entries_table->remove(cpc);
|
||||
FREE_C_HEAP_ARRAY(ConstantPoolCacheEntry, *p);
|
||||
}
|
||||
}
|
||||
|
||||
const char* class_loader_name_for_shared(Klass* k) {
|
||||
assert(k != nullptr, "Sanity");
|
||||
assert(k->is_shared(), "Must be");
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "oops/klass.hpp"
|
||||
#include "oops/oopHandle.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
|
||||
/*===============================================================================
|
||||
@ -108,6 +109,8 @@
|
||||
|
||||
class BootstrapInfo;
|
||||
class ClassFileStream;
|
||||
class ConstantPoolCache;
|
||||
class ConstantPoolCacheEntry;
|
||||
class Dictionary;
|
||||
class DumpTimeClassInfo;
|
||||
class DumpTimeSharedClassTable;
|
||||
@ -165,6 +168,15 @@ private:
|
||||
static DumpTimeLambdaProxyClassDictionary* _dumptime_lambda_proxy_class_dictionary;
|
||||
static DumpTimeLambdaProxyClassDictionary* _cloned_dumptime_lambda_proxy_class_dictionary;
|
||||
|
||||
// Doesn't need to be cloned as it's not modified during dump time.
|
||||
using SavedCpCacheEntriesTable = ResourceHashtable<
|
||||
ConstantPoolCache*,
|
||||
ConstantPoolCacheEntry*,
|
||||
15889, // prime number
|
||||
ResourceObj::C_HEAP,
|
||||
mtClassShared>;
|
||||
static SavedCpCacheEntriesTable* _saved_cpcache_entries_table;
|
||||
|
||||
static ArchiveInfo _static_archive;
|
||||
static ArchiveInfo _dynamic_archive;
|
||||
|
||||
@ -236,6 +248,11 @@ public:
|
||||
return ClassLoaderData::the_null_class_loader_data()->dictionary();
|
||||
}
|
||||
|
||||
static void set_saved_cpcache_entries(ConstantPoolCache* cpc, ConstantPoolCacheEntry* entries);
|
||||
static ConstantPoolCacheEntry* get_saved_cpcache_entries_locked(ConstantPoolCache* k);
|
||||
static void remove_saved_cpcache_entries(ConstantPoolCache* cpc);
|
||||
static void remove_saved_cpcache_entries_locked(ConstantPoolCache* cpc);
|
||||
|
||||
static void update_shared_entry(InstanceKlass* klass, int id);
|
||||
static void set_shared_class_misc_info(InstanceKlass* k, ClassFileStream* cfs);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2022, 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
|
||||
@ -33,6 +33,7 @@
|
||||
#include "oops/constantPool.hpp"
|
||||
#include "oops/generateOopMap.hpp"
|
||||
#include "prims/methodHandles.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
|
||||
@ -116,10 +117,16 @@ void Rewriter::make_constant_pool_cache(TRAPS) {
|
||||
MetadataFactory::free_metadata(loader_data, cache);
|
||||
_pool->set_cache(NULL); // so the verifier isn't confused
|
||||
} else {
|
||||
DEBUG_ONLY(
|
||||
if (DumpSharedSpaces) {
|
||||
cache->verify_just_initialized();
|
||||
})
|
||||
if (Arguments::is_dumping_archive()) {
|
||||
if (_pool->pool_holder()->is_shared()) {
|
||||
assert(DynamicDumpSharedSpaces, "must be");
|
||||
// We are linking a shared class from the base archive. This
|
||||
// class won't be written into the dynamic archive, so there's no
|
||||
// need to save its CpCaches.
|
||||
} else {
|
||||
cache->save_for_archive();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,6 +423,7 @@ void ConstantPool::remove_unshareable_info() {
|
||||
}
|
||||
}
|
||||
if (cache() != NULL) {
|
||||
// cache() is NULL if this class is not yet linked.
|
||||
cache()->remove_unshareable_info();
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "cds/heapShared.hpp"
|
||||
#include "classfile/resolutionErrors.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#include "classfile/vmClasses.hpp"
|
||||
#include "interpreter/bytecodeStream.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
@ -62,24 +63,6 @@ void ConstantPoolCacheEntry::initialize_entry(int index) {
|
||||
assert(constant_pool_index() == index, "");
|
||||
}
|
||||
|
||||
void ConstantPoolCacheEntry::verify_just_initialized(bool f2_used) {
|
||||
assert((_indices & (~cp_index_mask)) == 0, "sanity");
|
||||
assert(_f1 == NULL, "sanity");
|
||||
assert(_flags == 0, "sanity");
|
||||
if (!f2_used) {
|
||||
assert(_f2 == 0, "sanity");
|
||||
}
|
||||
}
|
||||
|
||||
void ConstantPoolCacheEntry::reinitialize(bool f2_used) {
|
||||
_indices &= cp_index_mask;
|
||||
_f1 = NULL;
|
||||
_flags = 0;
|
||||
if (!f2_used) {
|
||||
_f2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ConstantPoolCacheEntry::make_flags(TosState state,
|
||||
int option_bits,
|
||||
int field_index_or_method_params) {
|
||||
@ -700,66 +683,31 @@ void ConstantPoolCache::record_gc_epoch() {
|
||||
_gc_epoch = Continuations::gc_epoch();
|
||||
}
|
||||
|
||||
void ConstantPoolCache::verify_just_initialized() {
|
||||
DEBUG_ONLY(walk_entries_for_initialization(/*check_only = */ true));
|
||||
void ConstantPoolCache::save_for_archive() {
|
||||
#if INCLUDE_CDS
|
||||
ConstantPoolCacheEntry* copy = NEW_C_HEAP_ARRAY(ConstantPoolCacheEntry, length(), mtClassShared);
|
||||
for (int i = 0; i < length(); i++) {
|
||||
copy[i] = *entry_at(i);
|
||||
}
|
||||
|
||||
SystemDictionaryShared::set_saved_cpcache_entries(this, copy);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConstantPoolCache::remove_unshareable_info() {
|
||||
walk_entries_for_initialization(/*check_only = */ false);
|
||||
}
|
||||
|
||||
void ConstantPoolCache::walk_entries_for_initialization(bool check_only) {
|
||||
#if INCLUDE_CDS
|
||||
Arguments::assert_is_dumping_archive();
|
||||
// When dumping the archive, we want to clean up the ConstantPoolCache
|
||||
// to remove any effect of linking due to the execution of Java code --
|
||||
// each ConstantPoolCacheEntry will have the same contents as if
|
||||
// ConstantPoolCache::initialize has just returned:
|
||||
//
|
||||
// - We keep the ConstantPoolCache::constant_pool_index() bits for all entries.
|
||||
// - We keep the "f2" field for entries used by invokedynamic and invokehandle
|
||||
// - All other bits in the entries are cleared to zero.
|
||||
ResourceMark rm;
|
||||
|
||||
InstanceKlass* ik = constant_pool()->pool_holder();
|
||||
bool* f2_used = NEW_RESOURCE_ARRAY(bool, length());
|
||||
memset(f2_used, 0, sizeof(bool) * length());
|
||||
|
||||
Thread* current = Thread::current();
|
||||
|
||||
// Find all the slots that we need to preserve f2
|
||||
for (int i = 0; i < ik->methods()->length(); i++) {
|
||||
Method* m = ik->methods()->at(i);
|
||||
RawBytecodeStream bcs(methodHandle(current, m));
|
||||
while (!bcs.is_last_bytecode()) {
|
||||
Bytecodes::Code opcode = bcs.raw_next();
|
||||
switch (opcode) {
|
||||
case Bytecodes::_invokedynamic: {
|
||||
int index = Bytes::get_native_u4(bcs.bcp() + 1);
|
||||
int cp_cache_index = constant_pool()->invokedynamic_cp_cache_index(index);
|
||||
f2_used[cp_cache_index] = 1;
|
||||
}
|
||||
break;
|
||||
case Bytecodes::_invokehandle: {
|
||||
int cp_cache_index = Bytes::get_native_u2(bcs.bcp() + 1);
|
||||
f2_used[cp_cache_index] = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (check_only) {
|
||||
DEBUG_ONLY(
|
||||
for (int i=0; i<length(); i++) {
|
||||
entry_at(i)->verify_just_initialized(f2_used[i]);
|
||||
})
|
||||
} else {
|
||||
for (int i=0; i<length(); i++) {
|
||||
entry_at(i)->reinitialize(f2_used[i]);
|
||||
}
|
||||
// <this> is the copy to be written into the archive. It's in
|
||||
// the ArchiveBuilder's "buffer space". However, the saved_cpcache_entries
|
||||
// are recorded with the original ConstantPoolCache object.
|
||||
ConstantPoolCache* orig_cpc = ArchiveBuilder::current()->get_src_obj(this);
|
||||
ConstantPoolCacheEntry* saved = SystemDictionaryShared::get_saved_cpcache_entries_locked(orig_cpc);
|
||||
for (int i=0; i<length(); i++) {
|
||||
// Restore each entry to the initial state -- just after Rewriter::make_constant_pool_cache()
|
||||
// has finished.
|
||||
*entry_at(i) = saved[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
|
||||
@ -768,6 +716,12 @@ void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
|
||||
set_resolved_references(OopHandle());
|
||||
MetadataFactory::free_array<u2>(data, _reference_map);
|
||||
set_reference_map(NULL);
|
||||
|
||||
#if INCLUDE_CDS
|
||||
if (Arguments::is_dumping_archive()) {
|
||||
SystemDictionaryShared::remove_saved_cpcache_entries(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
|
@ -386,9 +386,6 @@ class ConstantPoolCacheEntry {
|
||||
// When shifting flags as a 32-bit int, make sure we don't need an extra mask for tos_state:
|
||||
assert((((u4)-1 >> tos_state_shift) & ~tos_state_mask) == 0, "no need for tos_state mask");
|
||||
}
|
||||
|
||||
void verify_just_initialized(bool f2_used);
|
||||
void reinitialize(bool f2_used);
|
||||
};
|
||||
|
||||
|
||||
@ -457,7 +454,7 @@ class ConstantPoolCache: public MetaspaceObj {
|
||||
|
||||
// CDS support
|
||||
void remove_unshareable_info();
|
||||
void verify_just_initialized();
|
||||
void save_for_archive();
|
||||
private:
|
||||
void walk_entries_for_initialization(bool check_only);
|
||||
void set_length(int length) { _length = length; }
|
||||
|
@ -576,6 +576,7 @@ void InstanceKlass::deallocate_record_components(ClassLoaderData* loader_data,
|
||||
// This function deallocates the metadata and C heap pointers that the
|
||||
// InstanceKlass points to.
|
||||
void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
SystemDictionaryShared::handle_class_unloading(this);
|
||||
|
||||
// Orphan the mirror first, CMS thinks it's still live.
|
||||
if (java_mirror() != NULL) {
|
||||
@ -691,8 +692,6 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
MetadataFactory::free_metadata(loader_data, annotations());
|
||||
}
|
||||
set_annotations(NULL);
|
||||
|
||||
SystemDictionaryShared::handle_class_unloading(this);
|
||||
}
|
||||
|
||||
bool InstanceKlass::is_record() const {
|
||||
|
Loading…
x
Reference in New Issue
Block a user