8213142: Use RAII to set the scanning source in G1ScanEvacuatedObjClosure
Reviewed-by: sangheki, kbarrett
--- a/src/hotspot/share/gc/g1/g1OopClosures.hpp Wed Oct 31 13:43:57 2018 +0100
+++ b/src/hotspot/share/gc/g1/g1OopClosures.hpp Wed Oct 31 13:43:57 2018 +0100
@@ -36,6 +36,7 @@
class DirtyCardToOopClosure;
class G1CMBitMap;
class G1ParScanThreadState;
+class G1ScanEvacuatedObjClosure;
class G1CMTask;
class ReferenceProcessor;
@@ -82,15 +83,22 @@
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
};
+
// This closure is applied to the fields of the objects that have just been copied during evacuation.
class G1ScanEvacuatedObjClosure : public G1ScanClosureBase {
- bool _scanning_in_young;
+ friend class G1ScanInYoungSetter;
+
+ enum ScanningInYoungValues {
+ False = 0,
+ True,
+ Uninitialized
+ };
+
+ ScanningInYoungValues _scanning_in_young;
public:
G1ScanEvacuatedObjClosure(G1CollectedHeap* g1h, G1ParScanThreadState* par_scan_state) :
- G1ScanClosureBase(g1h, par_scan_state), _scanning_in_young(false) { }
-
- void set_scanning_in_young(bool scanning_in_young) { _scanning_in_young = scanning_in_young; }
+ G1ScanClosureBase(g1h, par_scan_state), _scanning_in_young(Uninitialized) { }
template <class T> void do_oop_work(T* p);
virtual void do_oop(oop* p) { do_oop_work(p); }
@@ -104,6 +112,21 @@
}
};
+// RAII object to properly set the _scanning_in_young field in G1ScanEvacuatedObjClosure.
+class G1ScanInYoungSetter : public StackObj {
+ G1ScanEvacuatedObjClosure* _closure;
+
+public:
+ G1ScanInYoungSetter(G1ScanEvacuatedObjClosure* closure, bool new_value) : _closure(closure) {
+ assert(_closure->_scanning_in_young == G1ScanEvacuatedObjClosure::Uninitialized, "Must not be set");
+ _closure->_scanning_in_young = new_value ? G1ScanEvacuatedObjClosure::True : G1ScanEvacuatedObjClosure::False;
+ }
+
+ ~G1ScanInYoungSetter() {
+ DEBUG_ONLY(_closure->_scanning_in_young = G1ScanEvacuatedObjClosure::Uninitialized;)
+ }
+};
+
// Add back base class for metadata
class G1ParCopyHelper : public OopClosure {
protected:
--- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp Wed Oct 31 13:43:57 2018 +0100
+++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp Wed Oct 31 13:43:57 2018 +0100
@@ -84,7 +84,8 @@
prefetch_and_push(p, obj);
} else if (!HeapRegion::is_in_same_region(p, obj)) {
handle_non_cset_obj_common(state, p, obj);
- if (_scanning_in_young) {
+ assert(_scanning_in_young != Uninitialized, "Scan location has not been initialized.");
+ if (_scanning_in_young == True) {
return;
}
_par_scan_state->enqueue_card_if_tracked(p, obj);
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Wed Oct 31 13:43:57 2018 +0100
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Wed Oct 31 13:43:57 2018 +0100
@@ -311,7 +311,7 @@
oop* old_p = set_partial_array_mask(old);
do_oop_partial_array(old_p);
} else {
- _scanner.set_scanning_in_young(dest_state.is_young());
+ G1ScanInYoungSetter x(&_scanner, dest_state.is_young());
obj->oop_iterate_backwards(&_scanner);
}
return obj;
@@ -366,7 +366,7 @@
_g1h->preserve_mark_during_evac_failure(_worker_id, old, m);
- _scanner.set_scanning_in_young(r->is_young());
+ G1ScanInYoungSetter x(&_scanner, r->is_young());
old->oop_iterate_backwards(&_scanner);
return old;
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp Wed Oct 31 13:43:57 2018 +0100
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp Wed Oct 31 13:43:57 2018 +0100
@@ -114,7 +114,7 @@
}
HeapRegion* hr = _g1h->heap_region_containing(to_obj);
- _scanner.set_scanning_in_young(hr->is_young());
+ G1ScanInYoungSetter x(&_scanner, hr->is_young());
// Process indexes [start,end). It will also process the header
// along with the first chunk (i.e., the chunk with start == 0).
// Note that at this point the length field of to_obj_array is not