src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/memory/metaspace.cpp	Thu Aug 15 09:51:29 2013
--- new/src/share/vm/memory/metaspace.cpp	Thu Aug 15 09:51:26 2013

*** 33,42 **** --- 33,43 ---- #include "memory/metaspace.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "runtime/globals.hpp" + #include "runtime/java.hpp" #include "runtime/mutex.hpp" #include "runtime/orderAccess.hpp" #include "services/memTracker.hpp" #include "utilities/copy.hpp" #include "utilities/debug.hpp"
*** 52,61 **** --- 53,64 ---- const uint metadata_deallocate_a_lock_chunk = 3; size_t const allocation_from_dictionary_limit = 64 * K; MetaWord* last_allocated = 0; + size_t Metaspace::_class_metaspace_size; + // Used in declarations in SpaceManager and ChunkManager enum ChunkIndex { ZeroIndex = 0, SpecializedIndex = ZeroIndex, SmallIndex = SpecializedIndex + 1,
*** 259,272 **** --- 262,271 ---- VirtualSpace _virtual_space; MetaWord* _top; // count of chunks contained in this VirtualSpace uintx _container_count; // Convenience functions for logical bottom and end MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } // Convenience functions to access the _virtual_space char* low() const { return virtual_space()->low(); } char* high() const { return virtual_space()->high(); } // The first Metachunk will be allocated at the bottom of the
*** 282,291 **** --- 281,294 ---- VirtualSpaceNode(size_t byte_size); VirtualSpaceNode(ReservedSpace rs) : _top(NULL), _next(NULL), _rs(rs), _container_count(0) {} ~VirtualSpaceNode(); + // Convenience functions for logical bottom and end + MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } + MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } + // address of next available space in _virtual_space; // Accessors VirtualSpaceNode* next() { return _next; } void set_next(VirtualSpaceNode* v) { _next = v; }
*** 1311,1321 **** --- 1314,1325 ---- } } // Class virtual space should always be expanded. Call GC for the other // metadata virtual space. ! if (vsl == Metaspace::class_space_list()) return true; ! if (Metaspace::using_class_space() && + (vsl == Metaspace::class_space_list())) return true; // If this is part of an allocation after a GC, expand // unconditionally. if (MetaspaceGC::expand_after_GC()) { return true;
*** 2255,2265 **** --- 2259,2269 ---- void SpaceManager::deallocate(MetaWord* p, size_t word_size) { assert_lock_strong(_lock); size_t raw_word_size = get_raw_word_size(word_size); size_t min_size = TreeChunk<Metablock, FreeList>::min_size(); assert(raw_word_size >= min_size, ! err_msg("Should not deallocate dark matter " SIZE_FORMAT, word_size)); ! err_msg("Should not deallocate dark matter " SIZE_FORMAT "<" SIZE_FORMAT, word_size, min_size)); block_freelists()->return_block(p, raw_word_size); } // Adds a chunk to the list of chunks in use. void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
*** 2372,2382 **** --- 2376,2386 ---- } if (result == NULL) { result = grow_and_allocate(word_size); } ! if (result > 0) { ! if (result != 0) { inc_used_metrics(word_size); assert(result != (MetaWord*) chunks_in_use(MediumIndex), "Head of the list is being allocated"); }
*** 2476,2486 **** --- 2480,2491 ---- size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0}; size_t MetaspaceAux::_allocated_used_words[] = {0, 0}; size_t MetaspaceAux::free_bytes() { size_t result = 0; ! if (Metaspace::class_space_list() != NULL) { ! if (Metaspace::using_class_space() && + (Metaspace::class_space_list() != NULL)) { result = result + Metaspace::class_space_list()->free_bytes(); } if (Metaspace::space_list() != NULL) { result = result + Metaspace::space_list()->free_bytes(); }
*** 2547,2556 **** --- 2552,2564 ---- } return free * BytesPerWord; } size_t MetaspaceAux::capacity_bytes_slow(Metaspace::MetadataType mdtype) { + if ((mdtype == Metaspace::ClassType) && !Metaspace::using_class_space()) { + return 0; + } // Don't count the space in the freelists. That space will be // added to the capacity calculation as needed. size_t capacity = 0; ClassLoaderDataGraphMetaspaceIterator iter; while (iter.repeat()) {
*** 2561,2579 **** --- 2569,2592 ---- } return capacity * BytesPerWord; } size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) { size_t reserved = (mdtype == Metaspace::ClassType) ? Metaspace::class_space_list()->virtual_space_total() : ! Metaspace::space_list()->virtual_space_total(); return reserved * BytesPerWord; + if (mdtype == Metaspace::ClassType) { + return Metaspace::using_class_space() ? ! Metaspace::class_space_list()->virtual_space_total() * BytesPerWord : 0; + } else { + return Metaspace::space_list()->virtual_space_total() * BytesPerWord; + } } size_t MetaspaceAux::min_chunk_size() { return Metaspace::first_chunk_word_size(); } size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) { + if ((mdtype == Metaspace::ClassType) && !Metaspace::using_class_space()) { + return 0; + } ChunkManager* chunk = (mdtype == Metaspace::ClassType) ? Metaspace::class_space_list()->chunk_manager() : Metaspace::space_list()->chunk_manager(); chunk->slow_verify(); return chunk->free_chunks_total();
*** 2613,2623 **** --- 2626,2635 ---- gclog_or_tty->print("]"); } // This is printed when PrintGCDetails void MetaspaceAux::print_on(outputStream* out) { Metaspace::MetadataType ct = Metaspace::ClassType; Metaspace::MetadataType nct = Metaspace::NonClassType; out->print_cr(" Metaspace total " SIZE_FORMAT "K, used " SIZE_FORMAT "K," " reserved " SIZE_FORMAT "K",
*** 2627,2642 **** --- 2639,2657 ---- SIZE_FORMAT "K, used " SIZE_FORMAT "K," " reserved " SIZE_FORMAT "K", allocated_capacity_bytes(nct)/K, allocated_used_bytes(nct)/K, reserved_in_bytes(nct)/K); + if (Metaspace::using_class_space()) { + Metaspace::MetadataType ct = Metaspace::ClassType; out->print_cr(" class space " SIZE_FORMAT "K, used " SIZE_FORMAT "K," " reserved " SIZE_FORMAT "K", allocated_capacity_bytes(ct)/K, allocated_used_bytes(ct)/K, reserved_in_bytes(ct)/K); + } } // Print information for class space and data space separately. // This is almost the same as above. void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) {
*** 2657,2673 **** --- 2672,2712 ---- capacity_bytes / K); // Accounting can only be correct if we got the values during a safepoint assert(!SafepointSynchronize::is_at_safepoint() || used_and_free == capacity_bytes, "Accounting is wrong"); } ! // Print total fragmentation for class and data metaspaces separately ! void MetaspaceAux::print_waste(outputStream* out) { ! void MetaspaceAux::print_class_waste(outputStream* out) { + assert(Metaspace::using_class_space(), "class metaspace not used"); + size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0; + size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_humongous_count = 0; + ClassLoaderDataGraphMetaspaceIterator iter; + while (iter.repeat()) { + Metaspace* msp = iter.get_next(); + if (msp != NULL) { + cls_specialized_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SpecializedIndex); + cls_specialized_count += msp->class_vsm()->sum_count_in_chunks_in_use(SpecializedIndex); + cls_small_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SmallIndex); + cls_small_count += msp->class_vsm()->sum_count_in_chunks_in_use(SmallIndex); + cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex); + cls_medium_count += msp->class_vsm()->sum_count_in_chunks_in_use(MediumIndex); + cls_humongous_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); + } + } + out->print_cr(" class: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " + SIZE_FORMAT " small(s) " SIZE_FORMAT ", " + SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " + "large count " SIZE_FORMAT, + cls_specialized_count, cls_specialized_waste, + cls_small_count, cls_small_waste, + cls_medium_count, cls_medium_waste, cls_humongous_count); + } + // Print total fragmentation for data and class metaspaces separately + void MetaspaceAux::print_waste(outputStream* out) { size_t specialized_waste = 0, small_waste = 0, medium_waste = 0; size_t specialized_count = 0, small_count = 0, medium_count = 0, humongous_count = 0; size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0; size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_humongous_count = 0; ClassLoaderDataGraphMetaspaceIterator iter; while (iter.repeat()) { Metaspace* msp = iter.get_next(); if (msp != NULL) {
*** 2676,2709 **** --- 2715,2736 ---- small_waste += msp->vsm()->sum_waste_in_chunks_in_use(SmallIndex); small_count += msp->vsm()->sum_count_in_chunks_in_use(SmallIndex); medium_waste += msp->vsm()->sum_waste_in_chunks_in_use(MediumIndex); medium_count += msp->vsm()->sum_count_in_chunks_in_use(MediumIndex); humongous_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex); cls_specialized_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SpecializedIndex); cls_specialized_count += msp->class_vsm()->sum_count_in_chunks_in_use(SpecializedIndex); cls_small_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SmallIndex); cls_small_count += msp->class_vsm()->sum_count_in_chunks_in_use(SmallIndex); cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex); cls_medium_count += msp->class_vsm()->sum_count_in_chunks_in_use(MediumIndex); cls_humongous_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); } } out->print_cr("Total fragmentation waste (words) doesn't count free space"); out->print_cr(" data: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " SIZE_FORMAT " small(s) " SIZE_FORMAT ", " SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " "large count " SIZE_FORMAT, specialized_count, specialized_waste, small_count, small_waste, medium_count, medium_waste, humongous_count); out->print_cr(" class: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " SIZE_FORMAT " small(s) " SIZE_FORMAT ", " SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " "large count " SIZE_FORMAT, cls_specialized_count, cls_specialized_waste, cls_small_count, cls_small_waste, cls_medium_count, cls_medium_waste, cls_humongous_count); + if (Metaspace::using_class_space()) { + print_class_waste(out); + } } // Dump global metaspace things from the end of ClassLoaderDataGraph void MetaspaceAux::dump(outputStream* out) { out->print_cr("All Metaspace:");
*** 2712,2722 **** --- 2739,2751 ---- print_waste(out); } void MetaspaceAux::verify_free_chunks() { Metaspace::space_list()->chunk_manager()->verify(); + if (Metaspace::using_class_space()) { Metaspace::class_space_list()->chunk_manager()->verify(); + } } void MetaspaceAux::verify_capacity() { #ifdef ASSERT size_t running_sum_capacity_bytes = allocated_capacity_bytes();
*** 2774,2794 **** --- 2803,2939 ---- initialize(lock, type); } Metaspace::~Metaspace() { delete _vsm; + if (using_class_space()) { delete _class_vsm; + } } VirtualSpaceList* Metaspace::_space_list = NULL; VirtualSpaceList* Metaspace::_class_space_list = NULL; #define VIRTUALSPACEMULTIPLIER 2 + #ifdef _LP64 + void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address cds_base) { + // Figure out the narrow_klass_base and the narrow_klass_shift. The + // narrow_klass_base is the lower of the metaspace base and the cds base + // (if cds is enabled). The narrow_klass_shift depends on the distance + // between the lower base and higher address. + address lower_base; + address higher_address; + if (UseSharedSpaces) { + higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), + (address)(metaspace_base + class_metaspace_size())); + lower_base = MIN2(metaspace_base, cds_base); + } else { + higher_address = metaspace_base + class_metaspace_size(); + lower_base = metaspace_base; + } + Universe::set_narrow_klass_base(lower_base); + if ((uint64_t)(higher_address - lower_base) < (uint64_t)max_juint) { + Universe::set_narrow_klass_shift(0); + } else { + assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces"); + Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes); + } + } + + // Return TRUE if the specified metaspace_base and cds_base are close enough + // to work with compressed klass pointers. + bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) { + assert(cds_base != 0 && UseSharedSpaces, "Only use with CDS"); + assert(UseCompressedKlassPointers, "Only use with CompressedKlassPtrs"); + address lower_base = MIN2((address)metaspace_base, cds_base); + address higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), + (address)(metaspace_base + class_metaspace_size())); + return ((uint64_t)(higher_address - lower_base) < (uint64_t)max_juint); + } + + // Try to allocate the metaspace at the requested addr. + void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) { + assert(using_class_space(), "called improperly"); + assert(UseCompressedKlassPointers, "Only use with CompressedKlassPtrs"); + assert(class_metaspace_size() < KlassEncodingMetaspaceMax, + "Metaspace size is too big"); + + ReservedSpace metaspace_rs = ReservedSpace(class_metaspace_size(), + os::vm_allocation_granularity(), + false, requested_addr, 0); + if (!metaspace_rs.is_reserved()) { + if (UseSharedSpaces) { + // Keep trying to allocate the metaspace, increasing the requested_addr + // by 1GB each time, until we reach an address that will no longer allow + // use of CDS with compressed klass pointers. + char *addr = requested_addr; + while (!metaspace_rs.is_reserved() && (addr + 1*G > addr) && + can_use_cds_with_metaspace_addr(addr + 1*G, cds_base)) { + addr = addr + 1*G; + metaspace_rs = ReservedSpace(class_metaspace_size(), + os::vm_allocation_granularity(), false, addr, 0); + } + } + + // If no successful allocation then try to allocate the space anywhere. If + // that fails then OOM doom. At this point we cannot try allocating the + // metaspace as if UseCompressedKlassPointers is off because too much + // initialization has happened that depends on UseCompressedKlassPointers. + // So, UseCompressedKlassPointers cannot be turned off at this point. + if (!metaspace_rs.is_reserved()) { + metaspace_rs = ReservedSpace(class_metaspace_size(), + os::vm_allocation_granularity(), false); + if (!metaspace_rs.is_reserved()) { + vm_exit_during_initialization(err_msg("Could not allocate metaspace: %d bytes", + class_metaspace_size())); + } + } + } + + // If we got here then the metaspace got allocated. + MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass); + + // Verify that we can use shared spaces. Otherwise, turn off CDS. + if (UseSharedSpaces && !can_use_cds_with_metaspace_addr(metaspace_rs.base(), cds_base)) { + FileMapInfo::stop_sharing_and_unmap( + "Could not allocate metaspace at a compatible address"); + } + + set_narrow_klass_base_and_shift((address)metaspace_rs.base(), + UseSharedSpaces ? (address)cds_base : 0); + + initialize_class_space(metaspace_rs); + + if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { + gclog_or_tty->print_cr("Narrow klass base: " PTR_FORMAT ", Narrow klass shift: " SIZE_FORMAT, + Universe::narrow_klass_base(), Universe::narrow_klass_shift()); + gclog_or_tty->print_cr("Metaspace Size: " SIZE_FORMAT " Address: " PTR_FORMAT " Req Addr: " PTR_FORMAT, + class_metaspace_size(), metaspace_rs.base(), requested_addr); + } + } + + // For UseCompressedKlassPointers the class space is reserved above the top of + // the Java heap. The argument passed in is at the base of the compressed space. + void Metaspace::initialize_class_space(ReservedSpace rs) { + // The reserved space size may be bigger because of alignment, esp with UseLargePages + assert(rs.size() >= ClassMetaspaceSize, + err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); + assert(using_class_space(), "Must be using class space"); + _class_space_list = new VirtualSpaceList(rs); + } + + #endif + void Metaspace::global_initialize() { // Initialize the alignment for shared spaces. int max_alignment = os::vm_page_size(); + size_t cds_total = 0; + + set_class_metaspace_size(align_size_up(ClassMetaspaceSize, + os::vm_allocation_granularity())); + MetaspaceShared::set_max_alignment(max_alignment); if (DumpSharedSpaces) { SharedReadOnlySize = align_size_up(SharedReadOnlySize, max_alignment); SharedReadWriteSize = align_size_up(SharedReadWriteSize, max_alignment);
*** 2796,2814 **** --- 2941,2975 ---- SharedMiscCodeSize = align_size_up(SharedMiscCodeSize, max_alignment); // Initialize with the sum of the shared space sizes. The read-only // and read write metaspace chunks will be allocated out of this and the // remainder is the misc code and data chunks. size_t total = align_size_up(SharedReadOnlySize + SharedReadWriteSize + SharedMiscDataSize + SharedMiscCodeSize, os::vm_allocation_granularity()); size_t word_size = total/wordSize; _space_list = new VirtualSpaceList(word_size); + cds_total = FileMapInfo::shared_spaces_size(); + _space_list = new VirtualSpaceList(cds_total/wordSize); + + #ifdef _LP64 + // Set the compressed klass pointer base so that decoding of these pointers works + // properly when creating the shared archive. + assert(UseCompressedOops && UseCompressedKlassPointers, + "UseCompressedOops and UseCompressedKlassPointers must be set"); + Universe::set_narrow_klass_base((address)_space_list->current_virtual_space()->bottom()); + if (TraceMetavirtualspaceAllocation && Verbose) { + gclog_or_tty->print_cr("Setting_narrow_klass_base to Address: " PTR_FORMAT, + _space_list->current_virtual_space()->bottom()); + } + + // Set the shift to zero. + assert(class_metaspace_size() < (uint64_t)(max_juint) - cds_total, + "CDS region is too large"); + Universe::set_narrow_klass_shift(0); + #endif + } else { // If using shared space, open the file that contains the shared space // and map in the memory before initializing the rest of metaspace (so // the addresses don't conflict) + address cds_address = NULL; if (UseSharedSpaces) { FileMapInfo* mapinfo = new FileMapInfo(); memset(mapinfo, 0, sizeof(FileMapInfo)); // Open the shared archive file, read and validate the header. If
*** 2819,2829 **** --- 2980,3004 ---- FileMapInfo::set_current_info(mapinfo); } else { assert(!mapinfo->is_open() && !UseSharedSpaces, "archive file not closed or shared spaces not disabled."); } + cds_total = FileMapInfo::shared_spaces_size(); + cds_address = (address)mapinfo->region_base(0); + } + + #ifdef _LP64 + // If UseCompressedKlassPointers is set then allocate the metaspace area + // above the heap and above the CDS area (if it exists). + if (using_class_space()) { + if (UseSharedSpaces) { + allocate_metaspace_compressed_klass_ptrs((char *)(cds_address + cds_total), cds_address); + } else { + allocate_metaspace_compressed_klass_ptrs((char *)CompressedKlassPointersBase, 0); + } } + #endif // Initialize these before initializing the VirtualSpaceList _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord; _first_chunk_word_size = align_word_size_up(_first_chunk_word_size); // Make the first class chunk bigger than a medium chunk so it's not put
*** 2838,2881 **** --- 3013,3045 ---- // Initialize the list of virtual spaces. _space_list = new VirtualSpaceList(word_size); } } // For UseCompressedKlassPointers the class space is reserved as a piece of the // Java heap because the compression algorithm is the same for each. The // argument passed in is at the top of the compressed space void Metaspace::initialize_class_space(ReservedSpace rs) { // The reserved space size may be bigger because of alignment, esp with UseLargePages assert(rs.size() >= ClassMetaspaceSize, err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); _class_space_list = new VirtualSpaceList(rs); } void Metaspace::initialize(Mutex* lock, MetaspaceType type) { + void Metaspace::initialize(Mutex* lock, MetaspaceType type) { assert(space_list() != NULL, "Metadata VirtualSpaceList has not been initialized"); - _vsm = new SpaceManager(Metaspace::NonClassType, lock, space_list()); if (_vsm == NULL) { return; } size_t word_size; size_t class_word_size; ! vsm()->get_initial_chunk_sizes(type, &word_size, &class_word_size); &word_size, &class_word_size); + if (using_class_space()) { assert(class_space_list() != NULL, "Class VirtualSpaceList has not been initialized"); // Allocate SpaceManager for classes. ! _class_vsm = new SpaceManager(Metaspace::ClassType, lock, class_space_list()); ! _class_vsm = new SpaceManager(ClassType, lock, class_space_list()); if (_class_vsm == NULL) { return; } + } MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); // Allocate chunk for metadata objects Metachunk* new_chunk =
*** 2886,2901 **** --- 3050,3067 ---- // Add to this manager's list of chunks in use and current_chunk(). vsm()->add_chunk(new_chunk, true); } // Allocate chunk for class metadata objects + if (using_class_space()) { Metachunk* class_chunk = class_space_list()->get_initialization_chunk(class_word_size, class_vsm()->medium_chunk_bunch()); if (class_chunk != NULL) { class_vsm()->add_chunk(class_chunk, true); } + } _alloc_record_head = NULL; _alloc_record_tail = NULL; }
*** 2904,2914 **** --- 3070,3081 ---- return ReservedSpace::allocation_align_size_up(byte_size) / wordSize; } MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { // DumpSharedSpaces doesn't use class metadata area (yet) if (mdtype == ClassType && !DumpSharedSpaces) { + // Also, don't use class_vsm() unless UseCompressedKlassPointers is true. + if (mdtype == ClassType && using_class_space()) { return class_vsm()->allocate(word_size); } else { return vsm()->allocate(word_size); } }
*** 2935,2962 **** --- 3102,3137 ---- assert(DumpSharedSpaces, "only useful and valid for dumping shared spaces"); return (char*)vsm()->current_chunk()->bottom(); } size_t Metaspace::used_words_slow(MetadataType mdtype) const { // return vsm()->allocated_used_words(); return mdtype == ClassType ? class_vsm()->sum_used_in_chunks_in_use() : vsm()->sum_used_in_chunks_in_use(); // includes overhead! + if (mdtype == ClassType) { + return using_class_space() ? class_vsm()->sum_used_in_chunks_in_use() : 0; + } else { + return vsm()->sum_used_in_chunks_in_use(); // includes overhead! + } } size_t Metaspace::free_words(MetadataType mdtype) const { return mdtype == ClassType ? class_vsm()->sum_free_in_chunks_in_use() : ! vsm()->sum_free_in_chunks_in_use(); + if (mdtype == ClassType) { ! return using_class_space() ? class_vsm()->sum_free_in_chunks_in_use() : 0; + } else { + return vsm()->sum_free_in_chunks_in_use(); + } } // Space capacity in the Metaspace. It includes // space in the list of chunks from which allocations // have been made. Don't include space in the global freelist and // in the space available in the dictionary which // is already counted in some chunk. size_t Metaspace::capacity_words_slow(MetadataType mdtype) const { return mdtype == ClassType ? class_vsm()->sum_capacity_in_chunks_in_use() : ! vsm()->sum_capacity_in_chunks_in_use(); + if (mdtype == ClassType) { ! return using_class_space() ? class_vsm()->sum_capacity_in_chunks_in_use() : 0; + } else { + return vsm()->sum_capacity_in_chunks_in_use(); + } } size_t Metaspace::used_bytes_slow(MetadataType mdtype) const { return used_words_slow(mdtype) * BytesPerWord; }
*** 2975,2985 **** --- 3150,3160 ---- #ifdef ASSERT Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); #endif return; } ! if (is_class && using_class_space()) { class_vsm()->deallocate(ptr, word_size); } else { vsm()->deallocate(ptr, word_size); } } else {
*** 2990,3000 **** --- 3165,3175 ---- #ifdef ASSERT Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); #endif return; } ! if (is_class && using_class_space()) { class_vsm()->deallocate(ptr, word_size); } else { vsm()->deallocate(ptr, word_size); } }
*** 3099,3117 **** --- 3274,3296 ---- void Metaspace::purge() { MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); space_list()->purge(); + if (using_class_space()) { class_space_list()->purge(); + } } void Metaspace::print_on(outputStream* out) const { // Print both class virtual space counts and metaspace. if (Verbose) { vsm()->print_on(out); + if (using_class_space()) { class_vsm()->print_on(out); } + } } bool Metaspace::contains(const void * ptr) { if (MetaspaceShared::is_in_shared_space(ptr)) { return true;
*** 3120,3138 **** --- 3299,3321 ---- // at the end, the pointer will be in one of them. The virtual spaces // aren't deleted presently. When they are, some sort of locking might // be needed. Note, locking this can cause inversion problems with the // caller in MetaspaceObj::is_metadata() function. return space_list()->contains(ptr) || ! (using_class_space() && class_space_list()->contains(ptr)); } void Metaspace::verify() { vsm()->verify(); + if (using_class_space()) { class_vsm()->verify(); + } } void Metaspace::dump(outputStream* const out) const { out->print_cr("\nVirtual space manager: " INTPTR_FORMAT, vsm()); vsm()->dump(out); + if (using_class_space()) { out->print_cr("\nClass space manager: " INTPTR_FORMAT, class_vsm()); class_vsm()->dump(out); + } }

src/share/vm/memory/metaspace.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File