diff -r aabf54ccedb1 -r 6f3fd5150b67 src/share/vm/opto/macro.cpp --- a/src/share/vm/opto/macro.cpp Mon May 06 19:49:23 2013 -0700 +++ b/src/share/vm/opto/macro.cpp Wed May 08 15:08:01 2013 -0700 @@ -666,7 +666,7 @@ alloc->dump(); else res->dump(); - } else { + } else if (alloc->_is_scalar_replaceable) { tty->print("NotScalar (%s)", fail_eliminate); if (res == NULL) alloc->dump(); @@ -845,18 +845,14 @@ // to the allocated object with "sobj" int start = jvms->debug_start(); int end = jvms->debug_end(); - for (int i = start; i < end; i++) { - if (sfpt->in(i) == res) { - sfpt->set_req(i, sobj); - } - } + sfpt->replace_edges_in_range(res, sobj, start, end); safepoints_done.append_if_missing(sfpt); // keep it for rollback } return true; } // Process users of eliminated allocation. -void PhaseMacroExpand::process_users_of_allocation(AllocateNode *alloc) { +void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { Node* res = alloc->result_cast(); if (res != NULL) { for (DUIterator_Last jmin, j = res->last_outs(jmin); j >= jmin; ) { @@ -899,6 +895,17 @@ // Process other users of allocation's projections // if (_resproj != NULL && _resproj->outcnt() != 0) { + // First disconnect stores captured by Initialize node. + // If Initialize node is eliminated first in the following code, + // it will kill such stores and DUIterator_Last will assert. + for (DUIterator_Fast jmax, j = _resproj->fast_outs(jmax); j < jmax; j++) { + Node *use = _resproj->fast_out(j); + if (use->is_AddP()) { + // raw memory addresses used only by the initialization + _igvn.replace_node(use, C->top()); + --j; --jmax; + } + } for (DUIterator_Last jmin, j = _resproj->last_outs(jmin); j >= jmin; ) { Node *use = _resproj->last_out(j); uint oc1 = _resproj->outcnt(); @@ -923,9 +930,6 @@ #endif _igvn.replace_node(mem_proj, mem); } - } else if (use->is_AddP()) { - // raw memory addresses used only by the initialization - _igvn.replace_node(use, C->top()); } else { assert(false, "only Initialize or AddP expected"); } @@ -953,8 +957,18 @@ } bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { - - if (!EliminateAllocations || !alloc->_is_scalar_replaceable) { + if (!EliminateAllocations || !alloc->_is_non_escaping) { + return false; + } + Node* klass = alloc->in(AllocateNode::KlassNode); + const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr(); + Node* res = alloc->result_cast(); + // Eliminate boxing allocations which are not used + // regardless scalar replacable status. + bool boxing_alloc = C->eliminate_boxing() && + tklass->klass()->is_instance_klass() && + tklass->klass()->as_instance_klass()->is_box_klass(); + if (!alloc->_is_scalar_replaceable && (!boxing_alloc || (res != NULL))) { return false; } @@ -965,14 +979,22 @@ return false; } + if (!alloc->_is_scalar_replaceable) { + assert(res == NULL, "sanity"); + // We can only eliminate allocation if all debug info references + // are already replaced with SafePointScalarObject because + // we can't search for a fields value without instance_id. + if (safepoints.length() > 0) { + return false; + } + } + if (!scalar_replacement(alloc, safepoints)) { return false; } CompileLog* log = C->log(); if (log != NULL) { - Node* klass = alloc->in(AllocateNode::KlassNode); - const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr(); log->head("eliminate_allocation type='%d'", log->identify(tklass->klass())); JVMState* p = alloc->jvms(); @@ -997,6 +1019,43 @@ return true; } +bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) { + // EA should remove all uses of non-escaping boxing node. + if (!C->eliminate_boxing() || boxing->proj_out(TypeFunc::Parms) != NULL) { + return false; + } + + extract_call_projections(boxing); + + const TypeTuple* r = boxing->tf()->range(); + assert(r->cnt() > TypeFunc::Parms, "sanity"); + const TypeInstPtr* t = r->field_at(TypeFunc::Parms)->isa_instptr(); + assert(t != NULL, "sanity"); + + CompileLog* log = C->log(); + if (log != NULL) { + log->head("eliminate_boxing type='%d'", + log->identify(t->klass())); + JVMState* p = boxing->jvms(); + while (p != NULL) { + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); + p = p->caller(); + } + log->tail("eliminate_boxing"); + } + + process_users_of_allocation(boxing); + +#ifndef PRODUCT + if (PrintEliminateAllocations) { + tty->print("++++ Eliminated: %d ", boxing->_idx); + boxing->method()->print_short_name(tty); + tty->cr(); + } +#endif + + return true; +} //---------------------------set_eden_pointers------------------------- void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_adr) { @@ -2384,6 +2443,9 @@ case Node::Class_AllocateArray: success = eliminate_allocate_node(n->as_Allocate()); break; + case Node::Class_CallStaticJava: + success = eliminate_boxing_node(n->as_CallStaticJava()); + break; case Node::Class_Lock: case Node::Class_Unlock: assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); @@ -2424,6 +2486,11 @@ C->remove_macro_node(n); _igvn._worklist.push(n); success = true; + } else if (n->Opcode() == Op_CallStaticJava) { + // Remove it from macro list and put on IGVN worklist to optimize. + C->remove_macro_node(n); + _igvn._worklist.push(n); + success = true; } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { _igvn.replace_node(n, n->in(1)); success = true;