< 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 >