--- old/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp 2015-10-14 13:53:36.288806642 +0200 +++ new/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp 2015-10-14 13:53:36.185809132 +0200 @@ -32,6 +32,8 @@ #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" @@ -1466,6 +1468,55 @@ } } +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(); @@ -1962,10 +2013,43 @@ } else #endif { - if (os::is_MP()) { - __ lock(); + 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)); } - __ cmpxchgptr(newval, Address(addr, 0)); } } else { assert(op->code() == lir_cas_int, "lir_cas_int expected");