comparison src/share/vm/opto/parse2.cpp @ 6131:8f6ce6f1049b

7170463: C2 should recognize "obj.getClass() == A.class" code pattern Summary: optimize this code pattern obj.getClass() == A.class. Reviewed-by: jrose, kvn Contributed-by: Krystal Mok <sajia@taobao.com>
author kvn
date Fri, 25 May 2012 07:53:11 -0700
parents c124e2e7463e
children 70862d781d01
comparison
equal deleted inserted replaced
6088:7089278210e2 6131:8f6ce6f1049b
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 }