466 } |
466 } |
467 |
467 |
468 return ic->set_to_clean(); |
468 return ic->set_to_clean(); |
469 } |
469 } |
470 |
470 |
471 // static_stub_Relocations may have dangling references to |
|
472 // nmethods so trim them out here. Otherwise it looks like |
|
473 // compiled code is maintaining a link to dead metadata. |
|
474 void CompiledMethod::clean_ic_stubs() { |
|
475 #ifdef ASSERT |
|
476 address low_boundary = oops_reloc_begin(); |
|
477 RelocIterator iter(this, low_boundary); |
|
478 while (iter.next()) { |
|
479 address static_call_addr = NULL; |
|
480 if (iter.type() == relocInfo::opt_virtual_call_type) { |
|
481 CompiledIC* cic = CompiledIC_at(&iter); |
|
482 if (!cic->is_call_to_interpreted()) { |
|
483 static_call_addr = iter.addr(); |
|
484 } |
|
485 } else if (iter.type() == relocInfo::static_call_type) { |
|
486 CompiledStaticCall* csc = compiledStaticCall_at(iter.reloc()); |
|
487 if (!csc->is_call_to_interpreted()) { |
|
488 static_call_addr = iter.addr(); |
|
489 } |
|
490 } |
|
491 if (static_call_addr != NULL) { |
|
492 RelocIterator sciter(this, low_boundary); |
|
493 while (sciter.next()) { |
|
494 if (sciter.type() == relocInfo::static_stub_type && |
|
495 sciter.static_stub_reloc()->static_call() == static_call_addr) { |
|
496 sciter.static_stub_reloc()->clear_inline_cache(); |
|
497 } |
|
498 } |
|
499 } |
|
500 } |
|
501 #endif |
|
502 } |
|
503 |
|
504 // Clean references to unloaded nmethods at addr from this one, which is not unloaded. |
471 // Clean references to unloaded nmethods at addr from this one, which is not unloaded. |
505 template <class CompiledICorStaticCall> |
472 template <class CompiledICorStaticCall> |
506 static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, CompiledMethod* from, |
473 static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, CompiledMethod* from, |
507 bool clean_all) { |
474 bool clean_all) { |
508 // Ok, to lookup references to zombies here |
475 // Ok, to lookup references to zombies here |
547 |
514 |
548 if (!cleanup_inline_caches_impl(unloading_occurred, false)) { |
515 if (!cleanup_inline_caches_impl(unloading_occurred, false)) { |
549 return false; |
516 return false; |
550 } |
517 } |
551 |
518 |
552 // All static stubs need to be cleaned. |
|
553 clean_ic_stubs(); |
|
554 |
|
555 #ifdef ASSERT |
519 #ifdef ASSERT |
556 // Check that the metadata embedded in the nmethod is alive |
520 // Check that the metadata embedded in the nmethod is alive |
557 CheckClass check_class; |
521 CheckClass check_class; |
558 metadata_do(&check_class); |
522 metadata_do(&check_class); |
559 #endif |
523 #endif |
579 ResourceMark rm; |
543 ResourceMark rm; |
580 |
544 |
581 // Find all calls in an nmethod and clear the ones that point to non-entrant, |
545 // Find all calls in an nmethod and clear the ones that point to non-entrant, |
582 // zombie and unloaded nmethods. |
546 // zombie and unloaded nmethods. |
583 RelocIterator iter(this, oops_reloc_begin()); |
547 RelocIterator iter(this, oops_reloc_begin()); |
|
548 bool is_in_static_stub = false; |
584 while(iter.next()) { |
549 while(iter.next()) { |
585 |
550 |
586 switch (iter.type()) { |
551 switch (iter.type()) { |
587 |
552 |
588 case relocInfo::virtual_call_type: |
553 case relocInfo::virtual_call_type: |
608 case relocInfo::static_call_type: |
573 case relocInfo::static_call_type: |
609 if (!clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this, clean_all)) { |
574 if (!clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this, clean_all)) { |
610 return false; |
575 return false; |
611 } |
576 } |
612 break; |
577 break; |
|
578 |
|
579 case relocInfo::static_stub_type: { |
|
580 is_in_static_stub = true; |
|
581 break; |
|
582 } |
|
583 |
|
584 case relocInfo::metadata_type: { |
|
585 // Only the metadata relocations contained in static/opt virtual call stubs |
|
586 // contains the Method* passed to c2i adapters. It is the only metadata |
|
587 // relocation that needs to be walked, as it is the one metadata relocation |
|
588 // that violates the invariant that all metadata relocations have an oop |
|
589 // in the compiled method (due to deferred resolution and code patching). |
|
590 |
|
591 // This causes dead metadata to remain in compiled methods that are not |
|
592 // unloading. Unless these slippery metadata relocations of the static |
|
593 // stubs are at least cleared, subsequent class redefinition operations |
|
594 // will access potentially free memory, and JavaThread execution |
|
595 // concurrent to class unloading may call c2i adapters with dead methods. |
|
596 if (!is_in_static_stub) { |
|
597 // The first metadata relocation after a static stub relocation is the |
|
598 // metadata relocation of the static stub used to pass the Method* to |
|
599 // c2i adapters. |
|
600 continue; |
|
601 } |
|
602 is_in_static_stub = false; |
|
603 metadata_Relocation* r = iter.metadata_reloc(); |
|
604 Metadata* md = r->metadata_value(); |
|
605 if (md != NULL && md->is_method()) { |
|
606 Method* method = static_cast<Method*>(md); |
|
607 if (!method->method_holder()->is_loader_alive()) { |
|
608 Atomic::store((Method*)NULL, r->metadata_addr()); |
|
609 |
|
610 if (!r->metadata_is_immediate()) { |
|
611 r->fix_metadata_relocation(); |
|
612 } |
|
613 } |
|
614 } |
|
615 break; |
|
616 } |
613 |
617 |
614 default: |
618 default: |
615 break; |
619 break; |
616 } |
620 } |
617 } |
621 } |