8200233: Simple G1 evacuation path performance enhancements
authortschatzl
Wed, 11 Apr 2018 11:41:30 +0200
changeset 49744 5dcc893ad119
parent 49743 b2da6c360225
child 49745 e3e66c178518
8200233: Simple G1 evacuation path performance enhancements Summary: Implement some minor performance optimizations in the evacuation path including changing some stores to be OOP_NOT_NULL, specializing the compressed/uncompressed oops path and delay some load of the current heapregion until absolutely necessary. Reviewed-by: kbarrett, sjohanss
src/hotspot/share/gc/g1/g1OopClosures.inline.hpp
src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp
--- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp	Wed Apr 11 11:37:19 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp	Wed Apr 11 11:41:30 2018 +0200
@@ -248,7 +248,7 @@
       forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
     }
     assert(forwardee != NULL, "forwardee should not be NULL");
-    RawAccess<>::oop_store(p, forwardee);
+    RawAccess<OOP_NOT_NULL>::oop_store(p, forwardee);
     if (do_mark_object != G1MarkNone && forwardee != obj) {
       // If the object is self-forwarded we don't need to explicitly
       // mark it, the evacuation failure protocol will do so.
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Wed Apr 11 11:37:19 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Wed Apr 11 11:41:30 2018 +0200
@@ -161,9 +161,10 @@
   inline void do_oop_partial_array(oop* p);
 
   // This method is applied to the fields of the objects that have just been copied.
-  template <class T> inline void do_oop_evac(T* p, HeapRegion* from);
+  template <class T> inline void do_oop_evac(T* p);
 
-  template <class T> inline void deal_with_reference(T* ref_to_scan);
+  inline void deal_with_reference(oop* ref_to_scan);
+  inline void deal_with_reference(narrowOop* ref_to_scan);
 
   inline void dispatch_reference(StarTask ref);
 
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp	Wed Apr 11 11:37:19 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp	Wed Apr 11 11:41:30 2018 +0200
@@ -30,14 +30,15 @@
 #include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
 
-template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from) {
+template <class T> void G1ParScanThreadState::do_oop_evac(T* p) {
   // Reference should not be NULL here as such are never pushed to the task queue.
   oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
 
   // Although we never intentionally push references outside of the collection
   // set, due to (benign) races in the claim mechanism during RSet scanning more
   // than one thread might claim the same card. So the same card may be
-  // processed multiple times. So redo this check.
+  // processed multiple times, and so we might get references into old gen here.
+  // So we need to redo this check.
   const InCSetState in_cset_state = _g1h->in_cset_state(obj);
   if (in_cset_state.is_in_cset()) {
     markOop m = obj->mark_raw();
@@ -46,16 +47,17 @@
     } else {
       obj = copy_to_survivor_space(in_cset_state, obj, m);
     }
-    RawAccess<>::oop_store(p, obj);
+    RawAccess<OOP_NOT_NULL>::oop_store(p, obj);
   } else if (in_cset_state.is_humongous()) {
     _g1h->set_humongous_is_live(obj);
   } else {
     assert(in_cset_state.is_default(),
-         "In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value());
+           "In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value());
   }
 
   assert(obj != NULL, "Must be");
   if (!HeapRegion::is_in_same_region(p, obj)) {
+    HeapRegion* from = _g1h->heap_region_containing(p);
     update_rs(from, p, obj);
   }
 }
@@ -114,15 +116,19 @@
   to_obj_array->oop_iterate_range(&_scanner, start, end);
 }
 
-template <class T> inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) {
+inline void G1ParScanThreadState::deal_with_reference(oop* ref_to_scan) {
   if (!has_partial_array_mask(ref_to_scan)) {
-    HeapRegion* r = _g1h->heap_region_containing(ref_to_scan);
-    do_oop_evac(ref_to_scan, r);
+    do_oop_evac(ref_to_scan);
   } else {
-    do_oop_partial_array((oop*)ref_to_scan);
+    do_oop_partial_array(ref_to_scan);
   }
 }
 
+inline void G1ParScanThreadState::deal_with_reference(narrowOop* ref_to_scan) {
+  assert(!has_partial_array_mask(ref_to_scan), "NarrowOop* elements should never be partial arrays.");
+  do_oop_evac(ref_to_scan);
+}
+
 inline void G1ParScanThreadState::dispatch_reference(StarTask ref) {
   assert(verify_task(ref), "sanity");
   if (ref.is_narrow()) {