--- a/hotspot/src/share/vm/opto/escape.cpp Tue May 20 06:32:58 2008 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp Wed May 21 10:45:07 2008 -0700
@@ -888,6 +888,23 @@
record_for_optimizer(n);
if (alloc->is_Allocate() && ptn->_scalar_replaceable &&
(t->isa_instptr() || t->isa_aryptr())) {
+
+ // First, put on the worklist all Field edges from Connection Graph
+ // which is more accurate then putting immediate users from Ideal Graph.
+ for (uint e = 0; e < ptn->edge_count(); e++) {
+ Node *use = _nodes->adr_at(ptn->edge_target(e))->_node;
+ assert(ptn->edge_type(e) == PointsToNode::FieldEdge && use->is_AddP(),
+ "only AddP nodes are Field edges in CG");
+ if (use->outcnt() > 0) { // Don't process dead nodes
+ Node* addp2 = find_second_addp(use, use->in(AddPNode::Base));
+ if (addp2 != NULL) {
+ assert(alloc->is_AllocateArray(),"array allocation was expected");
+ alloc_worklist.append_if_missing(addp2);
+ }
+ alloc_worklist.append_if_missing(use);
+ }
+ }
+
// An allocation may have an Initialize which has raw stores. Scan
// the users of the raw allocation result and push AddP users
// on alloc_worklist.
@@ -919,6 +936,8 @@
tinst = igvn->type(base)->isa_oopptr();
} else if (n->is_Phi() ||
n->is_CheckCastPP() ||
+ n->Opcode() == Op_EncodeP ||
+ n->Opcode() == Op_DecodeN ||
(n->is_ConstraintCast() && n->Opcode() == Op_CastPP)) {
if (visited.test_set(n->_idx)) {
assert(n->is_Phi(), "loops only through Phi's");
@@ -935,13 +954,25 @@
tinst = igvn->type(val)->isa_oopptr();
assert(tinst != NULL && tinst->is_instance() &&
tinst->instance_id() == elem , "instance type expected.");
- const TypeOopPtr *tn_t = igvn->type(tn)->isa_oopptr();
+
+ const TypeOopPtr *tn_t = NULL;
+ const Type *tn_type = igvn->type(tn);
+ if (tn_type->isa_narrowoop()) {
+ tn_t = tn_type->is_narrowoop()->make_oopptr()->isa_oopptr();
+ } else {
+ tn_t = tn_type->isa_oopptr();
+ }
if (tn_t != NULL &&
tinst->cast_to_instance(TypeOopPtr::UNKNOWN_INSTANCE)->higher_equal(tn_t)) {
+ if (tn_type->isa_narrowoop()) {
+ tn_type = tinst->make_narrowoop();
+ } else {
+ tn_type = tinst;
+ }
igvn->hash_delete(tn);
- igvn->set_type(tn, tinst);
- tn->set_type(tinst);
+ igvn->set_type(tn, tn_type);
+ tn->set_type(tn_type);
igvn->hash_insert(tn);
record_for_optimizer(n);
}
@@ -978,6 +1009,8 @@
alloc_worklist.append_if_missing(use);
} else if (use->is_Phi() ||
use->is_CheckCastPP() ||
+ use->Opcode() == Op_EncodeP ||
+ use->Opcode() == Op_DecodeN ||
(use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
alloc_worklist.append_if_missing(use);
}
@@ -1199,7 +1232,7 @@
void ConnectionGraph::compute_escape() {
- // 1. Populate Connection Graph with Ideal nodes.
+ // 1. Populate Connection Graph (CG) with Ideal nodes.
Unique_Node_List worklist_init;
worklist_init.map(_compile->unique(), NULL); // preallocate space
@@ -1281,11 +1314,13 @@
remove_deferred(ni, &deferred_edges, &visited);
if (n->is_AddP()) {
// If this AddP computes an address which may point to more that one
- // object, nothing the address points to can be scalar replaceable.
+ // object or more then one field (array's element), nothing the address
+ // points to can be scalar replaceable.
Node *base = get_addp_base(n);
ptset.Clear();
PointsTo(ptset, base, igvn);
- if (ptset.Size() > 1) {
+ if (ptset.Size() > 1 ||
+ (ptset.Size() != 0 && ptn->offset() == Type::OffsetBot)) {
for( VectorSetI j(&ptset); j.test(); ++j ) {
uint pt = j.elem;
ptnode_adr(pt)->_scalar_replaceable = false;
@@ -1979,6 +2014,11 @@
assert(false, "Op_ConP");
break;
}
+ case Op_ConN:
+ {
+ assert(false, "Op_ConN");
+ break;
+ }
case Op_CreateEx:
{
assert(false, "Op_CreateEx");