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,