--- a/hotspot/src/share/vm/opto/escape.cpp Mon May 06 19:49:23 2013 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp Wed May 08 15:08:01 2013 -0700
@@ -63,15 +63,19 @@
// EA brings benefits only when the code has allocations and/or locks which
// are represented by ideal Macro nodes.
int cnt = C->macro_count();
- for( int i=0; i < cnt; i++ ) {
+ for (int i = 0; i < cnt; i++) {
Node *n = C->macro_node(i);
- if ( n->is_Allocate() )
+ if (n->is_Allocate())
return true;
- if( n->is_Lock() ) {
+ if (n->is_Lock()) {
Node* obj = n->as_Lock()->obj_node()->uncast();
- if( !(obj->is_Parm() || obj->is_Con()) )
+ if (!(obj->is_Parm() || obj->is_Con()))
return true;
}
+ if (n->is_CallStaticJava() &&
+ n->as_CallStaticJava()->is_boxing_method()) {
+ return true;
+ }
}
return false;
}
@@ -115,7 +119,7 @@
{ Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true);
// 1. Populate Connection Graph (CG) with PointsTo nodes.
- ideal_nodes.map(C->unique(), NULL); // preallocate space
+ ideal_nodes.map(C->live_nodes(), NULL); // preallocate space
// Initialize worklist
if (C->root() != NULL) {
ideal_nodes.push(C->root());
@@ -152,8 +156,11 @@
// escape status of the associated Allocate node some of them
// may be eliminated.
storestore_worklist.append(n);
+ } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) &&
+ (n->req() > MemBarNode::Precedent)) {
+ record_for_optimizer(n);
#ifdef ASSERT
- } else if(n->is_AddP()) {
+ } else if (n->is_AddP()) {
// Collect address nodes for graph verification.
addp_worklist.append(n);
#endif
@@ -206,8 +213,15 @@
int non_escaped_length = non_escaped_worklist.length();
for (int next = 0; next < non_escaped_length; next++) {
JavaObjectNode* ptn = non_escaped_worklist.at(next);
- if (ptn->escape_state() == PointsToNode::NoEscape &&
- ptn->scalar_replaceable()) {
+ bool noescape = (ptn->escape_state() == PointsToNode::NoEscape);
+ Node* n = ptn->ideal_node();
+ if (n->is_Allocate()) {
+ n->as_Allocate()->_is_non_escaping = noescape;
+ }
+ if (n->is_CallStaticJava()) {
+ n->as_CallStaticJava()->_is_non_escaping = noescape;
+ }
+ if (noescape && ptn->scalar_replaceable()) {
adjust_scalar_replaceable_state(ptn);
if (ptn->scalar_replaceable()) {
alloc_worklist.append(ptn->ideal_node());
@@ -330,8 +344,10 @@
// Don't mark as processed since call's arguments have to be processed.
delayed_worklist->push(n);
// Check if a call returns an object.
- if (n->as_Call()->returns_pointer() &&
- n->as_Call()->proj_out(TypeFunc::Parms) != NULL) {
+ if ((n->as_Call()->returns_pointer() &&
+ n->as_Call()->proj_out(TypeFunc::Parms) != NULL) ||
+ (n->is_CallStaticJava() &&
+ n->as_CallStaticJava()->is_boxing_method())) {
add_call_node(n->as_Call());
}
}
@@ -387,8 +403,8 @@
case Op_ConNKlass: {
// assume all oop constants globally escape except for null
PointsToNode::EscapeState es;
- if (igvn->type(n) == TypePtr::NULL_PTR ||
- igvn->type(n) == TypeNarrowOop::NULL_PTR) {
+ const Type* t = igvn->type(n);
+ if (t == TypePtr::NULL_PTR || t == TypeNarrowOop::NULL_PTR) {
es = PointsToNode::NoEscape;
} else {
es = PointsToNode::GlobalEscape;
@@ -797,6 +813,9 @@
// Returns a newly allocated unescaped object.
add_java_object(call, PointsToNode::NoEscape);
ptnode_adr(call_idx)->set_scalar_replaceable(false);
+ } else if (meth->is_boxing_method()) {
+ // Returns boxing object
+ add_java_object(call, PointsToNode::NoEscape);
} else {
BCEscapeAnalyzer* call_analyzer = meth->get_bcea();
call_analyzer->copy_dependencies(_compile->dependencies());
@@ -943,6 +962,9 @@
assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only");
#endif
ciMethod* meth = call->as_CallJava()->method();
+ if ((meth != NULL) && meth->is_boxing_method()) {
+ break; // Boxing methods do not modify any oops.
+ }
BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
// fall-through if not a Java method or no analyzer information
if (call_analyzer != NULL) {
@@ -2744,6 +2766,11 @@
// so it could be eliminated if it has no uses.
alloc->as_Allocate()->_is_scalar_replaceable = true;
}
+ if (alloc->is_CallStaticJava()) {
+ // Set the scalar_replaceable flag for boxing method
+ // so it could be eliminated if it has no uses.
+ alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
+ }
continue;
}
if (!n->is_CheckCastPP()) { // not unique CheckCastPP.
@@ -2782,6 +2809,11 @@
// so it could be eliminated.
alloc->as_Allocate()->_is_scalar_replaceable = true;
}
+ if (alloc->is_CallStaticJava()) {
+ // Set the scalar_replaceable flag for boxing method
+ // so it could be eliminated.
+ alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
+ }
set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
// in order for an object to be scalar-replaceable, it must be:
// - a direct allocation (not a call returning an object)
@@ -2911,7 +2943,9 @@
// Load/store to instance's field
memnode_worklist.append_if_missing(use);
} else if (use->is_MemBar()) {
- memnode_worklist.append_if_missing(use);
+ if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
+ memnode_worklist.append_if_missing(use);
+ }
} else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes
Node* addp2 = find_second_addp(use, n);
if (addp2 != NULL) {
@@ -3028,7 +3062,9 @@
continue;
memnode_worklist.append_if_missing(use);
} else if (use->is_MemBar()) {
- memnode_worklist.append_if_missing(use);
+ if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
+ memnode_worklist.append_if_missing(use);
+ }
#ifdef ASSERT
} else if(use->is_Mem()) {
assert(use->in(MemNode::Memory) != n, "EA: missing memory path");
@@ -3264,7 +3300,12 @@
if (ptn == NULL || !ptn->is_JavaObject())
continue;
PointsToNode::EscapeState es = ptn->escape_state();
- if (ptn->ideal_node()->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
+ if ((es != PointsToNode::NoEscape) && !Verbose) {
+ continue;
+ }
+ Node* n = ptn->ideal_node();
+ if (n->is_Allocate() || (n->is_CallStaticJava() &&
+ n->as_CallStaticJava()->is_boxing_method())) {
if (first) {
tty->cr();
tty->print("======== Connection graph for ");