From a924b9a76208693e1684171c42708147c4a7b7ce Mon Sep 17 00:00:00 2001 From: kvn Date: Fri, 1 Aug 2008 10:06:45 -0700 Subject: [PATCH] 6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type") Summary: fixed few addP node type and narrow oop type problems. Reviewed-by: rasbold, never --- src/share/vm/adlc/output_h.cpp | 13 +++++++++++++ src/share/vm/opto/addnode.cpp | 2 ++ src/share/vm/opto/callGenerator.cpp | 6 ++++++ src/share/vm/opto/compile.cpp | 1 + src/share/vm/opto/escape.cpp | 28 +++++++++++++++++++++++++--- src/share/vm/opto/escape.hpp | 2 +- src/share/vm/opto/loopnode.cpp | 2 ++ src/share/vm/opto/loopopts.cpp | 14 +++++++++----- src/share/vm/opto/memnode.cpp | 6 +++++- src/share/vm/opto/subnode.cpp | 12 ++++++++++-- src/share/vm/opto/type.cpp | 23 +++++++++++++---------- 11 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/share/vm/adlc/output_h.cpp b/src/share/vm/adlc/output_h.cpp index 78f160783..04cddcd28 100644 --- a/src/share/vm/adlc/output_h.cpp +++ b/src/share/vm/adlc/output_h.cpp @@ -1848,6 +1848,19 @@ void ArchDesc::declareClasses(FILE *fp) { fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveP\n", offset, offset+1, offset+1); } + else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveN") ) { + int offset = 1; + // Special special hack to see if the Cmp? has been incorporated in the conditional move + MatchNode *rl = instr->_matrule->_rChild->_lChild; + if( rl && !strcmp(rl->_opType, "Binary") ) { + MatchNode *rlr = rl->_rChild; + if (rlr && strncmp(rlr->_opType, "Cmp", 3) == 0) + offset = 2; + } + // Special hack for ideal CMoveN; ideal type depends on inputs + fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveN\n", + offset, offset+1, offset+1); + } else if( instr->needs_base_oop_edge(_globalNames) ) { // Special hack for ideal AddP. Bottom type is an oop IFF it has a // legal base-pointer input. Otherwise it is NOT an oop. diff --git a/src/share/vm/opto/addnode.cpp b/src/share/vm/opto/addnode.cpp index e5cc05b6b..f581f9249 100644 --- a/src/share/vm/opto/addnode.cpp +++ b/src/share/vm/opto/addnode.cpp @@ -695,6 +695,8 @@ const Type *AddPNode::mach_bottom_type( const MachNode* n) { guarantee(tptr == NULL, "must be only one pointer operand"); tptr = et->isa_oopptr(); guarantee(tptr != NULL, "non-int operand must be pointer"); + if (tptr->higher_equal(tp->add_offset(tptr->offset()))) + tp = tptr; // Set more precise type for bailout continue; } if ( eti->_hi != eti->_lo ) goto bottom_out; diff --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp index 3131cf6b3..72b04c5d0 100644 --- a/src/share/vm/opto/callGenerator.cpp +++ b/src/share/vm/opto/callGenerator.cpp @@ -464,6 +464,12 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) { } } + if (kit.stopped()) { + // Instance exactly does not matches the desired type. + kit.set_jvms(slow_jvms); + return kit.transfer_exceptions_into_jvms(); + } + // fall through if the instance exactly matches the desired type kit.replace_in_map(receiver, exact_receiver); diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp index ec28d0799..18114bafc 100644 --- a/src/share/vm/opto/compile.cpp +++ b/src/share/vm/opto/compile.cpp @@ -2111,6 +2111,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { n->subsume_by( cmpN ); } } + break; #endif case Op_ModI: diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp index fece33098..ef1466378 100644 --- a/src/share/vm/opto/escape.cpp +++ b/src/share/vm/opto/escape.cpp @@ -492,13 +492,13 @@ static Node* find_second_addp(Node* addp, Node* n) { // Adjust the type and inputs of an AddP which computes the // address of a field of an instance // -void ConnectionGraph::split_AddP(Node *addp, Node *base, PhaseGVN *igvn) { +bool ConnectionGraph::split_AddP(Node *addp, Node *base, PhaseGVN *igvn) { const TypeOopPtr *base_t = igvn->type(base)->isa_oopptr(); assert(base_t != NULL && base_t->is_known_instance(), "expecting instance oopptr"); const TypeOopPtr *t = igvn->type(addp)->isa_oopptr(); if (t == NULL) { // We are computing a raw address for a store captured by an Initialize - // compute an appropriate address type. + // compute an appropriate address type (cases #3 and #5). assert(igvn->type(addp) == TypeRawPtr::NOTNULL, "must be raw pointer"); assert(addp->in(AddPNode::Address)->is_Proj(), "base of raw address must be result projection from allocation"); int offs = (int)igvn->find_intptr_t_con(addp->in(AddPNode::Offset), Type::OffsetBot); @@ -508,6 +508,25 @@ void ConnectionGraph::split_AddP(Node *addp, Node *base, PhaseGVN *igvn) { int inst_id = base_t->instance_id(); assert(!t->is_known_instance() || t->instance_id() == inst_id, "old type must be non-instance or match new type"); + + // The type 't' could be subclass of 'base_t'. + // As result t->offset() could be large then base_t's size and it will + // cause the failure in add_offset() with narrow oops since TypeOopPtr() + // constructor verifies correctness of the offset. + // + // It could happend on subclass's branch (from the type profiling + // inlining) which was not eliminated during parsing since the exactness + // of the allocation type was not propagated to the subclass type check. + // + // Do nothing for such AddP node and don't process its users since + // this code branch will go away. + // + if (!t->is_known_instance() && + !t->klass()->equals(base_t->klass()) && + t->klass()->is_subtype_of(base_t->klass())) { + return false; // bail out + } + const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr(); // Do NOT remove the next call: ensure an new alias index is allocated // for the instance type @@ -542,6 +561,7 @@ void ConnectionGraph::split_AddP(Node *addp, Node *base, PhaseGVN *igvn) { } // Put on IGVN worklist since at least addp's type was changed above. record_for_optimizer(addp); + return true; } // @@ -969,7 +989,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) if (elem == _phantom_object) continue; // Assume the value was set outside this method. Node *base = get_map(elem); // CheckCastPP node - split_AddP(n, base, igvn); + if (!split_AddP(n, base, igvn)) continue; // wrong type tinst = igvn->type(base)->isa_oopptr(); } else if (n->is_Phi() || n->is_CheckCastPP() || @@ -1012,6 +1032,8 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) tn->set_type(tn_type); igvn->hash_insert(tn); record_for_optimizer(n); + } else { + continue; // wrong type } } } else { diff --git a/src/share/vm/opto/escape.hpp b/src/share/vm/opto/escape.hpp index 93cfd0ec8..1ce0cc9cf 100644 --- a/src/share/vm/opto/escape.hpp +++ b/src/share/vm/opto/escape.hpp @@ -286,7 +286,7 @@ private: // MemNode - new memory input for this node // ChecCastPP - allocation that this is a cast of // allocation - CheckCastPP of the allocation - void split_AddP(Node *addp, Node *base, PhaseGVN *igvn); + bool split_AddP(Node *addp, Node *base, PhaseGVN *igvn); PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray &orig_phi_worklist, PhaseGVN *igvn, bool &new_created); PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray &orig_phi_worklist, PhaseGVN *igvn); Node *find_mem(Node *mem, int alias_idx, PhaseGVN *igvn); diff --git a/src/share/vm/opto/loopnode.cpp b/src/share/vm/opto/loopnode.cpp index c411cdc34..7e853e6a1 100644 --- a/src/share/vm/opto/loopnode.cpp +++ b/src/share/vm/opto/loopnode.cpp @@ -2625,9 +2625,11 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify case Op_LoadF: case Op_LoadI: case Op_LoadKlass: + case Op_LoadNKlass: case Op_LoadL: case Op_LoadS: case Op_LoadP: + case Op_LoadN: case Op_LoadRange: case Op_LoadD_unaligned: case Op_LoadL_unaligned: diff --git a/src/share/vm/opto/loopopts.cpp b/src/share/vm/opto/loopopts.cpp index 3ac320cbf..06aab460d 100644 --- a/src/share/vm/opto/loopopts.cpp +++ b/src/share/vm/opto/loopopts.cpp @@ -96,6 +96,10 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) { // our new node, even though we may throw the node away. // (Note: This tweaking with igvn only works because x is a new node.) _igvn.set_type(x, t); + // If x is a TypeNode, capture any more-precise type permanently into Node + // othewise it will be not updated during igvn->transform since + // igvn->type(x) is set to x->Value() already. + x->raise_bottom_type(t); Node *y = x->Identity(&_igvn); if( y != x ) { wins++; @@ -464,11 +468,11 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) { case T_FLOAT: case T_DOUBLE: case T_ADDRESS: // (RawPtr) - case T_NARROWOOP: cost++; break; + case T_NARROWOOP: // Fall through case T_OBJECT: { // Base oops are OK, but not derived oops - const TypeOopPtr *tp = phi->type()->isa_oopptr(); + const TypeOopPtr *tp = phi->type()->make_ptr()->isa_oopptr(); // Derived pointers are Bad (tm): what's the Base (for GC purposes) of a // CMOVE'd derived pointer? It's a CMOVE'd derived base. Thus // CMOVE'ing a derived pointer requires we also CMOVE the base. If we @@ -499,11 +503,11 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) { return NULL; // Too much speculative goo } } - // See if the Phi is used by a Cmp. This will likely Split-If, a - // higher-payoff operation. + // See if the Phi is used by a Cmp or Narrow oop Decode/Encode. + // This will likely Split-If, a higher-payoff operation. for (DUIterator_Fast kmax, k = phi->fast_outs(kmax); k < kmax; k++) { Node* use = phi->fast_out(k); - if( use->is_Cmp() ) + if( use->is_Cmp() || use->is_DecodeN() || use->is_EncodeP() ) return NULL; } } diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp index edbadc5a0..dd9530885 100644 --- a/src/share/vm/opto/memnode.cpp +++ b/src/share/vm/opto/memnode.cpp @@ -1231,6 +1231,10 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) { // our new node, even though we may throw the node away. // (This tweaking with igvn only works because x is a new node.) igvn->set_type(x, t); + // If x is a TypeNode, capture any more-precise type permanently into Node + // othewise it will be not updated during igvn->transform since + // igvn->type(x) is set to x->Value() already. + x->raise_bottom_type(t); Node *y = x->Identity(igvn); if( y != x ) { wins++; @@ -1409,7 +1413,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { // had an original form like p1:(AddP x x (LShiftL quux 3)), where the // expression (LShiftL quux 3) independently optimized to the constant 8. if ((t->isa_int() == NULL) && (t->isa_long() == NULL) - && Opcode() != Op_LoadKlass) { + && Opcode() != Op_LoadKlass && Opcode() != Op_LoadNKlass) { // t might actually be lower than _type, if _type is a unique // concrete subclass of abstract class t. // Make sure the reference is not into the header, by comparing diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp index 90ad08700..ac7de63bf 100644 --- a/src/share/vm/opto/subnode.cpp +++ b/src/share/vm/opto/subnode.cpp @@ -681,7 +681,11 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) { // Now check for LoadKlass on left. Node* ldk1 = in(1); - if (ldk1->Opcode() != Op_LoadKlass) + if (ldk1->is_DecodeN()) { + ldk1 = ldk1->in(1); + if (ldk1->Opcode() != Op_LoadNKlass ) + return NULL; + } else if (ldk1->Opcode() != Op_LoadKlass ) return NULL; // Take apart the address of the LoadKlass: Node* adr1 = ldk1->in(MemNode::Address); @@ -702,7 +706,11 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) { // Check for a LoadKlass from primary supertype array. // Any nested loadklass from loadklass+con must be from the p.s. array. - if (ldk2->Opcode() != Op_LoadKlass) + if (ldk2->is_DecodeN()) { + // Keep ldk2 as DecodeN since it could be used in CmpP below. + if (ldk2->in(1)->Opcode() != Op_LoadNKlass ) + return NULL; + } else if (ldk2->Opcode() != Op_LoadKlass) return NULL; // Verify that we understand the situation diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp index 3a77c9da4..e850d018e 100644 --- a/src/share/vm/opto/type.cpp +++ b/src/share/vm/opto/type.cpp @@ -804,6 +804,7 @@ const Type *TypeF::xmeet( const Type *t ) const { case InstPtr: case KlassPtr: case AryPtr: + case NarrowOop: case Int: case Long: case DoubleTop: @@ -2263,6 +2264,7 @@ const Type *TypeOopPtr::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case NarrowOop: case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: @@ -3465,7 +3467,7 @@ bool TypeNarrowOop::empty(void) const { return _ooptype->empty(); } -//------------------------------meet------------------------------------------- +//------------------------------xmeet------------------------------------------ // Compute the MEET of two types. It returns a new Type object. const Type *TypeNarrowOop::xmeet( const Type *t ) const { // Perform a fast test for common case; meeting the same types together. @@ -3483,6 +3485,13 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case AnyPtr: + case RawPtr: + case OopPtr: + case InstPtr: + case KlassPtr: + case AryPtr: + case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: @@ -3499,16 +3508,9 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const { default: // All else is a mistake typerr(t); - case RawPtr: - case AnyPtr: - case OopPtr: - case InstPtr: - case KlassPtr: - case AryPtr: - typerr(t); - return Type::BOTTOM; - } // End of switch + + return this; } const Type *TypeNarrowOop::xdual() const { // Compute dual right now. @@ -3702,6 +3704,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case NarrowOop: case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: -- GitLab