Mercurial > hg > truffle
comparison src/share/vm/memory/metaspace.cpp @ 14521:29ccc4cbabca
Merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 12 Mar 2014 13:30:08 +0100 |
parents | aa8fab3bed11 |
children | 4ca6dc0799b6 |
comparison
equal
deleted
inserted
replaced
14520:f84115370178 | 14521:29ccc4cbabca |
---|---|
44 #include "services/memTracker.hpp" | 44 #include "services/memTracker.hpp" |
45 #include "services/memoryService.hpp" | 45 #include "services/memoryService.hpp" |
46 #include "utilities/copy.hpp" | 46 #include "utilities/copy.hpp" |
47 #include "utilities/debug.hpp" | 47 #include "utilities/debug.hpp" |
48 | 48 |
49 typedef BinaryTreeDictionary<Metablock, FreeList> BlockTreeDictionary; | 49 typedef BinaryTreeDictionary<Metablock, FreeList<Metablock> > BlockTreeDictionary; |
50 typedef BinaryTreeDictionary<Metachunk, FreeList> ChunkTreeDictionary; | 50 typedef BinaryTreeDictionary<Metachunk, FreeList<Metachunk> > ChunkTreeDictionary; |
51 | 51 |
52 // Set this constant to enable slow integrity checking of the free chunk lists | 52 // Set this constant to enable slow integrity checking of the free chunk lists |
53 const bool metaspace_slow_verify = false; | 53 const bool metaspace_slow_verify = false; |
54 | 54 |
55 size_t const allocation_from_dictionary_limit = 4 * K; | 55 size_t const allocation_from_dictionary_limit = 4 * K; |
511 void dec_virtual_space_count(); | 511 void dec_virtual_space_count(); |
512 | 512 |
513 // Unlink empty VirtualSpaceNodes and free it. | 513 // Unlink empty VirtualSpaceNodes and free it. |
514 void purge(ChunkManager* chunk_manager); | 514 void purge(ChunkManager* chunk_manager); |
515 | 515 |
516 bool contains(const void *ptr); | |
517 | |
518 void print_on(outputStream* st) const; | 516 void print_on(outputStream* st) const; |
519 | 517 |
520 class VirtualSpaceListIterator : public StackObj { | 518 class VirtualSpaceListIterator : public StackObj { |
521 VirtualSpaceNode* _virtual_spaces; | 519 VirtualSpaceNode* _virtual_spaces; |
522 public: | 520 public: |
556 friend class Metaspace; | 554 friend class Metaspace; |
557 friend class Metadebug; | 555 friend class Metadebug; |
558 | 556 |
559 private: | 557 private: |
560 | 558 |
561 // protects allocations and contains. | 559 // protects allocations |
562 Mutex* const _lock; | 560 Mutex* const _lock; |
563 | 561 |
564 // Type of metadata allocated. | 562 // Type of metadata allocated. |
565 Metaspace::MetadataType _mdtype; | 563 Metaspace::MetadataType _mdtype; |
566 | 564 |
593 static Mutex* const _expand_lock; | 591 static Mutex* const _expand_lock; |
594 | 592 |
595 private: | 593 private: |
596 // Accessors | 594 // Accessors |
597 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } | 595 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } |
598 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { _chunks_in_use[index] = v; } | 596 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { |
597 // ensure lock-free iteration sees fully initialized node | |
598 OrderAccess::storestore(); | |
599 _chunks_in_use[index] = v; | |
600 } | |
599 | 601 |
600 BlockFreelist* block_freelists() const { | 602 BlockFreelist* block_freelists() const { |
601 return (BlockFreelist*) &_block_freelists; | 603 return (BlockFreelist*) &_block_freelists; |
602 } | 604 } |
603 | 605 |
706 | 708 |
707 void dump(outputStream* const out) const; | 709 void dump(outputStream* const out) const; |
708 void print_on(outputStream* st) const; | 710 void print_on(outputStream* st) const; |
709 void locked_print_chunks_in_use_on(outputStream* st) const; | 711 void locked_print_chunks_in_use_on(outputStream* st) const; |
710 | 712 |
713 bool contains(const void *ptr); | |
714 | |
711 void verify(); | 715 void verify(); |
712 void verify_chunk_size(Metachunk* chunk); | 716 void verify_chunk_size(Metachunk* chunk); |
713 NOT_PRODUCT(void mangle_freed_chunks();) | 717 NOT_PRODUCT(void mangle_freed_chunks();) |
714 #ifdef ASSERT | 718 #ifdef ASSERT |
715 void verify_allocated_blocks_words(); | 719 void verify_allocated_blocks_words(); |
740 | 744 |
741 void VirtualSpaceNode::inc_container_count() { | 745 void VirtualSpaceNode::inc_container_count() { |
742 assert_lock_strong(SpaceManager::expand_lock()); | 746 assert_lock_strong(SpaceManager::expand_lock()); |
743 _container_count++; | 747 _container_count++; |
744 assert(_container_count == container_count_slow(), | 748 assert(_container_count == container_count_slow(), |
745 err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT | 749 err_msg("Inconsistency in container_count _container_count " SIZE_FORMAT |
746 " container_count_slow() " SIZE_FORMAT, | 750 " container_count_slow() " SIZE_FORMAT, |
747 _container_count, container_count_slow())); | 751 _container_count, container_count_slow())); |
748 } | 752 } |
749 | 753 |
750 void VirtualSpaceNode::dec_container_count() { | 754 void VirtualSpaceNode::dec_container_count() { |
753 } | 757 } |
754 | 758 |
755 #ifdef ASSERT | 759 #ifdef ASSERT |
756 void VirtualSpaceNode::verify_container_count() { | 760 void VirtualSpaceNode::verify_container_count() { |
757 assert(_container_count == container_count_slow(), | 761 assert(_container_count == container_count_slow(), |
758 err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT | 762 err_msg("Inconsistency in container_count _container_count " SIZE_FORMAT |
759 " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); | 763 " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); |
760 } | 764 } |
761 #endif | 765 #endif |
762 | 766 |
763 // BlockFreelist methods | 767 // BlockFreelist methods |
784 MetaWord* BlockFreelist::get_block(size_t word_size) { | 788 MetaWord* BlockFreelist::get_block(size_t word_size) { |
785 if (dictionary() == NULL) { | 789 if (dictionary() == NULL) { |
786 return NULL; | 790 return NULL; |
787 } | 791 } |
788 | 792 |
789 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) { | 793 if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) { |
790 // Dark matter. Too small for dictionary. | 794 // Dark matter. Too small for dictionary. |
791 return NULL; | 795 return NULL; |
792 } | 796 } |
793 | 797 |
794 Metablock* free_block = | 798 Metablock* free_block = |
804 } | 808 } |
805 | 809 |
806 MetaWord* new_block = (MetaWord*)free_block; | 810 MetaWord* new_block = (MetaWord*)free_block; |
807 assert(block_size >= word_size, "Incorrect size of block from freelist"); | 811 assert(block_size >= word_size, "Incorrect size of block from freelist"); |
808 const size_t unused = block_size - word_size; | 812 const size_t unused = block_size - word_size; |
809 if (unused >= TreeChunk<Metablock, FreeList>::min_size()) { | 813 if (unused >= TreeChunk<Metablock, FreeList<Metablock> >::min_size()) { |
810 return_block(new_block + word_size, unused); | 814 return_block(new_block + word_size, unused); |
811 } | 815 } |
812 | 816 |
813 return new_block; | 817 return new_block; |
814 } | 818 } |
1157 delete new_entry; | 1161 delete new_entry; |
1158 return false; | 1162 return false; |
1159 } else { | 1163 } else { |
1160 assert(new_entry->reserved_words() == vs_word_size, | 1164 assert(new_entry->reserved_words() == vs_word_size, |
1161 "Reserved memory size differs from requested memory size"); | 1165 "Reserved memory size differs from requested memory size"); |
1162 // ensure lock-free iteration sees fully initialized node | |
1163 OrderAccess::storestore(); | |
1164 link_vs(new_entry); | 1166 link_vs(new_entry); |
1165 return true; | 1167 return true; |
1166 } | 1168 } |
1167 } | 1169 } |
1168 | 1170 |
1284 VirtualSpaceNode* node = iter.get_next(); | 1286 VirtualSpaceNode* node = iter.get_next(); |
1285 node->print_on(st); | 1287 node->print_on(st); |
1286 } | 1288 } |
1287 } | 1289 } |
1288 } | 1290 } |
1289 | |
1290 bool VirtualSpaceList::contains(const void *ptr) { | |
1291 VirtualSpaceNode* list = virtual_space_list(); | |
1292 VirtualSpaceListIterator iter(list); | |
1293 while (iter.repeat()) { | |
1294 VirtualSpaceNode* node = iter.get_next(); | |
1295 if (node->reserved()->contains(ptr)) { | |
1296 return true; | |
1297 } | |
1298 } | |
1299 return false; | |
1300 } | |
1301 | |
1302 | 1291 |
1303 // MetaspaceGC methods | 1292 // MetaspaceGC methods |
1304 | 1293 |
1305 // VM_CollectForMetadataAllocation is the vm operation used to GC. | 1294 // VM_CollectForMetadataAllocation is the vm operation used to GC. |
1306 // Within the VM operation after the GC the attempt to allocate the metadata | 1295 // Within the VM operation after the GC the attempt to allocate the metadata |
1464 return; | 1453 return; |
1465 } | 1454 } |
1466 | 1455 |
1467 // No expansion, now see if we want to shrink | 1456 // No expansion, now see if we want to shrink |
1468 // We would never want to shrink more than this | 1457 // We would never want to shrink more than this |
1458 assert(capacity_until_GC >= minimum_desired_capacity, | |
1459 err_msg(SIZE_FORMAT " >= " SIZE_FORMAT, | |
1460 capacity_until_GC, minimum_desired_capacity)); | |
1469 size_t max_shrink_bytes = capacity_until_GC - minimum_desired_capacity; | 1461 size_t max_shrink_bytes = capacity_until_GC - minimum_desired_capacity; |
1470 assert(max_shrink_bytes >= 0, err_msg("max_shrink_bytes " SIZE_FORMAT, | |
1471 max_shrink_bytes)); | |
1472 | 1462 |
1473 // Should shrinking be considered? | 1463 // Should shrinking be considered? |
1474 if (MaxMetaspaceFreeRatio < 100) { | 1464 if (MaxMetaspaceFreeRatio < 100) { |
1475 const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0; | 1465 const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0; |
1476 const double minimum_used_percentage = 1.0 - maximum_free_percentage; | 1466 const double minimum_used_percentage = 1.0 - maximum_free_percentage; |
2248 } | 2238 } |
2249 | 2239 |
2250 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { | 2240 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { |
2251 assert_lock_strong(_lock); | 2241 assert_lock_strong(_lock); |
2252 size_t raw_word_size = get_raw_word_size(word_size); | 2242 size_t raw_word_size = get_raw_word_size(word_size); |
2253 size_t min_size = TreeChunk<Metablock, FreeList>::min_size(); | 2243 size_t min_size = TreeChunk<Metablock, FreeList<Metablock> >::min_size(); |
2254 assert(raw_word_size >= min_size, | 2244 assert(raw_word_size >= min_size, |
2255 err_msg("Should not deallocate dark matter " SIZE_FORMAT "<" SIZE_FORMAT, word_size, min_size)); | 2245 err_msg("Should not deallocate dark matter " SIZE_FORMAT "<" SIZE_FORMAT, word_size, min_size)); |
2256 block_freelists()->return_block(p, raw_word_size); | 2246 block_freelists()->return_block(p, raw_word_size); |
2257 } | 2247 } |
2258 | 2248 |
2304 } | 2294 } |
2305 | 2295 |
2306 void SpaceManager::retire_current_chunk() { | 2296 void SpaceManager::retire_current_chunk() { |
2307 if (current_chunk() != NULL) { | 2297 if (current_chunk() != NULL) { |
2308 size_t remaining_words = current_chunk()->free_word_size(); | 2298 size_t remaining_words = current_chunk()->free_word_size(); |
2309 if (remaining_words >= TreeChunk<Metablock, FreeList>::min_size()) { | 2299 if (remaining_words >= TreeChunk<Metablock, FreeList<Metablock> >::min_size()) { |
2310 block_freelists()->return_block(current_chunk()->allocate(remaining_words), remaining_words); | 2300 block_freelists()->return_block(current_chunk()->allocate(remaining_words), remaining_words); |
2311 inc_used_metrics(remaining_words); | 2301 inc_used_metrics(remaining_words); |
2312 } | 2302 } |
2313 } | 2303 } |
2314 } | 2304 } |
2390 } | 2380 } |
2391 | 2381 |
2392 return result; | 2382 return result; |
2393 } | 2383 } |
2394 | 2384 |
2385 // This function looks at the chunks in the metaspace without locking. | |
2386 // The chunks are added with store ordering and not deleted except for at | |
2387 // unloading time. | |
2388 bool SpaceManager::contains(const void *ptr) { | |
2389 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) | |
2390 { | |
2391 Metachunk* curr = chunks_in_use(i); | |
2392 while (curr != NULL) { | |
2393 if (curr->contains(ptr)) return true; | |
2394 curr = curr->next(); | |
2395 } | |
2396 } | |
2397 return false; | |
2398 } | |
2399 | |
2395 void SpaceManager::verify() { | 2400 void SpaceManager::verify() { |
2396 // If there are blocks in the dictionary, then | 2401 // If there are blocks in the dictionary, then |
2397 // verfication of chunks does not work since | 2402 // verification of chunks does not work since |
2398 // being in the dictionary alters a chunk. | 2403 // being in the dictionary alters a chunk. |
2399 if (block_freelists()->total_size() == 0) { | 2404 if (block_freelists()->total_size() == 0) { |
2400 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { | 2405 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
2401 Metachunk* curr = chunks_in_use(i); | 2406 Metachunk* curr = chunks_in_use(i); |
2402 while (curr != NULL) { | 2407 while (curr != NULL) { |
2861 lower_base = metaspace_base; | 2866 lower_base = metaspace_base; |
2862 | 2867 |
2863 uint64_t klass_encoding_max = UnscaledClassSpaceMax << LogKlassAlignmentInBytes; | 2868 uint64_t klass_encoding_max = UnscaledClassSpaceMax << LogKlassAlignmentInBytes; |
2864 // If compressed class space fits in lower 32G, we don't need a base. | 2869 // If compressed class space fits in lower 32G, we don't need a base. |
2865 if (higher_address <= (address)klass_encoding_max) { | 2870 if (higher_address <= (address)klass_encoding_max) { |
2866 lower_base = 0; // effectively lower base is zero. | 2871 lower_base = 0; // Effectively lower base is zero. |
2867 } | 2872 } |
2868 } | 2873 } |
2869 | 2874 |
2870 Universe::set_narrow_klass_base(lower_base); | 2875 Universe::set_narrow_klass_base(lower_base); |
2871 | 2876 |
3272 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { | 3277 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { |
3273 if (SafepointSynchronize::is_at_safepoint()) { | 3278 if (SafepointSynchronize::is_at_safepoint()) { |
3274 assert(Thread::current()->is_VM_thread(), "should be the VM thread"); | 3279 assert(Thread::current()->is_VM_thread(), "should be the VM thread"); |
3275 // Don't take Heap_lock | 3280 // Don't take Heap_lock |
3276 MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); | 3281 MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); |
3277 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) { | 3282 if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) { |
3278 // Dark matter. Too small for dictionary. | 3283 // Dark matter. Too small for dictionary. |
3279 #ifdef ASSERT | 3284 #ifdef ASSERT |
3280 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); | 3285 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); |
3281 #endif | 3286 #endif |
3282 return; | 3287 return; |
3287 vsm()->deallocate(ptr, word_size); | 3292 vsm()->deallocate(ptr, word_size); |
3288 } | 3293 } |
3289 } else { | 3294 } else { |
3290 MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); | 3295 MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); |
3291 | 3296 |
3292 if (word_size < TreeChunk<Metablock, FreeList>::min_size()) { | 3297 if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) { |
3293 // Dark matter. Too small for dictionary. | 3298 // Dark matter. Too small for dictionary. |
3294 #ifdef ASSERT | 3299 #ifdef ASSERT |
3295 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); | 3300 Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); |
3296 #endif | 3301 #endif |
3297 return; | 3302 return; |
3461 class_vsm()->print_on(out); | 3466 class_vsm()->print_on(out); |
3462 } | 3467 } |
3463 } | 3468 } |
3464 } | 3469 } |
3465 | 3470 |
3466 bool Metaspace::contains(const void * ptr) { | 3471 bool Metaspace::contains(const void* ptr) { |
3467 if (MetaspaceShared::is_in_shared_space(ptr)) { | 3472 if (vsm()->contains(ptr)) return true; |
3468 return true; | 3473 if (using_class_space()) { |
3469 } | 3474 return class_vsm()->contains(ptr); |
3470 // This is checked while unlocked. As long as the virtualspaces are added | 3475 } |
3471 // at the end, the pointer will be in one of them. The virtual spaces | 3476 return false; |
3472 // aren't deleted presently. When they are, some sort of locking might | |
3473 // be needed. Note, locking this can cause inversion problems with the | |
3474 // caller in MetaspaceObj::is_metadata() function. | |
3475 return space_list()->contains(ptr) || | |
3476 (using_class_space() && class_space_list()->contains(ptr)); | |
3477 } | 3477 } |
3478 | 3478 |
3479 void Metaspace::verify() { | 3479 void Metaspace::verify() { |
3480 vsm()->verify(); | 3480 vsm()->verify(); |
3481 if (using_class_space()) { | 3481 if (using_class_space()) { |