src/share/vm/opto/memnode.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/memnode.cpp	Mon May 19 21:08:39 2008
--- new/src/share/vm/opto/memnode.cpp	Mon May 19 21:08:39 2008

*** 131,141 **** --- 131,143 ---- result = optimize_simple_memory_chain(result, t_adr, phase); if (is_instance && igvn != NULL && result->is_Phi()) { PhiNode *mphi = result->as_Phi(); assert(mphi->bottom_type() == Type::MEMORY, "memory phi required"); const TypePtr *t = mphi->adr_type(); ! if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM) { ! if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM || + t->isa_oopptr() && !t->is_oopptr()->is_instance() && + t->is_oopptr()->cast_to_instance(t_oop->instance_id()) == t_oop) { // clone the Phi with our address type result = mphi->split_out_instance(t_adr, igvn); } else { assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr), "correct memory chain"); }
*** 261,271 **** --- 263,276 ---- // 'dom' dominates 'sub' if its control edge and control edges // of all its inputs dominate or equal to sub's control edge. // Currently 'sub' is either Allocate, Initialize or Start nodes. ! assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start(), "expecting only these nodes"); ! // Or Region for the check in LoadNode::Ideal(); + // 'sub' should have sub->in(0) != NULL. + assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start() || + sub->is_Region(), "expecting only these nodes"); // Get control edge of 'sub'. sub = sub->find_exact_control(sub->in(0)); if (sub == NULL || sub->is_top()) return false; // Conservative answer for dead code
*** 574,601 **** --- 579,606 ---- //------------------------------Ideal_DU_postCCP------------------------------- // Find any cast-away of null-ness and keep its control. Null cast-aways are // going away in this pass and we need to make this memory op depend on the // gating null check. + Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { + return Ideal_common_DU_postCCP(ccp, this, in(MemNode::Address)); + } // I tried to leave the CastPP's in. This makes the graph more accurate in // some sense; we get to keep around the knowledge that an oop is not-null // after some test. Alas, the CastPP's interfere with GVN (some values are // the regular oop, some are the CastPP of the oop, all merge at Phi's which // cannot collapse, etc). This cost us 10% on SpecJVM, even when I removed // some of the more trivial cases in the optimizer. Removing more useless // Phi's started allowing Loads to illegally float above null checks. I gave // up on this approach. CNC 10/20/2000 ! Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { Node *ctr = in(MemNode::Control); Node *mem = in(MemNode::Memory); Node *adr = in(MemNode::Address); ! Node *MemNode::Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr ) { Node *skipped_cast = NULL; // Need a null check? Regular static accesses do not because they are // from constant addresses. Array ops are gated by the range check (which // always includes a NULL check). Just check field ops. ! if( !ctr ) { ! if( n->in(MemNode::Control) == NULL ) { // Scan upwards for the highest location we can place this memory op. while( true ) { switch( adr->Opcode() ) { case Op_AddP: // No change to NULL-ness, so peek thru AddP's
*** 616,629 **** --- 621,634 ---- adr = adr->in(1); continue; } // CastPP is going away in this pass! We need this memory op to be // control-dependent on the test that is guarding the CastPP. ! ccp->hash_delete(this); ! set_req(MemNode::Control, adr->in(0)); ! ccp->hash_insert(this); ! return this; ! ccp->hash_delete(n); ! n->set_req(MemNode::Control, adr->in(0)); ! ccp->hash_insert(n); ! return n; case Op_Phi: // Attempt to float above a Phi to some dominating point. if (adr->in(0) != NULL && adr->in(0)->is_CountedLoop()) { // If we've already peeked through a Cast (which could have set the
*** 650,672 **** --- 655,678 ---- // the node in place. 4959717. skipped_cast = adr; adr = adr->in(1); continue; } ! ccp->hash_delete(this); ! set_req(MemNode::Control, adr->in(0)); ! ccp->hash_insert(this); ! return this; ! ccp->hash_delete(n); ! n->set_req(MemNode::Control, adr->in(0)); ! ccp->hash_insert(n); ! return n; // List of "safe" opcodes; those that implicitly block the memory // op below any null check. case Op_CastX2P: // no null checks on native pointers case Op_Parm: // 'this' pointer is not null case Op_LoadP: // Loading from within a klass case Op_LoadN: // Loading from within a klass case Op_LoadKlass: // Loading from within a klass case Op_ConP: // Loading from a klass + case Op_ConN: // Loading from a klass case Op_CreateEx: // Sucking up the guts of an exception oop case Op_Con: // Reading from TLS case Op_CMoveP: // CMoveP is pinned break; // No progress
*** 674,685 **** --- 680,691 ---- case Op_SCMemProj: // Memory state from store conditional ops #ifdef ASSERT { assert(adr->as_Proj()->_con == TypeFunc::Parms, "must be return value"); const Node* call = adr->in(0); ! if (call->is_CallStaticJava()) { ! const CallStaticJavaNode* call_java = call->as_CallStaticJava(); ! if (call->is_CallJava()) { ! const CallJavaNode* call_java = call->as_CallJava(); const TypeTuple *r = call_java->tf()->range(); assert(r->cnt() > TypeFunc::Parms, "must return value"); const Type* ret_type = r->field_at(TypeFunc::Parms); assert(ret_type && ret_type->isa_ptr(), "must return pointer"); // We further presume that this is one of
*** 747,757 **** --- 753,763 ---- case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt ); case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt ); case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() ); case T_OBJECT: #ifdef _LP64 ! if (adr->bottom_type()->is_narrow()) { ! if (adr->bottom_type()->is_ptr_to_narrowoop()) { const TypeNarrowOop* narrowtype; if (rt->isa_narrowoop()) { narrowtype = rt->is_narrowoop(); } else { narrowtype = rt->is_oopptr()->make_narrowoop();
*** 760,770 **** --- 766,776 ---- return DecodeNNode::decode(&gvn, load); } else #endif { ! assert(!adr->bottom_type()->is_narrow(), "should have got back a narrow oop"); ! assert(!adr->bottom_type()->is_ptr_to_narrowoop(), "should have got back a narrow oop"); return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr()); } } ShouldNotReachHere(); return (LoadNode*)NULL;
*** 1203,1212 **** --- 1209,1223 ---- // Do nothing here if Identity will find a value // (to avoid infinite chain of value phis generation). if ( !phase->eqv(this, this->Identity(phase)) ) return NULL; + // Skip the split if the loop head dominates some control edges + // of the address. + if (cnt == 3 && !MemNode::all_controls_dominate(address, region)) + goto find_store; + const Type* this_type = this->bottom_type(); int this_index = phase->C->get_alias_index(addr_t); int this_offset = addr_t->offset(); int this_iid = addr_t->is_oopptr()->instance_id(); int wins = 0;
*** 1281,1291 **** --- 1292,1302 ---- igvn->remove_dead_node(phi); } } } } + find_store: // Check for prior store with a different base or offset; make Load // independent. Skip through any number of them. Bail out if the stores // are in an endless dead cycle and report no progress. This is a key // transform for Reflection. However, if after skipping through the Stores // we can't then fold up against a prior store do NOT do the transform as
*** 1833,1843 **** --- 1844,1854 ---- case T_FLOAT: return new (C, 4) StoreFNode(ctl, mem, adr, adr_type, val); case T_DOUBLE: return new (C, 4) StoreDNode(ctl, mem, adr, adr_type, val); case T_ADDRESS: case T_OBJECT: #ifdef _LP64 ! if (adr->bottom_type()->is_narrow() || ! if (adr->bottom_type()->is_ptr_to_narrowoop() || (UseCompressedOops && val->bottom_type()->isa_klassptr() && adr->bottom_type()->isa_rawptr())) { const TypePtr* type = val->bottom_type()->is_ptr(); Node* cp = EncodePNode::encode(&gvn, val); return new (C, 4) StoreNNode(ctl, mem, adr, adr_type, cp);

src/share/vm/opto/memnode.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File