aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authorkvn <none@none>2008-11-07 09:29:38 -0800
committerkvn <none@none>2008-11-07 09:29:38 -0800
commit3f2d83243cf35b83bca4ae16b638791af4367faf (patch)
tree331c3bb7862b1dbd10cb63e0bbb8d28371a2d5fb /src/share/vm/opto
parent31ac38fcba01768dda0f6b2b454af51be74b02ef (diff)
6462850: generate biased locking code in C2 ideal graph
Summary: Inline biased locking code in C2 ideal graph during macro nodes expansion Reviewed-by: never
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r--src/share/vm/opto/c2_globals.hpp3
-rw-r--r--src/share/vm/opto/callnode.cpp1
-rw-r--r--src/share/vm/opto/callnode.hpp4
-rw-r--r--src/share/vm/opto/classes.hpp1
-rw-r--r--src/share/vm/opto/compile.cpp1
-rw-r--r--src/share/vm/opto/library_call.cpp27
-rw-r--r--src/share/vm/opto/loopTransform.cpp1
-rw-r--r--src/share/vm/opto/macro.cpp263
-rw-r--r--src/share/vm/opto/macro.hpp2
-rw-r--r--src/share/vm/opto/matcher.cpp1
-rw-r--r--src/share/vm/opto/memnode.cpp8
-rw-r--r--src/share/vm/opto/memnode.hpp13
-rw-r--r--src/share/vm/opto/type.hpp6
13 files changed, 298 insertions, 33 deletions
diff --git a/src/share/vm/opto/c2_globals.hpp b/src/share/vm/opto/c2_globals.hpp
index ab960fdc8..134209135 100644
--- a/src/share/vm/opto/c2_globals.hpp
+++ b/src/share/vm/opto/c2_globals.hpp
@@ -388,6 +388,9 @@
product(intx, EliminateAllocationArraySizeLimit, 64, \
"Array size (number of elements) limit for scalar replacement") \
\
+ product(bool, UseOptoBiasInlining, true, \
+ "Generate biased locking code in C2 ideal graph") \
+ \
product(intx, ValueSearchLimit, 1000, \
"Recursion limit in PhaseMacroExpand::value_from_mem_phi") \
\
diff --git a/src/share/vm/opto/callnode.cpp b/src/share/vm/opto/callnode.cpp
index 8e8fc24da..b9e9cbd55 100644
--- a/src/share/vm/opto/callnode.cpp
+++ b/src/share/vm/opto/callnode.cpp
@@ -967,6 +967,7 @@ SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp,
init_class_id(Class_SafePointScalarObject);
}
+bool SafePointScalarObjectNode::pinned() const { return true; }
uint SafePointScalarObjectNode::ideal_reg() const {
return 0; // No matching to machine instruction
diff --git a/src/share/vm/opto/callnode.hpp b/src/share/vm/opto/callnode.hpp
index 20192ddf0..45b6dd214 100644
--- a/src/share/vm/opto/callnode.hpp
+++ b/src/share/vm/opto/callnode.hpp
@@ -433,6 +433,10 @@ public:
uint n_fields() const { return _n_fields; }
DEBUG_ONLY(AllocateNode* alloc() const { return _alloc; })
+ // SafePointScalarObject should be always pinned to the control edge
+ // of the SafePoint node for which it was generated.
+ virtual bool pinned() const; // { return true; }
+
virtual uint size_of() const { return sizeof(*this); }
// Assumes that "this" is an argument to a safepoint node "s", and that
diff --git a/src/share/vm/opto/classes.hpp b/src/share/vm/opto/classes.hpp
index 0371736cf..14b431200 100644
--- a/src/share/vm/opto/classes.hpp
+++ b/src/share/vm/opto/classes.hpp
@@ -205,6 +205,7 @@ macro(StoreB)
macro(StoreC)
macro(StoreCM)
macro(StorePConditional)
+macro(StoreIConditional)
macro(StoreLConditional)
macro(StoreD)
macro(StoreF)
diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp
index df1a293f1..42eae3063 100644
--- a/src/share/vm/opto/compile.cpp
+++ b/src/share/vm/opto/compile.cpp
@@ -2001,6 +2001,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
case Op_StorePConditional:
case Op_StoreI:
case Op_StoreL:
+ case Op_StoreIConditional:
case Op_StoreLConditional:
case Op_CompareAndSwapI:
case Op_CompareAndSwapL:
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 52707d038..17a5c1f79 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -3485,11 +3485,32 @@ bool LibraryCallKit::inline_native_AtomicLong_attemptUpdate() {
const TypePtr *adr_type = _gvn.type(adr)->is_ptr();
int alias_idx = C->get_alias_index(adr_type);
- Node *result = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal));
- Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(result));
+ Node *cas = _gvn.transform(new (C, 5) StoreLConditionalNode(control(), memory(alias_idx), adr, newVal, oldVal));
+ Node *store_proj = _gvn.transform( new (C, 1) SCMemProjNode(cas));
set_memory(store_proj, alias_idx);
+ Node *bol = _gvn.transform( new (C, 2) BoolNode( cas, BoolTest::eq ) );
- push(result);
+ Node *result;
+ // CMove node is not used to be able fold a possible check code
+ // after attemptUpdate() call. This code could be transformed
+ // into CMove node by loop optimizations.
+ {
+ RegionNode *r = new (C, 3) RegionNode(3);
+ result = new (C, 3) PhiNode(r, TypeInt::BOOL);
+
+ Node *iff = create_and_xform_if(control(), bol, PROB_FAIR, COUNT_UNKNOWN);
+ Node *iftrue = opt_iff(r, iff);
+ r->init_req(1, iftrue);
+ result->init_req(1, intcon(1));
+ result->init_req(2, intcon(0));
+
+ set_control(_gvn.transform(r));
+ record_for_igvn(r);
+
+ C->set_has_split_ifs(true); // Has chance for split-if optimization
+ }
+
+ push(_gvn.transform(result));
return true;
}
diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
index f1c15b083..caa676f6f 100644
--- a/src/share/vm/opto/loopTransform.cpp
+++ b/src/share/vm/opto/loopTransform.cpp
@@ -1519,6 +1519,7 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
Node *bol = iff->in(1);
if( bol && bol->req() > 1 && bol->in(1) &&
((bol->in(1)->Opcode() == Op_StorePConditional ) ||
+ (bol->in(1)->Opcode() == Op_StoreIConditional ) ||
(bol->in(1)->Opcode() == Op_StoreLConditional ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
(bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp
index 7de433e3a..892f50183 100644
--- a/src/share/vm/opto/macro.cpp
+++ b/src/share/vm/opto/macro.cpp
@@ -82,16 +82,31 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal
}
}
-Node* PhaseMacroExpand::opt_iff(Node* region, Node* iff) {
- IfNode *opt_iff = transform_later(iff)->as_If();
+Node* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) {
+ Node* cmp;
+ if (mask != 0) {
+ Node* and_node = transform_later(new (C, 3) AndXNode(word, MakeConX(mask)));
+ cmp = transform_later(new (C, 3) CmpXNode(and_node, MakeConX(bits)));
+ } else {
+ cmp = word;
+ }
+ Node* bol = transform_later(new (C, 2) BoolNode(cmp, BoolTest::ne));
+ IfNode* iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
+ transform_later(iff);
- // Fast path taken; set region slot 2
- Node *fast_taken = transform_later( new (C, 1) IfFalseNode(opt_iff) );
- region->init_req(2,fast_taken); // Capture fast-control
+ // Fast path taken.
+ Node *fast_taken = transform_later( new (C, 1) IfFalseNode(iff) );
// Fast path not-taken, i.e. slow path
- Node *slow_taken = transform_later( new (C, 1) IfTrueNode(opt_iff) );
- return slow_taken;
+ Node *slow_taken = transform_later( new (C, 1) IfTrueNode(iff) );
+
+ if (return_fast_path) {
+ region->init_req(edge, slow_taken); // Capture slow-control
+ return fast_taken;
+ } else {
+ region->init_req(edge, fast_taken); // Capture fast-control
+ return slow_taken;
+ }
}
//--------------------copy_predefined_input_for_runtime_call--------------------
@@ -854,7 +869,7 @@ void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_ad
Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) {
Node* adr = basic_plus_adr(base, offset);
- const TypePtr* adr_type = TypeRawPtr::BOTTOM;
+ const TypePtr* adr_type = adr->bottom_type()->is_ptr();
Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt);
transform_later(value);
return value;
@@ -1583,12 +1598,194 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
Node* flock = lock->fastlock_node();
// Make the merge point
- Node *region = new (C, 3) RegionNode(3);
+ Node *region;
+ Node *mem_phi;
+ Node *slow_path;
+
+ if (UseOptoBiasInlining) {
+ /*
+ * See the full descrition in MacroAssembler::biased_locking_enter().
+ *
+ * if( (mark_word & biased_lock_mask) == biased_lock_pattern ) {
+ * // The object is biased.
+ * proto_node = klass->prototype_header;
+ * o_node = thread | proto_node;
+ * x_node = o_node ^ mark_word;
+ * if( (x_node & ~age_mask) == 0 ) { // Biased to the current thread ?
+ * // Done.
+ * } else {
+ * if( (x_node & biased_lock_mask) != 0 ) {
+ * // The klass's prototype header is no longer biased.
+ * cas(&mark_word, mark_word, proto_node)
+ * goto cas_lock;
+ * } else {
+ * // The klass's prototype header is still biased.
+ * if( (x_node & epoch_mask) != 0 ) { // Expired epoch?
+ * old = mark_word;
+ * new = o_node;
+ * } else {
+ * // Different thread or anonymous biased.
+ * old = mark_word & (epoch_mask | age_mask | biased_lock_mask);
+ * new = thread | old;
+ * }
+ * // Try to rebias.
+ * if( cas(&mark_word, old, new) == 0 ) {
+ * // Done.
+ * } else {
+ * goto slow_path; // Failed.
+ * }
+ * }
+ * }
+ * } else {
+ * // The object is not biased.
+ * cas_lock:
+ * if( FastLock(obj) == 0 ) {
+ * // Done.
+ * } else {
+ * slow_path:
+ * OptoRuntime::complete_monitor_locking_Java(obj);
+ * }
+ * }
+ */
+
+ region = new (C, 5) RegionNode(5);
+ // create a Phi for the memory state
+ mem_phi = new (C, 5) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
+
+ Node* fast_lock_region = new (C, 3) RegionNode(3);
+ Node* fast_lock_mem_phi = new (C, 3) PhiNode( fast_lock_region, Type::MEMORY, TypeRawPtr::BOTTOM);
+
+ // First, check mark word for the biased lock pattern.
+ Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type());
+
+ // Get fast path - mark word has the biased lock pattern.
+ ctrl = opt_bits_test(ctrl, fast_lock_region, 1, mark_node,
+ markOopDesc::biased_lock_mask_in_place,
+ markOopDesc::biased_lock_pattern, true);
+ // fast_lock_region->in(1) is set to slow path.
+ fast_lock_mem_phi->init_req(1, mem);
+
+ // Now check that the lock is biased to the current thread and has
+ // the same epoch and bias as Klass::_prototype_header.
+
+ // Special-case a fresh allocation to avoid building nodes:
+ Node* klass_node = AllocateNode::Ideal_klass(obj, &_igvn);
+ if (klass_node == NULL) {
+ Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
+ klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) );
+ klass_node->init_req(0, ctrl);
+ }
+ Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type());
- Node *bol = transform_later(new (C, 2) BoolNode(flock,BoolTest::ne));
- Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
- // Optimize test; set region slot 2
- Node *slow_path = opt_iff(region,iff);
+ Node* thread = transform_later(new (C, 1) ThreadLocalNode());
+ Node* cast_thread = transform_later(new (C, 2) CastP2XNode(ctrl, thread));
+ Node* o_node = transform_later(new (C, 3) OrXNode(cast_thread, proto_node));
+ Node* x_node = transform_later(new (C, 3) XorXNode(o_node, mark_node));
+
+ // Get slow path - mark word does NOT match the value.
+ Node* not_biased_ctrl = opt_bits_test(ctrl, region, 3, x_node,
+ (~markOopDesc::age_mask_in_place), 0);
+ // region->in(3) is set to fast path - the object is biased to the current thread.
+ mem_phi->init_req(3, mem);
+
+
+ // Mark word does NOT match the value (thread | Klass::_prototype_header).
+
+
+ // First, check biased pattern.
+ // Get fast path - _prototype_header has the same biased lock pattern.
+ ctrl = opt_bits_test(not_biased_ctrl, fast_lock_region, 2, x_node,
+ markOopDesc::biased_lock_mask_in_place, 0, true);
+
+ not_biased_ctrl = fast_lock_region->in(2); // Slow path
+ // fast_lock_region->in(2) - the prototype header is no longer biased
+ // and we have to revoke the bias on this object.
+ // We are going to try to reset the mark of this object to the prototype
+ // value and fall through to the CAS-based locking scheme.
+ Node* adr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
+ Node* cas = new (C, 5) StoreXConditionalNode(not_biased_ctrl, mem, adr,
+ proto_node, mark_node);
+ transform_later(cas);
+ Node* proj = transform_later( new (C, 1) SCMemProjNode(cas));
+ fast_lock_mem_phi->init_req(2, proj);
+
+
+ // Second, check epoch bits.
+ Node* rebiased_region = new (C, 3) RegionNode(3);
+ Node* old_phi = new (C, 3) PhiNode( rebiased_region, TypeX_X);
+ Node* new_phi = new (C, 3) PhiNode( rebiased_region, TypeX_X);
+
+ // Get slow path - mark word does NOT match epoch bits.
+ Node* epoch_ctrl = opt_bits_test(ctrl, rebiased_region, 1, x_node,
+ markOopDesc::epoch_mask_in_place, 0);
+ // The epoch of the current bias is not valid, attempt to rebias the object
+ // toward the current thread.
+ rebiased_region->init_req(2, epoch_ctrl);
+ old_phi->init_req(2, mark_node);
+ new_phi->init_req(2, o_node);
+
+ // rebiased_region->in(1) is set to fast path.
+ // The epoch of the current bias is still valid but we know
+ // nothing about the owner; it might be set or it might be clear.
+ Node* cmask = MakeConX(markOopDesc::biased_lock_mask_in_place |
+ markOopDesc::age_mask_in_place |
+ markOopDesc::epoch_mask_in_place);
+ Node* old = transform_later(new (C, 3) AndXNode(mark_node, cmask));
+ cast_thread = transform_later(new (C, 2) CastP2XNode(ctrl, thread));
+ Node* new_mark = transform_later(new (C, 3) OrXNode(cast_thread, old));
+ old_phi->init_req(1, old);
+ new_phi->init_req(1, new_mark);
+
+ transform_later(rebiased_region);
+ transform_later(old_phi);
+ transform_later(new_phi);
+
+ // Try to acquire the bias of the object using an atomic operation.
+ // If this fails we will go in to the runtime to revoke the object's bias.
+ cas = new (C, 5) StoreXConditionalNode(rebiased_region, mem, adr,
+ new_phi, old_phi);
+ transform_later(cas);
+ proj = transform_later( new (C, 1) SCMemProjNode(cas));
+
+ // Get slow path - Failed to CAS.
+ not_biased_ctrl = opt_bits_test(rebiased_region, region, 4, cas, 0, 0);
+ mem_phi->init_req(4, proj);
+ // region->in(4) is set to fast path - the object is rebiased to the current thread.
+
+ // Failed to CAS.
+ slow_path = new (C, 3) RegionNode(3);
+ Node *slow_mem = new (C, 3) PhiNode( slow_path, Type::MEMORY, TypeRawPtr::BOTTOM);
+
+ slow_path->init_req(1, not_biased_ctrl); // Capture slow-control
+ slow_mem->init_req(1, proj);
+
+ // Call CAS-based locking scheme (FastLock node).
+
+ transform_later(fast_lock_region);
+ transform_later(fast_lock_mem_phi);
+
+ // Get slow path - FastLock failed to lock the object.
+ ctrl = opt_bits_test(fast_lock_region, region, 2, flock, 0, 0);
+ mem_phi->init_req(2, fast_lock_mem_phi);
+ // region->in(2) is set to fast path - the object is locked to the current thread.
+
+ slow_path->init_req(2, ctrl); // Capture slow-control
+ slow_mem->init_req(2, fast_lock_mem_phi);
+
+ transform_later(slow_path);
+ transform_later(slow_mem);
+ // Reset lock's memory edge.
+ lock->set_req(TypeFunc::Memory, slow_mem);
+
+ } else {
+ region = new (C, 3) RegionNode(3);
+ // create a Phi for the memory state
+ mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
+
+ // Optimize test; set region slot 2
+ slow_path = opt_bits_test(ctrl, region, 2, flock, 0, 0);
+ mem_phi->init_req(2, mem);
+ }
// Make slow path call
CallNode *call = make_slow_call( (CallNode *) lock, OptoRuntime::complete_monitor_enter_Type(), OptoRuntime::complete_monitor_locking_Java(), NULL, slow_path, obj, box );
@@ -1614,16 +1811,11 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
transform_later(region);
_igvn.subsume_node(_fallthroughproj, region);
- // create a Phi for the memory state
- Node *mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
- Node *memproj = transform_later( new (C, 1) ProjNode(call, TypeFunc::Memory) );
+ Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
mem_phi->init_req(1, memproj );
- mem_phi->init_req(2, mem);
transform_later(mem_phi);
- _igvn.hash_delete(_memproj_fallthrough);
+ _igvn.hash_delete(_memproj_fallthrough);
_igvn.subsume_node(_memproj_fallthrough, mem_phi);
-
-
}
//------------------------------expand_unlock_node----------------------
@@ -1637,14 +1829,31 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
// No need for a null check on unlock
// Make the merge point
- RegionNode *region = new (C, 3) RegionNode(3);
+ Node *region;
+ Node *mem_phi;
+
+ if (UseOptoBiasInlining) {
+ // Check for biased locking unlock case, which is a no-op.
+ // See the full descrition in MacroAssembler::biased_locking_exit().
+ region = new (C, 4) RegionNode(4);
+ // create a Phi for the memory state
+ mem_phi = new (C, 4) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
+ mem_phi->init_req(3, mem);
+
+ Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type());
+ ctrl = opt_bits_test(ctrl, region, 3, mark_node,
+ markOopDesc::biased_lock_mask_in_place,
+ markOopDesc::biased_lock_pattern);
+ } else {
+ region = new (C, 3) RegionNode(3);
+ // create a Phi for the memory state
+ mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
+ }
FastUnlockNode *funlock = new (C, 3) FastUnlockNode( ctrl, obj, box );
funlock = transform_later( funlock )->as_FastUnlock();
- Node *bol = transform_later(new (C, 2) BoolNode(funlock,BoolTest::ne));
- Node *iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
// Optimize test; set region slot 2
- Node *slow_path = opt_iff(region,iff);
+ Node *slow_path = opt_bits_test(ctrl, region, 2, funlock, 0, 0);
CallNode *call = make_slow_call( (CallNode *) unlock, OptoRuntime::complete_monitor_exit_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), "complete_monitor_unlocking_C", slow_path, obj, box );
@@ -1666,16 +1875,12 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
transform_later(region);
_igvn.subsume_node(_fallthroughproj, region);
- // create a Phi for the memory state
- Node *mem_phi = new (C, 3) PhiNode( region, Type::MEMORY, TypeRawPtr::BOTTOM);
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
mem_phi->init_req(1, memproj );
mem_phi->init_req(2, mem);
transform_later(mem_phi);
- _igvn.hash_delete(_memproj_fallthrough);
+ _igvn.hash_delete(_memproj_fallthrough);
_igvn.subsume_node(_memproj_fallthrough, mem_phi);
-
-
}
//------------------------------expand_macro_nodes----------------------
diff --git a/src/share/vm/opto/macro.hpp b/src/share/vm/opto/macro.hpp
index 89ed2bd2f..d5c28a461 100644
--- a/src/share/vm/opto/macro.hpp
+++ b/src/share/vm/opto/macro.hpp
@@ -93,7 +93,7 @@ private:
int replace_input(Node *use, Node *oldref, Node *newref);
void copy_call_debug_info(CallNode *oldcall, CallNode * newcall);
- Node* opt_iff(Node* region, Node* iff);
+ Node* opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path = false);
void copy_predefined_input_for_runtime_call(Node * ctrl, CallNode* oldcall, CallNode* call);
CallNode* make_slow_call(CallNode *oldcall, const TypeFunc* slow_call_type, address slow_call,
const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1);
diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp
index 1fc7915b9..582cf2740 100644
--- a/src/share/vm/opto/matcher.cpp
+++ b/src/share/vm/opto/matcher.cpp
@@ -1951,6 +1951,7 @@ void Matcher::find_shared( Node *n ) {
// Now hack a few special opcodes
switch( n->Opcode() ) { // Handle some opcodes special
case Op_StorePConditional:
+ case Op_StoreIConditional:
case Op_StoreLConditional:
case Op_CompareAndSwapI:
case Op_CompareAndSwapL:
diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp
index ea7e062ae..4cfc0d233 100644
--- a/src/share/vm/opto/memnode.cpp
+++ b/src/share/vm/opto/memnode.cpp
@@ -227,6 +227,14 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
const Type *t_adr = phase->type( address );
if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL
+ PhaseIterGVN *igvn = phase->is_IterGVN();
+ if( can_reshape && igvn != NULL && igvn->_worklist.member(address) ) {
+ // The address's base and type may change when the address is processed.
+ // Delay this mem node transformation until the address is processed.
+ phase->is_IterGVN()->_worklist.push(this);
+ return NodeSentinel; // caller will return NULL
+ }
+
// Avoid independent memory operations
Node* old_mem = mem;
diff --git a/src/share/vm/opto/memnode.hpp b/src/share/vm/opto/memnode.hpp
index 2b40a676c..e1a84febc 100644
--- a/src/share/vm/opto/memnode.hpp
+++ b/src/share/vm/opto/memnode.hpp
@@ -632,6 +632,17 @@ public:
virtual uint ideal_reg() const { return Op_RegFlags; }
};
+//------------------------------StoreIConditionalNode---------------------------
+// Conditionally store int to memory, if no change since prior
+// load-locked. Sets flags for success or failure of the store.
+class StoreIConditionalNode : public LoadStoreNode {
+public:
+ StoreIConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ii ) : LoadStoreNode(c, mem, adr, val, ii) { }
+ virtual int Opcode() const;
+ // Produces flags
+ virtual uint ideal_reg() const { return Op_RegFlags; }
+};
+
//------------------------------StoreLConditionalNode---------------------------
// Conditionally store long to memory, if no change since prior
// load-locked. Sets flags for success or failure of the store.
@@ -639,6 +650,8 @@ class StoreLConditionalNode : public LoadStoreNode {
public:
StoreLConditionalNode( Node *c, Node *mem, Node *adr, Node *val, Node *ll ) : LoadStoreNode(c, mem, adr, val, ll) { }
virtual int Opcode() const;
+ // Produces flags
+ virtual uint ideal_reg() const { return Op_RegFlags; }
};
diff --git a/src/share/vm/opto/type.hpp b/src/share/vm/opto/type.hpp
index 69bc06a73..3d3f3ddd8 100644
--- a/src/share/vm/opto/type.hpp
+++ b/src/share/vm/opto/type.hpp
@@ -1183,6 +1183,9 @@ inline bool Type::is_floatingpoint() const {
#define RShiftXNode RShiftLNode
// For card marks and hashcodes
#define URShiftXNode URShiftLNode
+// UseOptoBiasInlining
+#define XorXNode XorLNode
+#define StoreXConditionalNode StoreLConditionalNode
// Opcodes
#define Op_LShiftX Op_LShiftL
#define Op_AndX Op_AndL
@@ -1222,6 +1225,9 @@ inline bool Type::is_floatingpoint() const {
#define RShiftXNode RShiftINode
// For card marks and hashcodes
#define URShiftXNode URShiftINode
+// UseOptoBiasInlining
+#define XorXNode XorINode
+#define StoreXConditionalNode StoreIConditionalNode
// Opcodes
#define Op_LShiftX Op_LShiftI
#define Op_AndX Op_AndI