--- a/hotspot/src/share/vm/opto/macro.cpp Wed Jul 16 10:08:57 2008 -0700
+++ b/hotspot/src/share/vm/opto/macro.cpp Wed Jul 16 16:04:39 2008 -0700
@@ -231,8 +231,7 @@
} else {
return mem;
}
- if (mem == orig_mem)
- return mem;
+ assert(mem != orig_mem, "dead memory loop");
}
}
@@ -241,21 +240,44 @@
// on the input paths.
// Note: this function is recursive, its depth is limied by the "level" argument
// Returns the computed Phi, or NULL if it cannot compute it.
-Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, int level) {
+Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) {
+ assert(mem->is_Phi(), "sanity");
+ int alias_idx = C->get_alias_index(adr_t);
+ int offset = adr_t->offset();
+ int instance_id = adr_t->instance_id();
+
+ // Check if an appropriate value phi already exists.
+ Node* region = mem->in(0);
+ for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) {
+ Node* phi = region->fast_out(k);
+ if (phi->is_Phi() && phi != mem &&
+ phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) {
+ return phi;
+ }
+ }
+ // Check if an appropriate new value phi already exists.
+ Node* new_phi = NULL;
+ uint size = value_phis->size();
+ for (uint i=0; i < size; i++) {
+ if ( mem->_idx == value_phis->index_at(i) ) {
+ return value_phis->node_at(i);
+ }
+ }
if (level <= 0) {
return NULL;
}
- int alias_idx = C->get_alias_index(adr_t);
- int offset = adr_t->offset();
- int instance_id = adr_t->instance_id();
-
Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
Node *alloc_mem = alloc->in(TypeFunc::Memory);
uint length = mem->req();
GrowableArray <Node *> values(length, length, NULL);
+ // create a new Phi for the value
+ PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
+ transform_later(phi);
+ value_phis->push(phi, mem->_idx);
+
for (uint j = 1; j < length; j++) {
Node *in = mem->in(j);
if (in == NULL || in->is_top()) {
@@ -280,33 +302,17 @@
} else if(val->is_Proj() && val->in(0) == alloc) {
values.at_put(j, _igvn.zerocon(ft));
} else if (val->is_Phi()) {
- // Check if an appropriate node already exists.
- Node* region = val->in(0);
- Node* old_phi = NULL;
- for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) {
- Node* phi = region->fast_out(k);
- if (phi->is_Phi() && phi != val &&
- phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) {
- old_phi = phi;
- break;
- }
+ val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1);
+ if (val == NULL) {
+ return NULL;
}
- if (old_phi == NULL) {
- val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, level-1);
- if (val == NULL) {
- return NULL;
- }
- values.at_put(j, val);
- } else {
- values.at_put(j, old_phi);
- }
+ values.at_put(j, val);
} else {
return NULL; // unknown node on this path
}
}
}
- // create a new Phi for the value
- PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
+ // Set Phi's inputs
for (uint j = 1; j < length; j++) {
if (values.at(j) == mem) {
phi->init_req(j, phi);
@@ -314,7 +320,6 @@
phi->init_req(j, values.at(j));
}
}
- transform_later(phi);
return phi;
}
@@ -329,7 +334,8 @@
Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
Node *alloc_ctrl = alloc->in(TypeFunc::Control);
Node *alloc_mem = alloc->in(TypeFunc::Memory);
- VectorSet visited(Thread::current()->resource_area());
+ Arena *a = Thread::current()->resource_area();
+ VectorSet visited(a);
bool done = sfpt_mem == alloc_mem;
@@ -389,9 +395,18 @@
return mem->in(MemNode::ValueIn);
} else if (mem->is_Phi()) {
// attempt to produce a Phi reflecting the values on the input paths of the Phi
- Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, 8);
+ Node_Stack value_phis(a, 8);
+ Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, 8);
if (phi != NULL) {
return phi;
+ } else {
+ // Kill all new Phis
+ while(value_phis.is_nonempty()) {
+ Node* n = value_phis.node();
+ _igvn.hash_delete(n);
+ _igvn.subsume_node(n, C->top());
+ value_phis.pop();
+ }
}
}
}