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 |
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() |