Mon, 13 Sep 2010 12:10:49 -0700
6919069: client compiler needs to capture more profile information for tiered work
Summary: Added profiling of instanceof and aastore.
Reviewed-by: kvn, jrose, never
1.1 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Sat Sep 11 15:21:37 2010 -0700 1.2 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Mon Sep 13 12:10:49 2010 -0700 1.3 @@ -2471,8 +2471,25 @@ 1.4 } 1.5 } 1.6 1.7 -void LIR_Assembler::emit_checkcast(LIR_OpTypeCheck *op) { 1.8 - assert(op->code() == lir_checkcast, "Invalid operation"); 1.9 + 1.10 +void LIR_Assembler::setup_md_access(ciMethod* method, int bci, 1.11 + ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) { 1.12 + md = method->method_data(); 1.13 + if (md == NULL) { 1.14 + bailout("out of memory building methodDataOop"); 1.15 + return; 1.16 + } 1.17 + data = md->bci_to_data(bci); 1.18 + assert(data != NULL, "need data for checkcast"); 1.19 + assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); 1.20 + if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) { 1.21 + // The offset is large so bias the mdo by the base of the slot so 1.22 + // that the ld can use simm13s to reference the slots of the data 1.23 + mdo_offset_bias = md->byte_offset_of_slot(data, DataLayout::header_offset()); 1.24 + } 1.25 +} 1.26 + 1.27 +void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { 1.28 // we always need a stub for the failure case. 1.29 CodeStub* stub = op->stub(); 1.30 Register obj = op->object()->as_register(); 1.31 @@ -2494,25 +2511,10 @@ 1.32 if (op->should_profile()) { 1.33 ciMethod* method = op->profiled_method(); 1.34 assert(method != NULL, "Should have method"); 1.35 - int bci = op->profiled_bci(); 1.36 - md = method->method_data(); 1.37 - if (md == NULL) { 1.38 - bailout("out of memory building methodDataOop"); 1.39 - return; 1.40 - } 1.41 - data = md->bci_to_data(bci); 1.42 - assert(data != NULL, "need data for checkcast"); 1.43 - assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for checkcast"); 1.44 - if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) { 1.45 - // The offset is large so bias the mdo by the base of the slot so 1.46 - // that the ld can use simm13s to reference the slots of the data 1.47 - mdo_offset_bias = md->byte_offset_of_slot(data, DataLayout::header_offset()); 1.48 - } 1.49 - 1.50 - // We need two temporaries to perform this operation on SPARC, 1.51 - // so to keep things simple we perform a redundant test here 1.52 - Label profile_done; 1.53 - __ br_notnull(obj, false, Assembler::pn, profile_done); 1.54 + setup_md_access(method, op->profiled_bci(), md, data, mdo_offset_bias); 1.55 + 1.56 + Label not_null; 1.57 + __ br_notnull(obj, false, Assembler::pn, not_null); 1.58 __ delayed()->nop(); 1.59 Register mdo = k_RInfo; 1.60 Register data_val = Rtmp1; 1.61 @@ -2525,13 +2527,17 @@ 1.62 __ ldub(flags_addr, data_val); 1.63 __ or3(data_val, BitData::null_seen_byte_constant(), data_val); 1.64 __ stb(data_val, flags_addr); 1.65 - __ bind(profile_done); 1.66 + __ ba(false, *obj_is_null); 1.67 + __ delayed()->nop(); 1.68 + __ bind(not_null); 1.69 + } else { 1.70 + __ br_null(obj, false, Assembler::pn, *obj_is_null); 1.71 + __ delayed()->nop(); 1.72 } 1.73 - Label profile_cast_failure; 1.74 - 1.75 - Label done, done_null; 1.76 - // Where to go in case of cast failure 1.77 - Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); 1.78 + 1.79 + Label profile_cast_failure, profile_cast_success; 1.80 + Label *failure_target = op->should_profile() ? &profile_cast_failure : failure; 1.81 + Label *success_target = op->should_profile() ? &profile_cast_success : success; 1.82 1.83 // patching may screw with our temporaries on sparc, 1.84 // so let's do it before loading the class 1.85 @@ -2541,8 +2547,6 @@ 1.86 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 1.87 } 1.88 assert(obj != k_RInfo, "must be different"); 1.89 - __ br_null(obj, false, Assembler::pn, done_null); 1.90 - __ delayed()->nop(); 1.91 1.92 // get object class 1.93 // not a safepoint as obj null check happens earlier 1.94 @@ -2559,12 +2563,12 @@ 1.95 need_slow_path = false; 1.96 // perform the fast part of the checking logic 1.97 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg, 1.98 - (need_slow_path ? &done : NULL), 1.99 + (need_slow_path ? success_target : NULL), 1.100 failure_target, NULL, 1.101 RegisterOrConstant(k->super_check_offset())); 1.102 } else { 1.103 // perform the fast part of the checking logic 1.104 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, &done, 1.105 + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, 1.106 failure_target, NULL); 1.107 } 1.108 if (need_slow_path) { 1.109 @@ -2575,27 +2579,24 @@ 1.110 __ cmp(G3, 0); 1.111 __ br(Assembler::equal, false, Assembler::pn, *failure_target); 1.112 __ delayed()->nop(); 1.113 + // Fall through to success case 1.114 } 1.115 } 1.116 - __ bind(done); 1.117 1.118 if (op->should_profile()) { 1.119 Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtmp1; 1.120 assert_different_registers(obj, mdo, recv, tmp1); 1.121 - 1.122 + __ bind(profile_cast_success); 1.123 jobject2reg(md->constant_encoding(), mdo); 1.124 if (mdo_offset_bias > 0) { 1.125 __ set(mdo_offset_bias, tmp1); 1.126 __ add(mdo, tmp1, mdo); 1.127 } 1.128 - Label update_done; 1.129 load(Address(obj, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); 1.130 - type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &update_done); 1.131 + type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, success); 1.132 // Jump over the failure case 1.133 - __ ba(false, update_done); 1.134 + __ ba(false, *success); 1.135 __ delayed()->nop(); 1.136 - 1.137 - 1.138 // Cast failure case 1.139 __ bind(profile_cast_failure); 1.140 jobject2reg(md->constant_encoding(), mdo); 1.141 @@ -2607,17 +2608,13 @@ 1.142 __ ld_ptr(data_addr, tmp1); 1.143 __ sub(tmp1, DataLayout::counter_increment, tmp1); 1.144 __ st_ptr(tmp1, data_addr); 1.145 - __ ba(false, *stub->entry()); 1.146 + __ ba(false, *failure); 1.147 __ delayed()->nop(); 1.148 - 1.149 - __ bind(update_done); 1.150 } 1.151 - 1.152 - __ bind(done_null); 1.153 - __ mov(obj, dst); 1.154 + __ ba(false, *success); 1.155 + __ delayed()->nop(); 1.156 } 1.157 1.158 - 1.159 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { 1.160 LIR_Code code = op->code(); 1.161 if (code == lir_store_check) { 1.162 @@ -2628,88 +2625,106 @@ 1.163 Register Rtmp1 = op->tmp3()->as_register(); 1.164 1.165 __ verify_oop(value); 1.166 - 1.167 CodeStub* stub = op->stub(); 1.168 - Label done; 1.169 - __ br_null(value, false, Assembler::pn, done); 1.170 - __ delayed()->nop(); 1.171 + // check if it needs to be profiled 1.172 + ciMethodData* md; 1.173 + ciProfileData* data; 1.174 + int mdo_offset_bias = 0; 1.175 + if (op->should_profile()) { 1.176 + ciMethod* method = op->profiled_method(); 1.177 + assert(method != NULL, "Should have method"); 1.178 + setup_md_access(method, op->profiled_bci(), md, data, mdo_offset_bias); 1.179 + } 1.180 + Label profile_cast_success, profile_cast_failure, done; 1.181 + Label *success_target = op->should_profile() ? &profile_cast_success : &done; 1.182 + Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); 1.183 + 1.184 + if (op->should_profile()) { 1.185 + Label not_null; 1.186 + __ br_notnull(value, false, Assembler::pn, not_null); 1.187 + __ delayed()->nop(); 1.188 + Register mdo = k_RInfo; 1.189 + Register data_val = Rtmp1; 1.190 + jobject2reg(md->constant_encoding(), mdo); 1.191 + if (mdo_offset_bias > 0) { 1.192 + __ set(mdo_offset_bias, data_val); 1.193 + __ add(mdo, data_val, mdo); 1.194 + } 1.195 + Address flags_addr(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias); 1.196 + __ ldub(flags_addr, data_val); 1.197 + __ or3(data_val, BitData::null_seen_byte_constant(), data_val); 1.198 + __ stb(data_val, flags_addr); 1.199 + __ ba(false, done); 1.200 + __ delayed()->nop(); 1.201 + __ bind(not_null); 1.202 + } else { 1.203 + __ br_null(value, false, Assembler::pn, done); 1.204 + __ delayed()->nop(); 1.205 + } 1.206 load(array, oopDesc::klass_offset_in_bytes(), k_RInfo, T_OBJECT, op->info_for_exception()); 1.207 load(value, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); 1.208 1.209 // get instance klass 1.210 load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL); 1.211 // perform the fast part of the checking logic 1.212 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, &done, stub->entry(), NULL); 1.213 + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, failure_target, NULL); 1.214 1.215 // call out-of-line instance of __ check_klass_subtype_slow_path(...): 1.216 assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); 1.217 __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); 1.218 __ delayed()->nop(); 1.219 __ cmp(G3, 0); 1.220 - __ br(Assembler::equal, false, Assembler::pn, *stub->entry()); 1.221 + __ br(Assembler::equal, false, Assembler::pn, *failure_target); 1.222 __ delayed()->nop(); 1.223 + // fall through to the success case 1.224 + 1.225 + if (op->should_profile()) { 1.226 + Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtmp1; 1.227 + assert_different_registers(value, mdo, recv, tmp1); 1.228 + __ bind(profile_cast_success); 1.229 + jobject2reg(md->constant_encoding(), mdo); 1.230 + if (mdo_offset_bias > 0) { 1.231 + __ set(mdo_offset_bias, tmp1); 1.232 + __ add(mdo, tmp1, mdo); 1.233 + } 1.234 + load(Address(value, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); 1.235 + type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &done); 1.236 + __ ba(false, done); 1.237 + __ delayed()->nop(); 1.238 + // Cast failure case 1.239 + __ bind(profile_cast_failure); 1.240 + jobject2reg(md->constant_encoding(), mdo); 1.241 + if (mdo_offset_bias > 0) { 1.242 + __ set(mdo_offset_bias, tmp1); 1.243 + __ add(mdo, tmp1, mdo); 1.244 + } 1.245 + Address data_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias); 1.246 + __ ld_ptr(data_addr, tmp1); 1.247 + __ sub(tmp1, DataLayout::counter_increment, tmp1); 1.248 + __ st_ptr(tmp1, data_addr); 1.249 + __ ba(false, *stub->entry()); 1.250 + __ delayed()->nop(); 1.251 + } 1.252 __ bind(done); 1.253 + } else if (code == lir_checkcast) { 1.254 + Register obj = op->object()->as_register(); 1.255 + Register dst = op->result_opr()->as_register(); 1.256 + Label success; 1.257 + emit_typecheck_helper(op, &success, op->stub()->entry(), &success); 1.258 + __ bind(success); 1.259 + __ mov(obj, dst); 1.260 } else if (code == lir_instanceof) { 1.261 Register obj = op->object()->as_register(); 1.262 - Register k_RInfo = op->tmp1()->as_register(); 1.263 - Register klass_RInfo = op->tmp2()->as_register(); 1.264 Register dst = op->result_opr()->as_register(); 1.265 - Register Rtmp1 = op->tmp3()->as_register(); 1.266 - ciKlass* k = op->klass(); 1.267 - 1.268 - Label done; 1.269 - if (obj == k_RInfo) { 1.270 - k_RInfo = klass_RInfo; 1.271 - klass_RInfo = obj; 1.272 - } 1.273 - // patching may screw with our temporaries on sparc, 1.274 - // so let's do it before loading the class 1.275 - if (k->is_loaded()) { 1.276 - jobject2reg(k->constant_encoding(), k_RInfo); 1.277 - } else { 1.278 - jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 1.279 - } 1.280 - assert(obj != k_RInfo, "must be different"); 1.281 - __ br_null(obj, true, Assembler::pn, done); 1.282 - __ delayed()->set(0, dst); 1.283 - 1.284 - // get object class 1.285 - // not a safepoint as obj null check happens earlier 1.286 - load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); 1.287 - if (op->fast_check()) { 1.288 - __ cmp(k_RInfo, klass_RInfo); 1.289 - __ brx(Assembler::equal, true, Assembler::pt, done); 1.290 - __ delayed()->set(1, dst); 1.291 - __ set(0, dst); 1.292 - __ bind(done); 1.293 - } else { 1.294 - bool need_slow_path = true; 1.295 - if (k->is_loaded()) { 1.296 - if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()) 1.297 - need_slow_path = false; 1.298 - // perform the fast part of the checking logic 1.299 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg, 1.300 - (need_slow_path ? &done : NULL), 1.301 - (need_slow_path ? &done : NULL), NULL, 1.302 - RegisterOrConstant(k->super_check_offset()), 1.303 - dst); 1.304 - } else { 1.305 - assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); 1.306 - // perform the fast part of the checking logic 1.307 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst, 1.308 - &done, &done, NULL, 1.309 - RegisterOrConstant(-1), 1.310 - dst); 1.311 - } 1.312 - if (need_slow_path) { 1.313 - // call out-of-line instance of __ check_klass_subtype_slow_path(...): 1.314 - assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); 1.315 - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); 1.316 - __ delayed()->nop(); 1.317 - __ mov(G3, dst); 1.318 - } 1.319 - __ bind(done); 1.320 - } 1.321 + Label success, failure, done; 1.322 + emit_typecheck_helper(op, &success, &failure, &failure); 1.323 + __ bind(failure); 1.324 + __ set(0, dst); 1.325 + __ ba(false, done); 1.326 + __ delayed()->nop(); 1.327 + __ bind(success); 1.328 + __ set(1, dst); 1.329 + __ bind(done); 1.330 } else { 1.331 ShouldNotReachHere(); 1.332 }
2.1 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Sat Sep 11 15:21:37 2010 -0700 2.2 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Mon Sep 13 12:10:49 2010 -0700 2.3 @@ -75,6 +75,9 @@ 2.4 void type_profile_helper(Register mdo, int mdo_offset_bias, 2.5 ciMethodData *md, ciProfileData *data, 2.6 Register recv, Register tmp1, Label* update_done); 2.7 + // Setup pointers to MDO, MDO slot, also compute offset bias to access the slot. 2.8 + void setup_md_access(ciMethod* method, int bci, 2.9 + ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias); 2.10 public: 2.11 void pack64(LIR_Opr src, LIR_Opr dst); 2.12 void unpack64(LIR_Opr src, LIR_Opr dst);
3.1 --- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Sat Sep 11 15:21:37 2010 -0700 3.2 +++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Mon Sep 13 12:10:49 2010 -0700 3.3 @@ -1047,7 +1047,9 @@ 3.4 LIR_Opr tmp1 = FrameMap::G1_oop_opr; 3.5 LIR_Opr tmp2 = FrameMap::G3_oop_opr; 3.6 LIR_Opr tmp3 = FrameMap::G4_oop_opr; 3.7 - __ instanceof(out_reg, obj.result(), x->klass(), tmp1, tmp2, tmp3, x->direct_compare(), patching_info); 3.8 + __ instanceof(out_reg, obj.result(), x->klass(), tmp1, tmp2, tmp3, 3.9 + x->direct_compare(), patching_info, 3.10 + x->profiled_method(), x->profiled_bci()); 3.11 } 3.12 3.13
4.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Sat Sep 11 15:21:37 2010 -0700 4.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Sep 13 12:10:49 2010 -0700 4.3 @@ -1624,7 +1624,7 @@ 4.4 __ jccb(Assembler::notEqual, next_test); 4.5 Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); 4.6 __ addptr(data_addr, DataLayout::counter_increment); 4.7 - __ jmpb(*update_done); 4.8 + __ jmp(*update_done); 4.9 __ bind(next_test); 4.10 } 4.11 4.12 @@ -1636,13 +1636,12 @@ 4.13 __ jccb(Assembler::notEqual, next_test); 4.14 __ movptr(recv_addr, recv); 4.15 __ movptr(Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))), DataLayout::counter_increment); 4.16 - __ jmpb(*update_done); 4.17 + __ jmp(*update_done); 4.18 __ bind(next_test); 4.19 } 4.20 } 4.21 4.22 -void LIR_Assembler::emit_checkcast(LIR_OpTypeCheck *op) { 4.23 - assert(op->code() == lir_checkcast, "Invalid operation"); 4.24 +void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { 4.25 // we always need a stub for the failure case. 4.26 CodeStub* stub = op->stub(); 4.27 Register obj = op->object()->as_register(); 4.28 @@ -1666,14 +1665,12 @@ 4.29 return; 4.30 } 4.31 data = md->bci_to_data(bci); 4.32 - assert(data != NULL, "need data for checkcast"); 4.33 - assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for checkcast"); 4.34 + assert(data != NULL, "need data for type check"); 4.35 + assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); 4.36 } 4.37 - Label profile_cast_failure; 4.38 - 4.39 - Label done, done_null; 4.40 - // Where to go in case of cast failure 4.41 - Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); 4.42 + Label profile_cast_success, profile_cast_failure; 4.43 + Label *success_target = op->should_profile() ? &profile_cast_success : success; 4.44 + Label *failure_target = op->should_profile() ? &profile_cast_failure : failure; 4.45 4.46 if (obj == k_RInfo) { 4.47 k_RInfo = dst; 4.48 @@ -1699,23 +1696,23 @@ 4.49 4.50 __ cmpptr(obj, (int32_t)NULL_WORD); 4.51 if (op->should_profile()) { 4.52 - Label profile_done; 4.53 - __ jccb(Assembler::notEqual, profile_done); 4.54 - // Object is null; update methodDataOop 4.55 + Label not_null; 4.56 + __ jccb(Assembler::notEqual, not_null); 4.57 + // Object is null; update MDO and exit 4.58 Register mdo = klass_RInfo; 4.59 __ movoop(mdo, md->constant_encoding()); 4.60 Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); 4.61 int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); 4.62 __ orl(data_addr, header_bits); 4.63 - __ jmp(done_null); 4.64 - __ bind(profile_done); 4.65 + __ jmp(*obj_is_null); 4.66 + __ bind(not_null); 4.67 } else { 4.68 - __ jcc(Assembler::equal, done_null); 4.69 + __ jcc(Assembler::equal, *obj_is_null); 4.70 } 4.71 __ verify_oop(obj); 4.72 4.73 if (op->fast_check()) { 4.74 - // get object classo 4.75 + // get object class 4.76 // not a safepoint as obj null check happens earlier 4.77 if (k->is_loaded()) { 4.78 #ifdef _LP64 4.79 @@ -1727,6 +1724,7 @@ 4.80 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); 4.81 } 4.82 __ jcc(Assembler::notEqual, *failure_target); 4.83 + // successful cast, fall through to profile or jump 4.84 } else { 4.85 // get object class 4.86 // not a safepoint as obj null check happens earlier 4.87 @@ -1740,16 +1738,17 @@ 4.88 #endif // _LP64 4.89 if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { 4.90 __ jcc(Assembler::notEqual, *failure_target); 4.91 + // successful cast, fall through to profile or jump 4.92 } else { 4.93 // See if we get an immediate positive hit 4.94 - __ jcc(Assembler::equal, done); 4.95 + __ jcc(Assembler::equal, *success_target); 4.96 // check for self 4.97 #ifdef _LP64 4.98 __ cmpptr(klass_RInfo, k_RInfo); 4.99 #else 4.100 __ cmpoop(klass_RInfo, k->constant_encoding()); 4.101 #endif // _LP64 4.102 - __ jcc(Assembler::equal, done); 4.103 + __ jcc(Assembler::equal, *success_target); 4.104 4.105 __ push(klass_RInfo); 4.106 #ifdef _LP64 4.107 @@ -1763,10 +1762,11 @@ 4.108 // result is a boolean 4.109 __ cmpl(klass_RInfo, 0); 4.110 __ jcc(Assembler::equal, *failure_target); 4.111 + // successful cast, fall through to profile or jump 4.112 } 4.113 } else { 4.114 // perform the fast part of the checking logic 4.115 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, failure_target, NULL); 4.116 + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); 4.117 // call out-of-line instance of __ check_klass_subtype_slow_path(...): 4.118 __ push(klass_RInfo); 4.119 __ push(k_RInfo); 4.120 @@ -1776,32 +1776,28 @@ 4.121 // result is a boolean 4.122 __ cmpl(k_RInfo, 0); 4.123 __ jcc(Assembler::equal, *failure_target); 4.124 + // successful cast, fall through to profile or jump 4.125 } 4.126 } 4.127 - __ bind(done); 4.128 - 4.129 if (op->should_profile()) { 4.130 Register mdo = klass_RInfo, recv = k_RInfo; 4.131 + __ bind(profile_cast_success); 4.132 __ movoop(mdo, md->constant_encoding()); 4.133 __ movptr(recv, Address(obj, oopDesc::klass_offset_in_bytes())); 4.134 Label update_done; 4.135 - type_profile_helper(mdo, md, data, recv, &update_done); 4.136 - __ jmpb(update_done); 4.137 + type_profile_helper(mdo, md, data, recv, success); 4.138 + __ jmp(*success); 4.139 4.140 __ bind(profile_cast_failure); 4.141 __ movoop(mdo, md->constant_encoding()); 4.142 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); 4.143 __ subptr(counter_addr, DataLayout::counter_increment); 4.144 - __ jmp(*stub->entry()); 4.145 - 4.146 - __ bind(update_done); 4.147 + __ jmp(*failure); 4.148 } 4.149 - __ bind(done_null); 4.150 - if (dst != obj) { 4.151 - __ mov(dst, obj); 4.152 - } 4.153 + __ jmp(*success); 4.154 } 4.155 4.156 + 4.157 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { 4.158 LIR_Code code = op->code(); 4.159 if (code == lir_store_check) { 4.160 @@ -1812,9 +1808,44 @@ 4.161 Register Rtmp1 = op->tmp3()->as_register(); 4.162 4.163 CodeStub* stub = op->stub(); 4.164 - Label done; 4.165 + 4.166 + // check if it needs to be profiled 4.167 + ciMethodData* md; 4.168 + ciProfileData* data; 4.169 + 4.170 + if (op->should_profile()) { 4.171 + ciMethod* method = op->profiled_method(); 4.172 + assert(method != NULL, "Should have method"); 4.173 + int bci = op->profiled_bci(); 4.174 + md = method->method_data(); 4.175 + if (md == NULL) { 4.176 + bailout("out of memory building methodDataOop"); 4.177 + return; 4.178 + } 4.179 + data = md->bci_to_data(bci); 4.180 + assert(data != NULL, "need data for type check"); 4.181 + assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); 4.182 + } 4.183 + Label profile_cast_success, profile_cast_failure, done; 4.184 + Label *success_target = op->should_profile() ? &profile_cast_success : &done; 4.185 + Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); 4.186 + 4.187 __ cmpptr(value, (int32_t)NULL_WORD); 4.188 - __ jcc(Assembler::equal, done); 4.189 + if (op->should_profile()) { 4.190 + Label not_null; 4.191 + __ jccb(Assembler::notEqual, not_null); 4.192 + // Object is null; update MDO and exit 4.193 + Register mdo = klass_RInfo; 4.194 + __ movoop(mdo, md->constant_encoding()); 4.195 + Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); 4.196 + int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); 4.197 + __ orl(data_addr, header_bits); 4.198 + __ jmp(done); 4.199 + __ bind(not_null); 4.200 + } else { 4.201 + __ jcc(Assembler::equal, done); 4.202 + } 4.203 + 4.204 add_debug_info_for_null_check_here(op->info_for_exception()); 4.205 __ movptr(k_RInfo, Address(array, oopDesc::klass_offset_in_bytes())); 4.206 __ movptr(klass_RInfo, Address(value, oopDesc::klass_offset_in_bytes())); 4.207 @@ -1822,7 +1853,7 @@ 4.208 // get instance klass 4.209 __ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc))); 4.210 // perform the fast part of the checking logic 4.211 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL); 4.212 + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); 4.213 // call out-of-line instance of __ check_klass_subtype_slow_path(...): 4.214 __ push(klass_RInfo); 4.215 __ push(k_RInfo); 4.216 @@ -1831,94 +1862,51 @@ 4.217 __ pop(k_RInfo); 4.218 // result is a boolean 4.219 __ cmpl(k_RInfo, 0); 4.220 - __ jcc(Assembler::equal, *stub->entry()); 4.221 + __ jcc(Assembler::equal, *failure_target); 4.222 + // fall through to the success case 4.223 + 4.224 + if (op->should_profile()) { 4.225 + Register mdo = klass_RInfo, recv = k_RInfo; 4.226 + __ bind(profile_cast_success); 4.227 + __ movoop(mdo, md->constant_encoding()); 4.228 + __ movptr(recv, Address(value, oopDesc::klass_offset_in_bytes())); 4.229 + Label update_done; 4.230 + type_profile_helper(mdo, md, data, recv, &done); 4.231 + __ jmpb(done); 4.232 + 4.233 + __ bind(profile_cast_failure); 4.234 + __ movoop(mdo, md->constant_encoding()); 4.235 + Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); 4.236 + __ subptr(counter_addr, DataLayout::counter_increment); 4.237 + __ jmp(*stub->entry()); 4.238 + } 4.239 + 4.240 __ bind(done); 4.241 - } else if (code == lir_instanceof) { 4.242 - Register obj = op->object()->as_register(); 4.243 - Register k_RInfo = op->tmp1()->as_register(); 4.244 - Register klass_RInfo = op->tmp2()->as_register(); 4.245 - Register dst = op->result_opr()->as_register(); 4.246 - ciKlass* k = op->klass(); 4.247 - 4.248 - Label done; 4.249 - Label zero; 4.250 - Label one; 4.251 - if (obj == k_RInfo) { 4.252 - k_RInfo = klass_RInfo; 4.253 - klass_RInfo = obj; 4.254 - } 4.255 - // patching may screw with our temporaries on sparc, 4.256 - // so let's do it before loading the class 4.257 - if (!k->is_loaded()) { 4.258 - jobject2reg_with_patching(k_RInfo, op->info_for_patch()); 4.259 - } else { 4.260 - LP64_ONLY(__ movoop(k_RInfo, k->constant_encoding())); 4.261 - } 4.262 - assert(obj != k_RInfo, "must be different"); 4.263 - 4.264 - __ verify_oop(obj); 4.265 - if (op->fast_check()) { 4.266 - __ cmpptr(obj, (int32_t)NULL_WORD); 4.267 - __ jcc(Assembler::equal, zero); 4.268 - // get object class 4.269 - // not a safepoint as obj null check happens earlier 4.270 - if (LP64_ONLY(false &&) k->is_loaded()) { 4.271 - NOT_LP64(__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding())); 4.272 - k_RInfo = noreg; 4.273 + } else 4.274 + if (code == lir_checkcast) { 4.275 + Register obj = op->object()->as_register(); 4.276 + Register dst = op->result_opr()->as_register(); 4.277 + Label success; 4.278 + emit_typecheck_helper(op, &success, op->stub()->entry(), &success); 4.279 + __ bind(success); 4.280 + if (dst != obj) { 4.281 + __ mov(dst, obj); 4.282 + } 4.283 + } else 4.284 + if (code == lir_instanceof) { 4.285 + Register obj = op->object()->as_register(); 4.286 + Register dst = op->result_opr()->as_register(); 4.287 + Label success, failure, done; 4.288 + emit_typecheck_helper(op, &success, &failure, &failure); 4.289 + __ bind(failure); 4.290 + __ xorptr(dst, dst); 4.291 + __ jmpb(done); 4.292 + __ bind(success); 4.293 + __ movptr(dst, 1); 4.294 + __ bind(done); 4.295 } else { 4.296 - __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); 4.297 - 4.298 + ShouldNotReachHere(); 4.299 } 4.300 - __ jcc(Assembler::equal, one); 4.301 - } else { 4.302 - // get object class 4.303 - // not a safepoint as obj null check happens earlier 4.304 - __ cmpptr(obj, (int32_t)NULL_WORD); 4.305 - __ jcc(Assembler::equal, zero); 4.306 - __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); 4.307 - 4.308 -#ifndef _LP64 4.309 - if (k->is_loaded()) { 4.310 - // See if we get an immediate positive hit 4.311 - __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); 4.312 - __ jcc(Assembler::equal, one); 4.313 - if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() == k->super_check_offset()) { 4.314 - // check for self 4.315 - __ cmpoop(klass_RInfo, k->constant_encoding()); 4.316 - __ jcc(Assembler::equal, one); 4.317 - __ push(klass_RInfo); 4.318 - __ pushoop(k->constant_encoding()); 4.319 - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); 4.320 - __ pop(klass_RInfo); 4.321 - __ pop(dst); 4.322 - __ jmp(done); 4.323 - } 4.324 - } 4.325 - else // next block is unconditional if LP64: 4.326 -#endif // LP64 4.327 - { 4.328 - assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); 4.329 - 4.330 - // perform the fast part of the checking logic 4.331 - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, dst, &one, &zero, NULL); 4.332 - // call out-of-line instance of __ check_klass_subtype_slow_path(...): 4.333 - __ push(klass_RInfo); 4.334 - __ push(k_RInfo); 4.335 - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); 4.336 - __ pop(klass_RInfo); 4.337 - __ pop(dst); 4.338 - __ jmp(done); 4.339 - } 4.340 - } 4.341 - __ bind(zero); 4.342 - __ xorptr(dst, dst); 4.343 - __ jmp(done); 4.344 - __ bind(one); 4.345 - __ movptr(dst, 1); 4.346 - __ bind(done); 4.347 - } else { 4.348 - ShouldNotReachHere(); 4.349 - } 4.350 4.351 } 4.352
5.1 --- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Sat Sep 11 15:21:37 2010 -0700 5.2 +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Mon Sep 13 12:10:49 2010 -0700 5.3 @@ -1156,10 +1156,10 @@ 5.4 patching_info = state_for(x, x->state_before()); 5.5 } 5.6 obj.load_item(); 5.7 - LIR_Opr tmp = new_register(objectType); 5.8 __ instanceof(reg, obj.result(), x->klass(), 5.9 - tmp, new_register(objectType), LIR_OprFact::illegalOpr, 5.10 - x->direct_compare(), patching_info); 5.11 + new_register(objectType), new_register(objectType), 5.12 + !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr, 5.13 + x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci()); 5.14 } 5.15 5.16
6.1 --- a/src/share/vm/c1/c1_Canonicalizer.cpp Sat Sep 11 15:21:37 2010 -0700 6.2 +++ b/src/share/vm/c1/c1_Canonicalizer.cpp Mon Sep 13 12:10:49 2010 -0700 6.3 @@ -673,6 +673,8 @@ 6.4 } else if (l->as_InstanceOf() != NULL) { 6.5 // NOTE: Code permanently disabled for now since it leaves the old InstanceOf 6.6 // instruction in the graph (it is pinned). Need to fix this at some point. 6.7 + // It should also be left in the graph when generating a profiled method version or Goto 6.8 + // has to know that it was an InstanceOf. 6.9 return; 6.10 // pattern: If ((obj instanceof klass) cond rc) => simplify to: IfInstanceOf or: Goto 6.11 InstanceOf* inst = l->as_InstanceOf();
7.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Sat Sep 11 15:21:37 2010 -0700 7.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Mon Sep 13 12:10:49 2010 -0700 7.3 @@ -967,6 +967,17 @@ 7.4 StoreIndexed* result = new StoreIndexed(array, index, length, type, value, lock_stack()); 7.5 append(result); 7.6 _memory->store_value(value); 7.7 + 7.8 + if (type == T_OBJECT && is_profiling()) { 7.9 + // Note that we'd collect profile data in this method if we wanted it. 7.10 + compilation()->set_would_profile(true); 7.11 + 7.12 + if (profile_checkcasts()) { 7.13 + result->set_profiled_method(method()); 7.14 + result->set_profiled_bci(bci()); 7.15 + result->set_should_profile(true); 7.16 + } 7.17 + } 7.18 } 7.19 7.20 7.21 @@ -1852,6 +1863,17 @@ 7.22 InstanceOf* i = new InstanceOf(klass, apop(), state_before); 7.23 ipush(append_split(i)); 7.24 i->set_direct_compare(direct_compare(klass)); 7.25 + 7.26 + if (is_profiling()) { 7.27 + // Note that we'd collect profile data in this method if we wanted it. 7.28 + compilation()->set_would_profile(true); 7.29 + 7.30 + if (profile_checkcasts()) { 7.31 + i->set_profiled_method(method()); 7.32 + i->set_profiled_bci(bci()); 7.33 + i->set_should_profile(true); 7.34 + } 7.35 + } 7.36 } 7.37 7.38
8.1 --- a/src/share/vm/c1/c1_Instruction.hpp Sat Sep 11 15:21:37 2010 -0700 8.2 +++ b/src/share/vm/c1/c1_Instruction.hpp Mon Sep 13 12:10:49 2010 -0700 8.3 @@ -906,11 +906,13 @@ 8.4 private: 8.5 Value _value; 8.6 8.7 + ciMethod* _profiled_method; 8.8 + int _profiled_bci; 8.9 public: 8.10 // creation 8.11 StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* lock_stack) 8.12 : AccessIndexed(array, index, length, elt_type, lock_stack) 8.13 - , _value(value) 8.14 + , _value(value), _profiled_method(NULL), _profiled_bci(0) 8.15 { 8.16 set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object())); 8.17 set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object())); 8.18 @@ -923,7 +925,13 @@ 8.19 IRScope* scope() const; // the state's scope 8.20 bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); } 8.21 bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); } 8.22 - 8.23 + // Helpers for methodDataOop profiling 8.24 + void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } 8.25 + void set_profiled_method(ciMethod* method) { _profiled_method = method; } 8.26 + void set_profiled_bci(int bci) { _profiled_bci = bci; } 8.27 + bool should_profile() const { return check_flag(ProfileMDOFlag); } 8.28 + ciMethod* profiled_method() const { return _profiled_method; } 8.29 + int profiled_bci() const { return _profiled_bci; } 8.30 // generic 8.31 virtual void input_values_do(ValueVisitor* f) { AccessIndexed::input_values_do(f); f->visit(&_value); } 8.32 }; 8.33 @@ -1297,9 +1305,14 @@ 8.34 Value _obj; 8.35 ValueStack* _state_before; 8.36 8.37 + ciMethod* _profiled_method; 8.38 + int _profiled_bci; 8.39 + 8.40 public: 8.41 // creation 8.42 - TypeCheck(ciKlass* klass, Value obj, ValueType* type, ValueStack* state_before) : StateSplit(type), _klass(klass), _obj(obj), _state_before(state_before) { 8.43 + TypeCheck(ciKlass* klass, Value obj, ValueType* type, ValueStack* state_before) 8.44 + : StateSplit(type), _klass(klass), _obj(obj), _state_before(state_before), 8.45 + _profiled_method(NULL), _profiled_bci(0) { 8.46 ASSERT_VALUES 8.47 set_direct_compare(false); 8.48 } 8.49 @@ -1318,20 +1331,22 @@ 8.50 virtual bool can_trap() const { return true; } 8.51 virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_obj); } 8.52 virtual void other_values_do(ValueVisitor* f); 8.53 + 8.54 + // Helpers for methodDataOop profiling 8.55 + void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } 8.56 + void set_profiled_method(ciMethod* method) { _profiled_method = method; } 8.57 + void set_profiled_bci(int bci) { _profiled_bci = bci; } 8.58 + bool should_profile() const { return check_flag(ProfileMDOFlag); } 8.59 + ciMethod* profiled_method() const { return _profiled_method; } 8.60 + int profiled_bci() const { return _profiled_bci; } 8.61 }; 8.62 8.63 8.64 LEAF(CheckCast, TypeCheck) 8.65 - private: 8.66 - ciMethod* _profiled_method; 8.67 - int _profiled_bci; 8.68 - 8.69 public: 8.70 // creation 8.71 CheckCast(ciKlass* klass, Value obj, ValueStack* state_before) 8.72 - : TypeCheck(klass, obj, objectType, state_before) 8.73 - , _profiled_method(NULL) 8.74 - , _profiled_bci(0) {} 8.75 + : TypeCheck(klass, obj, objectType, state_before) {} 8.76 8.77 void set_incompatible_class_change_check() { 8.78 set_flag(ThrowIncompatibleClassChangeErrorFlag, true); 8.79 @@ -1340,17 +1355,8 @@ 8.80 return check_flag(ThrowIncompatibleClassChangeErrorFlag); 8.81 } 8.82 8.83 - // Helpers for methodDataOop profiling 8.84 - void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } 8.85 - void set_profiled_method(ciMethod* method) { _profiled_method = method; } 8.86 - void set_profiled_bci(int bci) { _profiled_bci = bci; } 8.87 - bool should_profile() const { return check_flag(ProfileMDOFlag); } 8.88 - ciMethod* profiled_method() const { return _profiled_method; } 8.89 - int profiled_bci() const { return _profiled_bci; } 8.90 - 8.91 ciType* declared_type() const; 8.92 ciType* exact_type() const; 8.93 - 8.94 }; 8.95 8.96
9.1 --- a/src/share/vm/c1/c1_LIR.cpp Sat Sep 11 15:21:37 2010 -0700 9.2 +++ b/src/share/vm/c1/c1_LIR.cpp Mon Sep 13 12:10:49 2010 -0700 9.3 @@ -1019,11 +1019,7 @@ 9.4 } 9.5 9.6 void LIR_OpTypeCheck::emit_code(LIR_Assembler* masm) { 9.7 - if (code() == lir_checkcast) { 9.8 - masm->emit_checkcast(this); 9.9 - } else { 9.10 - masm->emit_opTypeCheck(this); 9.11 - } 9.12 + masm->emit_opTypeCheck(this); 9.13 if (stub()) { 9.14 masm->emit_code_stub(stub()); 9.15 } 9.16 @@ -1380,8 +1376,14 @@ 9.17 append(c); 9.18 } 9.19 9.20 -void LIR_List::instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch) { 9.21 - append(new LIR_OpTypeCheck(lir_instanceof, result, object, klass, tmp1, tmp2, tmp3, fast_check, NULL, info_for_patch, NULL)); 9.22 +void LIR_List::instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch, ciMethod* profiled_method, int profiled_bci) { 9.23 + LIR_OpTypeCheck* c = new LIR_OpTypeCheck(lir_instanceof, result, object, klass, tmp1, tmp2, tmp3, fast_check, NULL, info_for_patch, NULL); 9.24 + if (profiled_method != NULL) { 9.25 + c->set_profiled_method(profiled_method); 9.26 + c->set_profiled_bci(profiled_bci); 9.27 + c->set_should_profile(true); 9.28 + } 9.29 + append(c); 9.30 } 9.31 9.32
10.1 --- a/src/share/vm/c1/c1_LIR.hpp Sat Sep 11 15:21:37 2010 -0700 10.2 +++ b/src/share/vm/c1/c1_LIR.hpp Mon Sep 13 12:10:49 2010 -0700 10.3 @@ -2041,7 +2041,7 @@ 10.4 10.5 void fpop_raw() { append(new LIR_Op0(lir_fpop_raw)); } 10.6 10.7 - void instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch); 10.8 + void instanceof(LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_patch, ciMethod* profiled_method, int profiled_bci); 10.9 void store_check(LIR_Opr object, LIR_Opr array, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, CodeEmitInfo* info_for_exception); 10.10 10.11 void checkcast (LIR_Opr result, LIR_Opr object, ciKlass* klass,
11.1 --- a/src/share/vm/c1/c1_LIRAssembler.hpp Sat Sep 11 15:21:37 2010 -0700 11.2 +++ b/src/share/vm/c1/c1_LIRAssembler.hpp Mon Sep 13 12:10:49 2010 -0700 11.3 @@ -187,7 +187,7 @@ 11.4 void emit_alloc_obj(LIR_OpAllocObj* op); 11.5 void emit_alloc_array(LIR_OpAllocArray* op); 11.6 void emit_opTypeCheck(LIR_OpTypeCheck* op); 11.7 - void emit_checkcast(LIR_OpTypeCheck* op); 11.8 + void emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null); 11.9 void emit_compare_and_swap(LIR_OpCompareAndSwap* op); 11.10 void emit_lock(LIR_OpLock* op); 11.11 void emit_call(LIR_OpJavaCall* op);