mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8236604: Optimize SystemDictionary::resolve_well_known_classes for CDS
Serialize SystemDictionary::_well_known_classes into CDS and quickly resolve them at runtime in vm startup stage. Reviewed-by: iklam, coleenp
This commit is contained in:
parent
b247e6d908
commit
add146cc8b
7 changed files with 87 additions and 23 deletions
|
@ -1336,11 +1336,16 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
|
||||||
ik->restore_unshareable_info(loader_data, protection_domain, CHECK_NULL);
|
ik->restore_unshareable_info(loader_data, protection_domain, CHECK_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_shared_class_misc(ik, loader_data, CHECK_NULL);
|
||||||
|
return ik;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data, TRAPS) {
|
||||||
ik->print_class_load_logging(loader_data, NULL, NULL);
|
ik->print_class_load_logging(loader_data, NULL, NULL);
|
||||||
|
|
||||||
// For boot loader, ensure that GetSystemPackage knows that a class in this
|
// For boot loader, ensure that GetSystemPackage knows that a class in this
|
||||||
// package was loaded.
|
// package was loaded.
|
||||||
if (class_loader.is_null()) {
|
if (loader_data->is_the_null_class_loader_data()) {
|
||||||
int path_index = ik->shared_classpath_index();
|
int path_index = ik->shared_classpath_index();
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
|
ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
|
||||||
|
@ -1372,8 +1377,6 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ik;
|
|
||||||
}
|
}
|
||||||
#endif // INCLUDE_CDS
|
#endif // INCLUDE_CDS
|
||||||
|
|
||||||
|
@ -1785,7 +1788,9 @@ InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData*
|
||||||
|
|
||||||
void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
||||||
assert(k != NULL, "just checking");
|
assert(k != NULL, "just checking");
|
||||||
|
if (Universe::is_fully_initialized()) {
|
||||||
assert_locked_or_safepoint(Compile_lock);
|
assert_locked_or_safepoint(Compile_lock);
|
||||||
|
}
|
||||||
|
|
||||||
k->set_init_state(InstanceKlass::loaded);
|
k->set_init_state(InstanceKlass::loaded);
|
||||||
// make sure init_state store is already done.
|
// make sure init_state store is already done.
|
||||||
|
@ -1798,7 +1803,9 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k, TRAPS) {
|
||||||
|
|
||||||
// Now flush all code that depended on old class hierarchy.
|
// Now flush all code that depended on old class hierarchy.
|
||||||
// Note: must be done *after* linking k into the hierarchy (was bug 12/9/97)
|
// Note: must be done *after* linking k into the hierarchy (was bug 12/9/97)
|
||||||
|
if (Universe::is_fully_initialized()) {
|
||||||
CodeCache::flush_dependents_on(k);
|
CodeCache::flush_dependents_on(k);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -1911,13 +1918,53 @@ bool SystemDictionary::is_well_known_klass(Symbol* class_name) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void SystemDictionary::quick_resolve(InstanceKlass* klass, ClassLoaderData* loader_data, Handle domain, TRAPS) {
|
||||||
|
assert(!Universe::is_fully_initialized(), "We can make short cuts only during VM initialization");
|
||||||
|
assert(klass->is_shared(), "Must be shared class");
|
||||||
|
if (klass->class_loader_data() != NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add super and interfaces first
|
||||||
|
Klass* super = klass->super();
|
||||||
|
if (super != NULL && super->class_loader_data() == NULL) {
|
||||||
|
assert(super->is_instance_klass(), "Super should be instance klass");
|
||||||
|
quick_resolve(InstanceKlass::cast(super), loader_data, domain, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<InstanceKlass*>* ifs = klass->local_interfaces();
|
||||||
|
for (int i = 0; i < ifs->length(); i++) {
|
||||||
|
InstanceKlass* ik = ifs->at(i);
|
||||||
|
if (ik->class_loader_data() == NULL) {
|
||||||
|
quick_resolve(ik, loader_data, domain, CHECK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
klass->restore_unshareable_info(loader_data, domain, THREAD);
|
||||||
|
load_shared_class_misc(klass, loader_data, CHECK);
|
||||||
|
Dictionary* dictionary = loader_data->dictionary();
|
||||||
|
unsigned int hash = dictionary->compute_hash(klass->name());
|
||||||
|
dictionary->add_klass(hash, klass->name(), klass);
|
||||||
|
add_to_hierarchy(klass, CHECK);
|
||||||
|
assert(klass->is_loaded(), "Must be in at least loaded state");
|
||||||
|
}
|
||||||
|
|
||||||
bool SystemDictionary::resolve_wk_klass(WKID id, TRAPS) {
|
bool SystemDictionary::resolve_wk_klass(WKID id, TRAPS) {
|
||||||
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
|
||||||
int sid = wk_init_info[id - FIRST_WKID];
|
int sid = wk_init_info[id - FIRST_WKID];
|
||||||
Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
|
Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
|
||||||
InstanceKlass** klassp = &_well_known_klasses[id];
|
InstanceKlass** klassp = &_well_known_klasses[id];
|
||||||
|
|
||||||
if ((*klassp) == NULL) {
|
if (UseSharedSpaces && !JvmtiExport::should_post_class_prepare()) {
|
||||||
|
InstanceKlass* k = *klassp;
|
||||||
|
assert(k->is_shared_boot_class(), "must be");
|
||||||
|
|
||||||
|
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||||
|
quick_resolve(k, loader_data, Handle(), CHECK_false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_wk_klass_loaded(*klassp)) {
|
||||||
Klass* k = resolve_or_fail(symbol, true, CHECK_false);
|
Klass* k = resolve_or_fail(symbol, true, CHECK_false);
|
||||||
(*klassp) = InstanceKlass::cast(k);
|
(*klassp) = InstanceKlass::cast(k);
|
||||||
}
|
}
|
||||||
|
@ -1936,7 +1983,7 @@ void SystemDictionary::resolve_wk_klasses_until(WKID limit_id, WKID &start_id, T
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemDictionary::resolve_well_known_classes(TRAPS) {
|
void SystemDictionary::resolve_well_known_classes(TRAPS) {
|
||||||
assert(WK_KLASS(Object_klass) == NULL, "well-known classes should only be initialized once");
|
assert(!Object_klass_loaded(), "well-known classes should only be initialized once");
|
||||||
|
|
||||||
// Create the ModuleEntry for java.base. This call needs to be done here,
|
// Create the ModuleEntry for java.base. This call needs to be done here,
|
||||||
// after vmSymbols::initialize() is called but before any classes are pre-loaded.
|
// after vmSymbols::initialize() is called but before any classes are pre-loaded.
|
||||||
|
@ -1984,10 +2031,6 @@ void SystemDictionary::resolve_well_known_classes(TRAPS) {
|
||||||
java_lang_Class::compute_offsets();
|
java_lang_Class::compute_offsets();
|
||||||
|
|
||||||
// Fixup mirrors for classes loaded before java.lang.Class.
|
// Fixup mirrors for classes loaded before java.lang.Class.
|
||||||
// These calls iterate over the objects currently in the perm gen
|
|
||||||
// so calling them at this point is matters (not before when there
|
|
||||||
// are fewer objects and not later after there are more objects
|
|
||||||
// in the perm gen.
|
|
||||||
Universe::initialize_basic_type_mirrors(CHECK);
|
Universe::initialize_basic_type_mirrors(CHECK);
|
||||||
Universe::fixup_mirrors(CHECK);
|
Universe::fixup_mirrors(CHECK);
|
||||||
|
|
||||||
|
|
|
@ -387,13 +387,15 @@ public:
|
||||||
resolve_wk_klasses_until((WKID) limit, start_id, THREAD);
|
resolve_wk_klasses_until((WKID) limit, start_id, THREAD);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
#define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]
|
||||||
|
|
||||||
#define WK_KLASS_DECLARE(name, symbol) \
|
#define WK_KLASS_DECLARE(name, symbol) \
|
||||||
static InstanceKlass* name() { return check_klass(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
|
static InstanceKlass* name() { return check_klass(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
|
||||||
static InstanceKlass** name##_addr() { \
|
static InstanceKlass** name##_addr() { \
|
||||||
return &_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
|
return &_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
|
||||||
} \
|
} \
|
||||||
static bool name##_is_loaded() { \
|
static bool name##_is_loaded() { \
|
||||||
return _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] != NULL; \
|
return is_wk_klass_loaded(WK_KLASS(name)); \
|
||||||
}
|
}
|
||||||
WK_KLASSES_DO(WK_KLASS_DECLARE);
|
WK_KLASSES_DO(WK_KLASS_DECLARE);
|
||||||
#undef WK_KLASS_DECLARE
|
#undef WK_KLASS_DECLARE
|
||||||
|
@ -409,9 +411,6 @@ public:
|
||||||
}
|
}
|
||||||
static void well_known_klasses_do(MetaspaceClosure* it);
|
static void well_known_klasses_do(MetaspaceClosure* it);
|
||||||
|
|
||||||
// Local definition for direct access to the private array:
|
|
||||||
#define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]
|
|
||||||
|
|
||||||
static InstanceKlass* box_klass(BasicType t) {
|
static InstanceKlass* box_klass(BasicType t) {
|
||||||
assert((uint)t < T_VOID+1, "range check");
|
assert((uint)t < T_VOID+1, "range check");
|
||||||
return check_klass(_box_klasses[t]);
|
return check_klass(_box_klasses[t]);
|
||||||
|
@ -431,12 +430,16 @@ protected:
|
||||||
return ClassLoaderData::class_loader_data(class_loader());
|
return ClassLoaderData::class_loader_data(class_loader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_wk_klass_loaded(InstanceKlass* klass) {
|
||||||
|
return !(klass == NULL || !klass->is_loaded());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool Parameter_klass_loaded() { return WK_KLASS(reflect_Parameter_klass) != NULL; }
|
static bool Object_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(Object_klass)); }
|
||||||
static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; }
|
static bool Class_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(Class_klass)); }
|
||||||
static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; }
|
static bool Cloneable_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(Cloneable_klass)); }
|
||||||
static bool Object_klass_loaded() { return WK_KLASS(Object_klass) != NULL; }
|
static bool Parameter_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(reflect_Parameter_klass)); }
|
||||||
static bool ClassLoader_klass_loaded() { return WK_KLASS(ClassLoader_klass) != NULL; }
|
static bool ClassLoader_klass_loaded() { return is_wk_klass_loaded(WK_KLASS(ClassLoader_klass)); }
|
||||||
|
|
||||||
// Returns java system loader
|
// Returns java system loader
|
||||||
static oop java_system_loader();
|
static oop java_system_loader();
|
||||||
|
@ -596,6 +599,8 @@ protected:
|
||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
const ClassFileStream *cfs,
|
const ClassFileStream *cfs,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
// Second part of load_shared_class
|
||||||
|
static void load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data, TRAPS);
|
||||||
static InstanceKlass* load_shared_boot_class(Symbol* class_name,
|
static InstanceKlass* load_shared_boot_class(Symbol* class_name,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
|
static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
|
||||||
|
@ -628,6 +633,8 @@ protected:
|
||||||
|
|
||||||
// Resolve well-known classes so they can be used like SystemDictionary::String_klass()
|
// Resolve well-known classes so they can be used like SystemDictionary::String_klass()
|
||||||
static void resolve_well_known_classes(TRAPS);
|
static void resolve_well_known_classes(TRAPS);
|
||||||
|
// quick resolve using CDS for well-known classes only.
|
||||||
|
static void quick_resolve(InstanceKlass* klass, ClassLoaderData* loader_data, Handle domain, TRAPS);
|
||||||
|
|
||||||
// Class loader constraints
|
// Class loader constraints
|
||||||
static void check_constraints(unsigned int hash,
|
static void check_constraints(unsigned int hash,
|
||||||
|
|
|
@ -1410,6 +1410,12 @@ void SystemDictionaryShared::serialize_dictionary_headers(SerializeClosure* soc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemDictionaryShared::serialize_well_known_klasses(SerializeClosure* soc) {
|
||||||
|
for (int i = FIRST_WKID; i < WKID_LIMIT; i++) {
|
||||||
|
soc->do_ptr((void**)&_well_known_klasses[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const RunTimeSharedClassInfo*
|
const RunTimeSharedClassInfo*
|
||||||
SystemDictionaryShared::find_record(RunTimeSharedDictionary* static_dict, RunTimeSharedDictionary* dynamic_dict, Symbol* name) {
|
SystemDictionaryShared::find_record(RunTimeSharedDictionary* static_dict, RunTimeSharedDictionary* dynamic_dict, Symbol* name) {
|
||||||
if (!UseSharedSpaces || !name->is_shared()) {
|
if (!UseSharedSpaces || !name->is_shared()) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -303,6 +303,7 @@ public:
|
||||||
static void write_to_archive(bool is_static_archive = true);
|
static void write_to_archive(bool is_static_archive = true);
|
||||||
static void serialize_dictionary_headers(class SerializeClosure* soc,
|
static void serialize_dictionary_headers(class SerializeClosure* soc,
|
||||||
bool is_static_archive = true);
|
bool is_static_archive = true);
|
||||||
|
static void serialize_well_known_klasses(class SerializeClosure* soc);
|
||||||
static void print() { return print_on(tty); }
|
static void print() { return print_on(tty); }
|
||||||
static void print_on(outputStream* st) NOT_CDS_RETURN;
|
static void print_on(outputStream* st) NOT_CDS_RETURN;
|
||||||
static void print_table_statistics(outputStream* st) NOT_CDS_RETURN;
|
static void print_table_statistics(outputStream* st) NOT_CDS_RETURN;
|
||||||
|
|
|
@ -463,6 +463,9 @@ void MetaspaceShared::serialize(SerializeClosure* soc) {
|
||||||
SystemDictionaryShared::serialize_dictionary_headers(soc);
|
SystemDictionaryShared::serialize_dictionary_headers(soc);
|
||||||
|
|
||||||
InstanceMirrorKlass::serialize_offsets(soc);
|
InstanceMirrorKlass::serialize_offsets(soc);
|
||||||
|
|
||||||
|
// Dump/restore well known classes (pointers)
|
||||||
|
SystemDictionaryShared::serialize_well_known_klasses(soc);
|
||||||
soc->do_tag(--tag);
|
soc->do_tag(--tag);
|
||||||
|
|
||||||
serialize_cloned_cpp_vtptrs(soc);
|
serialize_cloned_cpp_vtptrs(soc);
|
||||||
|
|
|
@ -1153,7 +1153,9 @@ int InstanceKlass::nof_implementors() const {
|
||||||
//
|
//
|
||||||
// The _implementor field only exists for interfaces.
|
// The _implementor field only exists for interfaces.
|
||||||
void InstanceKlass::add_implementor(Klass* k) {
|
void InstanceKlass::add_implementor(Klass* k) {
|
||||||
|
if (Universe::is_fully_initialized()) {
|
||||||
assert_lock_strong(Compile_lock);
|
assert_lock_strong(Compile_lock);
|
||||||
|
}
|
||||||
assert(is_interface(), "not interface");
|
assert(is_interface(), "not interface");
|
||||||
// Filter out my subinterfaces.
|
// Filter out my subinterfaces.
|
||||||
// (Note: Interfaces are never on the subklass list.)
|
// (Note: Interfaces are never on the subklass list.)
|
||||||
|
|
|
@ -413,7 +413,9 @@ void Klass::set_next_sibling(Klass* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Klass::append_to_sibling_list() {
|
void Klass::append_to_sibling_list() {
|
||||||
|
if (Universe::is_fully_initialized()) {
|
||||||
assert_locked_or_safepoint(Compile_lock);
|
assert_locked_or_safepoint(Compile_lock);
|
||||||
|
}
|
||||||
debug_only(verify();)
|
debug_only(verify();)
|
||||||
// add ourselves to superklass' subklass list
|
// add ourselves to superklass' subklass list
|
||||||
InstanceKlass* super = superklass();
|
InstanceKlass* super = superklass();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue