src/share/vm/opto/graphKit.cpp

Print this page

        

*** 2267,2286 **** // the false path. Only reads invariant memory; sets no (visible) memory. // The PartialSubtypeCheckNode sets the hidden 1-word cache in the encoding // but that's not exposed to the optimizer. This call also doesn't take in an // Object; if you wish to check an Object you need to load the Object's class // prior to coming here. ! Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { // Fast check for identical types, perhaps identical constants. // The types can even be identical non-constants, in cases // involving Array.newInstance, Object.clone, etc. if (subklass == superklass) ! return top(); // false path is dead; no test needed. ! if (_gvn.type(superklass)->singleton()) { ! ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass(); ! ciKlass* subk = _gvn.type(subklass)->is_klassptr()->klass(); // In the common case of an exact superklass, try to fold up the // test before generating code. You may ask, why not just generate // the code and then let it fold up? The answer is that the generated // code will necessarily include null checks, which do not always --- 2267,2287 ---- // the false path. Only reads invariant memory; sets no (visible) memory. // The PartialSubtypeCheckNode sets the hidden 1-word cache in the encoding // but that's not exposed to the optimizer. This call also doesn't take in an // Object; if you wish to check an Object you need to load the Object's class // prior to coming here. ! Node* GraphKit::gen_subtype_check_any_phase(Node* subklass, Node* superklass, Node** ctrl, MergeMemNode* mem, PhaseGVN* gvn) { ! Compile* C = gvn->C; // Fast check for identical types, perhaps identical constants. // The types can even be identical non-constants, in cases // involving Array.newInstance, Object.clone, etc. if (subklass == superklass) ! return C->top(); // false path is dead; no test needed. ! if (gvn->type(superklass)->singleton()) { ! ciKlass* superk = gvn->type(superklass)->is_klassptr()->klass(); ! ciKlass* subk = gvn->type(subklass)->is_klassptr()->klass(); // In the common case of an exact superklass, try to fold up the // test before generating code. You may ask, why not just generate // the code and then let it fold up? The answer is that the generated // code will necessarily include null checks, which do not always
*** 2290,2313 **** // Here, the type of 'fa' is often exact, so the store check // of fa[1]=x will fold up, without testing the nullness of x. switch (C->static_subtype_check(superk, subk)) { case Compile::SSC_always_false: { ! Node* always_fail = control(); ! set_control(top()); return always_fail; } case Compile::SSC_always_true: ! return top(); case Compile::SSC_easy_test: { // Just do a direct pointer compare and be done. ! Node* cmp = _gvn.transform( new(C, 3) CmpPNode(subklass, superklass) ); ! Node* bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::eq) ); ! IfNode* iff = create_and_xform_if(control(), bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); ! set_control( _gvn.transform( new(C, 1) IfTrueNode (iff) ) ); ! return _gvn.transform( new(C, 1) IfFalseNode(iff) ); } case Compile::SSC_full_test: break; default: ShouldNotReachHere(); --- 2291,2316 ---- // Here, the type of 'fa' is often exact, so the store check // of fa[1]=x will fold up, without testing the nullness of x. switch (C->static_subtype_check(superk, subk)) { case Compile::SSC_always_false: { ! Node* always_fail = *ctrl; ! *ctrl = gvn->C->top(); return always_fail; } case Compile::SSC_always_true: ! return C->top(); case Compile::SSC_easy_test: { // Just do a direct pointer compare and be done. ! Node* cmp = gvn_transform(new(C, 3) CmpPNode(subklass, superklass), gvn); ! Node* bol = gvn_transform(new(C, 2) BoolNode(cmp, BoolTest::eq), gvn); ! IfNode* iff = new (C, 2) IfNode(*ctrl, bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); ! gvn_transform(iff, gvn); ! if (!bol->is_Con()) gvn_transform_ctrl(iff, gvn); ! *ctrl = gvn_transform(new(C, 1) IfTrueNode (iff), gvn); ! return gvn_transform(new(C, 1) IfFalseNode(iff), gvn); } case Compile::SSC_full_test: break; default: ShouldNotReachHere();
*** 2317,2396 **** // %%% Possible further optimization: Even if the superklass is not exact, // if the subklass is the unique subtype of the superklass, the check // will always succeed. We could leave a dependency behind to ensure this. // First load the super-klass's check-offset ! Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); ! Node *chk_off = _gvn.transform( new (C, 3) LoadINode( NULL, memory(p1), p1, _gvn.type(p1)->is_ptr() ) ); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); ! bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); // Load from the sub-klass's super-class display list, or a 1-word cache of // the secondary superclass list, or a failing value with a sentinel offset // if the super-klass is an interface or exceptionally deep in the Java // hierarchy and we have to scan the secondary superclass list the hard way. // Worst-case type is a little odd: NULL is allowed as a result (usually // klass loads can never produce a NULL). ! Node *chk_off_X = ConvI2X(chk_off); ! Node *p2 = _gvn.transform( new (C, 4) AddPNode(subklass,subklass,chk_off_X) ); // For some types like interfaces the following loadKlass is from a 1-word // cache which is mutable so can't use immutable memory. Other // types load from the super-class display table which is immutable. ! Node *kmem = might_be_cache ? memory(p2) : immutable_memory(); ! Node *nkls = _gvn.transform( LoadKlassNode::make( _gvn, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL ) ); // Compile speed common case: ARE a subtype and we canNOT fail if( superklass == nkls ) ! return top(); // false path is dead; no test needed. // See if we get an immediate positive hit. Happens roughly 83% of the // time. Test to see if the value loaded just previously from the subklass // is exactly the superklass. ! Node *cmp1 = _gvn.transform( new (C, 3) CmpPNode( superklass, nkls ) ); ! Node *bol1 = _gvn.transform( new (C, 2) BoolNode( cmp1, BoolTest::eq ) ); ! IfNode *iff1 = create_and_xform_if( control(), bol1, PROB_LIKELY(0.83f), COUNT_UNKNOWN ); ! Node *iftrue1 = _gvn.transform( new (C, 1) IfTrueNode ( iff1 ) ); ! set_control( _gvn.transform( new (C, 1) IfFalseNode( iff1 ) ) ); // Compile speed common case: Check for being deterministic right now. If // chk_off is a constant and not equal to cacheoff then we are NOT a // subklass. In this case we need exactly the 1 test above and we can // return those results immediately. if (!might_be_cache) { ! Node* not_subtype_ctrl = control(); ! set_control(iftrue1); // We need exactly the 1 test above return not_subtype_ctrl; } // Gather the various success & failures here RegionNode *r_ok_subtype = new (C, 4) RegionNode(4); ! record_for_igvn(r_ok_subtype); RegionNode *r_not_subtype = new (C, 3) RegionNode(3); ! record_for_igvn(r_not_subtype); r_ok_subtype->init_req(1, iftrue1); // Check for immediate negative hit. Happens roughly 11% of the time (which // is roughly 63% of the remaining cases). Test to see if the loaded // check-offset points into the subklass display list or the 1-element // cache. If it points to the display (and NOT the cache) and the display // missed then it's not a subtype. ! Node *cacheoff = _gvn.intcon(cacheoff_con); ! Node *cmp2 = _gvn.transform( new (C, 3) CmpINode( chk_off, cacheoff ) ); ! Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmp2, BoolTest::ne ) ); ! IfNode *iff2 = create_and_xform_if( control(), bol2, PROB_LIKELY(0.63f), COUNT_UNKNOWN ); ! r_not_subtype->init_req(1, _gvn.transform( new (C, 1) IfTrueNode (iff2) ) ); ! set_control( _gvn.transform( new (C, 1) IfFalseNode(iff2) ) ); // Check for self. Very rare to get here, but it is taken 1/3 the time. // No performance impact (too rare) but allows sharing of secondary arrays // which has some footprint reduction. ! Node *cmp3 = _gvn.transform( new (C, 3) CmpPNode( subklass, superklass ) ); ! Node *bol3 = _gvn.transform( new (C, 2) BoolNode( cmp3, BoolTest::eq ) ); ! IfNode *iff3 = create_and_xform_if( control(), bol3, PROB_LIKELY(0.36f), COUNT_UNKNOWN ); ! r_ok_subtype->init_req(2, _gvn.transform( new (C, 1) IfTrueNode ( iff3 ) ) ); ! set_control( _gvn.transform( new (C, 1) IfFalseNode( iff3 ) ) ); // -- Roads not taken here: -- // We could also have chosen to perform the self-check at the beginning // of this code sequence, as the assembler does. This would not pay off // the same way, since the optimizer, unlike the assembler, can perform --- 2320,2415 ---- // %%% Possible further optimization: Even if the superklass is not exact, // if the subklass is the unique subtype of the superklass, the check // will always succeed. We could leave a dependency behind to ensure this. // First load the super-klass's check-offset ! Node *p1 = gvn_transform(new (C, 4) AddPNode(superklass, superklass, gvn->MakeConX(in_bytes(Klass::super_check_offset_offset()))), gvn); ! Node* m = mem->memory_at(C->get_alias_index(gvn->type(p1)->is_ptr())); ! Node *chk_off = gvn_transform(new (C, 3) LoadINode(NULL, m, p1, gvn->type(p1)->is_ptr()), gvn); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); ! bool might_be_cache = (gvn->find_int_con(chk_off, cacheoff_con) == cacheoff_con); // Load from the sub-klass's super-class display list, or a 1-word cache of // the secondary superclass list, or a failing value with a sentinel offset // if the super-klass is an interface or exceptionally deep in the Java // hierarchy and we have to scan the secondary superclass list the hard way. // Worst-case type is a little odd: NULL is allowed as a result (usually // klass loads can never produce a NULL). ! Node *chk_off_X = LP64_ONLY(NULL) NOT_LP64(chk_off); ! #ifdef _LP64 ! jint chk_off_con = gvn->find_int_con(chk_off, Type::OffsetBot); ! if (chk_off_con != Type::OffsetBot) { ! chk_off_X = gvn->longcon((jlong) chk_off_con); ! } else { ! chk_off_X = gvn_transform(new (C, 2) ConvI2LNode(chk_off), gvn); ! } ! #endif ! Node *p2 = gvn_transform(new (C, 4) AddPNode(subklass,subklass,chk_off_X), gvn); // For some types like interfaces the following loadKlass is from a 1-word // cache which is mutable so can't use immutable memory. Other // types load from the super-class display table which is immutable. ! m = mem->memory_at(C->get_alias_index(gvn->type(p2)->is_ptr())); ! Node *kmem = might_be_cache ? m : C->immutable_memory(); ! Node *nkls = gvn_transform(LoadKlassNode::make(*gvn, kmem, p2, gvn->type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL), gvn); // Compile speed common case: ARE a subtype and we canNOT fail if( superklass == nkls ) ! return C->top(); // false path is dead; no test needed. // See if we get an immediate positive hit. Happens roughly 83% of the // time. Test to see if the value loaded just previously from the subklass // is exactly the superklass. ! Node *cmp1 = gvn_transform(new (C, 3) CmpPNode(superklass, nkls), gvn); ! Node *bol1 = gvn_transform(new (C, 2) BoolNode(cmp1, BoolTest::eq), gvn); ! IfNode *iff1 = new (C, 2) IfNode(*ctrl, bol1, PROB_LIKELY(0.83f), COUNT_UNKNOWN); ! gvn_transform(iff1, gvn); ! if (!bol1->is_Con()) gvn_transform_ctrl(iff1, gvn); ! Node *iftrue1 = gvn_transform( new (C, 1) IfTrueNode (iff1), gvn); ! *ctrl = gvn_transform(new (C, 1) IfFalseNode(iff1), gvn); // Compile speed common case: Check for being deterministic right now. If // chk_off is a constant and not equal to cacheoff then we are NOT a // subklass. In this case we need exactly the 1 test above and we can // return those results immediately. if (!might_be_cache) { ! Node* not_subtype_ctrl = *ctrl; ! *ctrl = iftrue1; // We need exactly the 1 test above return not_subtype_ctrl; } // Gather the various success & failures here RegionNode *r_ok_subtype = new (C, 4) RegionNode(4); ! gvn_transform_ctrl(r_ok_subtype, gvn); RegionNode *r_not_subtype = new (C, 3) RegionNode(3); ! gvn_transform_ctrl(r_not_subtype, gvn); r_ok_subtype->init_req(1, iftrue1); // Check for immediate negative hit. Happens roughly 11% of the time (which // is roughly 63% of the remaining cases). Test to see if the loaded // check-offset points into the subklass display list or the 1-element // cache. If it points to the display (and NOT the cache) and the display // missed then it's not a subtype. ! Node *cacheoff = gvn->intcon(cacheoff_con); ! Node *cmp2 = gvn_transform(new (C, 3) CmpINode(chk_off, cacheoff), gvn); ! Node *bol2 = gvn_transform(new (C, 2) BoolNode(cmp2, BoolTest::ne), gvn); ! IfNode *iff2 = new (C, 2) IfNode( *ctrl, bol2, PROB_LIKELY(0.63f), COUNT_UNKNOWN); ! gvn_transform(iff2, gvn); ! if (!bol2->is_Con()) gvn_transform_ctrl(iff2, gvn); ! r_not_subtype->init_req(1, gvn_transform(new (C, 1) IfTrueNode (iff2), gvn)); ! *ctrl = gvn_transform(new (C, 1) IfFalseNode(iff2), gvn); // Check for self. Very rare to get here, but it is taken 1/3 the time. // No performance impact (too rare) but allows sharing of secondary arrays // which has some footprint reduction. ! Node *cmp3 = gvn_transform(new (C, 3) CmpPNode( subklass, superklass), gvn); ! Node *bol3 = gvn_transform(new (C, 2) BoolNode( cmp3, BoolTest::eq), gvn); ! IfNode *iff3 = new (C, 2) IfNode( *ctrl, bol3, PROB_LIKELY(0.36f), COUNT_UNKNOWN); ! gvn_transform(iff3, gvn); ! if (!bol3->is_Con()) gvn_transform_ctrl(iff3, gvn); ! r_ok_subtype->init_req(2, gvn_transform(new (C, 1) IfTrueNode(iff3), gvn)); ! *ctrl = gvn_transform(new (C, 1) IfFalseNode(iff3), gvn); // -- Roads not taken here: -- // We could also have chosen to perform the self-check at the beginning // of this code sequence, as the assembler does. This would not pay off // the same way, since the optimizer, unlike the assembler, can perform
*** 2409,2430 **** // performance impact (too rare) but it's gotta be done. // Since the code is rarely used, there is no penalty for moving it // out of line, and it can only improve I-cache density. // The decision to inline or out-of-line this final check is platform // dependent, and is found in the AD file definition of PartialSubtypeCheck. ! Node* psc = _gvn.transform( ! new (C, 3) PartialSubtypeCheckNode(control(), subklass, superklass) ); ! Node *cmp4 = _gvn.transform( new (C, 3) CmpPNode( psc, null() ) ); ! Node *bol4 = _gvn.transform( new (C, 2) BoolNode( cmp4, BoolTest::ne ) ); ! IfNode *iff4 = create_and_xform_if( control(), bol4, PROB_FAIR, COUNT_UNKNOWN ); ! r_not_subtype->init_req(2, _gvn.transform( new (C, 1) IfTrueNode (iff4) ) ); ! r_ok_subtype ->init_req(3, _gvn.transform( new (C, 1) IfFalseNode(iff4) ) ); // Return false path; set default control to true path. ! set_control( _gvn.transform(r_ok_subtype) ); ! return _gvn.transform(r_not_subtype); } // Profile-driven exact type check: Node* GraphKit::type_check_receiver(Node* receiver, ciKlass* klass, float prob, --- 2428,2451 ---- // performance impact (too rare) but it's gotta be done. // Since the code is rarely used, there is no penalty for moving it // out of line, and it can only improve I-cache density. // The decision to inline or out-of-line this final check is platform // dependent, and is found in the AD file definition of PartialSubtypeCheck. ! Node* psc = gvn_transform( ! new (C, 3) PartialSubtypeCheckNode(*ctrl, subklass, superklass), gvn); ! Node *cmp4 = gvn_transform(new (C, 3) CmpPNode(psc, gvn->zerocon(T_OBJECT)), gvn); ! Node *bol4 = gvn_transform(new (C, 2) BoolNode(cmp4, BoolTest::ne), gvn); ! IfNode *iff4 = new (C, 2) IfNode(*ctrl, bol4, PROB_FAIR, COUNT_UNKNOWN); ! gvn_transform(iff4, gvn); ! if (!bol4->is_Con()) gvn_transform_ctrl(iff4, gvn); ! r_not_subtype->init_req(2, gvn_transform(new (C, 1) IfTrueNode (iff4), gvn)); ! r_ok_subtype ->init_req(3, gvn_transform(new (C, 1) IfFalseNode(iff4), gvn)); // Return false path; set default control to true path. ! *ctrl = gvn_transform(r_ok_subtype, gvn); ! return gvn_transform(r_not_subtype, gvn); } // Profile-driven exact type check: Node* GraphKit::type_check_receiver(Node* receiver, ciKlass* klass, float prob,