duke@435: /* hseigel@5784: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "classfile/javaClasses.hpp" stefank@2314: #include "classfile/systemDictionary.hpp" stefank@2314: #include "gc_implementation/shared/markSweep.inline.hpp" stefank@2314: #include "gc_interface/collectedHeap.hpp" stefank@2314: #include "gc_interface/collectedHeap.inline.hpp" stefank@2314: #include "memory/genCollectedHeap.hpp" stefank@2314: #include "memory/genOopClosures.inline.hpp" stefank@2314: #include "oops/instanceRefKlass.hpp" stefank@2314: #include "oops/oop.inline.hpp" stefank@2314: #include "utilities/preserveException.hpp" jprovino@4542: #include "utilities/macros.hpp" jprovino@4542: #if INCLUDE_ALL_GCS stefank@2314: #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" stefank@2314: #include "gc_implementation/g1/g1OopClosures.inline.hpp" stefank@2314: #include "gc_implementation/g1/g1RemSet.inline.hpp" stefank@2314: #include "gc_implementation/g1/heapRegionSeq.inline.hpp" stefank@2314: #include "gc_implementation/parNew/parOopClosures.inline.hpp" stefank@2314: #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" stefank@2314: #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" stefank@2314: #include "oops/oop.pcgc.inline.hpp" jprovino@4542: #endif // INCLUDE_ALL_GCS duke@435: coleenp@548: template coleenp@4047: void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) { coleenp@548: T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); ysr@1280: T heap_oop = oopDesc::load_heap_oop(referent_addr); duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { hseigel@5784: gclog_or_tty->print_cr("InstanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (void *)obj); duke@435: } duke@435: ) ysr@1280: if (!oopDesc::is_null(heap_oop)) { ysr@1280: oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); duke@435: if (!referent->is_gc_marked() && ysr@3117: MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) { ysr@3117: // reference was discovered, referent will be traversed later coleenp@4037: ref->InstanceKlass::oop_follow_contents(obj); duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { hseigel@5784: gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (void *)obj); duke@435: } duke@435: ) duke@435: return; duke@435: } else { duke@435: // treat referent as normal oop duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { hseigel@5784: gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (void *)obj); duke@435: } duke@435: ) duke@435: MarkSweep::mark_and_push(referent_addr); duke@435: } duke@435: } coleenp@548: T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); ysr@3117: if (ReferenceProcessor::pending_list_uses_discovered_field()) { ysr@3117: // Treat discovered as normal oop, if ref is not "active", ysr@3117: // i.e. if next is non-NULL. ysr@3117: T next_oop = oopDesc::load_heap_oop(next_addr); ysr@3117: if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" ysr@3117: T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); ysr@3117: debug_only( ysr@3117: if(TraceReferenceGC && PrintGCDetails) { ysr@3117: gclog_or_tty->print_cr(" Process discovered as normal " ysr@3117: INTPTR_FORMAT, discovered_addr); ysr@3117: } ysr@3117: ) ysr@3117: MarkSweep::mark_and_push(discovered_addr); ysr@3117: } ysr@3117: } else { ysr@3117: #ifdef ASSERT ysr@3117: // In the case of older JDKs which do not use the discovered ysr@3117: // field for the pending list, an inactive ref (next != NULL) ysr@3117: // must always have a NULL discovered field. ysr@3117: oop next = oopDesc::load_decode_heap_oop(next_addr); ysr@3117: oop discovered = java_lang_ref_Reference::discovered(obj); ysr@3117: assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), ysr@3117: err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", kvn@3128: (oopDesc*)obj)); ysr@3117: #endif ysr@3117: } ysr@3117: // treat next as normal oop. next is a link in the reference queue. duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { duke@435: gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); duke@435: } duke@435: ) duke@435: MarkSweep::mark_and_push(next_addr); coleenp@4037: ref->InstanceKlass::oop_follow_contents(obj); coleenp@548: } coleenp@548: coleenp@4047: void InstanceRefKlass::oop_follow_contents(oop obj) { coleenp@548: if (UseCompressedOops) { coleenp@548: specialized_oop_follow_contents(this, obj); coleenp@548: } else { coleenp@548: specialized_oop_follow_contents(this, obj); coleenp@548: } duke@435: } duke@435: jprovino@4542: #if INCLUDE_ALL_GCS coleenp@548: template coleenp@4047: void specialized_oop_follow_contents(InstanceRefKlass* ref, phh@1558: ParCompactionManager* cm, phh@1558: oop obj) { coleenp@548: T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); ysr@1280: T heap_oop = oopDesc::load_heap_oop(referent_addr); duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { hseigel@5784: gclog_or_tty->print_cr("InstanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (void *)obj); duke@435: } duke@435: ) ysr@1280: if (!oopDesc::is_null(heap_oop)) { ysr@1280: oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); duke@435: if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) && duke@435: PSParallelCompact::ref_processor()-> coleenp@548: discover_reference(obj, ref->reference_type())) { duke@435: // reference already enqueued, referent will be traversed later coleenp@4037: ref->InstanceKlass::oop_follow_contents(cm, obj); duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { hseigel@5784: gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (void *)obj); duke@435: } duke@435: ) duke@435: return; duke@435: } else { duke@435: // treat referent as normal oop duke@435: debug_only( duke@435: if(TraceReferenceGC && PrintGCDetails) { hseigel@5784: gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (void *)obj); duke@435: } duke@435: ) duke@435: PSParallelCompact::mark_and_push(cm, referent_addr); duke@435: } duke@435: } coleenp@548: T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); ysr@3117: if (ReferenceProcessor::pending_list_uses_discovered_field()) { ysr@3117: // Treat discovered as normal oop, if ref is not "active", ysr@3117: // i.e. if next is non-NULL. ysr@3117: T next_oop = oopDesc::load_heap_oop(next_addr); ysr@3117: if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" ysr@3117: T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); ysr@3117: debug_only( ysr@3117: if(TraceReferenceGC && PrintGCDetails) { ysr@3117: gclog_or_tty->print_cr(" Process discovered as normal " ysr@3117: INTPTR_FORMAT, discovered_addr); ysr@3117: } ysr@3117: ) ysr@3117: PSParallelCompact::mark_and_push(cm, discovered_addr); duke@435: } ysr@3117: } else { ysr@3117: #ifdef ASSERT ysr@3117: // In the case of older JDKs which do not use the discovered ysr@3117: // field for the pending list, an inactive ref (next != NULL) ysr@3117: // must always have a NULL discovered field. ysr@3117: T next = oopDesc::load_heap_oop(next_addr); ysr@3117: oop discovered = java_lang_ref_Reference::discovered(obj); ysr@3117: assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), ysr@3117: err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", kvn@3128: (oopDesc*)obj)); ysr@3117: #endif ysr@3117: } duke@435: PSParallelCompact::mark_and_push(cm, next_addr); coleenp@4037: ref->InstanceKlass::oop_follow_contents(cm, obj); coleenp@548: } coleenp@548: coleenp@4047: void InstanceRefKlass::oop_follow_contents(ParCompactionManager* cm, coleenp@548: oop obj) { coleenp@548: if (UseCompressedOops) { coleenp@548: specialized_oop_follow_contents(this, cm, obj); coleenp@548: } else { coleenp@548: specialized_oop_follow_contents(this, cm, obj); coleenp@548: } duke@435: } jprovino@4542: #endif // INCLUDE_ALL_GCS duke@435: coleenp@548: #ifdef ASSERT coleenp@548: template void trace_reference_gc(const char *s, oop obj, coleenp@548: T* referent_addr, coleenp@548: T* next_addr, coleenp@548: T* discovered_addr) { coleenp@548: if(TraceReferenceGC && PrintGCDetails) { coleenp@548: gclog_or_tty->print_cr("%s obj " INTPTR_FORMAT, s, (address)obj); coleenp@548: gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " coleenp@548: INTPTR_FORMAT, referent_addr, coleenp@548: referent_addr ? coleenp@548: (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL); coleenp@548: gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " coleenp@548: INTPTR_FORMAT, next_addr, coleenp@548: next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL); coleenp@548: gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " coleenp@548: INTPTR_FORMAT, discovered_addr, coleenp@548: discovered_addr ? coleenp@548: (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL); coleenp@548: } coleenp@548: } coleenp@548: #endif coleenp@548: coleenp@4047: template void specialized_oop_adjust_pointers(InstanceRefKlass *ref, oop obj) { coleenp@548: T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); coleenp@548: MarkSweep::adjust_pointer(referent_addr); coleenp@548: T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); coleenp@548: MarkSweep::adjust_pointer(next_addr); coleenp@548: T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); coleenp@548: MarkSweep::adjust_pointer(discovered_addr); coleenp@4047: debug_only(trace_reference_gc("InstanceRefKlass::oop_adjust_pointers", obj, coleenp@548: referent_addr, next_addr, discovered_addr);) coleenp@548: } duke@435: coleenp@4047: int InstanceRefKlass::oop_adjust_pointers(oop obj) { duke@435: int size = size_helper(); coleenp@4037: InstanceKlass::oop_adjust_pointers(obj); duke@435: coleenp@548: if (UseCompressedOops) { coleenp@548: specialized_oop_adjust_pointers(this, obj); coleenp@548: } else { coleenp@548: specialized_oop_adjust_pointers(this, obj); duke@435: } duke@435: return size; duke@435: } duke@435: coleenp@548: #define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \ ysr@3117: T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \ ysr@777: if (closure->apply_to_weak_ref_discovered_field()) { \ ysr@777: closure->do_oop##nv_suffix(disc_addr); \ ysr@777: } \ ysr@777: \ coleenp@548: T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \ ysr@1280: T heap_oop = oopDesc::load_heap_oop(referent_addr); \ ysr@3117: ReferenceProcessor* rp = closure->_ref_processor; \ ysr@3117: if (!oopDesc::is_null(heap_oop)) { \ ysr@1280: oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \ coleenp@548: if (!referent->is_gc_marked() && (rp != NULL) && \ coleenp@548: rp->discover_reference(obj, reference_type())) { \ coleenp@548: return size; \ ysr@3117: } else if (contains(referent_addr)) { \ coleenp@548: /* treat referent as normal oop */ \ coleenp@548: SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ coleenp@548: closure->do_oop##nv_suffix(referent_addr); \ coleenp@548: } \ coleenp@548: } \ ysr@3117: T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \ ysr@3117: if (ReferenceProcessor::pending_list_uses_discovered_field()) { \ ysr@3117: T next_oop = oopDesc::load_heap_oop(next_addr); \ ysr@3117: /* Treat discovered as normal oop, if ref is not "active" (next non-NULL) */\ ysr@3117: if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { \ ysr@3117: /* i.e. ref is not "active" */ \ ysr@3117: debug_only( \ ysr@3117: if(TraceReferenceGC && PrintGCDetails) { \ ysr@3117: gclog_or_tty->print_cr(" Process discovered as normal " \ ysr@3117: INTPTR_FORMAT, disc_addr); \ ysr@3117: } \ ysr@3117: ) \ ysr@3117: SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ ysr@3117: closure->do_oop##nv_suffix(disc_addr); \ ysr@3117: } \ ysr@3117: } else { \ ysr@3117: /* In the case of older JDKs which do not use the discovered field for */ \ ysr@3117: /* the pending list, an inactive ref (next != NULL) must always have a */ \ ysr@3117: /* NULL discovered field. */ \ ysr@3117: debug_only( \ ysr@3117: T next_oop = oopDesc::load_heap_oop(next_addr); \ ysr@3117: T disc_oop = oopDesc::load_heap_oop(disc_addr); \ ysr@3117: assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop), \ ysr@3117: err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL" \ kvn@3128: "discovered field", (oopDesc*)obj)); \ ysr@3117: ) \ ysr@3117: } \ coleenp@548: /* treat next as normal oop */ \ coleenp@548: if (contains(next_addr)) { \ coleenp@548: SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \ coleenp@548: closure->do_oop##nv_suffix(next_addr); \ coleenp@548: } \ coleenp@548: return size; \ coleenp@548: coleenp@548: coleenp@548: template bool contains(T *t) { return true; } coleenp@548: coleenp@4047: // Macro to define InstanceRefKlass::oop_oop_iterate for virtual/nonvirtual for coleenp@548: // all closures. Macros calling macros above for each oop size. coleenp@548: duke@435: #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ duke@435: \ coleenp@4047: int InstanceRefKlass:: \ duke@435: oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \ duke@435: /* Get size before changing pointers */ \ duke@435: SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\ duke@435: \ coleenp@4037: int size = InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \ duke@435: \ coleenp@548: if (UseCompressedOops) { \ coleenp@548: InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \ coleenp@548: } else { \ coleenp@548: InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \ duke@435: } \ duke@435: } duke@435: jprovino@4542: #if INCLUDE_ALL_GCS ysr@777: #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ ysr@777: \ coleenp@4047: int InstanceRefKlass:: \ ysr@777: oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \ ysr@777: /* Get size before changing pointers */ \ ysr@777: SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\ ysr@777: \ coleenp@4037: int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \ ysr@777: \ ysr@777: if (UseCompressedOops) { \ ysr@777: InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \ ysr@777: } else { \ ysr@777: InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \ ysr@777: } \ ysr@777: } jprovino@4542: #endif // INCLUDE_ALL_GCS ysr@777: ysr@777: duke@435: #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ duke@435: \ coleenp@4047: int InstanceRefKlass:: \ duke@435: oop_oop_iterate##nv_suffix##_m(oop obj, \ duke@435: OopClosureType* closure, \ duke@435: MemRegion mr) { \ duke@435: SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\ duke@435: \ coleenp@4037: int size = InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \ coleenp@548: if (UseCompressedOops) { \ coleenp@548: InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr.contains); \ coleenp@548: } else { \ coleenp@548: InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr.contains); \ duke@435: } \ duke@435: } duke@435: duke@435: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) jprovino@4542: #if INCLUDE_ALL_GCS ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) jprovino@4542: #endif // INCLUDE_ALL_GCS duke@435: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) ysr@777: ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) duke@435: jprovino@4542: #if INCLUDE_ALL_GCS coleenp@548: template coleenp@4047: void specialized_oop_push_contents(InstanceRefKlass *ref, coleenp@548: PSPromotionManager* pm, oop obj) { coleenp@548: T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); coleenp@548: if (PSScavenge::should_scavenge(referent_addr)) { duke@435: ReferenceProcessor* rp = PSScavenge::reference_processor(); coleenp@548: if (rp->discover_reference(obj, ref->reference_type())) { duke@435: // reference already enqueued, referent and next will be traversed later coleenp@4037: ref->InstanceKlass::oop_push_contents(pm, obj); duke@435: return; duke@435: } else { duke@435: // treat referent as normal oop duke@435: pm->claim_or_forward_depth(referent_addr); duke@435: } duke@435: } ysr@3117: // Treat discovered as normal oop, if ref is not "active", ysr@3117: // i.e. if next is non-NULL. coleenp@548: T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); ysr@3117: if (ReferenceProcessor::pending_list_uses_discovered_field()) { ysr@3117: T next_oop = oopDesc::load_heap_oop(next_addr); ysr@3117: if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" ysr@3117: T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); ysr@3117: debug_only( ysr@3117: if(TraceReferenceGC && PrintGCDetails) { ysr@3117: gclog_or_tty->print_cr(" Process discovered as normal " ysr@3117: INTPTR_FORMAT, discovered_addr); ysr@3117: } ysr@3117: ) ysr@3117: if (PSScavenge::should_scavenge(discovered_addr)) { ysr@3117: pm->claim_or_forward_depth(discovered_addr); ysr@3117: } ysr@3117: } ysr@3117: } else { ysr@3117: #ifdef ASSERT ysr@3117: // In the case of older JDKs which do not use the discovered ysr@3117: // field for the pending list, an inactive ref (next != NULL) ysr@3117: // must always have a NULL discovered field. ysr@3117: oop next = oopDesc::load_decode_heap_oop(next_addr); ysr@3117: oop discovered = java_lang_ref_Reference::discovered(obj); ysr@3117: assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), ysr@3117: err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", kvn@3128: (oopDesc*)obj)); ysr@3117: #endif ysr@3117: } ysr@3117: ysr@3117: // Treat next as normal oop; next is a link in the reference queue. coleenp@548: if (PSScavenge::should_scavenge(next_addr)) { duke@435: pm->claim_or_forward_depth(next_addr); duke@435: } coleenp@4037: ref->InstanceKlass::oop_push_contents(pm, obj); coleenp@548: } coleenp@548: coleenp@4047: void InstanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { coleenp@548: if (UseCompressedOops) { coleenp@548: specialized_oop_push_contents(this, pm, obj); coleenp@548: } else { coleenp@548: specialized_oop_push_contents(this, pm, obj); coleenp@548: } coleenp@548: } coleenp@548: coleenp@548: template coleenp@4047: void specialized_oop_update_pointers(InstanceRefKlass *ref, coleenp@548: ParCompactionManager* cm, oop obj) { coleenp@548: T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); coleenp@548: PSParallelCompact::adjust_pointer(referent_addr); coleenp@548: T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); coleenp@548: PSParallelCompact::adjust_pointer(next_addr); coleenp@548: T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); coleenp@548: PSParallelCompact::adjust_pointer(discovered_addr); coleenp@4047: debug_only(trace_reference_gc("InstanceRefKlass::oop_update_ptrs", obj, coleenp@548: referent_addr, next_addr, discovered_addr);) duke@435: } duke@435: coleenp@4047: int InstanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { coleenp@4037: InstanceKlass::oop_update_pointers(cm, obj); coleenp@548: if (UseCompressedOops) { coleenp@548: specialized_oop_update_pointers(this, cm, obj); coleenp@548: } else { coleenp@548: specialized_oop_update_pointers(this, cm, obj); coleenp@548: } coleenp@548: return size_helper(); coleenp@548: } jprovino@4542: #endif // INCLUDE_ALL_GCS duke@435: coleenp@4047: void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) { duke@435: // Clear the nonstatic oop-map entries corresponding to referent duke@435: // and nextPending field. They are treated specially by the duke@435: // garbage collector. duke@435: // The discovered field is used only by the garbage collector duke@435: // and is also treated specially. coleenp@4037: InstanceKlass* ik = InstanceKlass::cast(k); duke@435: duke@435: // Check that we have the right class duke@435: debug_only(static bool first_time = true); never@1577: assert(k == SystemDictionary::Reference_klass() && first_time, duke@435: "Invalid update of maps"); duke@435: debug_only(first_time = false); jcoomes@1373: assert(ik->nonstatic_oop_map_count() == 1, "just checking"); duke@435: duke@435: OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); duke@435: duke@435: // Check that the current map is (2,4) - currently points at field with duke@435: // offset 2 (words) and has 4 map entries. duke@435: debug_only(int offset = java_lang_ref_Reference::referent_offset); jcoomes@1374: debug_only(unsigned int count = ((java_lang_ref_Reference::discovered_offset - coleenp@548: java_lang_ref_Reference::referent_offset)/heapOopSize) + 1); duke@435: duke@435: if (UseSharedSpaces) { duke@435: assert(map->offset() == java_lang_ref_Reference::queue_offset && jcoomes@1373: map->count() == 1, "just checking"); duke@435: } else { jcoomes@1373: assert(map->offset() == offset && map->count() == count, duke@435: "just checking"); duke@435: duke@435: // Update map to (3,1) - point to offset of 3 (words) with 1 map entry. duke@435: map->set_offset(java_lang_ref_Reference::queue_offset); jcoomes@1373: map->set_count(1); duke@435: } duke@435: } duke@435: duke@435: duke@435: // Verification duke@435: coleenp@4047: void InstanceRefKlass::oop_verify_on(oop obj, outputStream* st) { coleenp@4037: InstanceKlass::oop_verify_on(obj, st); duke@435: // Verify referent field duke@435: oop referent = java_lang_ref_Reference::referent(obj); duke@435: duke@435: // We should make this general to all heaps duke@435: GenCollectedHeap* gch = NULL; duke@435: if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) duke@435: gch = GenCollectedHeap::heap(); duke@435: duke@435: if (referent != NULL) { duke@435: guarantee(referent->is_oop(), "referent field heap failed"); duke@435: } duke@435: // Verify next field duke@435: oop next = java_lang_ref_Reference::next(obj); duke@435: if (next != NULL) { ysr@777: guarantee(next->is_oop(), "next field verify failed"); duke@435: guarantee(next->is_instanceRef(), "next field verify failed"); duke@435: } duke@435: } duke@435: coleenp@4047: bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) { coleenp@2367: if (java_lang_ref_Reference::pending_list_lock() == NULL) return false; coleenp@2363: Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock()); coleenp@2363: return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock); coleenp@2363: } coleenp@2363: coleenp@4047: void InstanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) { duke@435: // we may enter this with pending exception set duke@435: PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument johnc@3811: johnc@3811: // Create a HandleMark in case we retry a GC multiple times. johnc@3811: // Each time we attempt the GC, we allocate the handle below johnc@3811: // to hold the pending list lock. We want to free this handle. johnc@3811: HandleMark hm; johnc@3811: duke@435: Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock()); duke@435: ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD); duke@435: assert(ObjectSynchronizer::current_thread_holds_lock( duke@435: JavaThread::current(), h_lock), duke@435: "Locking should have succeeded"); duke@435: if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; duke@435: } duke@435: coleenp@4047: void InstanceRefKlass::release_and_notify_pending_list_lock( duke@435: BasicLock *pending_list_basic_lock) { duke@435: // we may enter this with pending exception set duke@435: PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument johnc@3811: johnc@3811: // Create a HandleMark in case we retry a GC multiple times. johnc@3811: // Each time we attempt the GC, we allocate the handle below johnc@3811: // to hold the pending list lock. We want to free this handle. johnc@3811: HandleMark hm; johnc@3811: duke@435: Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock()); duke@435: assert(ObjectSynchronizer::current_thread_holds_lock( duke@435: JavaThread::current(), h_lock), duke@435: "Lock should be held"); duke@435: // Notify waiters on pending lists lock if there is any reference. duke@435: if (java_lang_ref_Reference::pending_list() != NULL) { duke@435: ObjectSynchronizer::notifyall(h_lock, THREAD); duke@435: } duke@435: ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD); duke@435: if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; duke@435: }