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

src/share/vm/opto/parse2.cpp

Print this page

        

*** 1231,1241 **** --- 1231,1306 ---- } } if (!have_con) // remaining adjustments need a con return; + sharpen_type_after_if(btest, con, tcon, val, tval); + } + + static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) { + Node* ldk; + if (n->is_DecodeN()) { + if (n->in(1)->Opcode() != Op_LoadNKlass) { + return NULL; + } else { + ldk = n->in(1); + } + } else if (n->Opcode() != Op_LoadKlass) { + return NULL; + } else { + ldk = n; + } + assert(ldk != NULL && ldk->is_Load(), "should have found a LoadKlass or LoadNKlass node"); + + Node* adr = ldk->in(MemNode::Address); + intptr_t off = 0; + Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off); + if (obj == NULL || off != oopDesc::klass_offset_in_bytes()) // loading oopDesc::_klass? + return NULL; + const TypePtr* tp = gvn->type(obj)->is_ptr(); + if (tp == NULL || !(tp->isa_instptr() || tp->isa_aryptr())) // is obj a Java object ptr? + return NULL; + + return obj; + } + + void Parse::sharpen_type_after_if(BoolTest::mask btest, + Node* con, const Type* tcon, + Node* val, const Type* tval) { + // Look for opportunities to sharpen the type of a node + // whose klass is compared with a constant klass. + if (btest == BoolTest::eq && tcon->isa_klassptr()) { + Node* obj = extract_obj_from_klass_load(&_gvn, val); + const TypeOopPtr* con_type = tcon->isa_klassptr()->as_instance_type(); + if (obj != NULL && (con_type->isa_instptr() || con_type->isa_aryptr())) { + // Found: + // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) + // or the narrowOop equivalent. + const Type* obj_type = _gvn.type(obj); + const TypeOopPtr* tboth = obj_type->join(con_type)->is_oopptr(); + if (tboth != obj_type) { + // obj has to be of the exact type Foo if the CmpP succeeds. + assert(tboth->klass_is_exact(), "klass should be exact"); + int obj_in_map = map()->find_edge(obj); + JVMState* jvms = this->jvms(); + if (obj_in_map >= 0 && + (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { + TypeNode* ccast = new (C, 2) CheckCastPPNode(control(), obj, tboth); + const Type* tcc = ccast->as_Type()->type(); + assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); + // Delay transform() call to allow recovery of pre-cast value + // at the control merge. + _gvn.set_type_bottom(ccast); + record_for_igvn(ccast); + // Here's the payoff. + replace_in_map(obj, ccast); + } + } + } + } + int val_in_map = map()->find_edge(val); if (val_in_map < 0) return; // replace_in_map would be useless { JVMState* jvms = this->jvms(); if (!(jvms->is_loc(val_in_map) ||
*** 1263,1272 **** --- 1328,1338 ---- const TypeF* tf = tcon->isa_float_constant(); const TypeD* td = tcon->isa_double_constant(); // Exclude tests vs float/double 0 as these could be // either +0 or -0. Just because you are equal to +0 // doesn't mean you ARE +0! + // Note, following code also replaces Long and Oop values. if ((!tf || tf->_f != 0.0) && (!td || td->_d != 0.0)) cast = con; // Replace non-constant val by con. } }
src/share/vm/opto/parse2.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File