src/share/vm/oops/instanceKlass.cpp

changeset 9184
fbcbfd2753b5
parent 9183
f95c67788f18
child 9203
53eec13fbaa5
child 9355
792ccf73293a
equal deleted inserted replaced
9183:f95c67788f18 9184:fbcbfd2753b5
2580 if (breakpoints() != 0x0) { 2580 if (breakpoints() != 0x0) {
2581 methods_do(clear_all_breakpoints); 2581 methods_do(clear_all_breakpoints);
2582 assert(breakpoints() == 0x0, "should have cleared breakpoints"); 2582 assert(breakpoints() == 0x0, "should have cleared breakpoints");
2583 } 2583 }
2584 2584
2585 // deallocate information about previous versions
2586 if (_previous_versions != NULL) {
2587 for (int i = _previous_versions->length() - 1; i >= 0; i--) {
2588 PreviousVersionNode * pv_node = _previous_versions->at(i);
2589 delete pv_node;
2590 }
2591 delete _previous_versions;
2592 _previous_versions = NULL;
2593 }
2594
2595 // deallocate the cached class file 2585 // deallocate the cached class file
2596 if (_cached_class_file != NULL) { 2586 if (_cached_class_file != NULL) {
2597 os::free(_cached_class_file, mtClass); 2587 os::free(_cached_class_file, mtClass);
2598 _cached_class_file = NULL; 2588 _cached_class_file = NULL;
2599 } 2589 }
3185 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); 3175 st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr();
3186 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); 3176 st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr();
3187 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); 3177 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
3188 { 3178 {
3189 bool have_pv = false; 3179 bool have_pv = false;
3190 PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); 3180 // previous versions are linked together through the InstanceKlass
3191 for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 3181 for (InstanceKlass* pv_node = _previous_versions;
3192 pv_node != NULL; pv_node = pvw.next_previous_version()) { 3182 pv_node != NULL;
3183 pv_node = pv_node->previous_versions()) {
3193 if (!have_pv) 3184 if (!have_pv)
3194 st->print(BULLET"previous version: "); 3185 st->print(BULLET"previous version: ");
3195 have_pv = true; 3186 have_pv = true;
3196 pv_node->prev_constant_pool()->print_value_on(st); 3187 pv_node->constants()->print_value_on(st);
3197 } 3188 }
3198 if (have_pv) st->cr(); 3189 if (have_pv) st->cr();
3199 } // pvw is cleaned up 3190 }
3200 3191
3201 if (generic_signature() != NULL) { 3192 if (generic_signature() != NULL) {
3202 st->print(BULLET"generic signature: "); 3193 st->print(BULLET"generic signature: ");
3203 generic_signature()->print_value_on(st); 3194 generic_signature()->print_value_on(st);
3204 st->cr(); 3195 st->cr();
3608 3599
3609 3600
3610 // RedefineClasses() support for previous versions: 3601 // RedefineClasses() support for previous versions:
3611 3602
3612 // Purge previous versions 3603 // Purge previous versions
3613 static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) { 3604 void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
3614 if (ik->previous_versions() != NULL) { 3605 if (ik->previous_versions() != NULL) {
3615 // This klass has previous versions so see what we can cleanup 3606 // This klass has previous versions so see what we can cleanup
3616 // while it is safe to do so. 3607 // while it is safe to do so.
3617 3608
3618 int deleted_count = 0; // leave debugging breadcrumbs 3609 int deleted_count = 0; // leave debugging breadcrumbs
3619 int live_count = 0; 3610 int live_count = 0;
3620 ClassLoaderData* loader_data = ik->class_loader_data() == NULL ? 3611 ClassLoaderData* loader_data = ik->class_loader_data();
3621 ClassLoaderData::the_null_class_loader_data() : 3612 assert(loader_data != NULL, "should never be null");
3622 ik->class_loader_data();
3623 3613
3624 // RC_TRACE macro has an embedded ResourceMark 3614 // RC_TRACE macro has an embedded ResourceMark
3625 RC_TRACE(0x00000200, ("purge: %s: previous version length=%d", 3615 RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
3626 ik->external_name(), ik->previous_versions()->length())); 3616
3627 3617 // previous versions are linked together through the InstanceKlass
3628 for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) { 3618 InstanceKlass* pv_node = ik->previous_versions();
3629 // check the previous versions array 3619 InstanceKlass* last = ik;
3630 PreviousVersionNode * pv_node = ik->previous_versions()->at(i); 3620 int version = 0;
3631 ConstantPool* cp_ref = pv_node->prev_constant_pool(); 3621
3632 assert(cp_ref != NULL, "cp ref was unexpectedly cleared"); 3622 // check the previous versions list
3633 3623 for (; pv_node != NULL; ) {
3634 ConstantPool* pvcp = cp_ref; 3624
3625 ConstantPool* pvcp = pv_node->constants();
3626 assert(pvcp != NULL, "cp ref was unexpectedly cleared");
3627
3628
3635 if (!pvcp->on_stack()) { 3629 if (!pvcp->on_stack()) {
3636 // If the constant pool isn't on stack, none of the methods 3630 // If the constant pool isn't on stack, none of the methods
3637 // are executing. Delete all the methods, the constant pool and 3631 // are executing. Unlink this previous_version.
3638 // and this previous version node. 3632 // The previous version InstanceKlass is on the ClassLoaderData deallocate list
3639 GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 3633 // so will be deallocated during the next phase of class unloading.
3640 if (method_refs != NULL) { 3634 pv_node = pv_node->previous_versions();
3641 for (int j = method_refs->length() - 1; j >= 0; j--) { 3635 last->link_previous_versions(pv_node);
3642 Method* method = method_refs->at(j);
3643 assert(method != NULL, "method ref was unexpectedly cleared");
3644 method_refs->remove_at(j);
3645 // method will be freed with associated class.
3646 }
3647 }
3648 // Remove the constant pool
3649 delete pv_node;
3650 // Since we are traversing the array backwards, we don't have to
3651 // do anything special with the index.
3652 ik->previous_versions()->remove_at(i);
3653 deleted_count++; 3636 deleted_count++;
3637 version++;
3654 continue; 3638 continue;
3655 } else { 3639 } else {
3656 RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i)); 3640 RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
3641 pv_node));
3657 assert(pvcp->pool_holder() != NULL, "Constant pool with no holder"); 3642 assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
3658 guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack"); 3643 guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
3659 live_count++; 3644 live_count++;
3660 } 3645 }
3661 3646
3662 // At least one method is live in this previous version, clean out 3647 // At least one method is live in this previous version so clean its MethodData.
3663 // the others or mark them as obsolete. 3648 // Reset dead EMCP methods not to get breakpoints.
3664 GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 3649 // All methods are deallocated when all of the methods for this class are no
3650 // longer running.
3651 Array<Method*>* method_refs = pv_node->methods();
3665 if (method_refs != NULL) { 3652 if (method_refs != NULL) {
3666 RC_TRACE(0x00000200, ("purge: previous methods length=%d", 3653 RC_TRACE(0x00000200, ("purge: previous methods length=%d",
3667 method_refs->length())); 3654 method_refs->length()));
3668 for (int j = method_refs->length() - 1; j >= 0; j--) { 3655 for (int j = 0; j < method_refs->length(); j++) {
3669 Method* method = method_refs->at(j); 3656 Method* method = method_refs->at(j);
3670 assert(method != NULL, "method ref was unexpectedly cleared"); 3657
3671
3672 // Remove the emcp method if it's not executing
3673 // If it's been made obsolete by a redefinition of a non-emcp
3674 // method, mark it as obsolete but leave it to clean up later.
3675 if (!method->on_stack()) { 3658 if (!method->on_stack()) {
3676 method_refs->remove_at(j); 3659 // no breakpoints for non-running methods
3677 } else if (emcp_method_count == 0) { 3660 if (method->is_running_emcp()) {
3678 method->set_is_obsolete(); 3661 method->set_running_emcp(false);
3662 }
3679 } else { 3663 } else {
3664 assert (method->is_obsolete() || method->is_running_emcp(),
3665 "emcp method cannot run after emcp bit is cleared");
3680 // RC_TRACE macro has an embedded ResourceMark 3666 // RC_TRACE macro has an embedded ResourceMark
3681 RC_TRACE(0x00000200, 3667 RC_TRACE(0x00000200,
3682 ("purge: %s(%s): prev method @%d in version @%d is alive", 3668 ("purge: %s(%s): prev method @%d in version @%d is alive",
3683 method->name()->as_C_string(), 3669 method->name()->as_C_string(),
3684 method->signature()->as_C_string(), j, i)); 3670 method->signature()->as_C_string(), j, version));
3685 if (method->method_data() != NULL) { 3671 if (method->method_data() != NULL) {
3686 // Clean out any weak method links 3672 // Clean out any weak method links for running methods
3673 // (also should include not EMCP methods)
3687 method->method_data()->clean_weak_method_links(); 3674 method->method_data()->clean_weak_method_links();
3688 } 3675 }
3689 } 3676 }
3690 } 3677 }
3691 } 3678 }
3692 } 3679 // next previous version
3693 assert(ik->previous_versions()->length() == live_count, "sanity check"); 3680 last = pv_node;
3681 pv_node = pv_node->previous_versions();
3682 version++;
3683 }
3694 RC_TRACE(0x00000200, 3684 RC_TRACE(0x00000200,
3695 ("purge: previous version stats: live=%d, deleted=%d", live_count, 3685 ("purge: previous version stats: live=%d, deleted=%d", live_count,
3696 deleted_count)); 3686 deleted_count));
3697 } 3687 }
3698 3688
3689 // Clean MethodData of this class's methods so they don't refer to
3690 // old methods that are no longer running.
3699 Array<Method*>* methods = ik->methods(); 3691 Array<Method*>* methods = ik->methods();
3700 int num_methods = methods->length(); 3692 int num_methods = methods->length();
3701 for (int index2 = 0; index2 < num_methods; ++index2) { 3693 for (int index2 = 0; index2 < num_methods; ++index2) {
3702 if (methods->at(index2)->method_data() != NULL) { 3694 if (methods->at(index2)->method_data() != NULL) {
3703 methods->at(index2)->method_data()->clean_weak_method_links(); 3695 methods->at(index2)->method_data()->clean_weak_method_links();
3704 } 3696 }
3705 } 3697 }
3706 } 3698 }
3707 3699
3708 // External interface for use during class unloading. 3700 void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
3709 void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { 3701 int emcp_method_count) {
3710 // Call with >0 emcp methods since they are not currently being redefined.
3711 purge_previous_versions_internal(ik, 1);
3712 }
3713
3714
3715 // Potentially add an information node that contains pointers to the
3716 // interesting parts of the previous version of the_class.
3717 // This is also where we clean out any unused references.
3718 // Note that while we delete nodes from the _previous_versions
3719 // array, we never delete the array itself until the klass is
3720 // unloaded. The has_been_redefined() query depends on that fact.
3721 //
3722 void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
3723 BitMap* emcp_methods, int emcp_method_count) {
3724 assert(Thread::current()->is_VM_thread(),
3725 "only VMThread can add previous versions");
3726
3727 if (_previous_versions == NULL) {
3728 // This is the first previous version so make some space.
3729 // Start with 2 elements under the assumption that the class
3730 // won't be redefined much.
3731 _previous_versions = new (ResourceObj::C_HEAP, mtClass)
3732 GrowableArray<PreviousVersionNode *>(2, true);
3733 }
3734
3735 ConstantPool* cp_ref = ikh->constants();
3736
3737 // RC_TRACE macro has an embedded ResourceMark
3738 RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d "
3739 "on_stack=%d",
3740 ikh->external_name(), _previous_versions->length(), emcp_method_count,
3741 cp_ref->on_stack()));
3742
3743 // If the constant pool for this previous version of the class
3744 // is not marked as being on the stack, then none of the methods
3745 // in this previous version of the class are on the stack so
3746 // we don't need to create a new PreviousVersionNode. However,
3747 // we still need to examine older previous versions below.
3748 Array<Method*>* old_methods = ikh->methods();
3749
3750 if (cp_ref->on_stack()) {
3751 PreviousVersionNode * pv_node = NULL;
3752 if (emcp_method_count == 0) {
3753 // non-shared ConstantPool gets a reference
3754 pv_node = new PreviousVersionNode(cp_ref, NULL);
3755 RC_TRACE(0x00000400,
3756 ("add: all methods are obsolete; flushing any EMCP refs"));
3757 } else {
3758 int local_count = 0;
3759 GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
3760 GrowableArray<Method*>(emcp_method_count, true);
3761 for (int i = 0; i < old_methods->length(); i++) {
3762 if (emcp_methods->at(i)) {
3763 // this old method is EMCP. Save it only if it's on the stack
3764 Method* old_method = old_methods->at(i);
3765 if (old_method->on_stack()) {
3766 method_refs->append(old_method);
3767 }
3768 if (++local_count >= emcp_method_count) {
3769 // no more EMCP methods so bail out now
3770 break;
3771 }
3772 }
3773 }
3774 // non-shared ConstantPool gets a reference
3775 pv_node = new PreviousVersionNode(cp_ref, method_refs);
3776 }
3777 // append new previous version.
3778 _previous_versions->append(pv_node);
3779 }
3780
3781 // Since the caller is the VMThread and we are at a safepoint, this
3782 // is a good time to clear out unused references.
3783
3784 RC_TRACE(0x00000400, ("add: previous version length=%d",
3785 _previous_versions->length()));
3786
3787 // Purge previous versions not executing on the stack
3788 purge_previous_versions_internal(this, emcp_method_count);
3789
3790 int obsolete_method_count = old_methods->length() - emcp_method_count; 3702 int obsolete_method_count = old_methods->length() - emcp_method_count;
3791 3703
3792 if (emcp_method_count != 0 && obsolete_method_count != 0 && 3704 if (emcp_method_count != 0 && obsolete_method_count != 0 &&
3793 _previous_versions->length() > 0) { 3705 _previous_versions != NULL) {
3794 // We have a mix of obsolete and EMCP methods so we have to 3706 // We have a mix of obsolete and EMCP methods so we have to
3795 // clear out any matching EMCP method entries the hard way. 3707 // clear out any matching EMCP method entries the hard way.
3796 int local_count = 0; 3708 int local_count = 0;
3797 for (int i = 0; i < old_methods->length(); i++) { 3709 for (int i = 0; i < old_methods->length(); i++) {
3798 if (!emcp_methods->at(i)) { 3710 Method* old_method = old_methods->at(i);
3711 if (old_method->is_obsolete()) {
3799 // only obsolete methods are interesting 3712 // only obsolete methods are interesting
3800 Method* old_method = old_methods->at(i);
3801 Symbol* m_name = old_method->name(); 3713 Symbol* m_name = old_method->name();
3802 Symbol* m_signature = old_method->signature(); 3714 Symbol* m_signature = old_method->signature();
3803 3715
3804 // we might not have added the last entry 3716 // previous versions are linked together through the InstanceKlass
3805 for (int j = _previous_versions->length() - 1; j >= 0; j--) { 3717 int j = 0;
3806 // check the previous versions array for non executing obsolete methods 3718 for (InstanceKlass* prev_version = _previous_versions;
3807 PreviousVersionNode * pv_node = _previous_versions->at(j); 3719 prev_version != NULL;
3808 3720 prev_version = prev_version->previous_versions(), j++) {
3809 GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 3721
3810 if (method_refs == NULL) { 3722 Array<Method*>* method_refs = prev_version->methods();
3811 // We have run into a PreviousVersion generation where 3723 for (int k = 0; k < method_refs->length(); k++) {
3812 // all methods were made obsolete during that generation's
3813 // RedefineClasses() operation. At the time of that
3814 // operation, all EMCP methods were flushed so we don't
3815 // have to go back any further.
3816 //
3817 // A NULL method_refs is different than an empty method_refs.
3818 // We cannot infer any optimizations about older generations
3819 // from an empty method_refs for the current generation.
3820 break;
3821 }
3822
3823 for (int k = method_refs->length() - 1; k >= 0; k--) {
3824 Method* method = method_refs->at(k); 3724 Method* method = method_refs->at(k);
3825 3725
3826 if (!method->is_obsolete() && 3726 if (!method->is_obsolete() &&
3827 method->name() == m_name && 3727 method->name() == m_name &&
3828 method->signature() == m_signature) { 3728 method->signature() == m_signature) {
3829 // The current RedefineClasses() call has made all EMCP 3729 // The current RedefineClasses() call has made all EMCP
3830 // versions of this method obsolete so mark it as obsolete 3730 // versions of this method obsolete so mark it as obsolete
3831 // and remove the reference.
3832 RC_TRACE(0x00000400, 3731 RC_TRACE(0x00000400,
3833 ("add: %s(%s): flush obsolete method @%d in version @%d", 3732 ("add: %s(%s): flush obsolete method @%d in version @%d",
3834 m_name->as_C_string(), m_signature->as_C_string(), k, j)); 3733 m_name->as_C_string(), m_signature->as_C_string(), k, j));
3835 3734
3836 method->set_is_obsolete(); 3735 method->set_is_obsolete();
3837 // Leave obsolete methods on the previous version list to
3838 // clean up later.
3839 break; 3736 break;
3840 } 3737 }
3841 } 3738 }
3842 3739
3843 // The previous loop may not find a matching EMCP method, but 3740 // The previous loop may not find a matching EMCP method, but
3844 // that doesn't mean that we can optimize and not go any 3741 // that doesn't mean that we can optimize and not go any
3845 // further back in the PreviousVersion generations. The EMCP 3742 // further back in the PreviousVersion generations. The EMCP
3846 // method for this generation could have already been deleted, 3743 // method for this generation could have already been made obsolete,
3847 // but there still may be an older EMCP method that has not 3744 // but there still may be an older EMCP method that has not
3848 // been deleted. 3745 // been made obsolete.
3849 } 3746 }
3850 3747
3851 if (++local_count >= obsolete_method_count) { 3748 if (++local_count >= obsolete_method_count) {
3852 // no more obsolete methods so bail out now 3749 // no more obsolete methods so bail out now
3853 break; 3750 break;
3854 } 3751 }
3855 } 3752 }
3856 } 3753 }
3857 } 3754 }
3755 }
3756
3757 // Save the scratch_class as the previous version if any of the methods are running.
3758 // The previous_versions are used to set breakpoints in EMCP methods and they are
3759 // also used to clean MethodData links to redefined methods that are no longer running.
3760 void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
3761 int emcp_method_count) {
3762 assert(Thread::current()->is_VM_thread(),
3763 "only VMThread can add previous versions");
3764
3765 // RC_TRACE macro has an embedded ResourceMark
3766 RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
3767 scratch_class->external_name(), emcp_method_count));
3768
3769 // Clean out old previous versions
3770 purge_previous_versions(this);
3771
3772 // Mark newly obsolete methods in remaining previous versions. An EMCP method from
3773 // a previous redefinition may be made obsolete by this redefinition.
3774 Array<Method*>* old_methods = scratch_class->methods();
3775 mark_newly_obsolete_methods(old_methods, emcp_method_count);
3776
3777 // If the constant pool for this previous version of the class
3778 // is not marked as being on the stack, then none of the methods
3779 // in this previous version of the class are on the stack so
3780 // we don't need to add this as a previous version.
3781 ConstantPool* cp_ref = scratch_class->constants();
3782 if (!cp_ref->on_stack()) {
3783 RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
3784 return;
3785 }
3786
3787 if (emcp_method_count != 0) {
3788 // At least one method is still running, check for EMCP methods
3789 for (int i = 0; i < old_methods->length(); i++) {
3790 Method* old_method = old_methods->at(i);
3791 if (!old_method->is_obsolete() && old_method->on_stack()) {
3792 // if EMCP method (not obsolete) is on the stack, mark as EMCP so that
3793 // we can add breakpoints for it.
3794
3795 // We set the method->on_stack bit during safepoints for class redefinition and
3796 // class unloading and use this bit to set the is_running_emcp bit.
3797 // After the safepoint, the on_stack bit is cleared and the running emcp
3798 // method may exit. If so, we would set a breakpoint in a method that
3799 // is never reached, but this won't be noticeable to the programmer.
3800 old_method->set_running_emcp(true);
3801 RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
3802 old_method->name_and_sig_as_C_string(), old_method));
3803 } else if (!old_method->is_obsolete()) {
3804 RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
3805 old_method->name_and_sig_as_C_string(), old_method));
3806 }
3807 }
3808 }
3809
3810 // Add previous version if any methods are still running.
3811 RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
3812 assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
3813 scratch_class->link_previous_versions(previous_versions());
3814 link_previous_versions(scratch_class());
3858 } // end add_previous_version() 3815 } // end add_previous_version()
3859
3860
3861 // Determine if InstanceKlass has a previous version.
3862 bool InstanceKlass::has_previous_version() const {
3863 return (_previous_versions != NULL && _previous_versions->length() > 0);
3864 } // end has_previous_version()
3865
3866
3867 InstanceKlass* InstanceKlass::get_klass_version(int version) {
3868 if (constants()->version() == version) {
3869 return this;
3870 }
3871 PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
3872 for (PreviousVersionNode * pv_node = pvw.next_previous_version();
3873 pv_node != NULL; pv_node = pvw.next_previous_version()) {
3874 ConstantPool* prev_cp = pv_node->prev_constant_pool();
3875 if (prev_cp->version() == version) {
3876 return prev_cp->pool_holder();
3877 }
3878 }
3879 return NULL; // None found
3880 }
3881
3882 3816
3883 Method* InstanceKlass::method_with_idnum(int idnum) { 3817 Method* InstanceKlass::method_with_idnum(int idnum) {
3884 Method* m = NULL; 3818 Method* m = NULL;
3885 if (idnum < methods()->length()) { 3819 if (idnum < methods()->length()) {
3886 m = methods()->at(idnum); 3820 m = methods()->at(idnum);
3934 } 3868 }
3935 3869
3936 unsigned char * InstanceKlass::get_cached_class_file_bytes() { 3870 unsigned char * InstanceKlass::get_cached_class_file_bytes() {
3937 return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file); 3871 return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
3938 } 3872 }
3939
3940
3941 // Construct a PreviousVersionNode entry for the array hung off
3942 // the InstanceKlass.
3943 PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
3944 GrowableArray<Method*>* prev_EMCP_methods) {
3945
3946 _prev_constant_pool = prev_constant_pool;
3947 _prev_EMCP_methods = prev_EMCP_methods;
3948 }
3949
3950
3951 // Destroy a PreviousVersionNode
3952 PreviousVersionNode::~PreviousVersionNode() {
3953 if (_prev_constant_pool != NULL) {
3954 _prev_constant_pool = NULL;
3955 }
3956
3957 if (_prev_EMCP_methods != NULL) {
3958 delete _prev_EMCP_methods;
3959 }
3960 }
3961
3962 // Construct a helper for walking the previous versions array
3963 PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
3964 _thread = thread;
3965 _previous_versions = ik->previous_versions();
3966 _current_index = 0;
3967 _current_p = NULL;
3968 _current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
3969 }
3970
3971
3972 // Return the interesting information for the next previous version
3973 // of the klass. Returns NULL if there are no more previous versions.
3974 PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
3975 if (_previous_versions == NULL) {
3976 // no previous versions so nothing to return
3977 return NULL;
3978 }
3979
3980 _current_p = NULL; // reset to NULL
3981 _current_constant_pool_handle = NULL;
3982
3983 int length = _previous_versions->length();
3984
3985 while (_current_index < length) {
3986 PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
3987
3988 // Save a handle to the constant pool for this previous version,
3989 // which keeps all the methods from being deallocated.
3990 _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
3991 _current_p = pv_node;
3992 return pv_node;
3993 }
3994
3995 return NULL;
3996 } // end next_previous_version()

mercurial