Mercurial > hg > graal-jvmci-8
diff src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @ 1783:d5d065957597
6953144: Tiered compilation
Summary: Infrastructure for tiered compilation support (interpreter + c1 + c2) for 32 and 64 bit. Simple tiered policy implementation.
Reviewed-by: kvn, never, phh, twisti
author | iveresov |
---|---|
date | Fri, 03 Sep 2010 17:51:07 -0700 |
parents | e9ff18c4ace7 |
children | 7f9553bedfd5 |
line wrap: on
line diff
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Sep 02 11:40:02 2010 -0700 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Sep 03 17:51:07 2010 -0700 @@ -1613,7 +1613,194 @@ __ bind(*op->stub()->continuation()); } - +void LIR_Assembler::type_profile_helper(Register mdo, + ciMethodData *md, ciProfileData *data, + Register recv, Label* update_done) { + uint i; + for (i = 0; i < ReceiverTypeData::row_limit(); i++) { + Label next_test; + // See if the receiver is receiver[n]. + __ cmpptr(recv, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)))); + __ jccb(Assembler::notEqual, next_test); + Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); + __ addptr(data_addr, DataLayout::counter_increment); + __ jmpb(*update_done); + __ bind(next_test); + } + + // Didn't find receiver; find next empty slot and fill it in + for (i = 0; i < ReceiverTypeData::row_limit(); i++) { + Label next_test; + Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))); + __ cmpptr(recv_addr, (intptr_t)NULL_WORD); + __ jccb(Assembler::notEqual, next_test); + __ movptr(recv_addr, recv); + __ movptr(Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))), DataLayout::counter_increment); + __ jmpb(*update_done); + __ bind(next_test); + } +} + +void LIR_Assembler::emit_checkcast(LIR_OpTypeCheck *op) { + assert(op->code() == lir_checkcast, "Invalid operation"); + // we always need a stub for the failure case. + CodeStub* stub = op->stub(); + Register obj = op->object()->as_register(); + Register k_RInfo = op->tmp1()->as_register(); + Register klass_RInfo = op->tmp2()->as_register(); + Register dst = op->result_opr()->as_register(); + ciKlass* k = op->klass(); + Register Rtmp1 = noreg; + + // check if it needs to be profiled + ciMethodData* md; + ciProfileData* data; + + if (op->should_profile()) { + ciMethod* method = op->profiled_method(); + assert(method != NULL, "Should have method"); + int bci = op->profiled_bci(); + md = method->method_data(); + if (md == NULL) { + bailout("out of memory building methodDataOop"); + return; + } + data = md->bci_to_data(bci); + assert(data != NULL, "need data for checkcast"); + assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for checkcast"); + } + Label profile_cast_failure; + + Label done, done_null; + // Where to go in case of cast failure + Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); + + if (obj == k_RInfo) { + k_RInfo = dst; + } else if (obj == klass_RInfo) { + klass_RInfo = dst; + } + if (k->is_loaded()) { + select_different_registers(obj, dst, k_RInfo, klass_RInfo); + } else { + Rtmp1 = op->tmp3()->as_register(); + select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); + } + + assert_different_registers(obj, k_RInfo, klass_RInfo); + if (!k->is_loaded()) { + jobject2reg_with_patching(k_RInfo, op->info_for_patch()); + } else { +#ifdef _LP64 + __ movoop(k_RInfo, k->constant_encoding()); +#endif // _LP64 + } + assert(obj != k_RInfo, "must be different"); + + __ cmpptr(obj, (int32_t)NULL_WORD); + if (op->should_profile()) { + Label profile_done; + __ jccb(Assembler::notEqual, profile_done); + // Object is null; update methodDataOop + Register mdo = klass_RInfo; + __ movoop(mdo, md->constant_encoding()); + Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); + int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); + __ orl(data_addr, header_bits); + __ jmp(done_null); + __ bind(profile_done); + } else { + __ jcc(Assembler::equal, done_null); + } + __ verify_oop(obj); + + if (op->fast_check()) { + // get object classo + // not a safepoint as obj null check happens earlier + if (k->is_loaded()) { +#ifdef _LP64 + __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); +#else + __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); +#endif // _LP64 + } else { + __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); + } + __ jcc(Assembler::notEqual, *failure_target); + } else { + // get object class + // not a safepoint as obj null check happens earlier + __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); + if (k->is_loaded()) { + // See if we get an immediate positive hit +#ifdef _LP64 + __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset())); +#else + __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); +#endif // _LP64 + if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { + __ jcc(Assembler::notEqual, *failure_target); + } else { + // See if we get an immediate positive hit + __ jcc(Assembler::equal, done); + // check for self +#ifdef _LP64 + __ cmpptr(klass_RInfo, k_RInfo); +#else + __ cmpoop(klass_RInfo, k->constant_encoding()); +#endif // _LP64 + __ jcc(Assembler::equal, done); + + __ push(klass_RInfo); +#ifdef _LP64 + __ push(k_RInfo); +#else + __ pushoop(k->constant_encoding()); +#endif // _LP64 + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + __ pop(klass_RInfo); + __ pop(klass_RInfo); + // result is a boolean + __ cmpl(klass_RInfo, 0); + __ jcc(Assembler::equal, *failure_target); + } + } else { + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, failure_target, NULL); + // call out-of-line instance of __ check_klass_subtype_slow_path(...): + __ push(klass_RInfo); + __ push(k_RInfo); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + __ pop(klass_RInfo); + __ pop(k_RInfo); + // result is a boolean + __ cmpl(k_RInfo, 0); + __ jcc(Assembler::equal, *failure_target); + } + } + __ bind(done); + + if (op->should_profile()) { + Register mdo = klass_RInfo, recv = k_RInfo; + __ movoop(mdo, md->constant_encoding()); + __ movptr(recv, Address(obj, oopDesc::klass_offset_in_bytes())); + Label update_done; + type_profile_helper(mdo, md, data, recv, &update_done); + __ jmpb(update_done); + + __ bind(profile_cast_failure); + __ movoop(mdo, md->constant_encoding()); + Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); + __ subptr(counter_addr, DataLayout::counter_increment); + __ jmp(*stub->entry()); + + __ bind(update_done); + } + __ bind(done_null); + if (dst != obj) { + __ mov(dst, obj); + } +} void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { LIR_Code code = op->code(); @@ -1646,140 +1833,6 @@ __ cmpl(k_RInfo, 0); __ jcc(Assembler::equal, *stub->entry()); __ bind(done); - } else if (op->code() == lir_checkcast) { - // we always need a stub for the failure case. - CodeStub* stub = op->stub(); - Register obj = op->object()->as_register(); - Register k_RInfo = op->tmp1()->as_register(); - Register klass_RInfo = op->tmp2()->as_register(); - Register dst = op->result_opr()->as_register(); - ciKlass* k = op->klass(); - Register Rtmp1 = noreg; - - Label done; - if (obj == k_RInfo) { - k_RInfo = dst; - } else if (obj == klass_RInfo) { - klass_RInfo = dst; - } - if (k->is_loaded()) { - select_different_registers(obj, dst, k_RInfo, klass_RInfo); - } else { - Rtmp1 = op->tmp3()->as_register(); - select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); - } - - assert_different_registers(obj, k_RInfo, klass_RInfo); - if (!k->is_loaded()) { - jobject2reg_with_patching(k_RInfo, op->info_for_patch()); - } else { -#ifdef _LP64 - __ movoop(k_RInfo, k->constant_encoding()); -#else - k_RInfo = noreg; -#endif // _LP64 - } - assert(obj != k_RInfo, "must be different"); - __ cmpptr(obj, (int32_t)NULL_WORD); - if (op->profiled_method() != NULL) { - ciMethod* method = op->profiled_method(); - int bci = op->profiled_bci(); - - Label profile_done; - __ jcc(Assembler::notEqual, profile_done); - // Object is null; update methodDataOop - ciMethodData* md = method->method_data(); - if (md == NULL) { - bailout("out of memory building methodDataOop"); - return; - } - ciProfileData* data = md->bci_to_data(bci); - assert(data != NULL, "need data for checkcast"); - assert(data->is_BitData(), "need BitData for checkcast"); - Register mdo = klass_RInfo; - __ movoop(mdo, md->constant_encoding()); - Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); - int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); - __ orl(data_addr, header_bits); - __ jmp(done); - __ bind(profile_done); - } else { - __ jcc(Assembler::equal, done); - } - __ verify_oop(obj); - - if (op->fast_check()) { - // get object classo - // not a safepoint as obj null check happens earlier - if (k->is_loaded()) { -#ifdef _LP64 - __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); -#else - __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); -#endif // _LP64 - } else { - __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); - - } - __ jcc(Assembler::notEqual, *stub->entry()); - __ bind(done); - } else { - // get object class - // not a safepoint as obj null check happens earlier - __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); - if (k->is_loaded()) { - // See if we get an immediate positive hit -#ifdef _LP64 - __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset())); -#else - __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); -#endif // _LP64 - if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { - __ jcc(Assembler::notEqual, *stub->entry()); - } else { - // See if we get an immediate positive hit - __ jcc(Assembler::equal, done); - // check for self -#ifdef _LP64 - __ cmpptr(klass_RInfo, k_RInfo); -#else - __ cmpoop(klass_RInfo, k->constant_encoding()); -#endif // _LP64 - __ jcc(Assembler::equal, done); - - __ push(klass_RInfo); -#ifdef _LP64 - __ push(k_RInfo); -#else - __ pushoop(k->constant_encoding()); -#endif // _LP64 - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); - __ pop(klass_RInfo); - __ pop(klass_RInfo); - // result is a boolean - __ cmpl(klass_RInfo, 0); - __ jcc(Assembler::equal, *stub->entry()); - } - __ bind(done); - } else { - // perform the fast part of the checking logic - __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL); - // call out-of-line instance of __ check_klass_subtype_slow_path(...): - __ push(klass_RInfo); - __ push(k_RInfo); - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); - __ pop(klass_RInfo); - __ pop(k_RInfo); - // result is a boolean - __ cmpl(k_RInfo, 0); - __ jcc(Assembler::equal, *stub->entry()); - __ bind(done); - } - - } - if (dst != obj) { - __ mov(dst, obj); - } } else if (code == lir_instanceof) { Register obj = op->object()->as_register(); Register k_RInfo = op->tmp1()->as_register(); @@ -1922,7 +1975,6 @@ } } - void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { Assembler::Condition acond, ncond; switch (condition) { @@ -3253,13 +3305,13 @@ // Perform additional virtual call profiling for invokevirtual and // invokeinterface bytecodes if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) && - Tier1ProfileVirtualCalls) { + C1ProfileVirtualCalls) { assert(op->recv()->is_single_cpu(), "recv must be allocated"); Register recv = op->recv()->as_register(); assert_different_registers(mdo, recv); assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls"); ciKlass* known_klass = op->known_holder(); - if (Tier1OptimizeVirtualCallProfiling && known_klass != NULL) { + if (C1OptimizeVirtualCallProfiling && known_klass != NULL) { // We know the type that will be seen at this call site; we can // statically update the methodDataOop rather than needing to do // dynamic tests on the receiver type @@ -3272,7 +3324,7 @@ ciKlass* receiver = vc_data->receiver(i); if (known_klass->equals(receiver)) { Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); - __ addl(data_addr, DataLayout::counter_increment); + __ addptr(data_addr, DataLayout::counter_increment); return; } } @@ -3288,49 +3340,26 @@ Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); __ movoop(recv_addr, known_klass->constant_encoding()); Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); - __ addl(data_addr, DataLayout::counter_increment); + __ addptr(data_addr, DataLayout::counter_increment); return; } } } else { __ movptr(recv, Address(recv, oopDesc::klass_offset_in_bytes())); Label update_done; - uint i; - for (i = 0; i < VirtualCallData::row_limit(); i++) { - Label next_test; - // See if the receiver is receiver[n]. - __ cmpptr(recv, Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)))); - __ jcc(Assembler::notEqual, next_test); - Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); - __ addl(data_addr, DataLayout::counter_increment); - __ jmp(update_done); - __ bind(next_test); - } - - // Didn't find receiver; find next empty slot and fill it in - for (i = 0; i < VirtualCallData::row_limit(); i++) { - Label next_test; - Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); - __ cmpptr(recv_addr, (int32_t)NULL_WORD); - __ jcc(Assembler::notEqual, next_test); - __ movptr(recv_addr, recv); - __ movl(Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))), DataLayout::counter_increment); - __ jmp(update_done); - __ bind(next_test); - } + type_profile_helper(mdo, md, data, recv, &update_done); // Receiver did not match any saved receiver and there is no empty row for it. // Increment total counter to indicate polymorphic case. - __ addl(counter_addr, DataLayout::counter_increment); + __ addptr(counter_addr, DataLayout::counter_increment); __ bind(update_done); } } else { // Static call - __ addl(counter_addr, DataLayout::counter_increment); + __ addptr(counter_addr, DataLayout::counter_increment); } } - void LIR_Assembler::emit_delay(LIR_OpDelay*) { Unimplemented(); }