Mercurial > hg > truffle
comparison src/share/vm/memory/metaspace.cpp @ 17935:7384f6a12fc1
8038212: Method::is_valid_method() check has performance regression impact for stackwalking
Summary: Only prune metaspace virtual spaces at safepoint so walking them is safe outside a safepoint.
Reviewed-by: mgerdin, mgronlun, hseigel, stefank
author | coleenp |
---|---|
date | Thu, 15 May 2014 18:23:26 -0400 |
parents | 270d7cb38f40 |
children | 78bbf4d43a14 |
comparison
equal
deleted
inserted
replaced
17934:366c198c896d | 17935:7384f6a12fc1 |
---|---|
312 | 312 |
313 // Convenience functions for logical bottom and end | 313 // Convenience functions for logical bottom and end |
314 MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } | 314 MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } |
315 MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } | 315 MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } |
316 | 316 |
317 bool contains(const void* ptr) { return ptr >= low() && ptr < high(); } | |
318 | |
317 size_t reserved_words() const { return _virtual_space.reserved_size() / BytesPerWord; } | 319 size_t reserved_words() const { return _virtual_space.reserved_size() / BytesPerWord; } |
318 size_t committed_words() const { return _virtual_space.actual_committed_size() / BytesPerWord; } | 320 size_t committed_words() const { return _virtual_space.actual_committed_size() / BytesPerWord; } |
319 | 321 |
320 bool is_pre_committed() const { return _virtual_space.special(); } | 322 bool is_pre_committed() const { return _virtual_space.special(); } |
321 | 323 |
553 void inc_committed_words(size_t v); | 555 void inc_committed_words(size_t v); |
554 void dec_committed_words(size_t v); | 556 void dec_committed_words(size_t v); |
555 void inc_virtual_space_count(); | 557 void inc_virtual_space_count(); |
556 void dec_virtual_space_count(); | 558 void dec_virtual_space_count(); |
557 | 559 |
560 bool contains(const void* ptr); | |
561 | |
558 // Unlink empty VirtualSpaceNodes and free it. | 562 // Unlink empty VirtualSpaceNodes and free it. |
559 void purge(ChunkManager* chunk_manager); | 563 void purge(ChunkManager* chunk_manager); |
560 | 564 |
561 void print_on(outputStream* st) const; | 565 void print_on(outputStream* st) const; |
562 | 566 |
637 | 641 |
638 private: | 642 private: |
639 // Accessors | 643 // Accessors |
640 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } | 644 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } |
641 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { | 645 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { |
642 // ensure lock-free iteration sees fully initialized node | |
643 OrderAccess::storestore(); | |
644 _chunks_in_use[index] = v; | 646 _chunks_in_use[index] = v; |
645 } | 647 } |
646 | 648 |
647 BlockFreelist* block_freelists() const { | 649 BlockFreelist* block_freelists() const { |
648 return (BlockFreelist*) &_block_freelists; | 650 return (BlockFreelist*) &_block_freelists; |
753 | 755 |
754 void dump(outputStream* const out) const; | 756 void dump(outputStream* const out) const; |
755 void print_on(outputStream* st) const; | 757 void print_on(outputStream* st) const; |
756 void locked_print_chunks_in_use_on(outputStream* st) const; | 758 void locked_print_chunks_in_use_on(outputStream* st) const; |
757 | 759 |
758 bool contains(const void *ptr); | |
759 | |
760 void verify(); | 760 void verify(); |
761 void verify_chunk_size(Metachunk* chunk); | 761 void verify_chunk_size(Metachunk* chunk); |
762 NOT_PRODUCT(void mangle_freed_chunks();) | 762 NOT_PRODUCT(void mangle_freed_chunks();) |
763 #ifdef ASSERT | 763 #ifdef ASSERT |
764 void verify_allocated_blocks_words(); | 764 void verify_allocated_blocks_words(); |
1074 | 1074 |
1075 // Walk the list of VirtualSpaceNodes and delete | 1075 // Walk the list of VirtualSpaceNodes and delete |
1076 // nodes with a 0 container_count. Remove Metachunks in | 1076 // nodes with a 0 container_count. Remove Metachunks in |
1077 // the node from their respective freelists. | 1077 // the node from their respective freelists. |
1078 void VirtualSpaceList::purge(ChunkManager* chunk_manager) { | 1078 void VirtualSpaceList::purge(ChunkManager* chunk_manager) { |
1079 assert(SafepointSynchronize::is_at_safepoint(), "must be called at safepoint for contains to work"); | |
1079 assert_lock_strong(SpaceManager::expand_lock()); | 1080 assert_lock_strong(SpaceManager::expand_lock()); |
1080 // Don't use a VirtualSpaceListIterator because this | 1081 // Don't use a VirtualSpaceListIterator because this |
1081 // list is being changed and a straightforward use of an iterator is not safe. | 1082 // list is being changed and a straightforward use of an iterator is not safe. |
1082 VirtualSpaceNode* purged_vsl = NULL; | 1083 VirtualSpaceNode* purged_vsl = NULL; |
1083 VirtualSpaceNode* prev_vsl = virtual_space_list(); | 1084 VirtualSpaceNode* prev_vsl = virtual_space_list(); |
1107 prev_vsl = vsl; | 1108 prev_vsl = vsl; |
1108 } | 1109 } |
1109 } | 1110 } |
1110 #ifdef ASSERT | 1111 #ifdef ASSERT |
1111 if (purged_vsl != NULL) { | 1112 if (purged_vsl != NULL) { |
1112 // List should be stable enough to use an iterator here. | 1113 // List should be stable enough to use an iterator here. |
1113 VirtualSpaceListIterator iter(virtual_space_list()); | 1114 VirtualSpaceListIterator iter(virtual_space_list()); |
1114 while (iter.repeat()) { | 1115 while (iter.repeat()) { |
1115 VirtualSpaceNode* vsl = iter.get_next(); | 1116 VirtualSpaceNode* vsl = iter.get_next(); |
1116 assert(vsl != purged_vsl, "Purge of vsl failed"); | 1117 assert(vsl != purged_vsl, "Purge of vsl failed"); |
1117 } | 1118 } |
1118 } | 1119 } |
1119 #endif | 1120 #endif |
1121 } | |
1122 | |
1123 | |
1124 // This function looks at the mmap regions in the metaspace without locking. | |
1125 // The chunks are added with store ordering and not deleted except for at | |
1126 // unloading time during a safepoint. | |
1127 bool VirtualSpaceList::contains(const void* ptr) { | |
1128 // List should be stable enough to use an iterator here because removing virtual | |
1129 // space nodes is only allowed at a safepoint. | |
1130 VirtualSpaceListIterator iter(virtual_space_list()); | |
1131 while (iter.repeat()) { | |
1132 VirtualSpaceNode* vsn = iter.get_next(); | |
1133 if (vsn->contains(ptr)) { | |
1134 return true; | |
1135 } | |
1136 } | |
1137 return false; | |
1120 } | 1138 } |
1121 | 1139 |
1122 void VirtualSpaceList::retire_current_virtual_space() { | 1140 void VirtualSpaceList::retire_current_virtual_space() { |
1123 assert_lock_strong(SpaceManager::expand_lock()); | 1141 assert_lock_strong(SpaceManager::expand_lock()); |
1124 | 1142 |
1206 delete new_entry; | 1224 delete new_entry; |
1207 return false; | 1225 return false; |
1208 } else { | 1226 } else { |
1209 assert(new_entry->reserved_words() == vs_word_size, | 1227 assert(new_entry->reserved_words() == vs_word_size, |
1210 "Reserved memory size differs from requested memory size"); | 1228 "Reserved memory size differs from requested memory size"); |
1229 // ensure lock-free iteration sees fully initialized node | |
1230 OrderAccess::storestore(); | |
1211 link_vs(new_entry); | 1231 link_vs(new_entry); |
1212 return true; | 1232 return true; |
1213 } | 1233 } |
1214 } | 1234 } |
1215 | 1235 |
2429 } | 2449 } |
2430 | 2450 |
2431 return result; | 2451 return result; |
2432 } | 2452 } |
2433 | 2453 |
2434 // This function looks at the chunks in the metaspace without locking. | |
2435 // The chunks are added with store ordering and not deleted except for at | |
2436 // unloading time. | |
2437 bool SpaceManager::contains(const void *ptr) { | |
2438 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) | |
2439 { | |
2440 Metachunk* curr = chunks_in_use(i); | |
2441 while (curr != NULL) { | |
2442 if (curr->contains(ptr)) return true; | |
2443 curr = curr->next(); | |
2444 } | |
2445 } | |
2446 return false; | |
2447 } | |
2448 | |
2449 void SpaceManager::verify() { | 2454 void SpaceManager::verify() { |
2450 // If there are blocks in the dictionary, then | 2455 // If there are blocks in the dictionary, then |
2451 // verfication of chunks does not work since | 2456 // verfication of chunks does not work since |
2452 // being in the dictionary alters a chunk. | 2457 // being in the dictionary alters a chunk. |
2453 if (block_freelists()->total_size() == 0) { | 2458 if (block_freelists()->total_size() == 0) { |
3548 } | 3553 } |
3549 } | 3554 } |
3550 } | 3555 } |
3551 | 3556 |
3552 bool Metaspace::contains(const void* ptr) { | 3557 bool Metaspace::contains(const void* ptr) { |
3553 if (vsm()->contains(ptr)) return true; | 3558 if (UseSharedSpaces && MetaspaceShared::is_in_shared_space(ptr)) { |
3554 if (using_class_space()) { | 3559 return true; |
3555 return class_vsm()->contains(ptr); | 3560 } |
3556 } | 3561 |
3557 return false; | 3562 if (using_class_space() && get_space_list(ClassType)->contains(ptr)) { |
3563 return true; | |
3564 } | |
3565 | |
3566 return get_space_list(NonClassType)->contains(ptr); | |
3558 } | 3567 } |
3559 | 3568 |
3560 void Metaspace::verify() { | 3569 void Metaspace::verify() { |
3561 vsm()->verify(); | 3570 vsm()->verify(); |
3562 if (using_class_space()) { | 3571 if (using_class_space()) { |
3797 | 3806 |
3798 void TestVirtualSpaceNode_test() { | 3807 void TestVirtualSpaceNode_test() { |
3799 TestVirtualSpaceNodeTest::test(); | 3808 TestVirtualSpaceNodeTest::test(); |
3800 TestVirtualSpaceNodeTest::test_is_available(); | 3809 TestVirtualSpaceNodeTest::test_is_available(); |
3801 } | 3810 } |
3802 | |
3803 #endif | 3811 #endif |