diff -r 7131f20389fb -r c26474fd5ac0 hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Sep 19 08:47:46 2013 +0200 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Sep 20 09:30:02 2013 -0400 @@ -2847,24 +2847,17 @@ st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); { - ResourceMark rm; - // PreviousVersionInfo objects returned via PreviousVersionWalker - // contain a GrowableArray of handles. We have to clean up the - // GrowableArray _after_ the PreviousVersionWalker destructor - // has destroyed the handles. - { - bool have_pv = false; - PreviousVersionWalker pvw((InstanceKlass*)this); - for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); - pv_info != NULL; pv_info = pvw.next_previous_version()) { - if (!have_pv) - st->print(BULLET"previous version: "); - have_pv = true; - pv_info->prev_constant_pool_handle()()->print_value_on(st); - } - if (have_pv) st->cr(); - } // pvw is cleaned up - } // rm is cleaned up + bool have_pv = false; + PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); + for (PreviousVersionNode * pv_node = pvw.next_previous_version(); + pv_node != NULL; pv_node = pvw.next_previous_version()) { + if (!have_pv) + st->print(BULLET"previous version: "); + have_pv = true; + pv_node->prev_constant_pool()->print_value_on(st); + } + if (have_pv) st->cr(); + } // pvw is cleaned up if (generic_signature() != NULL) { st->print(BULLET"generic signature: "); @@ -3392,34 +3385,34 @@ Array* old_methods = ikh->methods(); if (cp_ref->on_stack()) { - PreviousVersionNode * pv_node = NULL; - if (emcp_method_count == 0) { + PreviousVersionNode * pv_node = NULL; + if (emcp_method_count == 0) { // non-shared ConstantPool gets a reference - pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), NULL); - RC_TRACE(0x00000400, - ("add: all methods are obsolete; flushing any EMCP refs")); - } else { - int local_count = 0; + pv_node = new PreviousVersionNode(cp_ref, NULL); + RC_TRACE(0x00000400, + ("add: all methods are obsolete; flushing any EMCP refs")); + } else { + int local_count = 0; GrowableArray* method_refs = new (ResourceObj::C_HEAP, mtClass) - GrowableArray(emcp_method_count, true); - for (int i = 0; i < old_methods->length(); i++) { - if (emcp_methods->at(i)) { - // this old method is EMCP. Save it only if it's on the stack - Method* old_method = old_methods->at(i); - if (old_method->on_stack()) { - method_refs->append(old_method); + GrowableArray(emcp_method_count, true); + for (int i = 0; i < old_methods->length(); i++) { + if (emcp_methods->at(i)) { + // this old method is EMCP. Save it only if it's on the stack + Method* old_method = old_methods->at(i); + if (old_method->on_stack()) { + method_refs->append(old_method); + } + if (++local_count >= emcp_method_count) { + // no more EMCP methods so bail out now + break; } - if (++local_count >= emcp_method_count) { - // no more EMCP methods so bail out now - break; } } - } // non-shared ConstantPool gets a reference - pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), method_refs); + pv_node = new PreviousVersionNode(cp_ref, method_refs); } // append new previous version. - _previous_versions->append(pv_node); + _previous_versions->append(pv_node); } // Since the caller is the VMThread and we are at a safepoint, this @@ -3520,6 +3513,8 @@ return m; } } + // None found, return null for the caller to handle. + return NULL; } return m; } @@ -3536,10 +3531,9 @@ // Construct a PreviousVersionNode entry for the array hung off // the InstanceKlass. PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, - bool prev_cp_is_weak, GrowableArray* prev_EMCP_methods) { + GrowableArray* prev_EMCP_methods) { _prev_constant_pool = prev_constant_pool; - _prev_cp_is_weak = prev_cp_is_weak; _prev_EMCP_methods = prev_EMCP_methods; } @@ -3555,99 +3549,38 @@ } } - -// Construct a PreviousVersionInfo entry -PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) { - _prev_constant_pool_handle = constantPoolHandle(); // NULL handle - _prev_EMCP_method_handles = NULL; - - ConstantPool* cp = pv_node->prev_constant_pool(); - assert(cp != NULL, "constant pool ref was unexpectedly cleared"); - if (cp == NULL) { - return; // robustness - } - - // make the ConstantPool* safe to return - _prev_constant_pool_handle = constantPoolHandle(cp); - - GrowableArray* method_refs = pv_node->prev_EMCP_methods(); - if (method_refs == NULL) { - // the InstanceKlass did not have any EMCP methods - return; - } - - _prev_EMCP_method_handles = new GrowableArray(10); - - int n_methods = method_refs->length(); - for (int i = 0; i < n_methods; i++) { - Method* method = method_refs->at(i); - assert (method != NULL, "method has been cleared"); - if (method == NULL) { - continue; // robustness - } - // make the Method* safe to return - _prev_EMCP_method_handles->append(methodHandle(method)); - } -} - - -// Destroy a PreviousVersionInfo -PreviousVersionInfo::~PreviousVersionInfo() { - // Since _prev_EMCP_method_handles is not C-heap allocated, we - // don't have to delete it. -} - - // Construct a helper for walking the previous versions array -PreviousVersionWalker::PreviousVersionWalker(InstanceKlass *ik) { +PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) { + _thread = thread; _previous_versions = ik->previous_versions(); _current_index = 0; - // _hm needs no initialization _current_p = NULL; -} - - -// Destroy a PreviousVersionWalker -PreviousVersionWalker::~PreviousVersionWalker() { - // Delete the current info just in case the caller didn't walk to - // the end of the previous versions list. No harm if _current_p is - // already NULL. - delete _current_p; - - // When _hm is destroyed, all the Handles returned in - // PreviousVersionInfo objects will be destroyed. - // Also, after this destructor is finished it will be - // safe to delete the GrowableArray allocated in the - // PreviousVersionInfo objects. + _current_constant_pool_handle = constantPoolHandle(thread, ik->constants()); } // Return the interesting information for the next previous version // of the klass. Returns NULL if there are no more previous versions. -PreviousVersionInfo* PreviousVersionWalker::next_previous_version() { +PreviousVersionNode* PreviousVersionWalker::next_previous_version() { if (_previous_versions == NULL) { // no previous versions so nothing to return return NULL; } - delete _current_p; // cleanup the previous info for the caller - _current_p = NULL; // reset to NULL so we don't delete same object twice + _current_p = NULL; // reset to NULL + _current_constant_pool_handle = NULL; int length = _previous_versions->length(); while (_current_index < length) { PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); - PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP, mtClass) - PreviousVersionInfo(pv_node); - - constantPoolHandle cp_h = pv_info->prev_constant_pool_handle(); - assert (!cp_h.is_null(), "null cp found in previous version"); - - // The caller will need to delete pv_info when they are done with it. - _current_p = pv_info; - return pv_info; + + // Save a handle to the constant pool for this previous version, + // which keeps all the methods from being deallocated. + _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool()); + _current_p = pv_node; + return pv_node; } - // all of the underlying nodes' info has been deleted return NULL; } // end next_previous_version()