src/share/vm/opto/escape.cpp
Print this page
rev 3419 : 7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
Summary: use shorter instruction sequences for atomic add and atomic exchange when possible.
Reviewed-by:
@@ -280,10 +280,30 @@
#endif
}
return has_non_escaping_obj;
}
+// Utility function for nodes that load an object
+void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
+ // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+ // ThreadLocal has RawPtr type.
+ const Type* t = _igvn->type(n);
+ if (t->make_ptr() != NULL) {
+ Node* adr = n->in(MemNode::Address);
+#ifdef ASSERT
+ if (!adr->is_AddP()) {
+ assert(_igvn->type(adr)->isa_rawptr(), "sanity");
+ } else {
+ assert((ptnode_adr(adr->_idx) == NULL ||
+ ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
+ }
+#endif
+ add_local_var_and_edge(n, PointsToNode::NoEscape,
+ adr, delayed_worklist);
+ }
+}
+
// Populate Connection Graph with PointsTo nodes and create simple
// connection graph edges.
void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
assert(!_verify, "this method sould not be called for verification");
PhaseGVN* igvn = _igvn;
@@ -385,26 +405,11 @@
break;
}
case Op_LoadP:
case Op_LoadN:
case Op_LoadPLocked: {
- // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
- // ThreadLocal has RawPrt type.
- const Type* t = igvn->type(n);
- if (t->make_ptr() != NULL) {
- Node* adr = n->in(MemNode::Address);
-#ifdef ASSERT
- if (!adr->is_AddP()) {
- assert(igvn->type(adr)->isa_rawptr(), "sanity");
- } else {
- assert((ptnode_adr(adr->_idx) == NULL ||
- ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
- }
-#endif
- add_local_var_and_edge(n, PointsToNode::NoEscape,
- adr, delayed_worklist);
- }
+ add_objload_to_connection_graph(n, delayed_worklist);
break;
}
case Op_Parm: {
map_ideal_node(n, phantom_obj);
break;
@@ -415,11 +420,11 @@
map_ideal_node(n, phantom_obj); // Result is unknown
break;
}
case Op_Phi: {
// Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
- // ThreadLocal has RawPrt type.
+ // ThreadLocal has RawPtr type.
const Type* t = n->as_Phi()->type();
if (t->make_ptr() != NULL) {
add_local_var(n, PointsToNode::NoEscape);
// Do not add edges during first iteration because some could be
// not defined yet.
@@ -444,10 +449,15 @@
add_local_var_and_edge(n, PointsToNode::GlobalEscape,
n->in(TypeFunc::Parms), delayed_worklist);
}
break;
}
+ case Op_GetAndSetP:
+ case Op_GetAndSetN: {
+ add_objload_to_connection_graph(n, delayed_worklist);
+ // fallthrough
+ }
case Op_StoreP:
case Op_StoreN:
case Op_StorePConditional:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN: {
@@ -583,22 +593,22 @@
}
case Op_LoadP:
case Op_LoadN:
case Op_LoadPLocked: {
// Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
- // ThreadLocal has RawPrt type.
+ // ThreadLocal has RawPtr type.
const Type* t = _igvn->type(n);
if (t->make_ptr() != NULL) {
Node* adr = n->in(MemNode::Address);
add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
break;
}
ELSE_FAIL("Op_LoadP");
}
case Op_Phi: {
// Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
- // ThreadLocal has RawPrt type.
+ // ThreadLocal has RawPtr type.
const Type* t = n->as_Phi()->type();
if (t->make_ptr() != NULL) {
for (uint i = 1; i < n->req(); i++) {
Node* in = n->in(i);
if (in == NULL)
@@ -636,12 +646,20 @@
}
case Op_StoreP:
case Op_StoreN:
case Op_StorePConditional:
case Op_CompareAndSwapP:
- case Op_CompareAndSwapN: {
+ case Op_CompareAndSwapN:
+ case Op_GetAndSetP:
+ case Op_GetAndSetN: {
Node* adr = n->in(MemNode::Address);
+ if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) {
+ const Type* t = _igvn->type(n);
+ if (t->make_ptr() != NULL) {
+ add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
+ }
+ }
const Type *adr_type = _igvn->type(adr);
adr_type = adr_type->make_ptr();
if (adr_type->isa_oopptr() ||
(opcode == Op_StoreP || opcode == Op_StoreN) &&
(adr_type == TypeRawPtr::NOTNULL &&