--- old/src/share/vm/c1/c1_LIRGenerator.cpp 2011-03-28 10:10:09.804902000 -0700 +++ new/src/share/vm/c1/c1_LIRGenerator.cpp 2011-03-28 10:10:09.582810000 -0700 @@ -1104,6 +1104,38 @@ set_no_result(x); } +// Examble: ref.get() +// Combination of LoadField and g1 pre-write barrier +void LIRGenerator::do_Reference_get(Intrinsic* x) { + + const int referent_offset = java_lang_ref_Reference::referent_offset; + guarantee(referent_offset > 0, "referent offset not initialized"); + + assert(x->number_of_arguments() == 1, "wrong type"); + + LIRItem reference(x->argument_at(0), this); + reference.load_item(); + + // need to perform the null check on the reference objecy + CodeEmitInfo* info = NULL; + if (x->needs_null_check()) { + info = state_for(x); + } + + LIR_Address* referent_field_adr = + new LIR_Address(reference.result(), referent_offset, T_OBJECT); + + LIR_Opr result = rlock_result(x); + + __ load(referent_field_adr, result, info); + + // Register the value in the referent field with the pre-barrier + pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, + result /* pre_val */, + false /* do_load */, + false /* patch */, + NULL /* info */); +} // Example: object.getClass () void LIRGenerator::do_getClass(Intrinsic* x) { @@ -1246,13 +1278,14 @@ // Various barriers -void LIRGenerator::pre_barrier(LIR_Opr addr_opr, bool patch, CodeEmitInfo* info) { +void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, + bool do_load, bool patch, CodeEmitInfo* info) { // Do the pre-write barrier, if any. switch (_bs->kind()) { #ifndef SERIALGC case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: - G1SATBCardTableModRef_pre_barrier(addr_opr, patch, info); + G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info); break; #endif // SERIALGC case BarrierSet::CardTableModRef: @@ -1293,9 +1326,8 @@ //////////////////////////////////////////////////////////////////////// #ifndef SERIALGC -void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, bool patch, CodeEmitInfo* info) { - if (G1DisablePreBarrier) return; - +void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, + bool do_load, bool patch, CodeEmitInfo* info) { // First we test whether marking is in progress. BasicType flag_type; if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { @@ -1314,26 +1346,40 @@ // Read the marking-in-progress flag. LIR_Opr flag_val = new_register(T_INT); __ load(mark_active_flag_addr, flag_val); + __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); - LIR_PatchCode pre_val_patch_code = - patch ? lir_patch_normal : lir_patch_none; + LIR_PatchCode pre_val_patch_code = lir_patch_none; - LIR_Opr pre_val = new_register(T_OBJECT); + CodeStub* slow; - __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); - if (!addr_opr->is_address()) { - assert(addr_opr->is_register(), "must be"); - addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT)); + if (do_load) { + assert(pre_val == LIR_OprFact::illegalOpr, "sanity"); + assert(addr_opr != LIR_OprFact::illegalOpr, "sanity"); + + if (patch) + pre_val_patch_code = lir_patch_normal; + + pre_val = new_register(T_OBJECT); + + if (!addr_opr->is_address()) { + assert(addr_opr->is_register(), "must be"); + addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT)); + } + slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info); + } else { + assert(addr_opr == LIR_OprFact::illegalOpr, "sanity"); + assert(pre_val->is_register(), "must be"); + assert(pre_val->type() == T_OBJECT, "must be an object"); + assert(info == NULL, "sanity"); + + slow = new G1PreBarrierStub(pre_val); } - CodeStub* slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, - info); + __ branch(lir_cond_notEqual, T_INT, slow); __ branch_destination(slow->continuation()); } void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { - if (G1DisablePostBarrier) return; - // If the "new_val" is a constant NULL, no barrier is necessary. if (new_val->is_constant() && new_val->as_constant_ptr()->as_jobject() == NULL) return; @@ -1555,6 +1601,8 @@ if (is_oop) { // Do the pre-write barrier, if any. pre_barrier(LIR_OprFact::address(address), + LIR_OprFact::illegalOpr /* pre_val */, + true /* do_load*/, needs_patching, (info ? new CodeEmitInfo(info) : NULL)); } @@ -1984,9 +2032,54 @@ off.load_item(); src.load_item(); - LIR_Opr reg = reg = rlock_result(x, x->basic_type()); + LIR_Opr reg = rlock_result(x, x->basic_type()); get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile()); + + // We might be reading the value of the referent field of a + // Reference object in order to attach it back to the live + // object graph. If G1 is enabled then we need to record + // the value that is being returned in to an SATB log + // buffer. + // We need to generate code similar to the following... + // + // if (offset == java_lang_ref_Reference::referent_offset) { + // if (src != NULL) { + // if (klass(src)->reference_type() != REF_NONE) { + // pre_barrier(..., reg, ...); + // } + // } + // } + if (UseG1GC && type == T_OBJECT) { + LabelObj* L = new LabelObj(); + + __ cmp(lir_cond_notEqual, off.result(), + LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset)); + __ branch(lir_cond_notEqual, L->label()); + + __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL)); + __ branch(lir_cond_equal, L->label()); + + LIR_Opr klass = new_register(T_OBJECT); + __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), klass); + + LIR_Opr ref_typ = new_register(T_INT); + int ref_type_offset = instanceKlass::reference_type_offset_in_bytes() + + sizeof(oopDesc); + + __ move(new LIR_Address(klass, ref_type_offset, T_INT), ref_typ); + __ cmp(lir_cond_equal, ref_typ, LIR_OprFact::intConst(REF_NONE)); + __ branch(lir_cond_equal, L->label()); + + pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, + reg /* pre_val */, + false /* do_load */, + false /* patch */, + NULL /* info */); + + __ branch_destination(L->label()); + } + if (x->is_volatile() && os::is_MP()) __ membar_acquire(); } @@ -2652,6 +2745,10 @@ do_AttemptUpdate(x); break; + case vmIntrinsics::_Reference_get: + do_Reference_get(x); + break; + default: ShouldNotReachHere(); break; } }