# HG changeset patch # User zgu # Date 1580757616 18000 # Mon Feb 03 14:20:16 2020 -0500 # Node ID af93c2684f4249e9eb395ea46ef98fd9f466dccb # Parent 2a0de7812409d2886b7fea376372616b55c96f4d 8237632: Shenandoah fails some vmTestbase_nsk_jvmti tests with "Forwardee must point to a heap address" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -234,12 +234,15 @@ } // Step 4. Check for multiple forwardings + /* + Disable for now. JVMTI heap walking creates 'forwarded' pattern outside cset oop fwd2 = oop(ShenandoahForwarding::get_forwardee_raw_unchecked(fwd)); if (fwd != fwd2) { print_failure(_safe_all, obj, interior_loc, NULL, "Shenandoah assert_correct failed", "Multiple forwardings", file, line); } + */ } } @@ -375,3 +378,12 @@ ShenandoahMessageBuffer msg("Must ba at a Shenandoah safepoint or held %s lock", lock->name()); report_vm_error(file, line, msg.buffer()); } + +#ifdef ASSERT +bool ShenandoahAsserts::can_verify_oop(oop obj) { + if (CompressedOops::is_null(obj)) return true; + ShenandoahHeap* const heap = ShenandoahHeap::heap_no_check(); + if (heap->in_collection_set(obj)) return true; + return false; +} +#endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp @@ -69,52 +69,76 @@ static void assert_locked_or_shenandoah_safepoint(Mutex* lock, const char* file, int line); #ifdef ASSERT + // Shenandoah uses oop's marked pattern to indicate forwarding. Unfortunately, ObjectMarker (jvmtiTagMap.cpp) + // also uses this pattern to indicate visited. + // In ObjectMarker's destructor, it invokes heap iteration to reset the marked bits to their original values. + // That trips over many assertions on heap iteration code paths, but there are invariants: + // 1. Marked pattern in collection set indicates forwarding + // 2. Marked pattern off collection set indicates visited by ObjectMarker (because oops seen by + // ObjectMarker were LRB'd) + // 3. No off collection set marked pattern at any shenandoah safepoint. In fact, no off collection set + // marked pattern at any safepoints other than VM_HeapWalkOperation safepoints. + // This is an important invariant, since traversal degenerated GC clears collection set before + // entering degenerated GC cycle. + // So, we will need temporary disable assertions for oops with marked pattern outside collection set. + // Note: We only enforce this check for debug assertion to preserve full capacities of verifier, + // because verifier always runs at safepoints. + static bool can_verify_oop(oop obj); + #define shenandoah_assert_in_heap(interior_loc, obj) \ - ShenandoahAsserts::assert_in_heap(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_in_heap(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_in_correct_region(interior_loc, obj) \ - ShenandoahAsserts::assert_in_correct_region(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_in_correct_region(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_correct_if(interior_loc, obj, condition) \ - if (condition) ShenandoahAsserts::assert_correct(interior_loc, obj, __FILE__, __LINE__); + if (condition && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_correct(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_correct_except(interior_loc, obj, exception) \ - if (!(exception)) ShenandoahAsserts::assert_correct(interior_loc, obj, __FILE__, __LINE__); + if (!(exception) && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_correct(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_correct(interior_loc, obj) \ - ShenandoahAsserts::assert_correct(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_correct(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_forwarded_if(interior_loc, obj, condition) \ - if (condition) ShenandoahAsserts::assert_forwarded(interior_loc, obj, __FILE__, __LINE__); + if (condition && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_forwarded(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_forwarded_except(interior_loc, obj, exception) \ - if (!(exception)) ShenandoahAsserts::assert_forwarded(interior_loc, obj, __FILE__, __LINE__); + if (!(exception) && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_forwarded(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_forwarded(interior_loc, obj) \ - ShenandoahAsserts::assert_forwarded(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_forwarded(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_forwarded_if(interior_loc, obj, condition) \ - if (condition) ShenandoahAsserts::assert_not_forwarded(interior_loc, obj, __FILE__, __LINE__); + if (condition && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_not_forwarded(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_forwarded_except(interior_loc, obj, exception) \ - if (!(exception)) ShenandoahAsserts::assert_not_forwarded(interior_loc, obj, __FILE__, __LINE__); + if (!(exception) && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_not_forwarded(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_forwarded(interior_loc, obj) \ - ShenandoahAsserts::assert_not_forwarded(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_not_forwarded(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_marked_if(interior_loc, obj, condition) \ - if (condition) ShenandoahAsserts::assert_marked(interior_loc, obj, __FILE__, __LINE__); + if (condition && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_marked(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_marked_except(interior_loc, obj, exception) \ - if (!(exception)) ShenandoahAsserts::assert_marked(interior_loc, obj, __FILE__, __LINE__); + if (!(exception) && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_marked(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_marked(interior_loc, obj) \ - ShenandoahAsserts::assert_marked(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_marked(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_in_cset_if(interior_loc, obj, condition) \ - if (condition) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__); + if (condition && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_in_cset_except(interior_loc, obj, exception) \ - if (!(exception)) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__); + if (!(exception) && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_in_cset(interior_loc, obj) \ - ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_in_cset_if(interior_loc, obj, condition) \ - if (condition) ShenandoahAsserts::assert_not_in_cset(interior_loc, obj, __FILE__, __LINE__); + if (condition && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_not_in_cset(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_in_cset_except(interior_loc, obj, exception) \ - if (!(exception)) ShenandoahAsserts::assert_not_in_cset(interior_loc, obj, __FILE__, __LINE__); + if (!(exception) && ShenandoahAsserts::can_verify_oop(obj)) ShenandoahAsserts::assert_not_in_cset(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_in_cset(interior_loc, obj) \ - ShenandoahAsserts::assert_not_in_cset(interior_loc, obj, __FILE__, __LINE__); + if (ShenandoahAsserts::can_verify_oop(obj)) \ + ShenandoahAsserts::assert_not_in_cset(interior_loc, obj, __FILE__, __LINE__); #define shenandoah_assert_not_in_cset_loc_if(interior_loc, condition) \ if (condition) ShenandoahAsserts::assert_not_in_cset_loc(interior_loc, __FILE__, __LINE__); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -193,20 +193,24 @@ oop ShenandoahBarrierSet::load_reference_barrier_impl(oop obj) { assert(ShenandoahLoadRefBarrier, "should be enabled"); if (!CompressedOops::is_null(obj)) { - bool evac_in_progress = _heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL); - oop fwd = resolve_forwarded_not_null(obj); - if (evac_in_progress && - _heap->in_collection_set(obj) && - obj == fwd) { - Thread *t = Thread::current(); - ShenandoahEvacOOMScope oom_evac_scope; - return _heap->evacuate_object(obj, t); - } else { - return fwd; + if (_heap->in_collection_set(obj)) { + oop fwd = resolve_forwarded_not_null(obj); + bool evac_in_progress = _heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION | ShenandoahHeap::TRAVERSAL); + if (evac_in_progress && obj == fwd) { + Thread *t = Thread::current(); + ShenandoahEvacOOMScope oom_evac_scope; + return _heap->evacuate_object(obj, t); + } else { + return fwd; + } + } else if (_heap->is_concurrent_traversal_in_progress() && + _heap->is_degenerated_gc_in_progress()) { + // Traversal GC clears collection set before entering degenerated GC. + // At this point, marked pattern indicates forwarding. + return resolve_forwarded_not_null(obj); } - } else { - return obj; } + return obj; } void ShenandoahBarrierSet::on_thread_create(Thread* thread) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp @@ -84,6 +84,7 @@ static inline oop resolve_forwarded_not_null(oop p); static inline oop resolve_forwarded(oop p); + static inline oop resolve_forwarded_checked(oop p); template inline void satb_barrier(T* field); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -32,11 +32,15 @@ #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" +#include "gc/shenandoah/shenandoahSafepoint.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "memory/iterator.inline.hpp" #include "oops/oop.inline.hpp" inline oop ShenandoahBarrierSet::resolve_forwarded_not_null(oop p) { + assert(ShenandoahHeap::heap()->in_collection_set(p) || + ShenandoahSafepoint::is_at_shenandoah_safepoint(), + "No forwarding oops outside cset"); return ShenandoahForwarding::get_forwardee(p); } @@ -48,6 +52,17 @@ } } +inline oop ShenandoahBarrierSet::resolve_forwarded_checked(oop p) { + if (p == NULL) return p; + ShenandoahHeap* const heap = ShenandoahHeap::heap(); + if (heap->in_collection_set(p) || + (heap->is_concurrent_traversal_in_progress() && heap->is_degenerated_gc_in_progress())) { + return resolve_forwarded_not_null(p); + } else { + return p; + } +} + inline void ShenandoahBarrierSet::enqueue(oop obj) { shenandoah_assert_not_forwarded_if(NULL, obj, _heap->is_concurrent_traversal_in_progress()); assert(_satb_mark_queue_set.is_active(), "only get here when SATB active"); @@ -119,7 +134,9 @@ if (value != NULL) { ShenandoahBarrierSet *const bs = ShenandoahBarrierSet::barrier_set(); value = bs->load_reference_barrier_native(value, addr); - bs->keep_alive_if_weak(value); + if (value != NULL) { + bs->keep_alive_if_weak(value); + } } return value; } @@ -185,7 +202,7 @@ compare_value = expected; res = Raw::oop_atomic_cmpxchg(addr, compare_value, new_value); expected = res; - } while ((compare_value != expected) && (resolve_forwarded(compare_value) == resolve_forwarded(expected))); + } while ((compare_value != expected) && (resolve_forwarded_checked(compare_value) == resolve_forwarded_checked(expected))); // Note: We don't need a keep-alive-barrier here. We already enqueue any loaded reference for SATB anyway, // because it must be the previous value. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2019, 2020, Red Hat, Inc. All rights reserved. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as @@ -32,12 +32,22 @@ class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure { private: + ShenandoahHeap* const _heap; ShenandoahMarkingContext* const _mark_context; public: inline ShenandoahForwardedIsAliveClosure(); inline bool do_object_b(oop obj); }; +class ShenandoahForwardedIsAliveNoCSetCheckClosure: public BoolObjectClosure { +private: + ShenandoahMarkingContext* const _mark_context; +public: + inline ShenandoahForwardedIsAliveNoCSetCheckClosure(); + inline bool do_object_b(oop obj); +}; + + class ShenandoahIsAliveClosure: public BoolObjectClosure { private: ShenandoahMarkingContext* const _mark_context; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp @@ -28,12 +28,14 @@ #include "gc/shenandoah/shenandoahClosures.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahNMethod.inline.hpp" +#include "gc/shenandoah/shenandoahSafepoint.hpp" #include "gc/shenandoah/shenandoahTraversalGC.hpp" #include "oops/compressedOops.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/thread.hpp" ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() : + _heap(ShenandoahHeap::heap()), _mark_context(ShenandoahHeap::heap()->marking_context()) { } @@ -41,10 +43,25 @@ if (CompressedOops::is_null(obj)) { return false; } - obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); + if (_heap->in_collection_set(obj)) { + obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); + } shenandoah_assert_not_forwarded_if(NULL, obj, (ShenandoahHeap::heap()->is_concurrent_mark_in_progress() || - ShenandoahHeap::heap()->is_concurrent_traversal_in_progress())); + ShenandoahHeap::heap()->is_concurrent_traversal_in_progress())); + return _mark_context->is_marked(obj); +} + +ShenandoahForwardedIsAliveNoCSetCheckClosure::ShenandoahForwardedIsAliveNoCSetCheckClosure() : + _mark_context(ShenandoahHeap::heap()->marking_context()) { + assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only used at a safepoint"); +} + +bool ShenandoahForwardedIsAliveNoCSetCheckClosure::do_object_b(oop obj) { + if (CompressedOops::is_null(obj)) { + return false; + } + obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); return _mark_context->is_marked(obj); } @@ -86,6 +103,7 @@ _heap(ShenandoahHeap::heap()), _traversal_set(ShenandoahHeap::heap()->traversal_gc()->traversal_set()) { assert(_heap->is_traversal_mode(), "Why we here?"); + assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); } template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.inline.hpp @@ -240,7 +240,9 @@ case NONE: break; case RESOLVE: - obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); + if (heap->in_collection_set(obj)) { + obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); + } break; case SIMPLE: // We piggy-back reference updating to the marking tasks. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1227,28 +1227,26 @@ private: MarkBitMap* _bitmap; Stack* _oop_stack; + ShenandoahHeap* const _heap; + ShenandoahMarkingContext* const _marking_context; template void do_oop_work(T* p) { T o = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(o)) { oop obj = CompressedOops::decode_not_null(o); - oop fwd = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(obj); - if (fwd == NULL) { - // There is an odd interaction with VM_HeapWalkOperation, see jvmtiTagMap.cpp. - // - // That operation walks the reachable objects on its own, storing the marking - // wavefront in the object marks. When it is done, it calls the CollectedHeap - // to iterate over all objects to clean up the mess. When it reaches here, - // the Shenandoah fwdptr resolution code encounters the marked objects with - // NULL forwardee. Trying to act on that would crash the VM. Or fail the - // asserts, should we go for resolve_forwarded_pointer(obj). - // - // Therefore, we have to dodge it by doing the raw access to forwardee, and - // assuming the object had no forwardee, if that thing is NULL. - } else { - obj = fwd; + + // In concurrent roots phase, there are dead oops in weak roots. + if (_heap->is_concurrent_root_in_progress() && + !_marking_context->is_marked(obj)) { + return; } + + // Only oops in collection set have forwarding pointers + if (_heap->in_collection_set(obj)) { + obj = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(obj); + } + assert(oopDesc::is_oop(obj), "must be a valid oop"); if (!_bitmap->is_marked((HeapWord*) obj)) { _bitmap->mark((HeapWord*) obj); @@ -1258,7 +1256,8 @@ } public: ObjectIterateScanRootClosure(MarkBitMap* bitmap, Stack* oop_stack) : - _bitmap(bitmap), _oop_stack(oop_stack) {} + _bitmap(bitmap), _oop_stack(oop_stack), _heap(ShenandoahHeap::heap()), + _marking_context(ShenandoahHeap::heap()->marking_context()) {} void do_oop(oop* p) { do_oop_work(p); } void do_oop(narrowOop* p) { do_oop_work(p); } }; @@ -1303,15 +1302,7 @@ // First, we process GC roots according to current GC cycle. This populates the work stack with initial objects. ShenandoahHeapIterationRootScanner rp; ObjectIterateScanRootClosure oops(&_aux_bit_map, &oop_stack); - - // If we are unloading classes right now, we should not touch weak roots, - // on the off-chance we would evacuate them and make them live accidentally. - // In other cases, we have to scan all roots. - if (is_evacuation_in_progress() && unload_classes()) { - rp.strong_roots_do(&oops); - } else { - rp.roots_do(&oops); - } + rp.roots_do(&oops); // Work through the oop stack to traverse heap. while (! oop_stack.is_empty()) { @@ -2080,15 +2071,15 @@ ShenandoahGCPhase phase(timing_phase); if (has_forwarded_objects()) { if (is_traversal_mode()) { - ShenandoahForwardedIsAliveClosure is_alive; + ShenandoahForwardedIsAliveNoCSetCheckClosure is_alive; ShenandoahTraversalUpdateRefsClosure keep_alive; - ShenandoahParallelWeakRootsCleaningTask + ShenandoahParallelWeakRootsCleaningTask cleaning_task(&is_alive, &keep_alive, num_workers); _workers->run_task(&cleaning_task); } else { - ShenandoahForwardedIsAliveClosure is_alive; + ShenandoahForwardedIsAliveNoCSetCheckClosure is_alive; ShenandoahUpdateRefsClosure keep_alive; - ShenandoahParallelWeakRootsCleaningTask + ShenandoahParallelWeakRootsCleaningTask cleaning_task(&is_alive, &keep_alive, num_workers); _workers->run_task(&cleaning_task); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -176,7 +176,10 @@ // which leaves a short window where the new array elements can be from-space. // In this case, we can just resolve the result again. As we resolve, we need to consider // the contended write might have been NULL. - oop result = ShenandoahBarrierSet::resolve_forwarded(witness); + oop result = witness; + if (!CompressedOops::is_null(witness) && in_collection_set(witness)) { + result = ShenandoahBarrierSet::resolve_forwarded(witness); + } shenandoah_assert_not_forwarded_except(p, result, (result == NULL)); shenandoah_assert_not_in_cset_except(p, result, (result == NULL) || cancelled_gc()); return result; @@ -317,7 +320,7 @@ template inline bool ShenandoahHeap::requires_marking(const void* entry) const { oop obj = oop(entry); - if (RESOLVE) { + if (RESOLVE && in_collection_set(obj)) { obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj); } return !_marking_context->is_marked(obj); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -266,17 +266,3 @@ _weak_roots.oops_do(oops, 0); _dedup_roots.oops_do(&always_true, oops, 0); } - - void ShenandoahHeapIterationRootScanner::strong_roots_do(OopClosure* oops) { - assert(Thread::current()->is_VM_thread(), "Only by VM thread"); - // Must use _claim_none to avoid interfering with concurrent CLDG iteration - CLDToOopClosure clds(oops, ClassLoaderData::_claim_none); - MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations); - ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL); - ResourceMark rm; - - _serial_roots.oops_do(oops, 0); - _vm_roots.oops_do(oops, 0); - _cld_roots.always_strong_cld_do(&clds, 0); - _thread_roots.threads_do(&tc_cl, 0); - } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -264,7 +264,6 @@ ShenandoahHeapIterationRootScanner(); void roots_do(OopClosure* cl); - void strong_roots_do(OopClosure* cl); }; // Evacuate all roots at a safepoint diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSafepoint.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSafepoint.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahSafepoint.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSAFEPOINT_HPP +#define SHARE_GC_SHENANDOAH_SHENANDOAHSAFEPOINT_HPP + +#include "memory/allocation.hpp" +#include "runtime/vmThread.hpp" +#include "runtime/vmOperations.hpp" + + +class ShenandoahSafepoint : public AllStatic { +public: + // check if Shenandoah GC safepoint is in progress + static inline bool is_at_shenandoah_safepoint() { + if (!SafepointSynchronize::is_at_safepoint()) return false; + + VM_Operation* vm_op = VMThread::vm_operation(); + if (vm_op == NULL) return false; + + VM_Operation::VMOp_Type type = vm_op->type(); + return type == VM_Operation::VMOp_ShenandoahInitMark || + type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac || + type == VM_Operation::VMOp_ShenandoahFinalEvac || + type == VM_Operation::VMOp_ShenandoahInitTraversalGC || + type == VM_Operation::VMOp_ShenandoahFinalTraversalGC || + type == VM_Operation::VMOp_ShenandoahInitUpdateRefs || + type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs || + type == VM_Operation::VMOp_ShenandoahFullGC || + type == VM_Operation::VMOp_ShenandoahDegeneratedGC; + } +}; + +#endif // SHARE_GC_SHENANDOAH_SHENANDOAHSAFEPOINT_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp @@ -1045,7 +1045,7 @@ ShenandoahPhaseTimings::Phase phase_process = ShenandoahPhaseTimings::weakrefs_process; shenandoah_assert_rp_isalive_not_installed(); - ShenandoahForwardedIsAliveClosure is_alive; + ShenandoahForwardedIsAliveNoCSetCheckClosure is_alive; ReferenceProcessorIsAliveMutator fix_isalive(rp, &is_alive); WorkGang* workers = _heap->workers(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -96,28 +96,6 @@ ~ShenandoahAllocTrace(); }; -class ShenandoahSafepoint : public AllStatic { -public: - // check if Shenandoah GC safepoint is in progress - static inline bool is_at_shenandoah_safepoint() { - if (!SafepointSynchronize::is_at_safepoint()) return false; - - VM_Operation* vm_op = VMThread::vm_operation(); - if (vm_op == NULL) return false; - - VM_Operation::VMOp_Type type = vm_op->type(); - return type == VM_Operation::VMOp_ShenandoahInitMark || - type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac || - type == VM_Operation::VMOp_ShenandoahFinalEvac || - type == VM_Operation::VMOp_ShenandoahInitTraversalGC || - type == VM_Operation::VMOp_ShenandoahFinalTraversalGC || - type == VM_Operation::VMOp_ShenandoahInitUpdateRefs || - type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs || - type == VM_Operation::VMOp_ShenandoahFullGC || - type == VM_Operation::VMOp_ShenandoahDegeneratedGC; - } -}; - class ShenandoahWorkerSession : public StackObj { protected: uint _worker_id; diff --git a/test/hotspot/jtreg/gc/shenandoah/jvmti/TestHeapDump.java b/test/hotspot/jtreg/gc/shenandoah/jvmti/TestHeapDump.java --- a/test/hotspot/jtreg/gc/shenandoah/jvmti/TestHeapDump.java +++ b/test/hotspot/jtreg/gc/shenandoah/jvmti/TestHeapDump.java @@ -49,6 +49,26 @@ * @run main/othervm/native/timeout=300 -agentlib:TestHeapDump -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx128m -XX:ShenandoahGCHeuristics=aggressive -XX:+UseStringDeduplication TestHeapDump */ +/** + * @test TestHeapDump + * @summary Tests JVMTI heap dumps + * @key gc + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @compile TestHeapDump.java + * @run main/othervm/native/timeout=300 -agentlib:TestHeapDump -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -Xmx128m -XX:ShenandoahGCHeuristics=aggressive TestHeapDump + * + */ + +/** + * @test TestHeapDump + * @summary Tests JVMTI heap dumps + * @key gc + * @requires vm.gc.Shenandoah & !vm.graal.enabled + * @compile TestHeapDump.java + * @run main/othervm/native/timeout=300 -agentlib:TestHeapDump -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCMode=traversal -Xmx128m -XX:ShenandoahGCHeuristics=aggressive -XX:-UseCompressedOops TestHeapDump + * + */ + import java.lang.ref.Reference; public class TestHeapDump {