Mercurial > hg > truffle
diff src/share/vm/memory/referenceProcessor.cpp @ 113:ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
Summary: Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv
Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
author | coleenp |
---|---|
date | Sun, 13 Apr 2008 17:43:42 -0400 |
parents | f21b879b4c72 |
children | d1605aabd0a1 37f87013dfd8 |
line wrap: on
line diff
--- a/src/share/vm/memory/referenceProcessor.cpp Fri Apr 11 09:56:35 2008 -0400 +++ b/src/share/vm/memory/referenceProcessor.cpp Sun Apr 13 17:43:42 2008 -0400 @@ -28,16 +28,32 @@ // List of discovered references. class DiscoveredList { public: - DiscoveredList() : _head(NULL), _len(0) { } - oop head() const { return _head; } - oop* head_ptr() { return &_head; } - void set_head(oop o) { _head = o; } - bool empty() const { return _head == ReferenceProcessor::_sentinelRef; } + DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } + oop head() const { + return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) : + _oop_head; + } + HeapWord* adr_head() { + return UseCompressedOops ? (HeapWord*)&_compressed_head : + (HeapWord*)&_oop_head; + } + void set_head(oop o) { + if (UseCompressedOops) { + // Must compress the head ptr. + _compressed_head = oopDesc::encode_heap_oop_not_null(o); + } else { + _oop_head = o; + } + } + bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } size_t length() { return _len; } void set_length(size_t len) { _len = len; } private: + // Set value depending on UseCompressedOops. This could be a template class + // but then we have to fix all the instantiations and declarations that use this class. + oop _oop_head; + narrowOop _compressed_head; size_t _len; - oop _head; }; oop ReferenceProcessor::_sentinelRef = NULL; @@ -49,11 +65,11 @@ } void ReferenceProcessor::init_statics() { - assert(_sentinelRef == NULL, "should be initialized precsiely once"); + assert(_sentinelRef == NULL, "should be initialized precisely once"); EXCEPTION_MARK; _sentinelRef = instanceKlass::cast( - SystemDictionary::object_klass())-> - allocate_permanent_instance(THREAD); + SystemDictionary::reference_klass())-> + allocate_permanent_instance(THREAD); // Initialize the master soft ref clock. java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); @@ -69,15 +85,13 @@ "Unrecongnized RefDiscoveryPolicy"); } - -ReferenceProcessor* ReferenceProcessor::create_ref_processor( - MemRegion span, - bool atomic_discovery, - bool mt_discovery, - BoolObjectClosure* is_alive_non_header, - int parallel_gc_threads, - bool mt_processing) -{ +ReferenceProcessor* +ReferenceProcessor::create_ref_processor(MemRegion span, + bool atomic_discovery, + bool mt_discovery, + BoolObjectClosure* is_alive_non_header, + int parallel_gc_threads, + bool mt_processing) { int mt_degree = 1; if (parallel_gc_threads > 1) { mt_degree = parallel_gc_threads; @@ -93,10 +107,11 @@ return rp; } - ReferenceProcessor::ReferenceProcessor(MemRegion span, - bool atomic_discovery, bool mt_discovery, int mt_degree, - bool mt_processing) : + bool atomic_discovery, + bool mt_discovery, + int mt_degree, + bool mt_processing) : _discovering_refs(false), _enqueuing_is_done(false), _is_alive_non_header(NULL), @@ -114,10 +129,10 @@ _discoveredWeakRefs = &_discoveredSoftRefs[_num_q]; _discoveredFinalRefs = &_discoveredWeakRefs[_num_q]; _discoveredPhantomRefs = &_discoveredFinalRefs[_num_q]; - assert(_sentinelRef != NULL, "_sentinelRef is NULL"); + assert(sentinel_ref() != NULL, "_sentinelRef is NULL"); // Initialized all entries to _sentinelRef for (int i = 0; i < _num_q * subclasses_of_ref; i++) { - _discoveredSoftRefs[i].set_head(_sentinelRef); + _discoveredSoftRefs[i].set_head(sentinel_ref()); _discoveredSoftRefs[i].set_length(0); } } @@ -134,16 +149,19 @@ void ReferenceProcessor::weak_oops_do(OopClosure* f) { for (int i = 0; i < _num_q * subclasses_of_ref; i++) { - f->do_oop(_discoveredSoftRefs[i].head_ptr()); + if (UseCompressedOops) { + f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head()); + } else { + f->do_oop((oop*)_discoveredSoftRefs[i].adr_head()); + } } } void ReferenceProcessor::oops_do(OopClosure* f) { - f->do_oop(&_sentinelRef); + f->do_oop(adr_sentinel_ref()); } -void ReferenceProcessor::update_soft_ref_master_clock() -{ +void ReferenceProcessor::update_soft_ref_master_clock() { // Update (advance) the soft ref master clock field. This must be done // after processing the soft ref list. jlong now = os::javaTimeMillis(); @@ -164,9 +182,7 @@ // past clock value. } - -void -ReferenceProcessor::process_discovered_references( +void ReferenceProcessor::process_discovered_references( ReferencePolicy* policy, BoolObjectClosure* is_alive, OopClosure* keep_alive, @@ -223,15 +239,13 @@ } } - #ifndef PRODUCT // Calculate the number of jni handles. -unsigned int ReferenceProcessor::count_jni_refs() -{ +uint ReferenceProcessor::count_jni_refs() { class AlwaysAliveClosure: public BoolObjectClosure { public: - bool do_object_b(oop obj) { return true; } - void do_object(oop obj) { assert(false, "Don't call"); } + virtual bool do_object_b(oop obj) { return true; } + virtual void do_object(oop obj) { assert(false, "Don't call"); } }; class CountHandleClosure: public OopClosure { @@ -239,9 +253,8 @@ int _count; public: CountHandleClosure(): _count(0) {} - void do_oop(oop* unused) { - _count++; - } + void do_oop(oop* unused) { _count++; } + void do_oop(narrowOop* unused) { ShouldNotReachHere(); } int count() { return _count; } }; CountHandleClosure global_handle_count; @@ -262,36 +275,48 @@ #endif JNIHandles::weak_oops_do(is_alive, keep_alive); // Finally remember to keep sentinel around - keep_alive->do_oop(&_sentinelRef); + keep_alive->do_oop(adr_sentinel_ref()); complete_gc->do_void(); } -bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { - NOT_PRODUCT(verify_ok_to_handle_reflists()); + +template <class T> +static bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, + AbstractRefProcTaskExecutor* task_executor) { + // Remember old value of pending references list - oop* pending_list_addr = java_lang_ref_Reference::pending_list_addr(); - oop old_pending_list_value = *pending_list_addr; + T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr(); + T old_pending_list_value = *pending_list_addr; // Enqueue references that are not made active again, and // clear the decks for the next collection (cycle). - enqueue_discovered_reflists(pending_list_addr, task_executor); + ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor); // Do the oop-check on pending_list_addr missed in // enqueue_discovered_reflist. We should probably // do a raw oop_check so that future such idempotent // oop_stores relying on the oop-check side-effect // may be elided automatically and safely without // affecting correctness. - oop_store(pending_list_addr, *(pending_list_addr)); + oop_store(pending_list_addr, oopDesc::load_decode_heap_oop(pending_list_addr)); // Stop treating discovered references specially. - disable_discovery(); + ref->disable_discovery(); // Return true if new pending references were added return old_pending_list_value != *pending_list_addr; } +bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { + NOT_PRODUCT(verify_ok_to_handle_reflists()); + if (UseCompressedOops) { + return enqueue_discovered_ref_helper<narrowOop>(this, task_executor); + } else { + return enqueue_discovered_ref_helper<oop>(this, task_executor); + } +} + void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, - oop* pending_list_addr) { + HeapWord* pending_list_addr) { // Given a list of refs linked through the "discovered" field // (java.lang.ref.Reference.discovered) chain them through the // "next" field (java.lang.ref.Reference.next) and prepend @@ -305,19 +330,19 @@ // the next field and clearing it (except for the last // non-sentinel object which is treated specially to avoid // confusion with an active reference). - while (obj != _sentinelRef) { + while (obj != sentinel_ref()) { assert(obj->is_instanceRef(), "should be reference object"); oop next = java_lang_ref_Reference::discovered(obj); if (TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, - (oopDesc*) obj, (oopDesc*) next); + gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, + obj, next); } - assert(*java_lang_ref_Reference::next_addr(obj) == NULL, - "The reference should not be enqueued"); - if (next == _sentinelRef) { // obj is last + assert(java_lang_ref_Reference::next(obj) == NULL, + "The reference should not be enqueued"); + if (next == sentinel_ref()) { // obj is last // Swap refs_list into pendling_list_addr and // set obj's next to what we read from pending_list_addr. - oop old = (oop)Atomic::xchg_ptr(refs_list.head(), pending_list_addr); + oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); // Need oop_check on pending_list_addr above; // see special oop-check code at the end of // enqueue_discovered_reflists() further below. @@ -341,15 +366,14 @@ public: RefProcEnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList discovered_refs[], - oop* pending_list_addr, + HeapWord* pending_list_addr, oop sentinel_ref, int n_queues) : EnqueueTask(ref_processor, discovered_refs, pending_list_addr, sentinel_ref, n_queues) { } - virtual void work(unsigned int work_id) - { + virtual void work(unsigned int work_id) { assert(work_id < (unsigned int)_ref_processor.num_q(), "Index out-of-bounds"); // Simplest first cut: static partitioning. int index = work_id; @@ -363,18 +387,18 @@ }; // Enqueue references that are not made active again -void ReferenceProcessor::enqueue_discovered_reflists(oop* pending_list_addr, +void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor) { if (_processing_is_mt && task_executor != NULL) { // Parallel code RefProcEnqueueTask tsk(*this, _discoveredSoftRefs, - pending_list_addr, _sentinelRef, _num_q); + pending_list_addr, sentinel_ref(), _num_q); task_executor->execute(tsk); } else { // Serial code: call the parent class's implementation for (int i = 0; i < _num_q * subclasses_of_ref; i++) { enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); - _discoveredSoftRefs[i].set_head(_sentinelRef); + _discoveredSoftRefs[i].set_head(sentinel_ref()); _discoveredSoftRefs[i].set_length(0); } } @@ -388,14 +412,13 @@ BoolObjectClosure* is_alive); // End Of List. - inline bool has_next() const - { return _next != ReferenceProcessor::_sentinelRef; } + inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); } // Get oop to the Reference object. - inline oop obj() const { return _ref; } + inline oop obj() const { return _ref; } // Get oop to the referent object. - inline oop referent() const { return _referent; } + inline oop referent() const { return _referent; } // Returns true if referent is alive. inline bool is_referent_alive() const; @@ -417,13 +440,26 @@ inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); } // Make the referent alive. - inline void make_referent_alive() { _keep_alive->do_oop(_referent_addr); } + inline void make_referent_alive() { + if (UseCompressedOops) { + _keep_alive->do_oop((narrowOop*)_referent_addr); + } else { + _keep_alive->do_oop((oop*)_referent_addr); + } + } // Update the discovered field. - inline void update_discovered() { _keep_alive->do_oop(_prev_next); } + inline void update_discovered() { + // First _prev_next ref actually points into DiscoveredList (gross). + if (UseCompressedOops) { + _keep_alive->do_oop((narrowOop*)_prev_next); + } else { + _keep_alive->do_oop((oop*)_prev_next); + } + } // NULL out referent pointer. - inline void clear_referent() { *_referent_addr = NULL; } + inline void clear_referent() { oop_store_raw(_referent_addr, NULL); } // Statistics NOT_PRODUCT( @@ -436,11 +472,11 @@ private: DiscoveredList& _refs_list; - oop* _prev_next; + HeapWord* _prev_next; oop _ref; - oop* _discovered_addr; + HeapWord* _discovered_addr; oop _next; - oop* _referent_addr; + HeapWord* _referent_addr; oop _referent; OopClosure* _keep_alive; BoolObjectClosure* _is_alive; @@ -457,7 +493,7 @@ OopClosure* keep_alive, BoolObjectClosure* is_alive) : _refs_list(refs_list), - _prev_next(refs_list.head_ptr()), + _prev_next(refs_list.adr_head()), _ref(refs_list.head()), #ifdef ASSERT _first_seen(refs_list.head()), @@ -471,19 +507,18 @@ _is_alive(is_alive) { } -inline bool DiscoveredListIterator::is_referent_alive() const -{ +inline bool DiscoveredListIterator::is_referent_alive() const { return _is_alive->do_object_b(_referent); } -inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) -{ +inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref); - assert(_discovered_addr && (*_discovered_addr)->is_oop_or_null(), + oop discovered = java_lang_ref_Reference::discovered(_ref); + assert(_discovered_addr && discovered->is_oop_or_null(), "discovered field is bad"); - _next = *_discovered_addr; + _next = discovered; _referent_addr = java_lang_ref_Reference::referent_addr(_ref); - _referent = *_referent_addr; + _referent = java_lang_ref_Reference::referent(_ref); assert(Universe::heap()->is_in_reserved_or_null(_referent), "Wrong oop found in java.lang.Reference object"); assert(allow_null_referent ? @@ -492,32 +527,32 @@ "bad referent"); } -inline void DiscoveredListIterator::next() -{ +inline void DiscoveredListIterator::next() { _prev_next = _discovered_addr; move_to_next(); } -inline void DiscoveredListIterator::remove() -{ +inline void DiscoveredListIterator::remove() { assert(_ref->is_oop(), "Dropping a bad reference"); - // Clear the discovered_addr field so that the object does - // not look like it has been discovered. - *_discovered_addr = NULL; - // Remove Reference object from list. - *_prev_next = _next; + oop_store_raw(_discovered_addr, NULL); + // First _prev_next ref actually points into DiscoveredList (gross). + if (UseCompressedOops) { + // Remove Reference object from list. + oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next); + } else { + // Remove Reference object from list. + oopDesc::store_heap_oop((oop*)_prev_next, _next); + } NOT_PRODUCT(_removed++); move_to_next(); } -inline void DiscoveredListIterator::move_to_next() -{ +inline void DiscoveredListIterator::move_to_next() { _ref = _next; assert(_ref != _first_seen, "cyclic ref_list found"); NOT_PRODUCT(_processed++); } - // NOTE: process_phase*() are largely similar, and at a high level // merely iterate over the extant list applying a predicate to // each of its elements and possibly removing that element from the @@ -531,13 +566,13 @@ // referents are not alive, but that should be kept alive for policy reasons. // Keep alive the transitive closure of all such referents. void -ReferenceProcessor::process_phase1(DiscoveredList& refs_list_addr, +ReferenceProcessor::process_phase1(DiscoveredList& refs_list, ReferencePolicy* policy, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc) { assert(policy != NULL, "Must have a non-NULL policy"); - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); // Decide which softly reachable refs should be kept alive. while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -545,7 +580,7 @@ if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", - (address)iter.obj(), iter.obj()->blueprint()->internal_name()); + iter.obj(), iter.obj()->blueprint()->internal_name()); } // Make the Reference object active again iter.make_active(); @@ -570,20 +605,19 @@ // Traverse the list and remove any Refs that are not active, or // whose referents are either alive or NULL. void -ReferenceProcessor::pp2_work(DiscoveredList& refs_list_addr, +ReferenceProcessor::pp2_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, - OopClosure* keep_alive) -{ + OopClosure* keep_alive) { assert(discovery_is_atomic(), "Error"); - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); - DEBUG_ONLY(oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj());) - assert(*next_addr == NULL, "Should not discover inactive Reference"); + DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());) + assert(next == NULL, "Should not discover inactive Reference"); if (iter.is_referent_alive()) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)", - (address)iter.obj(), iter.obj()->blueprint()->internal_name()); + iter.obj(), iter.obj()->blueprint()->internal_name()); } // The referent is reachable after all. // Update the referent pointer as necessary: Note that this @@ -605,25 +639,28 @@ } void -ReferenceProcessor::pp2_work_concurrent_discovery( - DiscoveredList& refs_list_addr, - BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc) -{ +ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list, + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + VoidClosure* complete_gc) { assert(!discovery_is_atomic(), "Error"); - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); + HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); + oop next = java_lang_ref_Reference::next(iter.obj()); if ((iter.referent() == NULL || iter.is_referent_alive() || - *next_addr != NULL)) { - assert((*next_addr)->is_oop_or_null(), "bad next field"); + next != NULL)) { + assert(next->is_oop_or_null(), "bad next field"); // Remove Reference object from list iter.remove(); // Trace the cohorts iter.make_referent_alive(); - keep_alive->do_oop(next_addr); + if (UseCompressedOops) { + keep_alive->do_oop((narrowOop*)next_addr); + } else { + keep_alive->do_oop((oop*)next_addr); + } } else { iter.next(); } @@ -639,15 +676,15 @@ } // Traverse the list and process the referents, by either -// either clearing them or keeping them (and their reachable +// clearing them or keeping them (and their reachable // closure) alive. void -ReferenceProcessor::process_phase3(DiscoveredList& refs_list_addr, +ReferenceProcessor::process_phase3(DiscoveredList& refs_list, bool clear_referent, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc) { - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.update_discovered(); iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); @@ -661,7 +698,7 @@ if (TraceReferenceGC) { gclog_or_tty->print_cr("Adding %sreference (" INTPTR_FORMAT ": %s) as pending", clear_referent ? "cleared " : "", - (address)iter.obj(), iter.obj()->blueprint()->internal_name()); + iter.obj(), iter.obj()->blueprint()->internal_name()); } assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); // If discovery is concurrent, we may have objects with null referents, @@ -679,15 +716,15 @@ } void -ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& ref_list) { - oop obj = ref_list.head(); - while (obj != _sentinelRef) { - oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); - obj = *discovered_addr; - *discovered_addr = NULL; +ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { + oop obj = refs_list.head(); + while (obj != sentinel_ref()) { + oop discovered = java_lang_ref_Reference::discovered(obj); + java_lang_ref_Reference::set_discovered_raw(obj, NULL); + obj = discovered; } - ref_list.set_head(_sentinelRef); - ref_list.set_length(0); + refs_list.set_head(sentinel_ref()); + refs_list.set_length(0); } void @@ -777,7 +814,7 @@ // find an element to split the list on for (size_t j = 0; j < refs_to_move; ++j) { move_tail = new_head; - new_head = *java_lang_ref_Reference::discovered_addr(new_head); + new_head = java_lang_ref_Reference::discovered(new_head); } java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); ref_lists[to_idx].set_head(move_head); @@ -875,17 +912,17 @@ size_t length = refs_list.length(); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); - assert((*next_addr)->is_oop_or_null(), "bad next field"); + oop next = java_lang_ref_Reference::next(iter.obj()); + assert(next->is_oop_or_null(), "bad next field"); // If referent has been cleared or Reference is not active, // drop it. - if (iter.referent() == NULL || *next_addr != NULL) { + if (iter.referent() == NULL || next != NULL) { debug_only( if (PrintGCDetails && TraceReferenceGC) { gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: " INTPTR_FORMAT " with next field: " INTPTR_FORMAT " and referent: " INTPTR_FORMAT, - (address)iter.obj(), (address)*next_addr, (address)iter.referent()); + iter.obj(), next, iter.referent()); } ) // Remove Reference object from list @@ -950,18 +987,21 @@ return list; } -inline void ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& list, - oop obj, oop* discovered_addr) { +inline void +ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, + oop obj, + HeapWord* discovered_addr) { assert(_discovery_is_mt, "!_discovery_is_mt should have been handled by caller"); // First we must make sure this object is only enqueued once. CAS in a non null // discovered_addr. - oop retest = (oop)Atomic::cmpxchg_ptr(list.head(), discovered_addr, NULL); + oop retest = oopDesc::atomic_compare_exchange_oop(refs_list.head(), discovered_addr, + NULL); if (retest == NULL) { // This thread just won the right to enqueue the object. // We have separate lists for enqueueing so no synchronization // is necessary. - list.set_head(obj); - list.set_length(list.length() + 1); + refs_list.set_head(obj); + refs_list.set_length(refs_list.length() + 1); } else { // If retest was non NULL, another thread beat us to it: // The reference has already been discovered... @@ -972,7 +1012,6 @@ } } - // We mention two of several possible choices here: // #0: if the reference object is not in the "originating generation" // (or part of the heap being collected, indicated by our "span" @@ -1006,8 +1045,8 @@ return false; } // We only enqueue active references. - oop* next_addr = java_lang_ref_Reference::next_addr(obj); - if (*next_addr != NULL) { + oop next = java_lang_ref_Reference::next(obj); + if (next != NULL) { return false; } @@ -1034,14 +1073,14 @@ } } - oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); - assert(discovered_addr != NULL && (*discovered_addr)->is_oop_or_null(), - "bad discovered field"); - if (*discovered_addr != NULL) { + HeapWord* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); + oop discovered = java_lang_ref_Reference::discovered(obj); + assert(discovered->is_oop_or_null(), "bad discovered field"); + if (discovered != NULL) { // The reference has already been discovered... if (TraceReferenceGC) { gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", - (oopDesc*)obj, obj->blueprint()->internal_name()); + obj, obj->blueprint()->internal_name()); } if (RefDiscoveryPolicy == ReferentBasedDiscovery) { // assumes that an object is not processed twice; @@ -1088,7 +1127,7 @@ if (_discovery_is_mt) { add_to_discovered_list_mt(*list, obj, discovered_addr); } else { - *discovered_addr = list->head(); + oop_store_raw(discovered_addr, list->head()); list->set_head(obj); list->set_length(list->length() + 1); } @@ -1106,7 +1145,7 @@ oop referent = java_lang_ref_Reference::referent(obj); if (PrintGCDetails) { gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", - (oopDesc*) obj, obj->blueprint()->internal_name()); + obj, obj->blueprint()->internal_name()); } assert(referent->is_oop(), "Enqueued a bad referent"); } @@ -1181,17 +1220,20 @@ // are not active (have a non-NULL next field). NOTE: For this to work // correctly, refs discovery can not be happening concurrently with this // step. -void ReferenceProcessor::preclean_discovered_reflist( - DiscoveredList& refs_list, BoolObjectClosure* is_alive, - OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { - +void +ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + VoidClosure* complete_gc, + YieldClosure* yield) { DiscoveredListIterator iter(refs_list, keep_alive, is_alive); size_t length = refs_list.length(); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); + oop obj = iter.obj(); + oop next = java_lang_ref_Reference::next(obj); if (iter.referent() == NULL || iter.is_referent_alive() || - *next_addr != NULL) { + next != NULL) { // The referent has been cleared, or is alive, or the Reference is not // active; we need to trace and mark its cohort. if (TraceReferenceGC) { @@ -1203,7 +1245,13 @@ --length; // Keep alive its cohort. iter.make_referent_alive(); - keep_alive->do_oop(next_addr); + if (UseCompressedOops) { + narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj); + keep_alive->do_oop(next_addr); + } else { + oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); + keep_alive->do_oop(next_addr); + } } else { iter.next(); } @@ -1241,7 +1289,7 @@ #endif void ReferenceProcessor::verify() { - guarantee(_sentinelRef != NULL && _sentinelRef->is_oop(), "Lost _sentinelRef"); + guarantee(sentinel_ref() != NULL && sentinel_ref()->is_oop(), "Lost _sentinelRef"); } #ifndef PRODUCT @@ -1249,12 +1297,12 @@ guarantee(!_discovering_refs, "Discovering refs?"); for (int i = 0; i < _num_q * subclasses_of_ref; i++) { oop obj = _discoveredSoftRefs[i].head(); - while (obj != _sentinelRef) { + while (obj != sentinel_ref()) { oop next = java_lang_ref_Reference::discovered(obj); java_lang_ref_Reference::set_discovered(obj, (oop) NULL); obj = next; } - _discoveredSoftRefs[i].set_head(_sentinelRef); + _discoveredSoftRefs[i].set_head(sentinel_ref()); _discoveredSoftRefs[i].set_length(0); } }