< 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 >