2767 st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr(); |
2767 st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr(); |
2768 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); |
2768 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); |
2769 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); |
2769 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); |
2770 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); |
2770 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); |
2771 { |
2771 { |
2772 ResourceMark rm; |
2772 bool have_pv = false; |
2773 // PreviousVersionInfo objects returned via PreviousVersionWalker |
2773 PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); |
2774 // contain a GrowableArray of handles. We have to clean up the |
2774 for (PreviousVersionNode * pv_node = pvw.next_previous_version(); |
2775 // GrowableArray _after_ the PreviousVersionWalker destructor |
2775 pv_node != NULL; pv_node = pvw.next_previous_version()) { |
2776 // has destroyed the handles. |
2776 if (!have_pv) |
2777 { |
2777 st->print(BULLET"previous version: "); |
2778 bool have_pv = false; |
2778 have_pv = true; |
2779 PreviousVersionWalker pvw((InstanceKlass*)this); |
2779 pv_node->prev_constant_pool()->print_value_on(st); |
2780 for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); |
2780 } |
2781 pv_info != NULL; pv_info = pvw.next_previous_version()) { |
2781 if (have_pv) st->cr(); |
2782 if (!have_pv) |
2782 } // pvw is cleaned up |
2783 st->print(BULLET"previous version: "); |
|
2784 have_pv = true; |
|
2785 pv_info->prev_constant_pool_handle()()->print_value_on(st); |
|
2786 } |
|
2787 if (have_pv) st->cr(); |
|
2788 } // pvw is cleaned up |
|
2789 } // rm is cleaned up |
|
2790 |
2783 |
2791 if (generic_signature() != NULL) { |
2784 if (generic_signature() != NULL) { |
2792 st->print(BULLET"generic signature: "); |
2785 st->print(BULLET"generic signature: "); |
2793 generic_signature()->print_value_on(st); |
2786 generic_signature()->print_value_on(st); |
2794 st->cr(); |
2787 st->cr(); |
3315 // we don't need to create a new PreviousVersionNode. However, |
3308 // we don't need to create a new PreviousVersionNode. However, |
3316 // we still need to examine older previous versions below. |
3309 // we still need to examine older previous versions below. |
3317 Array<Method*>* old_methods = ikh->methods(); |
3310 Array<Method*>* old_methods = ikh->methods(); |
3318 |
3311 |
3319 if (cp_ref->on_stack()) { |
3312 if (cp_ref->on_stack()) { |
3320 PreviousVersionNode * pv_node = NULL; |
3313 PreviousVersionNode * pv_node = NULL; |
3321 if (emcp_method_count == 0) { |
3314 if (emcp_method_count == 0) { |
3322 // non-shared ConstantPool gets a reference |
3315 // non-shared ConstantPool gets a reference |
3323 pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), NULL); |
3316 pv_node = new PreviousVersionNode(cp_ref, NULL); |
3324 RC_TRACE(0x00000400, |
3317 RC_TRACE(0x00000400, |
3325 ("add: all methods are obsolete; flushing any EMCP refs")); |
3318 ("add: all methods are obsolete; flushing any EMCP refs")); |
3326 } else { |
3319 } else { |
3327 int local_count = 0; |
3320 int local_count = 0; |
3328 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) |
3321 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) |
3329 GrowableArray<Method*>(emcp_method_count, true); |
3322 GrowableArray<Method*>(emcp_method_count, true); |
3330 for (int i = 0; i < old_methods->length(); i++) { |
3323 for (int i = 0; i < old_methods->length(); i++) { |
3331 if (emcp_methods->at(i)) { |
3324 if (emcp_methods->at(i)) { |
3332 // this old method is EMCP. Save it only if it's on the stack |
3325 // this old method is EMCP. Save it only if it's on the stack |
3333 Method* old_method = old_methods->at(i); |
3326 Method* old_method = old_methods->at(i); |
3334 if (old_method->on_stack()) { |
3327 if (old_method->on_stack()) { |
3335 method_refs->append(old_method); |
3328 method_refs->append(old_method); |
|
3329 } |
|
3330 if (++local_count >= emcp_method_count) { |
|
3331 // no more EMCP methods so bail out now |
|
3332 break; |
3336 } |
3333 } |
3337 if (++local_count >= emcp_method_count) { |
|
3338 // no more EMCP methods so bail out now |
|
3339 break; |
|
3340 } |
3334 } |
3341 } |
3335 } |
3342 } |
|
3343 // non-shared ConstantPool gets a reference |
3336 // non-shared ConstantPool gets a reference |
3344 pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), method_refs); |
3337 pv_node = new PreviousVersionNode(cp_ref, method_refs); |
3345 } |
3338 } |
3346 // append new previous version. |
3339 // append new previous version. |
3347 _previous_versions->append(pv_node); |
3340 _previous_versions->append(pv_node); |
3348 } |
3341 } |
3349 |
3342 |
3350 // Since the caller is the VMThread and we are at a safepoint, this |
3343 // Since the caller is the VMThread and we are at a safepoint, this |
3351 // is a good time to clear out unused references. |
3344 // is a good time to clear out unused references. |
3352 |
3345 |
3478 if (_prev_EMCP_methods != NULL) { |
3472 if (_prev_EMCP_methods != NULL) { |
3479 delete _prev_EMCP_methods; |
3473 delete _prev_EMCP_methods; |
3480 } |
3474 } |
3481 } |
3475 } |
3482 |
3476 |
3483 |
|
3484 // Construct a PreviousVersionInfo entry |
|
3485 PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) { |
|
3486 _prev_constant_pool_handle = constantPoolHandle(); // NULL handle |
|
3487 _prev_EMCP_method_handles = NULL; |
|
3488 |
|
3489 ConstantPool* cp = pv_node->prev_constant_pool(); |
|
3490 assert(cp != NULL, "constant pool ref was unexpectedly cleared"); |
|
3491 if (cp == NULL) { |
|
3492 return; // robustness |
|
3493 } |
|
3494 |
|
3495 // make the ConstantPool* safe to return |
|
3496 _prev_constant_pool_handle = constantPoolHandle(cp); |
|
3497 |
|
3498 GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); |
|
3499 if (method_refs == NULL) { |
|
3500 // the InstanceKlass did not have any EMCP methods |
|
3501 return; |
|
3502 } |
|
3503 |
|
3504 _prev_EMCP_method_handles = new GrowableArray<methodHandle>(10); |
|
3505 |
|
3506 int n_methods = method_refs->length(); |
|
3507 for (int i = 0; i < n_methods; i++) { |
|
3508 Method* method = method_refs->at(i); |
|
3509 assert (method != NULL, "method has been cleared"); |
|
3510 if (method == NULL) { |
|
3511 continue; // robustness |
|
3512 } |
|
3513 // make the Method* safe to return |
|
3514 _prev_EMCP_method_handles->append(methodHandle(method)); |
|
3515 } |
|
3516 } |
|
3517 |
|
3518 |
|
3519 // Destroy a PreviousVersionInfo |
|
3520 PreviousVersionInfo::~PreviousVersionInfo() { |
|
3521 // Since _prev_EMCP_method_handles is not C-heap allocated, we |
|
3522 // don't have to delete it. |
|
3523 } |
|
3524 |
|
3525 |
|
3526 // Construct a helper for walking the previous versions array |
3477 // Construct a helper for walking the previous versions array |
3527 PreviousVersionWalker::PreviousVersionWalker(InstanceKlass *ik) { |
3478 PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) { |
|
3479 _thread = thread; |
3528 _previous_versions = ik->previous_versions(); |
3480 _previous_versions = ik->previous_versions(); |
3529 _current_index = 0; |
3481 _current_index = 0; |
3530 // _hm needs no initialization |
|
3531 _current_p = NULL; |
3482 _current_p = NULL; |
3532 } |
3483 _current_constant_pool_handle = constantPoolHandle(thread, ik->constants()); |
3533 |
|
3534 |
|
3535 // Destroy a PreviousVersionWalker |
|
3536 PreviousVersionWalker::~PreviousVersionWalker() { |
|
3537 // Delete the current info just in case the caller didn't walk to |
|
3538 // the end of the previous versions list. No harm if _current_p is |
|
3539 // already NULL. |
|
3540 delete _current_p; |
|
3541 |
|
3542 // When _hm is destroyed, all the Handles returned in |
|
3543 // PreviousVersionInfo objects will be destroyed. |
|
3544 // Also, after this destructor is finished it will be |
|
3545 // safe to delete the GrowableArray allocated in the |
|
3546 // PreviousVersionInfo objects. |
|
3547 } |
3484 } |
3548 |
3485 |
3549 |
3486 |
3550 // Return the interesting information for the next previous version |
3487 // Return the interesting information for the next previous version |
3551 // of the klass. Returns NULL if there are no more previous versions. |
3488 // of the klass. Returns NULL if there are no more previous versions. |
3552 PreviousVersionInfo* PreviousVersionWalker::next_previous_version() { |
3489 PreviousVersionNode* PreviousVersionWalker::next_previous_version() { |
3553 if (_previous_versions == NULL) { |
3490 if (_previous_versions == NULL) { |
3554 // no previous versions so nothing to return |
3491 // no previous versions so nothing to return |
3555 return NULL; |
3492 return NULL; |
3556 } |
3493 } |
3557 |
3494 |
3558 delete _current_p; // cleanup the previous info for the caller |
3495 _current_p = NULL; // reset to NULL |
3559 _current_p = NULL; // reset to NULL so we don't delete same object twice |
3496 _current_constant_pool_handle = NULL; |
3560 |
3497 |
3561 int length = _previous_versions->length(); |
3498 int length = _previous_versions->length(); |
3562 |
3499 |
3563 while (_current_index < length) { |
3500 while (_current_index < length) { |
3564 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); |
3501 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); |
3565 PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP, mtClass) |
3502 |
3566 PreviousVersionInfo(pv_node); |
3503 // Save a handle to the constant pool for this previous version, |
3567 |
3504 // which keeps all the methods from being deallocated. |
3568 constantPoolHandle cp_h = pv_info->prev_constant_pool_handle(); |
3505 _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool()); |
3569 assert (!cp_h.is_null(), "null cp found in previous version"); |
3506 _current_p = pv_node; |
3570 |
3507 return pv_node; |
3571 // The caller will need to delete pv_info when they are done with it. |
3508 } |
3572 _current_p = pv_info; |
3509 |
3573 return pv_info; |
|
3574 } |
|
3575 |
|
3576 // all of the underlying nodes' info has been deleted |
|
3577 return NULL; |
3510 return NULL; |
3578 } // end next_previous_version() |
3511 } // end next_previous_version() |