1231 } |
1231 } |
1232 } |
1232 } |
1233 if (!have_con) // remaining adjustments need a con |
1233 if (!have_con) // remaining adjustments need a con |
1234 return; |
1234 return; |
1235 |
1235 |
|
1236 sharpen_type_after_if(btest, con, tcon, val, tval); |
|
1237 } |
|
1238 |
|
1239 |
|
1240 static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) { |
|
1241 Node* ldk; |
|
1242 if (n->is_DecodeN()) { |
|
1243 if (n->in(1)->Opcode() != Op_LoadNKlass) { |
|
1244 return NULL; |
|
1245 } else { |
|
1246 ldk = n->in(1); |
|
1247 } |
|
1248 } else if (n->Opcode() != Op_LoadKlass) { |
|
1249 return NULL; |
|
1250 } else { |
|
1251 ldk = n; |
|
1252 } |
|
1253 assert(ldk != NULL && ldk->is_Load(), "should have found a LoadKlass or LoadNKlass node"); |
|
1254 |
|
1255 Node* adr = ldk->in(MemNode::Address); |
|
1256 intptr_t off = 0; |
|
1257 Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off); |
|
1258 if (obj == NULL || off != oopDesc::klass_offset_in_bytes()) // loading oopDesc::_klass? |
|
1259 return NULL; |
|
1260 const TypePtr* tp = gvn->type(obj)->is_ptr(); |
|
1261 if (tp == NULL || !(tp->isa_instptr() || tp->isa_aryptr())) // is obj a Java object ptr? |
|
1262 return NULL; |
|
1263 |
|
1264 return obj; |
|
1265 } |
|
1266 |
|
1267 void Parse::sharpen_type_after_if(BoolTest::mask btest, |
|
1268 Node* con, const Type* tcon, |
|
1269 Node* val, const Type* tval) { |
|
1270 // Look for opportunities to sharpen the type of a node |
|
1271 // whose klass is compared with a constant klass. |
|
1272 if (btest == BoolTest::eq && tcon->isa_klassptr()) { |
|
1273 Node* obj = extract_obj_from_klass_load(&_gvn, val); |
|
1274 const TypeOopPtr* con_type = tcon->isa_klassptr()->as_instance_type(); |
|
1275 if (obj != NULL && (con_type->isa_instptr() || con_type->isa_aryptr())) { |
|
1276 // Found: |
|
1277 // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) |
|
1278 // or the narrowOop equivalent. |
|
1279 const Type* obj_type = _gvn.type(obj); |
|
1280 const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr(); |
|
1281 if (tboth != NULL && tboth != obj_type && tboth->higher_equal(obj_type)) { |
|
1282 // obj has to be of the exact type Foo if the CmpP succeeds. |
|
1283 assert(tboth->klass_is_exact(), "klass should be exact"); |
|
1284 int obj_in_map = map()->find_edge(obj); |
|
1285 JVMState* jvms = this->jvms(); |
|
1286 if (obj_in_map >= 0 && |
|
1287 (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { |
|
1288 TypeNode* ccast = new (C, 2) CheckCastPPNode(control(), obj, tboth); |
|
1289 const Type* tcc = ccast->as_Type()->type(); |
|
1290 assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); |
|
1291 // Delay transform() call to allow recovery of pre-cast value |
|
1292 // at the control merge. |
|
1293 _gvn.set_type_bottom(ccast); |
|
1294 record_for_igvn(ccast); |
|
1295 // Here's the payoff. |
|
1296 replace_in_map(obj, ccast); |
|
1297 } |
|
1298 } |
|
1299 } |
|
1300 } |
1236 |
1301 |
1237 int val_in_map = map()->find_edge(val); |
1302 int val_in_map = map()->find_edge(val); |
1238 if (val_in_map < 0) return; // replace_in_map would be useless |
1303 if (val_in_map < 0) return; // replace_in_map would be useless |
1239 { |
1304 { |
1240 JVMState* jvms = this->jvms(); |
1305 JVMState* jvms = this->jvms(); |
1263 const TypeF* tf = tcon->isa_float_constant(); |
1328 const TypeF* tf = tcon->isa_float_constant(); |
1264 const TypeD* td = tcon->isa_double_constant(); |
1329 const TypeD* td = tcon->isa_double_constant(); |
1265 // Exclude tests vs float/double 0 as these could be |
1330 // Exclude tests vs float/double 0 as these could be |
1266 // either +0 or -0. Just because you are equal to +0 |
1331 // either +0 or -0. Just because you are equal to +0 |
1267 // doesn't mean you ARE +0! |
1332 // doesn't mean you ARE +0! |
|
1333 // Note, following code also replaces Long and Oop values. |
1268 if ((!tf || tf->_f != 0.0) && |
1334 if ((!tf || tf->_f != 0.0) && |
1269 (!td || td->_d != 0.0)) |
1335 (!td || td->_d != 0.0)) |
1270 cast = con; // Replace non-constant val by con. |
1336 cast = con; // Replace non-constant val by con. |
1271 } |
1337 } |
1272 } |
1338 } |