< prev index next >

src/share/vm/opto/graphKit.cpp

Print this page
rev 13055 : Implement barriers for maintaining connection matrix.

@@ -28,10 +28,13 @@
 #include "gc/g1/heapRegion.hpp"
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/cardTableModRefBS.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shenandoah/brooksPointer.hpp"
+#include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
+#include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahHeapRegion.hpp"
 #include "memory/resourceArea.hpp"
 #include "opto/addnode.hpp"
 #include "opto/castnode.hpp"
 #include "opto/convertnode.hpp"
 #include "opto/graphKit.hpp"

@@ -4141,12 +4144,14 @@
     g1_write_barrier_pre(do_load, obj, adr, alias_idx, val, val_type, pre_val, bt);
     return NULL;
   }
 
   if (! ShenandoahReduceStoreValBarrier) {
+    val = shenandoah_read_barrier_storeval(val);
+    shenandoah_update_matrix(adr, val);
     g1_write_barrier_pre(do_load, obj, adr, alias_idx, val, val_type, pre_val, bt);
-    return shenandoah_read_barrier_storeval(val);
+    return val;
   }
 
   if (do_load) {
     // We need to generate the load of the previous value
     assert(obj != NULL, "must have a base");

@@ -4261,10 +4266,64 @@
   final_sync(ideal);
   g1_write_barrier_pre_helper(*this, adr);
   return val;
 }
 
+void GraphKit::shenandoah_update_matrix(Node* adr, Node* val) {
+  assert(val != NULL, "checked before");
+  if (adr == NULL) {
+    return; // Nothing to do
+  }
+  assert(adr != NULL, "must not happen");
+  if (val->bottom_type()->higher_equal(TypePtr::NULL_PTR)) {
+    // Nothing to do.
+    return;
+  }
+
+  ShenandoahConnectionMatrix* matrix = ShenandoahHeap::heap()->connection_matrix();
+
+  enum { _not_null_path = 1, _null_path, PATH_LIMIT };
+  RegionNode* region = new RegionNode(PATH_LIMIT);
+  Node* prev_mem = memory(Compile::AliasIdxRaw);
+  Node* memphi    = PhiNode::make(region, prev_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
+  Node* null_ctrl = top();
+  Node* not_null_val = null_check_oop(val, &null_ctrl);
+
+  // Null path: nothing to do.
+  region->init_req(_null_path, null_ctrl);
+  memphi->init_req(_null_path, prev_mem);
+
+  // Not null path. Update the matrix.
+  Node* heapbase = MakeConX((intx) ShenandoahHeap::heap()->first_region_bottom());
+  Node* region_size_shift = intcon((jint) ShenandoahHeapRegion::RegionSizeShift);
+  Node* stride = MakeConX((intx) matrix->stride());
+  Node* matrix_base = makecon(TypeRawPtr::make(matrix->matrix_addr()));
+  // Compute region index for adr.
+  Node* adr_idx = _gvn.transform(new CastP2XNode(control(), adr));
+  adr_idx = _gvn.transform(new SubXNode(adr_idx, heapbase));
+  adr_idx = _gvn.transform(new URShiftXNode(adr_idx, region_size_shift));
+  // Compute region index for val.
+  Node* val_idx = _gvn.transform(new CastP2XNode(control(), not_null_val));
+  val_idx = _gvn.transform(new SubXNode(val_idx, heapbase));
+  val_idx = _gvn.transform(new URShiftXNode(val_idx, region_size_shift));
+  // Compute matrix index & address.
+  Node* matrix_idx = _gvn.transform(new MulXNode(adr_idx, stride));
+  matrix_idx = _gvn.transform(new AddXNode(matrix_idx, val_idx));
+  Node* matrix_adr = basic_plus_adr(top(), matrix_base, matrix_idx);
+  // Do the store.
+  const TypePtr* adr_type = TypeRawPtr::BOTTOM;
+  Node* store = _gvn.transform(StoreNode::make(_gvn, control(), memory(Compile::AliasIdxRaw), matrix_adr, adr_type, intcon(1), T_BOOLEAN, MemNode::unordered));
+
+  region->init_req(_not_null_path, control());
+  memphi->init_req(_not_null_path, store);
+
+  // Merge control flows and memory.
+  set_control(_gvn.transform(region));
+  record_for_igvn(region);
+  set_memory(_gvn.transform(memphi), Compile::AliasIdxRaw);
+}
+
 /*
  * G1 similar to any GC with a Young Generation requires a way to keep track of
  * references from Old Generation to Young Generation to make sure all live
  * objects are found. G1 also requires to keep track of object references
  * between different regions to enable evacuation of old regions, which is done
< prev index next >