Mercurial > hg > truffle
diff src/share/vm/memory/universe.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | d2a62e0f25eb |
children | aed758eda82a |
line wrap: on
line diff
--- a/src/share/vm/memory/universe.cpp Fri Aug 31 16:39:35 2012 -0700 +++ b/src/share/vm/memory/universe.cpp Sat Sep 01 13:25:18 2012 -0400 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" @@ -33,35 +34,23 @@ #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/cardTableModRefBS.hpp" -#include "memory/filemap.hpp" #include "memory/gcLocker.inline.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/genRemSet.hpp" #include "memory/generation.hpp" +#include "memory/metadataFactory.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" -#include "memory/permGen.hpp" #include "memory/space.hpp" #include "memory/universe.hpp" #include "memory/universe.inline.hpp" -#include "oops/arrayKlassKlass.hpp" -#include "oops/compiledICHolderKlass.hpp" -#include "oops/constMethodKlass.hpp" -#include "oops/constantPoolKlass.hpp" -#include "oops/constantPoolOop.hpp" -#include "oops/cpCacheKlass.hpp" -#include "oops/cpCacheOop.hpp" +#include "oops/constantPool.hpp" +#include "oops/instanceClassLoaderKlass.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" -#include "oops/instanceKlassKlass.hpp" #include "oops/instanceRefKlass.hpp" -#include "oops/klassKlass.hpp" -#include "oops/klassOop.hpp" -#include "oops/methodDataKlass.hpp" -#include "oops/methodKlass.hpp" -#include "oops/objArrayKlassKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayKlass.hpp" -#include "oops/typeArrayKlassKlass.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/aprofiler.hpp" #include "runtime/arguments.hpp" @@ -101,28 +90,16 @@ #endif // Known objects -klassOop Universe::_boolArrayKlassObj = NULL; -klassOop Universe::_byteArrayKlassObj = NULL; -klassOop Universe::_charArrayKlassObj = NULL; -klassOop Universe::_intArrayKlassObj = NULL; -klassOop Universe::_shortArrayKlassObj = NULL; -klassOop Universe::_longArrayKlassObj = NULL; -klassOop Universe::_singleArrayKlassObj = NULL; -klassOop Universe::_doubleArrayKlassObj = NULL; -klassOop Universe::_typeArrayKlassObjs[T_VOID+1] = { NULL /*, NULL...*/ }; -klassOop Universe::_objectArrayKlassObj = NULL; -klassOop Universe::_methodKlassObj = NULL; -klassOop Universe::_constMethodKlassObj = NULL; -klassOop Universe::_methodDataKlassObj = NULL; -klassOop Universe::_klassKlassObj = NULL; -klassOop Universe::_arrayKlassKlassObj = NULL; -klassOop Universe::_objArrayKlassKlassObj = NULL; -klassOop Universe::_typeArrayKlassKlassObj = NULL; -klassOop Universe::_instanceKlassKlassObj = NULL; -klassOop Universe::_constantPoolKlassObj = NULL; -klassOop Universe::_constantPoolCacheKlassObj = NULL; -klassOop Universe::_compiledICHolderKlassObj = NULL; -klassOop Universe::_systemObjArrayKlassObj = NULL; +Klass* Universe::_boolArrayKlassObj = NULL; +Klass* Universe::_byteArrayKlassObj = NULL; +Klass* Universe::_charArrayKlassObj = NULL; +Klass* Universe::_intArrayKlassObj = NULL; +Klass* Universe::_shortArrayKlassObj = NULL; +Klass* Universe::_longArrayKlassObj = NULL; +Klass* Universe::_singleArrayKlassObj = NULL; +Klass* Universe::_doubleArrayKlassObj = NULL; +Klass* Universe::_typeArrayKlassObjs[T_VOID+1] = { NULL /*, NULL...*/ }; +Klass* Universe::_objectArrayKlassObj = NULL; oop Universe::_int_mirror = NULL; oop Universe::_float_mirror = NULL; oop Universe::_double_mirror = NULL; @@ -135,16 +112,11 @@ oop Universe::_mirrors[T_VOID+1] = { NULL /*, NULL...*/ }; oop Universe::_main_thread_group = NULL; oop Universe::_system_thread_group = NULL; -typeArrayOop Universe::_the_empty_byte_array = NULL; -typeArrayOop Universe::_the_empty_short_array = NULL; -typeArrayOop Universe::_the_empty_int_array = NULL; -objArrayOop Universe::_the_empty_system_obj_array = NULL; objArrayOop Universe::_the_empty_class_klass_array = NULL; -objArrayOop Universe::_the_array_interfaces_array = NULL; +Array<Klass*>* Universe::_the_array_interfaces_array = NULL; oop Universe::_the_null_string = NULL; oop Universe::_the_min_jint_string = NULL; LatestMethodOopCache* Universe::_finalizer_register_cache = NULL; -LatestMethodOopCache* Universe::_loader_addClass_cache = NULL; ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL; oop Universe::_out_of_memory_error_java_heap = NULL; oop Universe::_out_of_memory_error_perm_gen = NULL; @@ -157,12 +129,15 @@ oop Universe::_arithmetic_exception_instance = NULL; oop Universe::_virtual_machine_error_instance = NULL; oop Universe::_vm_exception = NULL; +Array<int>* Universe::_the_empty_int_array = NULL; +Array<u2>* Universe::_the_empty_short_array = NULL; +Array<Klass*>* Universe::_the_empty_klass_array = NULL; +Array<Method*>* Universe::_the_empty_method_array = NULL; // These variables are guarded by FullGCALot_lock. debug_only(objArrayOop Universe::_fullgc_alot_dummy_array = NULL;) debug_only(int Universe::_fullgc_alot_dummy_next = 0;) - // Heap int Universe::_verify_count = 0; @@ -178,7 +153,7 @@ NarrowOopStruct Universe::_narrow_oop = { NULL, 0, true }; -void Universe::basic_type_classes_do(void f(klassOop)) { +void Universe::basic_type_classes_do(void f(Klass*)) { f(boolArrayKlassObj()); f(byteArrayKlassObj()); f(charArrayKlassObj()); @@ -189,20 +164,6 @@ f(doubleArrayKlassObj()); } - -void Universe::system_classes_do(void f(klassOop)) { - f(methodKlassObj()); - f(constMethodKlassObj()); - f(methodDataKlassObj()); - f(klassKlassObj()); - f(arrayKlassKlassObj()); - f(objArrayKlassKlassObj()); - f(typeArrayKlassKlassObj()); - f(instanceKlassKlassObj()); - f(constantPoolKlassObj()); - f(systemObjArrayKlassObj()); -} - void Universe::oops_do(OopClosure* f, bool do_all) { f->do_oop((oop*) &_int_mirror); @@ -215,63 +176,19 @@ f->do_oop((oop*) &_short_mirror); f->do_oop((oop*) &_void_mirror); - // It's important to iterate over these guys even if they are null, - // since that's how shared heaps are restored. for (int i = T_BOOLEAN; i < T_VOID+1; i++) { f->do_oop((oop*) &_mirrors[i]); } assert(_mirrors[0] == NULL && _mirrors[T_BOOLEAN - 1] == NULL, "checking"); - // %%% Consider moving those "shared oops" over here with the others. - f->do_oop((oop*)&_boolArrayKlassObj); - f->do_oop((oop*)&_byteArrayKlassObj); - f->do_oop((oop*)&_charArrayKlassObj); - f->do_oop((oop*)&_intArrayKlassObj); - f->do_oop((oop*)&_shortArrayKlassObj); - f->do_oop((oop*)&_longArrayKlassObj); - f->do_oop((oop*)&_singleArrayKlassObj); - f->do_oop((oop*)&_doubleArrayKlassObj); - f->do_oop((oop*)&_objectArrayKlassObj); - { - for (int i = 0; i < T_VOID+1; i++) { - if (_typeArrayKlassObjs[i] != NULL) { - assert(i >= T_BOOLEAN, "checking"); - f->do_oop((oop*)&_typeArrayKlassObjs[i]); - } else if (do_all) { - f->do_oop((oop*)&_typeArrayKlassObjs[i]); - } - } - } - f->do_oop((oop*)&_methodKlassObj); - f->do_oop((oop*)&_constMethodKlassObj); - f->do_oop((oop*)&_methodDataKlassObj); - f->do_oop((oop*)&_klassKlassObj); - f->do_oop((oop*)&_arrayKlassKlassObj); - f->do_oop((oop*)&_objArrayKlassKlassObj); - f->do_oop((oop*)&_typeArrayKlassKlassObj); - f->do_oop((oop*)&_instanceKlassKlassObj); - f->do_oop((oop*)&_constantPoolKlassObj); - f->do_oop((oop*)&_constantPoolCacheKlassObj); - f->do_oop((oop*)&_compiledICHolderKlassObj); - f->do_oop((oop*)&_systemObjArrayKlassObj); - f->do_oop((oop*)&_the_empty_byte_array); - f->do_oop((oop*)&_the_empty_short_array); - f->do_oop((oop*)&_the_empty_int_array); - f->do_oop((oop*)&_the_empty_system_obj_array); f->do_oop((oop*)&_the_empty_class_klass_array); - f->do_oop((oop*)&_the_array_interfaces_array); f->do_oop((oop*)&_the_null_string); f->do_oop((oop*)&_the_min_jint_string); - _finalizer_register_cache->oops_do(f); - _loader_addClass_cache->oops_do(f); - _reflect_invoke_cache->oops_do(f); f->do_oop((oop*)&_out_of_memory_error_java_heap); f->do_oop((oop*)&_out_of_memory_error_perm_gen); f->do_oop((oop*)&_out_of_memory_error_array_size); f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit); - if (_preallocated_out_of_memory_error_array != (oop)NULL) { // NULL when DumpSharedSpaces f->do_oop((oop*)&_preallocated_out_of_memory_error_array); - } f->do_oop((oop*)&_null_ptr_exception_instance); f->do_oop((oop*)&_arithmetic_exception_instance); f->do_oop((oop*)&_virtual_machine_error_instance); @@ -281,6 +198,38 @@ debug_only(f->do_oop((oop*)&_fullgc_alot_dummy_array);) } +// Serialize metadata in and out of CDS archive, not oops. +void Universe::serialize(SerializeClosure* f, bool do_all) { + + f->do_ptr((void**)&_boolArrayKlassObj); + f->do_ptr((void**)&_byteArrayKlassObj); + f->do_ptr((void**)&_charArrayKlassObj); + f->do_ptr((void**)&_intArrayKlassObj); + f->do_ptr((void**)&_shortArrayKlassObj); + f->do_ptr((void**)&_longArrayKlassObj); + f->do_ptr((void**)&_singleArrayKlassObj); + f->do_ptr((void**)&_doubleArrayKlassObj); + f->do_ptr((void**)&_objectArrayKlassObj); + + { + for (int i = 0; i < T_VOID+1; i++) { + if (_typeArrayKlassObjs[i] != NULL) { + assert(i >= T_BOOLEAN, "checking"); + f->do_ptr((void**)&_typeArrayKlassObjs[i]); + } else if (do_all) { + f->do_ptr((void**)&_typeArrayKlassObjs[i]); + } + } + } + + f->do_ptr((void**)&_the_array_interfaces_array); + f->do_ptr((void**)&_the_empty_int_array); + f->do_ptr((void**)&_the_empty_short_array); + f->do_ptr((void**)&_the_empty_method_array); + f->do_ptr((void**)&_the_empty_klass_array); + _finalizer_register_cache->serialize(f); + _reflect_invoke_cache->serialize(f); +} void Universe::check_alignment(uintx size, uintx alignment, const char* name) { if (size < alignment || size % alignment != 0) { @@ -292,9 +241,20 @@ } } +void initialize_basic_type_klass(Klass* k, TRAPS) { + Klass* ok = SystemDictionary::Object_klass(); + if (UseSharedSpaces) { + assert(k->super() == ok, "u3"); + k->restore_unshareable_info(CHECK); + } else { + k->initialize_supers(ok, CHECK); + } + k->append_to_sibling_list(); +} void Universe::genesis(TRAPS) { ResourceMark rm; + { FlagSetting fs(_bootstrapping, true); { MutexLocker mc(Compile_lock); @@ -303,13 +263,6 @@ compute_base_vtable_size(); if (!UseSharedSpaces) { - _klassKlassObj = klassKlass::create_klass(CHECK); - _arrayKlassKlassObj = arrayKlassKlass::create_klass(CHECK); - - _objArrayKlassKlassObj = objArrayKlassKlass::create_klass(CHECK); - _instanceKlassKlassObj = instanceKlassKlass::create_klass(CHECK); - _typeArrayKlassKlassObj = typeArrayKlassKlass::create_klass(CHECK); - _boolArrayKlassObj = typeArrayKlass::create_klass(T_BOOLEAN, sizeof(jboolean), CHECK); _charArrayKlassObj = typeArrayKlass::create_klass(T_CHAR, sizeof(jchar), CHECK); _singleArrayKlassObj = typeArrayKlass::create_klass(T_FLOAT, sizeof(jfloat), CHECK); @@ -328,21 +281,13 @@ _typeArrayKlassObjs[T_INT] = _intArrayKlassObj; _typeArrayKlassObjs[T_LONG] = _longArrayKlassObj; - _methodKlassObj = methodKlass::create_klass(CHECK); - _constMethodKlassObj = constMethodKlass::create_klass(CHECK); - _methodDataKlassObj = methodDataKlass::create_klass(CHECK); - _constantPoolKlassObj = constantPoolKlass::create_klass(CHECK); - _constantPoolCacheKlassObj = constantPoolCacheKlass::create_klass(CHECK); + ClassLoaderData* null_cld = ClassLoaderData::the_null_class_loader_data(); - _compiledICHolderKlassObj = compiledICHolderKlass::create_klass(CHECK); - _systemObjArrayKlassObj = objArrayKlassKlass::cast(objArrayKlassKlassObj())->allocate_system_objArray_klass(CHECK); - - _the_empty_byte_array = oopFactory::new_permanent_byteArray(0, CHECK); - _the_empty_short_array = oopFactory::new_permanent_shortArray(0, CHECK); - _the_empty_int_array = oopFactory::new_permanent_intArray(0, CHECK); - _the_empty_system_obj_array = oopFactory::new_system_objArray(0, CHECK); - - _the_array_interfaces_array = oopFactory::new_system_objArray(2, CHECK); + _the_array_interfaces_array = MetadataFactory::new_array<Klass*>(null_cld, 2, NULL, CHECK); + _the_empty_int_array = MetadataFactory::new_array<int>(null_cld, 0, CHECK); + _the_empty_short_array = MetadataFactory::new_array<u2>(null_cld, 0, CHECK); + _the_empty_method_array = MetadataFactory::new_array<Method*>(null_cld, 0, CHECK); + _the_empty_klass_array = MetadataFactory::new_array<Klass*>(null_cld, 0, CHECK); } } @@ -350,83 +295,53 @@ SystemDictionary::initialize(CHECK); - klassOop ok = SystemDictionary::Object_klass(); + Klass* ok = SystemDictionary::Object_klass(); _the_null_string = StringTable::intern("null", CHECK); _the_min_jint_string = StringTable::intern("-2147483648", CHECK); if (UseSharedSpaces) { // Verify shared interfaces array. - assert(_the_array_interfaces_array->obj_at(0) == + assert(_the_array_interfaces_array->at(0) == SystemDictionary::Cloneable_klass(), "u3"); - assert(_the_array_interfaces_array->obj_at(1) == + assert(_the_array_interfaces_array->at(1) == SystemDictionary::Serializable_klass(), "u3"); - - // Verify element klass for system obj array klass - assert(objArrayKlass::cast(_systemObjArrayKlassObj)->element_klass() == ok, "u1"); - assert(objArrayKlass::cast(_systemObjArrayKlassObj)->bottom_klass() == ok, "u2"); - - // Verify super class for the classes created above - assert(Klass::cast(boolArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(charArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(singleArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(doubleArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(byteArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(shortArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(intArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(longArrayKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(constantPoolKlassObj() )->super() == ok, "u3"); - assert(Klass::cast(systemObjArrayKlassObj())->super() == ok, "u3"); } else { // Set up shared interfaces array. (Do this before supers are set up.) - _the_array_interfaces_array->obj_at_put(0, SystemDictionary::Cloneable_klass()); - _the_array_interfaces_array->obj_at_put(1, SystemDictionary::Serializable_klass()); - - // Set element klass for system obj array klass - objArrayKlass::cast(_systemObjArrayKlassObj)->set_element_klass(ok); - objArrayKlass::cast(_systemObjArrayKlassObj)->set_bottom_klass(ok); - - // Set super class for the classes created above - Klass::cast(boolArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(charArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(singleArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(doubleArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(byteArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(shortArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(intArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(longArrayKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(constantPoolKlassObj() )->initialize_supers(ok, CHECK); - Klass::cast(systemObjArrayKlassObj())->initialize_supers(ok, CHECK); - Klass::cast(boolArrayKlassObj() )->set_super(ok); - Klass::cast(charArrayKlassObj() )->set_super(ok); - Klass::cast(singleArrayKlassObj() )->set_super(ok); - Klass::cast(doubleArrayKlassObj() )->set_super(ok); - Klass::cast(byteArrayKlassObj() )->set_super(ok); - Klass::cast(shortArrayKlassObj() )->set_super(ok); - Klass::cast(intArrayKlassObj() )->set_super(ok); - Klass::cast(longArrayKlassObj() )->set_super(ok); - Klass::cast(constantPoolKlassObj() )->set_super(ok); - Klass::cast(systemObjArrayKlassObj())->set_super(ok); + _the_array_interfaces_array->at_put(0, SystemDictionary::Cloneable_klass()); + _the_array_interfaces_array->at_put(1, SystemDictionary::Serializable_klass()); } - Klass::cast(boolArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(charArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(singleArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(doubleArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(byteArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(shortArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(intArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(longArrayKlassObj() )->append_to_sibling_list(); - Klass::cast(constantPoolKlassObj() )->append_to_sibling_list(); - Klass::cast(systemObjArrayKlassObj())->append_to_sibling_list(); + initialize_basic_type_klass(boolArrayKlassObj(), CHECK); + initialize_basic_type_klass(charArrayKlassObj(), CHECK); + initialize_basic_type_klass(singleArrayKlassObj(), CHECK); + initialize_basic_type_klass(doubleArrayKlassObj(), CHECK); + initialize_basic_type_klass(byteArrayKlassObj(), CHECK); + initialize_basic_type_klass(shortArrayKlassObj(), CHECK); + initialize_basic_type_klass(intArrayKlassObj(), CHECK); + initialize_basic_type_klass(longArrayKlassObj(), CHECK); } // end of core bootstrapping + // Maybe this could be lifted up now that object array can be initialized + // during the bootstrapping. + + // OLD // Initialize _objectArrayKlass after core bootstraping to make // sure the super class is set up properly for _objectArrayKlass. - _objectArrayKlassObj = instanceKlass:: + // --- + // NEW + // Since some of the old system object arrays have been converted to + // ordinary object arrays, _objectArrayKlass will be loaded when + // SystemDictionary::initialize(CHECK); is run. See the extra check + // for Object_klass_loaded in objArrayKlassKlass::allocate_objArray_klass_impl. + _objectArrayKlassObj = InstanceKlass:: cast(SystemDictionary::Object_klass())->array_klass(1, CHECK); + // OLD // Add the class to the class hierarchy manually to make sure that // its vtable is initialized after core bootstrapping is completed. + // --- + // New + // Have already been initialized. Klass::cast(_objectArrayKlassObj)->append_to_sibling_list(); // Compute is_jdk version flags. @@ -435,7 +350,7 @@ // Only 1.5 or later has the java.lang.management.MemoryUsage class. if (JDK_Version::is_partially_initialized()) { uint8_t jdk_version; - klassOop k = SystemDictionary::resolve_or_null( + Klass* k = SystemDictionary::resolve_or_null( vmSymbols::java_lang_management_MemoryUsage(), THREAD); CLEAR_PENDING_EXCEPTION; // ignore exceptions if (k == NULL) { @@ -479,17 +394,12 @@ } else { size = FullGCALotDummies * 2; } - objArrayOop naked_array = oopFactory::new_system_objArray(size, CHECK); + objArrayOop naked_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), size, CHECK); objArrayHandle dummy_array(THREAD, naked_array); int i = 0; while (i < size) { - if (!UseConcMarkSweepGC) { // Allocate dummy in old generation - oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK); - dummy_array->obj_at_put(i++, dummy); - } - // Allocate dummy in permanent generation - oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_permanent_instance(CHECK); + oop dummy = InstanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK); dummy_array->obj_at_put(i++, dummy); } { @@ -506,7 +416,11 @@ #endif } - +// CDS support for patching vtables in metadata in the shared archive. +// All types inherited from Metadata have vtables, but not types inherited +// from MetaspaceObj, because the latter does not have virtual functions. +// If the metadata type has a vtable, it cannot be shared in the read-only +// section of the CDS archive, because the vtable pointer is patched. static inline void* dereference(void* addr) { return *(void**)addr; } @@ -520,56 +434,17 @@ void Universe::init_self_patching_vtbl_list(void** list, int count) { int n = 0; - { klassKlass o; add_vtable(list, &n, &o, count); } - { arrayKlassKlass o; add_vtable(list, &n, &o, count); } - { objArrayKlassKlass o; add_vtable(list, &n, &o, count); } - { instanceKlassKlass o; add_vtable(list, &n, &o, count); } - { instanceKlass o; add_vtable(list, &n, &o, count); } + { InstanceKlass o; add_vtable(list, &n, &o, count); } + { instanceClassLoaderKlass o; add_vtable(list, &n, &o, count); } { instanceMirrorKlass o; add_vtable(list, &n, &o, count); } { instanceRefKlass o; add_vtable(list, &n, &o, count); } - { typeArrayKlassKlass o; add_vtable(list, &n, &o, count); } { typeArrayKlass o; add_vtable(list, &n, &o, count); } - { methodKlass o; add_vtable(list, &n, &o, count); } - { constMethodKlass o; add_vtable(list, &n, &o, count); } - { constantPoolKlass o; add_vtable(list, &n, &o, count); } - { constantPoolCacheKlass o; add_vtable(list, &n, &o, count); } { objArrayKlass o; add_vtable(list, &n, &o, count); } - { methodDataKlass o; add_vtable(list, &n, &o, count); } - { compiledICHolderKlass o; add_vtable(list, &n, &o, count); } -#ifndef PRODUCT - // In non-product builds CHeapObj is derived from AllocatedObj, - // so symbols in CDS archive should have their vtable pointer patched. - { Symbol o; add_vtable(list, &n, &o, count); } -#endif + { Method o; add_vtable(list, &n, &o, count); } + { ConstantPool o; add_vtable(list, &n, &o, count); } } - -class FixupMirrorClosure: public ObjectClosure { - public: - virtual void do_object(oop obj) { - if (obj->is_klass()) { - EXCEPTION_MARK; - KlassHandle k(THREAD, klassOop(obj)); - // We will never reach the CATCH below since Exceptions::_throw will cause - // the VM to exit if an exception is thrown during initialization - java_lang_Class::fixup_mirror(k, CATCH); - // This call unconditionally creates a new mirror for k, - // and links in k's component_mirror field if k is an array. - // If k is an objArray, k's element type must already have - // a mirror. In other words, this closure must process - // the component type of an objArray k before it processes k. - // This works because the permgen iterator presents arrays - // and their component types in order of creation. - } - } -}; - void Universe::initialize_basic_type_mirrors(TRAPS) { - if (UseSharedSpaces) { - assert(_int_mirror != NULL, "already loaded"); - assert(_void_mirror == _mirrors[T_VOID], "consistently loaded"); - } else { - assert(_int_mirror==NULL, "basic type mirrors already initialized"); _int_mirror = java_lang_Class::create_basic_type_mirror("int", T_INT, CHECK); @@ -599,9 +474,8 @@ _mirrors[T_LONG] = _long_mirror; _mirrors[T_SHORT] = _short_mirror; _mirrors[T_VOID] = _void_mirror; - //_mirrors[T_OBJECT] = instanceKlass::cast(_object_klass)->java_mirror(); - //_mirrors[T_ARRAY] = instanceKlass::cast(_object_klass)->java_mirror(); - } + //_mirrors[T_OBJECT] = InstanceKlass::cast(_object_klass)->java_mirror(); + //_mirrors[T_ARRAY] = InstanceKlass::cast(_object_klass)->java_mirror(); } void Universe::fixup_mirrors(TRAPS) { @@ -610,14 +484,22 @@ // walk over permanent objects created so far (mostly classes) and fixup their mirrors. Note // that the number of objects allocated at this point is very small. assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded"); - + HandleMark hm(THREAD); // Cache the start of the static fields instanceMirrorKlass::init_offset_of_static_fields(); - FixupMirrorClosure blk; - Universe::heap()->permanent_object_iterate(&blk); + GrowableArray <Klass*>* list = java_lang_Class::fixup_mirror_list(); + int list_length = list->length(); + for (int i = 0; i < list_length; i++) { + Klass* k = list->at(i); + assert(k->is_klass(), "List should only hold classes"); + EXCEPTION_MARK; + KlassHandle kh(THREAD, k); + java_lang_Class::fixup_mirror(kh, CATCH); } - + delete java_lang_Class::fixup_mirror_list(); + java_lang_Class::set_fixup_mirror_list(NULL); +} static bool has_run_finalizers_on_exit = false; @@ -650,20 +532,20 @@ // In case those ever change we use handles for oops void Universe::reinitialize_vtable_of(KlassHandle k_h, TRAPS) { // init vtable of k and all subclasses - Klass* ko = k_h()->klass_part(); + Klass* ko = k_h(); klassVtable* vt = ko->vtable(); if (vt) vt->initialize_vtable(false, CHECK); if (ko->oop_is_instance()) { - instanceKlass* ik = (instanceKlass*)ko; - for (KlassHandle s_h(THREAD, ik->subklass()); s_h() != NULL; s_h = (THREAD, s_h()->klass_part()->next_sibling())) { + InstanceKlass* ik = (InstanceKlass*)ko; + for (KlassHandle s_h(THREAD, ik->subklass()); s_h() != NULL; s_h = (THREAD, s_h()->next_sibling())) { reinitialize_vtable_of(s_h, CHECK); } } } -void initialize_itable_for_klass(klassOop k, TRAPS) { - instanceKlass::cast(k)->itable()->initialize_itable(false, CHECK); +void initialize_itable_for_klass(Klass* k, TRAPS) { + InstanceKlass::cast(k)->itable()->initialize_itable(false, CHECK); } @@ -758,49 +640,28 @@ GC_locker::lock(); // do not allow gc during bootstrapping JavaClasses::compute_hard_coded_offsets(); - // Get map info from shared archive file. - if (DumpSharedSpaces) - UseSharedSpaces = false; - - FileMapInfo* mapinfo = NULL; - if (UseSharedSpaces) { - mapinfo = NEW_C_HEAP_OBJ(FileMapInfo, mtInternal); - memset(mapinfo, 0, sizeof(FileMapInfo)); - - // Open the shared archive file, read and validate the header. If - // initialization files, shared spaces [UseSharedSpaces] are - // disabled and the file is closed. - - if (mapinfo->initialize()) { - FileMapInfo::set_current_info(mapinfo); - } else { - assert(!mapinfo->is_open() && !UseSharedSpaces, - "archive file not closed or shared spaces not disabled."); - } - } - jint status = Universe::initialize_heap(); if (status != JNI_OK) { return status; } - // We have a heap so create the methodOop caches before - // CompactingPermGenGen::initialize_oops() tries to populate them. + // Create memory for metadata. Must be after initializing heap for + // DumpSharedSpaces. + ClassLoaderData::init_null_class_loader_data(); + + // We have a heap so create the Method* caches before + // Metaspace::initialize_shared_spaces() tries to populate them. Universe::_finalizer_register_cache = new LatestMethodOopCache(); - Universe::_loader_addClass_cache = new LatestMethodOopCache(); Universe::_reflect_invoke_cache = new ActiveMethodOopsCache(); if (UseSharedSpaces) { - // Read the data structures supporting the shared spaces (shared // system dictionary, symbol table, etc.). After that, access to // the file (other than the mapped regions) is no longer needed, and // the file is closed. Closing the file does not affect the // currently mapped regions. - - CompactingPermGenGen::initialize_oops(); - mapinfo->close(); - + MetaspaceShared::initialize_shared_spaces(); + StringTable::create_table(); } else { SymbolTable::create_table(); StringTable::create_table(); @@ -992,6 +853,54 @@ return JNI_OK; } + +// Reserve the Java heap, which is now the same for all GCs. +ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { + // Add in the class metaspace area so the classes in the headers can + // be compressed the same as instances. + size_t total_reserved = heap_size + ClassMetaspaceSize; + char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); + + ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr); + + if (UseCompressedOops) { + if (addr != NULL && !total_rs.is_reserved()) { + // Failed to reserve at specified address - the requested memory + // region is taken already, for example, by 'java' launcher. + // Try again to reserver heap higher. + addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); + + ReservedHeapSpace total_rs0(total_reserved, alignment, + UseLargePages, addr); + + if (addr != NULL && !total_rs0.is_reserved()) { + // Failed to reserve at specified address again - give up. + addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop); + assert(addr == NULL, ""); + + ReservedHeapSpace total_rs1(total_reserved, alignment, + UseLargePages, addr); + total_rs = total_rs1; + } else { + total_rs = total_rs0; + } + } + } + + if (!total_rs.is_reserved()) { + vm_exit_during_initialization(err_msg("Could not reserve enough space for object heap %d bytes", total_reserved)); + return total_rs; + } + + // Split the reserved space into main Java heap and a space for classes + // so that they can be compressed using the same algorithm as compressed oops + ReservedSpace heap_rs = total_rs.first_part(heap_size); + ReservedSpace class_rs = total_rs.last_part(heap_size, alignment); + Metaspace::initialize_class_space(class_rs); + return heap_rs; +} + + // It's the caller's repsonsibility to ensure glitch-freedom // (if required). void Universe::update_heap_info_at_gc() { @@ -1026,55 +935,56 @@ { ResourceMark rm; Interpreter::initialize(); // needed for interpreter entry points if (!UseSharedSpaces) { + HandleMark hm(THREAD); KlassHandle ok_h(THREAD, SystemDictionary::Object_klass()); Universe::reinitialize_vtable_of(ok_h, CHECK_false); Universe::reinitialize_itables(CHECK_false); } } - klassOop k; + HandleMark hm(THREAD); + Klass* k; instanceKlassHandle k_h; - if (!UseSharedSpaces) { // Setup preallocated empty java.lang.Class array Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false); + // Setup preallocated OutOfMemoryError errors k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false); k_h = instanceKlassHandle(THREAD, k); - Universe::_out_of_memory_error_java_heap = k_h->allocate_permanent_instance(CHECK_false); - Universe::_out_of_memory_error_perm_gen = k_h->allocate_permanent_instance(CHECK_false); - Universe::_out_of_memory_error_array_size = k_h->allocate_permanent_instance(CHECK_false); + Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_perm_gen = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false); Universe::_out_of_memory_error_gc_overhead_limit = - k_h->allocate_permanent_instance(CHECK_false); + k_h->allocate_instance(CHECK_false); // Setup preallocated NullPointerException // (this is currently used for a cheap & dirty solution in compiler exception handling) k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false); - Universe::_null_ptr_exception_instance = instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false); + Universe::_null_ptr_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false); // Setup preallocated ArithmeticException // (this is currently used for a cheap & dirty solution in compiler exception handling) k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false); - Universe::_arithmetic_exception_instance = instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false); + Universe::_arithmetic_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false); // Virtual Machine Error for when we get into a situation we can't resolve k = SystemDictionary::resolve_or_fail( vmSymbols::java_lang_VirtualMachineError(), true, CHECK_false); - bool linked = instanceKlass::cast(k)->link_class_or_fail(CHECK_false); + bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false); if (!linked) { tty->print_cr("Unable to link/verify VirtualMachineError class"); return false; // initialization failed } Universe::_virtual_machine_error_instance = - instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false); + InstanceKlass::cast(k)->allocate_instance(CHECK_false); - Universe::_vm_exception = instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false); + Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false); - } if (!DumpSharedSpaces) { // These are the only Java fields that are currently set during shared space dumping. // We prefer to not handle this generally, so we always reinitialize these detail messages. Handle msg = java_lang_String::create_from_str("Java heap space", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_java_heap, msg()); - msg = java_lang_String::create_from_str("PermGen space", CHECK_false); + msg = java_lang_String::create_from_str("Metadata space", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_perm_gen, msg()); msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK_false); @@ -1088,13 +998,13 @@ // Setup the array of errors that have preallocated backtrace k = Universe::_out_of_memory_error_java_heap->klass(); - assert(k->klass_part()->name() == vmSymbols::java_lang_OutOfMemoryError(), "should be out of memory error"); + assert(k->name() == vmSymbols::java_lang_OutOfMemoryError(), "should be out of memory error"); k_h = instanceKlassHandle(THREAD, k); int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0; Universe::_preallocated_out_of_memory_error_array = oopFactory::new_objArray(k_h(), len, CHECK_false); for (int i=0; i<len; i++) { - oop err = k_h->allocate_permanent_instance(CHECK_false); + oop err = k_h->allocate_instance(CHECK_false); Handle err_h = Handle(THREAD, err); java_lang_Throwable::allocate_backtrace(err_h, CHECK_false); Universe::preallocated_out_of_memory_errors()->obj_at_put(i, err_h()); @@ -1106,8 +1016,8 @@ // Setup static method for registering finalizers // The finalizer klass must be linked before looking up the method, in // case it needs to get rewritten. - instanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false); - methodOop m = instanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method( + InstanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false); + Method* m = InstanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method( vmSymbols::register_method_name(), vmSymbols::register_method_signature()); if (m == NULL || !m->is_static()) { @@ -1131,16 +1041,6 @@ } Universe::_reflect_invoke_cache->init(k_h(), m, CHECK_false); - // Setup method for registering loaded classes in class loader vector - instanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false); - m = instanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); - if (m == NULL || m->is_static()) { - THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(), - "java.lang.ClassLoader.addClass", false); - } - Universe::_loader_addClass_cache->init( - SystemDictionary::ClassLoader_klass(), m, CHECK_false); - // The folowing is initializing converter functions for serialization in // JVM.cpp. If we clean up the StrictMath code above we may want to find // a better solution for this as well. @@ -1156,6 +1056,9 @@ // ("weak") refs processing infrastructure initialization Universe::heap()->post_initialize(); + // Initialize performance counters for metaspaces + MetaspaceCounters::initialize_performance_counters(); + GC_locker::unlock(); // allow gc after bootstrapping MemoryService::set_universe_heap(Universe::_collectedHeap); @@ -1204,14 +1107,14 @@ CallSiteDepChange changes(call_site(), method_handle()); // Compute the dependent nmethods that have a reference to a - // CallSite object. We use instanceKlass::mark_dependent_nmethod + // CallSite object. We use InstanceKlass::mark_dependent_nmethod // directly instead of CodeCache::mark_for_deoptimization because we // want dependents on the call site class only not all classes in // the ContextStream. int marked = 0; { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - instanceKlass* call_site_klass = instanceKlass::cast(call_site->klass()); + InstanceKlass* call_site_klass = InstanceKlass::cast(call_site->klass()); marked = call_site_klass->mark_dependent_nmethods(changes); } if (marked > 0) { @@ -1363,6 +1266,10 @@ } if (!silent) gclog_or_tty->print("dict "); SystemDictionary::verify(); +#ifndef PRODUCT + if (!silent) gclog_or_tty->print("cldg "); + ClassLoaderDataGraph::verify(); +#endif if (!silent) gclog_or_tty->print("hand "); JNIHandles::verify(); if (!silent) gclog_or_tty->print("C-heap "); @@ -1433,62 +1340,10 @@ return _verify_oop_data[1]; } - -uintptr_t Universe::verify_klass_mask() { - /* $$$ - // A klass can never live in the new space. Since the new and old - // spaces can change size, we must settle for bounds-checking against - // the bottom of the world, plus the smallest possible new and old - // space sizes that may arise during execution. - size_t min_new_size = Universe::new_size(); // in bytes - size_t min_old_size = Universe::old_size(); // in bytes - calculate_verify_data(_verify_klass_data, - (HeapWord*)((uintptr_t)_new_gen->low_boundary + min_new_size + min_old_size), - _perm_gen->high_boundary); - */ - // Why doesn't the above just say that klass's always live in the perm - // gen? I'll see if that seems to work... - MemRegion permanent_reserved; - switch (Universe::heap()->kind()) { - default: - // ???: What if a CollectedHeap doesn't have a permanent generation? - ShouldNotReachHere(); - break; - case CollectedHeap::GenCollectedHeap: - case CollectedHeap::G1CollectedHeap: { - SharedHeap* sh = (SharedHeap*) Universe::heap(); - permanent_reserved = sh->perm_gen()->reserved(); - break; - } -#ifndef SERIALGC - case CollectedHeap::ParallelScavengeHeap: { - ParallelScavengeHeap* psh = (ParallelScavengeHeap*) Universe::heap(); - permanent_reserved = psh->perm_gen()->reserved(); - break; - } -#endif // SERIALGC - } - calculate_verify_data(_verify_klass_data, - permanent_reserved.start(), - permanent_reserved.end()); - - return _verify_klass_data[0]; -} - - - -uintptr_t Universe::verify_klass_bits() { - verify_klass_mask(); - return _verify_klass_data[1]; -} - - uintptr_t Universe::verify_mark_mask() { return markOopDesc::lock_mask_in_place; } - - uintptr_t Universe::verify_mark_bits() { intptr_t mask = verify_mark_mask(); intptr_t bits = (intptr_t)markOopDesc::prototype(); @@ -1503,12 +1358,10 @@ verify_oop_bits(); verify_mark_mask(); verify_mark_bits(); - verify_klass_mask(); - verify_klass_bits(); } -void CommonMethodOopCache::init(klassOop k, methodOop m, TRAPS) { +void CommonMethodOopCache::init(Klass* k, Method* m, TRAPS) { if (!UseSharedSpaces) { _klass = k; } @@ -1526,27 +1379,24 @@ ActiveMethodOopsCache::~ActiveMethodOopsCache() { if (_prev_methods != NULL) { - for (int i = _prev_methods->length() - 1; i >= 0; i--) { - jweak method_ref = _prev_methods->at(i); - if (method_ref != NULL) { - JNIHandles::destroy_weak_global(method_ref); - } - } delete _prev_methods; _prev_methods = NULL; } } -void ActiveMethodOopsCache::add_previous_version(const methodOop method) { +void ActiveMethodOopsCache::add_previous_version(Method* const method) { assert(Thread::current()->is_VM_thread(), "only VMThread can add previous versions"); + // Only append the previous method if it is executing on the stack. + if (method->on_stack()) { + if (_prev_methods == NULL) { // This is the first previous version so make some space. // Start with 2 elements under the assumption that the class // won't be redefined much. - _prev_methods = new (ResourceObj::C_HEAP, mtClass) GrowableArray<jweak>(2, true); + _prev_methods = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Method*>(2, true); } // RC_TRACE macro has an embedded ResourceMark @@ -1555,42 +1405,35 @@ method->name()->as_C_string(), method->signature()->as_C_string(), _prev_methods->length())); - methodHandle method_h(method); - jweak method_ref = JNIHandles::make_weak_global(method_h); - _prev_methods->append(method_ref); + _prev_methods->append(method); + } + - // Using weak references allows previous versions of the cached - // method to be GC'ed when they are no longer needed. Since the - // caller is the VMThread and we are at a safepoint, this is a good - // time to clear out unused weak references. + // Since the caller is the VMThread and we are at a safepoint, this is a good + // time to clear out unused method references. + + if (_prev_methods == NULL) return; for (int i = _prev_methods->length() - 1; i >= 0; i--) { - jweak method_ref = _prev_methods->at(i); - assert(method_ref != NULL, "weak method ref was unexpectedly cleared"); - if (method_ref == NULL) { + Method* method = _prev_methods->at(i); + assert(method != NULL, "weak method ref was unexpectedly cleared"); + + if (!method->on_stack()) { + // This method isn't running anymore so remove it _prev_methods->remove_at(i); - // Since we are traversing the array backwards, we don't have to - // do anything special with the index. - continue; // robustness - } - - methodOop m = (methodOop)JNIHandles::resolve(method_ref); - if (m == NULL) { - // this method entry has been GC'ed so remove it - JNIHandles::destroy_weak_global(method_ref); - _prev_methods->remove_at(i); + MetadataFactory::free_metadata(method->method_holder()->class_loader_data(), method); } else { // RC_TRACE macro has an embedded ResourceMark RC_TRACE(0x00000400, ("add: %s(%s): previous cached method @%d is alive", - m->name()->as_C_string(), m->signature()->as_C_string(), i)); + method->name()->as_C_string(), method->signature()->as_C_string(), i)); } } } // end add_previous_version() -bool ActiveMethodOopsCache::is_same_method(const methodOop method) const { - instanceKlass* ik = instanceKlass::cast(klass()); - methodOop check_method = ik->method_with_idnum(method_idnum()); +bool ActiveMethodOopsCache::is_same_method(Method* const method) const { + InstanceKlass* ik = InstanceKlass::cast(klass()); + Method* check_method = ik->method_with_idnum(method_idnum()); assert(check_method != NULL, "sanity check"); if (check_method == method) { // done with the easy case @@ -1601,13 +1444,7 @@ // The cached method has been redefined at least once so search // the previous versions for a match. for (int i = 0; i < _prev_methods->length(); i++) { - jweak method_ref = _prev_methods->at(i); - assert(method_ref != NULL, "weak method ref was unexpectedly cleared"); - if (method_ref == NULL) { - continue; // robustness - } - - check_method = (methodOop)JNIHandles::resolve(method_ref); + check_method = _prev_methods->at(i); if (check_method == method) { // a previous version matches return true; @@ -1620,9 +1457,9 @@ } -methodOop LatestMethodOopCache::get_methodOop() { - instanceKlass* ik = instanceKlass::cast(klass()); - methodOop m = ik->method_with_idnum(method_idnum()); +Method* LatestMethodOopCache::get_Method() { + InstanceKlass* ik = InstanceKlass::cast(klass()); + Method* m = ik->method_with_idnum(method_idnum()); assert(m != NULL, "sanity check"); return m; }