src/share/vm/memory/metaspaceShared.cpp
Print this page
rev 9227 : [mq] cds
*** 21,30 ****
--- 21,32 ----
* questions.
*
*/
#include "precompiled.hpp"
+ #include "classfile/classListParser.hpp"
+ #include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/sharedClassUtil.hpp"
#include "classfile/symbolTable.hpp"
*** 40,49 ****
--- 42,52 ----
#include "oops/oop.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/signature.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
+ #include "utilities/defaultStream.hpp"
#include "utilities/hashtable.inline.hpp"
int MetaspaceShared::_max_alignment = 0;
ReservedSpace* MetaspaceShared::_shared_rs = NULL;
*** 95,104 ****
--- 98,111 ----
InstanceKlass* ik = InstanceKlass::cast(k);
ik->array_klasses_do(collect_classes);
}
}
+ static void collect_classes2(Klass* k, ClassLoaderData* class_data) {
+ collect_classes(k);
+ }
+
static void remove_unshareable_in_classes() {
for (int i = 0; i < _global_klass_objects->length(); i++) {
Klass* k = _global_klass_objects->at(i);
k->remove_unshareable_info();
}
*** 420,435 ****
GrowableArray<Klass*> *_class_promote_order;
VirtualSpace _md_vs;
VirtualSpace _mc_vs;
CompactHashtableWriter* _string_cht;
GrowableArray<MemRegion> *_string_regions;
public:
VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data,
GrowableArray<Klass*> *class_promote_order) :
_loader_data(loader_data) {
-
// Split up and initialize the misc code and data spaces
ReservedSpace* shared_rs = MetaspaceShared::shared_rs();
size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize;
ReservedSpace shared_ro_rw = shared_rs->first_part(metadata_size);
ReservedSpace misc_section = shared_rs->last_part(metadata_size);
--- 427,445 ----
GrowableArray<Klass*> *_class_promote_order;
VirtualSpace _md_vs;
VirtualSpace _mc_vs;
CompactHashtableWriter* _string_cht;
GrowableArray<MemRegion> *_string_regions;
+ char* _md_alloc_low;
+ char* _md_alloc_top;
+ char* _md_alloc_max;
+ static VM_PopulateDumpSharedSpace* _instance;
public:
VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data,
GrowableArray<Klass*> *class_promote_order) :
_loader_data(loader_data) {
// Split up and initialize the misc code and data spaces
ReservedSpace* shared_rs = MetaspaceShared::shared_rs();
size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize;
ReservedSpace shared_ro_rw = shared_rs->first_part(metadata_size);
ReservedSpace misc_section = shared_rs->last_part(metadata_size);
*** 438,460 ****
--- 448,503 ----
ReservedSpace md_rs = misc_section.first_part(SharedMiscDataSize);
ReservedSpace mc_rs = misc_section.last_part(SharedMiscDataSize);
_md_vs.initialize(md_rs, SharedMiscDataSize);
_mc_vs.initialize(mc_rs, SharedMiscCodeSize);
_class_promote_order = class_promote_order;
+
+ _md_alloc_low = _md_vs.low();
+ _md_alloc_top = _md_alloc_low + sizeof(char*);
+ _md_alloc_max = _md_vs.low() + SharedMiscDataSize;
+
+ assert(_instance == NULL, "must be singleton");
+ _instance = this;
+ }
+
+ ~VM_PopulateDumpSharedSpace() {
+ assert(_instance == this, "must be singleton");
+ _instance = NULL;
+ }
+
+ static VM_PopulateDumpSharedSpace* instance() {
+ assert(_instance != NULL, "sanity");
+ return _instance;
}
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
void doit(); // outline because gdb sucks
+ char* misc_data_space_alloc(size_t num_bytes) {
+ size_t alignment = sizeof(char*);
+ num_bytes = align_size_up(num_bytes, alignment);
+ _md_alloc_top = (char*)align_ptr_up(_md_alloc_top, alignment);
+ if (_md_alloc_top + num_bytes > _md_alloc_max) {
+ report_out_of_shared_space(SharedMiscData);
+ }
+
+ char* p = _md_alloc_top;
+ _md_alloc_top += num_bytes;
+
+ memset(p, 0, num_bytes);
+ return p;
+ }
+
private:
void handle_misc_data_space_failure(bool success) {
if (!success) {
report_out_of_shared_space(SharedMiscData);
}
}
}; // class VM_PopulateDumpSharedSpace
+ VM_PopulateDumpSharedSpace* VM_PopulateDumpSharedSpace::_instance;
void VM_PopulateDumpSharedSpace::doit() {
Thread* THREAD = VMThread::vm_thread();
NOT_PRODUCT(SystemDictionary::verify();)
// The following guarantee is meant to ensure that no loader constraints
*** 473,483 ****
// At this point, many classes have been loaded.
// Gather systemDictionary classes in a global array and do everything to
// that so we don't have to walk the SystemDictionary again.
_global_klass_objects = new GrowableArray<Klass*>(1000);
Universe::basic_type_classes_do(collect_classes);
! SystemDictionary::classes_do(collect_classes);
tty->print_cr("Number of classes %d", _global_klass_objects->length());
{
int num_type_array = 0, num_obj_array = 0, num_inst = 0;
for (int i = 0; i < _global_klass_objects->length(); i++) {
--- 516,530 ----
// At this point, many classes have been loaded.
// Gather systemDictionary classes in a global array and do everything to
// that so we don't have to walk the SystemDictionary again.
_global_klass_objects = new GrowableArray<Klass*>(1000);
Universe::basic_type_classes_do(collect_classes);
!
! // Need to call SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*))
! // as we may have some classes with NULL ClassLoaderData* in the dictionary. Other
! // variants of SystemDictionary::classes_do will skip those classes.
! SystemDictionary::classes_do(collect_classes2);
tty->print_cr("Number of classes %d", _global_klass_objects->length());
{
int num_type_array = 0, num_obj_array = 0, num_inst = 0;
for (int i = 0; i < _global_klass_objects->length(); i++) {
*** 513,522 ****
--- 560,573 ----
char* md_end = _md_vs.high();
char* mc_low = _mc_vs.low();
char* mc_top = mc_low;
char* mc_end = _mc_vs.high();
+ assert(_md_alloc_top != NULL, "sanity");
+ *(char**)_md_alloc_low = _md_alloc_top;
+ md_top = _md_alloc_top;
+
// Reserve space for the list of Klass*s whose vtables are used
// for patching others as needed.
void** vtbl_list = (void**)md_top;
int vtbl_list_size = MetaspaceShared::vtbl_list_size;
*** 733,742 ****
--- 784,794 ----
// Preload classes from a list, populate the shared spaces and dump to a
// file.
void MetaspaceShared::preload_and_dump(TRAPS) {
TraceTime timer("Dump Shared Spaces", TraceStartupTime);
ResourceMark rm;
+ char class_list_path_str[JVM_MAXPATHLEN];
tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
MetaspaceShared::shared_rs()->size(),
p2i(MetaspaceShared::shared_rs()->base()));
*** 745,755 ****
const char* class_list_path;
if (SharedClassListFile == NULL) {
// Construct the path to the class list (in jre/lib)
// Walk up two directories from the location of the VM and
// optionally tack on "lib" (depending on platform)
- char class_list_path_str[JVM_MAXPATHLEN];
os::jvm_path(class_list_path_str, sizeof(class_list_path_str));
for (int i = 0; i < 3; i++) {
char *end = strrchr(class_list_path_str, *os::file_separator());
if (end != NULL) *end = '\0';
}
--- 797,806 ----
*** 783,792 ****
--- 834,848 ----
// java.util.HashMap
static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
+ // Need to allocate the op here:
+ // op.misc_data_space_alloc() will be called during preload_and_dump().
+ ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+ VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
+
tty->print_cr("Loading classes to share ...");
_has_error_classes = false;
class_count += preload_and_dump(class_list_path, class_promote_order,
THREAD);
if (ExtraSharedClassListFile) {
*** 807,854 ****
// fails verification, all other interfaces that were not specified in the classlist but
// are implemented by K are not verified.
link_and_cleanup_shared_classes(CATCH);
tty->print_cr("Rewriting and linking classes: done");
- // Create and dump the shared spaces. Everything so far is loaded
- // with the null class loader.
- ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
- VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
VMThread::execute(&op);
-
// Since various initialization steps have been undone by this process,
// it is not reasonable to continue running a java process.
exit(0);
}
! int MetaspaceShared::preload_and_dump(const char * class_list_path,
GrowableArray<Klass*>* class_promote_order,
TRAPS) {
! FILE* file = fopen(class_list_path, "r");
! char class_name[256];
int class_count = 0;
! if (file != NULL) {
! while ((fgets(class_name, sizeof class_name, file)) != NULL) {
! if (*class_name == '#') { // comment
! continue;
! }
! // Remove trailing newline
! size_t name_len = strlen(class_name);
! if (class_name[name_len-1] == '\n') {
! class_name[name_len-1] = '\0';
! }
- // Got a class name - load it.
- TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
- guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
- Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol,
- THREAD);
CLEAR_PENDING_EXCEPTION;
if (klass != NULL) {
if (PrintSharedSpaces && Verbose && WizardMode) {
! tty->print_cr("Shared spaces preloaded: %s", class_name);
}
InstanceKlass* ik = InstanceKlass::cast(klass);
// Should be class load order as per -XX:+TraceClassLoadingPreorder
--- 863,893 ----
// fails verification, all other interfaces that were not specified in the classlist but
// are implemented by K are not verified.
link_and_cleanup_shared_classes(CATCH);
tty->print_cr("Rewriting and linking classes: done");
VMThread::execute(&op);
// Since various initialization steps have been undone by this process,
// it is not reasonable to continue running a java process.
exit(0);
}
!
! int MetaspaceShared::preload_and_dump(const char* class_list_path,
GrowableArray<Klass*>* class_promote_order,
TRAPS) {
! ClassListParser parser(class_list_path);
int class_count = 0;
! while (parser.parse_one_line()) {
! Klass* klass = ClassLoaderExt::load_one_class(&parser, THREAD);
CLEAR_PENDING_EXCEPTION;
if (klass != NULL) {
if (PrintSharedSpaces && Verbose && WizardMode) {
! ResourceMark rm;
! tty->print_cr("Shared spaces preloaded: %s", klass->external_name());
}
InstanceKlass* ik = InstanceKlass::cast(klass);
// Should be class load order as per -XX:+TraceClassLoadingPreorder
*** 860,880 ****
// cpCache) are located together.
try_link_class(ik, THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
class_count++;
- } else {
- //tty->print_cr("Preload failed: %s", class_name);
}
}
- fclose(file);
- } else {
- char errmsg[JVM_MAXPATHLEN];
- os::lasterror(errmsg, JVM_MAXPATHLEN);
- tty->print_cr("Loading classlist failed: %s", errmsg);
- exit(1);
- }
return class_count;
}
// Returns true if the class's status has changed
--- 899,910 ----
*** 906,915 ****
--- 936,950 ----
} else {
return false;
}
}
+ // Allocate misc data blocks during dumping.
+ char* MetaspaceShared::misc_data_space_alloc(size_t num_bytes) {
+ return VM_PopulateDumpSharedSpace::instance()->misc_data_space_alloc(num_bytes);
+ }
+
// Closure for serializing initialization data in from a data area
// (ptr_array) read from the shared file.
class ReadClosure : public SerializeClosure {
private:
*** 1031,1040 ****
--- 1066,1077 ----
void MetaspaceShared::initialize_shared_spaces() {
FileMapInfo *mapinfo = FileMapInfo::current_info();
char* buffer = mapinfo->header()->region_addr(md);
+ buffer = *((char**)buffer); // skip over the md_alloc'ed blocks
+
// Skip over (reserve space for) a list of addresses of C++ vtables
// for Klass objects. They get filled in later.
void** vtbl_list = (void**)buffer;
buffer += MetaspaceShared::vtbl_list_size * sizeof(void*);