Mercurial > hg > truffle
comparison src/share/vm/oops/instanceKlass.cpp @ 12281:4f9a42c33738
8022887: Assertion hit while using class and redefining it with RedefineClasses simultaneously
Summary: Need to refetch each method from InstanceKlass after all safepoints. Removed leaky PreviousVersionInfo code.
Reviewed-by: dcubed, sspitsyn
author | coleenp |
---|---|
date | Fri, 20 Sep 2013 09:30:02 -0400 |
parents | e22ee8e7ae62 |
children | 0f37d1badced |
comparison
equal
deleted
inserted
replaced
12279:6eb908998b32 | 12281:4f9a42c33738 |
---|---|
2845 st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr(); | 2845 st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr(); |
2846 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); | 2846 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); |
2847 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); | 2847 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); |
2848 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); | 2848 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); |
2849 { | 2849 { |
2850 ResourceMark rm; | 2850 bool have_pv = false; |
2851 // PreviousVersionInfo objects returned via PreviousVersionWalker | 2851 PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); |
2852 // contain a GrowableArray of handles. We have to clean up the | 2852 for (PreviousVersionNode * pv_node = pvw.next_previous_version(); |
2853 // GrowableArray _after_ the PreviousVersionWalker destructor | 2853 pv_node != NULL; pv_node = pvw.next_previous_version()) { |
2854 // has destroyed the handles. | 2854 if (!have_pv) |
2855 { | 2855 st->print(BULLET"previous version: "); |
2856 bool have_pv = false; | 2856 have_pv = true; |
2857 PreviousVersionWalker pvw((InstanceKlass*)this); | 2857 pv_node->prev_constant_pool()->print_value_on(st); |
2858 for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); | 2858 } |
2859 pv_info != NULL; pv_info = pvw.next_previous_version()) { | 2859 if (have_pv) st->cr(); |
2860 if (!have_pv) | 2860 } // pvw is cleaned up |
2861 st->print(BULLET"previous version: "); | |
2862 have_pv = true; | |
2863 pv_info->prev_constant_pool_handle()()->print_value_on(st); | |
2864 } | |
2865 if (have_pv) st->cr(); | |
2866 } // pvw is cleaned up | |
2867 } // rm is cleaned up | |
2868 | 2861 |
2869 if (generic_signature() != NULL) { | 2862 if (generic_signature() != NULL) { |
2870 st->print(BULLET"generic signature: "); | 2863 st->print(BULLET"generic signature: "); |
2871 generic_signature()->print_value_on(st); | 2864 generic_signature()->print_value_on(st); |
2872 st->cr(); | 2865 st->cr(); |
3390 // we don't need to create a new PreviousVersionNode. However, | 3383 // we don't need to create a new PreviousVersionNode. However, |
3391 // we still need to examine older previous versions below. | 3384 // we still need to examine older previous versions below. |
3392 Array<Method*>* old_methods = ikh->methods(); | 3385 Array<Method*>* old_methods = ikh->methods(); |
3393 | 3386 |
3394 if (cp_ref->on_stack()) { | 3387 if (cp_ref->on_stack()) { |
3395 PreviousVersionNode * pv_node = NULL; | 3388 PreviousVersionNode * pv_node = NULL; |
3396 if (emcp_method_count == 0) { | 3389 if (emcp_method_count == 0) { |
3397 // non-shared ConstantPool gets a reference | 3390 // non-shared ConstantPool gets a reference |
3398 pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), NULL); | 3391 pv_node = new PreviousVersionNode(cp_ref, NULL); |
3399 RC_TRACE(0x00000400, | 3392 RC_TRACE(0x00000400, |
3400 ("add: all methods are obsolete; flushing any EMCP refs")); | 3393 ("add: all methods are obsolete; flushing any EMCP refs")); |
3401 } else { | 3394 } else { |
3402 int local_count = 0; | 3395 int local_count = 0; |
3403 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) | 3396 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) |
3404 GrowableArray<Method*>(emcp_method_count, true); | 3397 GrowableArray<Method*>(emcp_method_count, true); |
3405 for (int i = 0; i < old_methods->length(); i++) { | 3398 for (int i = 0; i < old_methods->length(); i++) { |
3406 if (emcp_methods->at(i)) { | 3399 if (emcp_methods->at(i)) { |
3407 // this old method is EMCP. Save it only if it's on the stack | 3400 // this old method is EMCP. Save it only if it's on the stack |
3408 Method* old_method = old_methods->at(i); | 3401 Method* old_method = old_methods->at(i); |
3409 if (old_method->on_stack()) { | 3402 if (old_method->on_stack()) { |
3410 method_refs->append(old_method); | 3403 method_refs->append(old_method); |
3404 } | |
3405 if (++local_count >= emcp_method_count) { | |
3406 // no more EMCP methods so bail out now | |
3407 break; | |
3411 } | 3408 } |
3412 if (++local_count >= emcp_method_count) { | |
3413 // no more EMCP methods so bail out now | |
3414 break; | |
3415 } | 3409 } |
3416 } | 3410 } |
3417 } | |
3418 // non-shared ConstantPool gets a reference | 3411 // non-shared ConstantPool gets a reference |
3419 pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), method_refs); | 3412 pv_node = new PreviousVersionNode(cp_ref, method_refs); |
3420 } | 3413 } |
3421 // append new previous version. | 3414 // append new previous version. |
3422 _previous_versions->append(pv_node); | 3415 _previous_versions->append(pv_node); |
3423 } | 3416 } |
3424 | 3417 |
3425 // Since the caller is the VMThread and we are at a safepoint, this | 3418 // Since the caller is the VMThread and we are at a safepoint, this |
3426 // is a good time to clear out unused references. | 3419 // is a good time to clear out unused references. |
3427 | 3420 |
3518 m = methods()->at(index); | 3511 m = methods()->at(index); |
3519 if (m->method_idnum() == idnum) { | 3512 if (m->method_idnum() == idnum) { |
3520 return m; | 3513 return m; |
3521 } | 3514 } |
3522 } | 3515 } |
3516 // None found, return null for the caller to handle. | |
3517 return NULL; | |
3523 } | 3518 } |
3524 return m; | 3519 return m; |
3525 } | 3520 } |
3526 | 3521 |
3527 jint InstanceKlass::get_cached_class_file_len() { | 3522 jint InstanceKlass::get_cached_class_file_len() { |
3534 | 3529 |
3535 | 3530 |
3536 // Construct a PreviousVersionNode entry for the array hung off | 3531 // Construct a PreviousVersionNode entry for the array hung off |
3537 // the InstanceKlass. | 3532 // the InstanceKlass. |
3538 PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, | 3533 PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, |
3539 bool prev_cp_is_weak, GrowableArray<Method*>* prev_EMCP_methods) { | 3534 GrowableArray<Method*>* prev_EMCP_methods) { |
3540 | 3535 |
3541 _prev_constant_pool = prev_constant_pool; | 3536 _prev_constant_pool = prev_constant_pool; |
3542 _prev_cp_is_weak = prev_cp_is_weak; | |
3543 _prev_EMCP_methods = prev_EMCP_methods; | 3537 _prev_EMCP_methods = prev_EMCP_methods; |
3544 } | 3538 } |
3545 | 3539 |
3546 | 3540 |
3547 // Destroy a PreviousVersionNode | 3541 // Destroy a PreviousVersionNode |
3553 if (_prev_EMCP_methods != NULL) { | 3547 if (_prev_EMCP_methods != NULL) { |
3554 delete _prev_EMCP_methods; | 3548 delete _prev_EMCP_methods; |
3555 } | 3549 } |
3556 } | 3550 } |
3557 | 3551 |
3558 | |
3559 // Construct a PreviousVersionInfo entry | |
3560 PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) { | |
3561 _prev_constant_pool_handle = constantPoolHandle(); // NULL handle | |
3562 _prev_EMCP_method_handles = NULL; | |
3563 | |
3564 ConstantPool* cp = pv_node->prev_constant_pool(); | |
3565 assert(cp != NULL, "constant pool ref was unexpectedly cleared"); | |
3566 if (cp == NULL) { | |
3567 return; // robustness | |
3568 } | |
3569 | |
3570 // make the ConstantPool* safe to return | |
3571 _prev_constant_pool_handle = constantPoolHandle(cp); | |
3572 | |
3573 GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); | |
3574 if (method_refs == NULL) { | |
3575 // the InstanceKlass did not have any EMCP methods | |
3576 return; | |
3577 } | |
3578 | |
3579 _prev_EMCP_method_handles = new GrowableArray<methodHandle>(10); | |
3580 | |
3581 int n_methods = method_refs->length(); | |
3582 for (int i = 0; i < n_methods; i++) { | |
3583 Method* method = method_refs->at(i); | |
3584 assert (method != NULL, "method has been cleared"); | |
3585 if (method == NULL) { | |
3586 continue; // robustness | |
3587 } | |
3588 // make the Method* safe to return | |
3589 _prev_EMCP_method_handles->append(methodHandle(method)); | |
3590 } | |
3591 } | |
3592 | |
3593 | |
3594 // Destroy a PreviousVersionInfo | |
3595 PreviousVersionInfo::~PreviousVersionInfo() { | |
3596 // Since _prev_EMCP_method_handles is not C-heap allocated, we | |
3597 // don't have to delete it. | |
3598 } | |
3599 | |
3600 | |
3601 // Construct a helper for walking the previous versions array | 3552 // Construct a helper for walking the previous versions array |
3602 PreviousVersionWalker::PreviousVersionWalker(InstanceKlass *ik) { | 3553 PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) { |
3554 _thread = thread; | |
3603 _previous_versions = ik->previous_versions(); | 3555 _previous_versions = ik->previous_versions(); |
3604 _current_index = 0; | 3556 _current_index = 0; |
3605 // _hm needs no initialization | |
3606 _current_p = NULL; | 3557 _current_p = NULL; |
3607 } | 3558 _current_constant_pool_handle = constantPoolHandle(thread, ik->constants()); |
3608 | |
3609 | |
3610 // Destroy a PreviousVersionWalker | |
3611 PreviousVersionWalker::~PreviousVersionWalker() { | |
3612 // Delete the current info just in case the caller didn't walk to | |
3613 // the end of the previous versions list. No harm if _current_p is | |
3614 // already NULL. | |
3615 delete _current_p; | |
3616 | |
3617 // When _hm is destroyed, all the Handles returned in | |
3618 // PreviousVersionInfo objects will be destroyed. | |
3619 // Also, after this destructor is finished it will be | |
3620 // safe to delete the GrowableArray allocated in the | |
3621 // PreviousVersionInfo objects. | |
3622 } | 3559 } |
3623 | 3560 |
3624 | 3561 |
3625 // Return the interesting information for the next previous version | 3562 // Return the interesting information for the next previous version |
3626 // of the klass. Returns NULL if there are no more previous versions. | 3563 // of the klass. Returns NULL if there are no more previous versions. |
3627 PreviousVersionInfo* PreviousVersionWalker::next_previous_version() { | 3564 PreviousVersionNode* PreviousVersionWalker::next_previous_version() { |
3628 if (_previous_versions == NULL) { | 3565 if (_previous_versions == NULL) { |
3629 // no previous versions so nothing to return | 3566 // no previous versions so nothing to return |
3630 return NULL; | 3567 return NULL; |
3631 } | 3568 } |
3632 | 3569 |
3633 delete _current_p; // cleanup the previous info for the caller | 3570 _current_p = NULL; // reset to NULL |
3634 _current_p = NULL; // reset to NULL so we don't delete same object twice | 3571 _current_constant_pool_handle = NULL; |
3635 | 3572 |
3636 int length = _previous_versions->length(); | 3573 int length = _previous_versions->length(); |
3637 | 3574 |
3638 while (_current_index < length) { | 3575 while (_current_index < length) { |
3639 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); | 3576 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); |
3640 PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP, mtClass) | 3577 |
3641 PreviousVersionInfo(pv_node); | 3578 // Save a handle to the constant pool for this previous version, |
3642 | 3579 // which keeps all the methods from being deallocated. |
3643 constantPoolHandle cp_h = pv_info->prev_constant_pool_handle(); | 3580 _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool()); |
3644 assert (!cp_h.is_null(), "null cp found in previous version"); | 3581 _current_p = pv_node; |
3645 | 3582 return pv_node; |
3646 // The caller will need to delete pv_info when they are done with it. | 3583 } |
3647 _current_p = pv_info; | 3584 |
3648 return pv_info; | |
3649 } | |
3650 | |
3651 // all of the underlying nodes' info has been deleted | |
3652 return NULL; | 3585 return NULL; |
3653 } // end next_previous_version() | 3586 } // end next_previous_version() |