Mercurial > hg > truffle
comparison src/share/vm/memory/metaspace.cpp @ 14190:ce86c36b8921
8029178: Parallel class loading test anonymous-simple gets SIGSEGV in Metaspace::contains
Summary: Metaspace::contains cannot look at purged metaspaces while CMS concurrently deallocates them.
Reviewed-by: mgerdin, sspitsyn, jmasa
author | coleenp |
---|---|
date | Tue, 07 Jan 2014 13:26:56 -0500 |
parents | 11b116661830 |
children | db1ff6781ab4 |
comparison
equal
deleted
inserted
replaced
14189:1a899ea6b7ed | 14190:ce86c36b8921 |
---|---|
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 |
705 // debugging support. | 707 // debugging support. |
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; |
712 | |
713 bool contains(const void *ptr); | |
710 | 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 |
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 |
2390 } | 2379 } |
2391 | 2380 |
2392 return result; | 2381 return result; |
2393 } | 2382 } |
2394 | 2383 |
2384 // This function looks at the chunks in the metaspace without locking. | |
2385 // The chunks are added with store ordering and not deleted except for at | |
2386 // unloading time. | |
2387 bool SpaceManager::contains(const void *ptr) { | |
2388 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) | |
2389 { | |
2390 Metachunk* curr = chunks_in_use(i); | |
2391 while (curr != NULL) { | |
2392 if (curr->contains(ptr)) return true; | |
2393 curr = curr->next(); | |
2394 } | |
2395 } | |
2396 return false; | |
2397 } | |
2398 | |
2395 void SpaceManager::verify() { | 2399 void SpaceManager::verify() { |
2396 // If there are blocks in the dictionary, then | 2400 // If there are blocks in the dictionary, then |
2397 // verfication of chunks does not work since | 2401 // verfication of chunks does not work since |
2398 // being in the dictionary alters a chunk. | 2402 // being in the dictionary alters a chunk. |
2399 if (block_freelists()->total_size() == 0) { | 2403 if (block_freelists()->total_size() == 0) { |
3461 class_vsm()->print_on(out); | 3465 class_vsm()->print_on(out); |
3462 } | 3466 } |
3463 } | 3467 } |
3464 } | 3468 } |
3465 | 3469 |
3466 bool Metaspace::contains(const void * ptr) { | 3470 bool Metaspace::contains(const void* ptr) { |
3467 if (MetaspaceShared::is_in_shared_space(ptr)) { | 3471 if (vsm()->contains(ptr)) return true; |
3468 return true; | 3472 if (using_class_space()) { |
3469 } | 3473 return class_vsm()->contains(ptr); |
3470 // This is checked while unlocked. As long as the virtualspaces are added | 3474 } |
3471 // at the end, the pointer will be in one of them. The virtual spaces | 3475 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 } | 3476 } |
3478 | 3477 |
3479 void Metaspace::verify() { | 3478 void Metaspace::verify() { |
3480 vsm()->verify(); | 3479 vsm()->verify(); |
3481 if (using_class_space()) { | 3480 if (using_class_space()) { |