< prev index next >

src/cpu/x86/vm/c1_LIRAssembler_x86.cpp

Print this page

        

*** 30,39 **** --- 30,41 ---- #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" #include "c1/c1_ValueStack.hpp" #include "ci/ciArrayKlass.hpp" #include "ci/ciInstance.hpp" + #include "gc/shenandoah/brooksPointer.hpp" + #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/cardTableModRefBS.hpp" #include "gc/shared/collectedHeap.hpp" #include "nativeInst_x86.hpp" #include "oops/objArrayKlass.hpp"
*** 1464,1473 **** --- 1466,1524 ---- } __ jcc(acond,*(op->label())); } } + void LIR_Assembler::emit_opShenandoahWriteBarrier(LIR_OpShenandoahWriteBarrier* op) { + Label done; + Register obj = op->in_opr()->as_register(); + Register res = op->result_opr()->as_register(); + Register tmp1 = op->tmp1_opr()->as_register(); + Register tmp2 = op->tmp2_opr()->as_register(); + assert_different_registers(res, tmp1, tmp2); + + if (res != obj) { + __ mov(res, obj); + } + + // Check for null. + if (op->need_null_check()) { + __ testptr(res, res); + __ jcc(Assembler::zero, done); + } + + // Check for evacuation-in-progress + Address evacuation_in_progress = Address(r15_thread, in_bytes(JavaThread::evacuation_in_progress_offset())); + __ cmpb(evacuation_in_progress, 0); + + // The read-barrier. + __ movptr(res, Address(res, BrooksPointer::BYTE_OFFSET)); + + __ jcc(Assembler::equal, done); + + // Check for object in collection set. + __ movptr(tmp1, res); + __ shrptr(tmp1, ShenandoahHeapRegion::RegionSizeShift); + __ movptr(tmp2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr()); + __ movbool(tmp2, Address(tmp2, tmp1, Address::times_1)); + __ testb(tmp2, 0x1); + __ jcc(Assembler::zero, done); + + if (res != rax) { + __ xchgptr(res, rax); // Move obj into rax and save rax into obj. + } + + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::shenandoah_write_barrier_slow_id))); + + if (res != rax) { + __ xchgptr(rax, res); // Swap back obj with rax. + } + + __ bind(done); + + } + void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { LIR_Opr src = op->in_opr(); LIR_Opr dest = op->result_opr(); switch (op->bytecode()) {
*** 1960,1974 **** --- 2011,2058 ---- // cmpval (rax) is implicitly used by this instruction __ cmpxchgl(rscratch1, Address(addr, 0)); } else #endif { + if (UseShenandoahGC) { + Label done; + Label retry; + + __ bind(retry); + + // Save original cmp-value into tmp1, before following cas destroys it. + __ movptr(op->tmp1()->as_register(), op->cmp_value()->as_register()); + + if (os::is_MP()) { + __ lock(); + } + __ cmpxchgptr(newval, Address(addr, 0)); + + // If the cmpxchg succeeded, then we're done. + __ jcc(Assembler::equal, done); + + // Resolve the original cmp value. + oopDesc::bs()->interpreter_read_barrier(masm(), op->tmp1()->as_register()); + // Resolve the old value at address. We get the old value in cmp/rax + // when the comparison in cmpxchg failed. + __ movptr(op->tmp2()->as_register(), cmpval); + oopDesc::bs()->interpreter_read_barrier(masm(), op->tmp2()->as_register()); + + // We're done if the expected/cmp value is not the same as old. It's a valid + // cmpxchg failure then. Otherwise we need special treatment for Shenandoah + // to prevent false positives. + __ cmpptr(op->tmp1()->as_register(), op->tmp2()->as_register()); + __ jcc(Assembler::equal, retry); + + __ bind(done); + } else { if (os::is_MP()) { __ lock(); } __ cmpxchgptr(newval, Address(addr, 0)); } + } } else { assert(op->code() == lir_cas_int, "lir_cas_int expected"); if (os::is_MP()) { __ lock(); }
< prev index next >