< prev index next >

src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp

Print this page

        

@@ -399,10 +399,57 @@
 #ifndef _LP64
   __ pop(thread);
 #endif
 }
 
+// ((WeakHandle)result).peek();
+void ShenandoahBarrierSetAssembler::peek_weak_handle(MacroAssembler* masm, Register rresult, Register rtmp) {
+  assert_different_registers(rresult, rtmp);
+  Label resolved;
+
+  // A null weak handle resolves to null.
+  __ cmpptr(rresult, 0);
+  __ jcc(Assembler::equal, resolved);
+
+  // Only 64 bit platforms support GCs that require a tmp register
+  // Only IN_HEAP loads require a thread_tmp register
+  // WeakHandle::peek is an indirection like jweak.
+  __ access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE,
+                 rresult, Address(rresult, 0), rtmp, /*tmp_thread*/noreg);
+  __ bind(resolved);
+}
+
+void ShenandoahBarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
+  BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod();
+  if (bs == NULL) {
+    return;
+  }
+
+  Label bad_call;
+  __ cmpptr(rbx, 0); // rbx contains the incoming method for c2i adapters.
+  __ jcc(Assembler::equal, bad_call);
+
+  // Pointer chase to the method holder to find out if the method is concurrently unloading.
+  Label method_live;
+  __ load_method_holder_cld(rscratch1, rbx);
+
+  // Is it a strong CLD?
+  __ movl(rscratch2, Address(rscratch1, ClassLoaderData::keep_alive_offset()));
+  __ cmpptr(rscratch2, 0);
+  __ jcc(Assembler::greater, method_live);
+
+  // Is it a weak but alive CLD?
+  __ movptr(rscratch1, Address(rscratch1, ClassLoaderData::holder_offset()));
+  peek_weak_handle(masm, rscratch1, rscratch2);
+  __ cmpptr(rscratch1, 0);
+  __ jcc(Assembler::notEqual, method_live);
+
+  __ bind(bad_call);
+  __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+  __ bind(method_live);
+}
+
 void ShenandoahBarrierSetAssembler::load_reference_barrier_native(MacroAssembler* masm, Register dst) {
   if (!ShenandoahLoadRefBarrier) {
     return;
   }
 

@@ -786,12 +833,14 @@
   ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
   __ bind(*stub->entry());
 
   Register obj = stub->obj()->as_register();
   Register res = stub->result()->as_register();
+  Register addr = stub->addr()->as_register();
   Register tmp1 = stub->tmp1()->as_register();
   Register tmp2 = stub->tmp2()->as_register();
+  assert_different_registers(obj, res, addr, tmp1, tmp2);
 
   Label slow_path;
 
   assert(res == rax, "result must arrive in rax");
 

@@ -816,33 +865,13 @@
   __ movptr(tmp2, Address(tmp2, tmp1, Address::times_1));
   __ testptr(tmp2, 0xFF);
 #endif
   __ jcc(Assembler::zero, *stub->continuation());
 
-  // Test if object is resolved.
-  __ movptr(tmp1, Address(res, oopDesc::mark_offset_in_bytes()));
-  // Test if both lowest bits are set. We trick it by negating the bits
-  // then test for both bits clear.
-  __ notptr(tmp1);
-#ifdef _LP64
-  __ testb(tmp1, markOopDesc::marked_value);
-#else
-  // On x86_32, C1 register allocator can give us the register without 8-bit support.
-  // Do the full-register access and test to avoid compilation failures.
-  __ testptr(tmp1, markOopDesc::marked_value);
-#endif
-  __ jccb(Assembler::notZero, slow_path);
-  // Clear both lower bits. It's still inverted, so set them, and then invert back.
-  __ orptr(tmp1, markOopDesc::marked_value);
-  __ notptr(tmp1);
-  // At this point, tmp1 contains the decoded forwarding pointer.
-  __ mov(res, tmp1);
-
-  __ jmp(*stub->continuation());
-
   __ bind(slow_path);
   ce->store_parameter(res, 0);
+  ce->store_parameter(addr, 1);
   __ call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin()));
 
   __ jmp(*stub->continuation());
 }
 

@@ -909,12 +938,25 @@
 void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) {
   __ prologue("shenandoah_load_reference_barrier", false);
   // arg0 : object to be resolved
 
   __ save_live_registers_no_oop_map(true);
-  __ load_parameter(0, LP64_ONLY(c_rarg0) NOT_LP64(rax));
-  __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier), LP64_ONLY(c_rarg0) NOT_LP64(rax));
+
+#ifdef _LP64
+  __ load_parameter(0, c_rarg0);
+  __ load_parameter(1, c_rarg1);
+  if (UseCompressedOops) {
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_fixup_narrow), c_rarg0, c_rarg1);
+  } else {
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_fixup), c_rarg0, c_rarg1);
+  }
+#else
+  __ load_parameter(0, rax);
+  __ load_parameter(1, rbx);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_fixup), rax, rbx);
+#endif
+
   __ restore_live_registers_except_rax(true);
 
   __ epilogue();
 }
 
< prev index next >