< prev index next >
src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
Print this page
rev 8961 : [mq]: diff-shenandoah.patch
@@ -30,10 +30,11 @@
#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/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,10 +1465,59 @@
}
__ 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, -8));
+
+ __ 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,15 +2010,48 @@
// 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 >