8227635: Shenandoah: SHBSA::load_at() needs to deal IN_NATIVE load
Reviewed-by: rkennke, roland
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Wed Jul 17 04:33:37 2019 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Sat Jul 13 12:14:24 2019 -0400
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
#include "gc/shenandoah/shenandoahForwarding.hpp"
-#include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahHeapRegion.hpp"
#include "gc/shenandoah/shenandoahHeuristics.hpp"
#include "gc/shenandoah/shenandoahRuntime.hpp"
@@ -282,6 +282,40 @@
__ leave();
}
+void ShenandoahBarrierSetAssembler::load_reference_barrier_native(MacroAssembler* masm, Register dst, Register tmp) {
+ if (!ShenandoahLoadRefBarrier) {
+ return;
+ }
+
+ assert(dst != rscratch2, "need rscratch2");
+
+ Label is_null;
+ Label done;
+
+ __ cbz(dst, is_null);
+
+ __ enter();
+
+ Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+ __ ldrb(rscratch2, gc_state);
+
+ // Check for heap in evacuation phase
+ __ tbz(rscratch2, ShenandoahHeap::EVACUATION_BITPOS, done);
+
+ __ mov(rscratch2, dst);
+ __ push_call_clobbered_registers();
+ __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native));
+ __ mov(r0, rscratch2);
+ __ blrt(lr, 1, 0, MacroAssembler::ret_type_integral);
+ __ mov(rscratch2, r0);
+ __ pop_call_clobbered_registers();
+ __ mov(dst, rscratch2);
+
+ __ bind(done);
+ __ leave();
+ __ bind(is_null);
+}
+
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
if (ShenandoahStoreValEnqueueBarrier) {
// Save possibly live regs.
@@ -309,15 +343,25 @@
void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register dst, Address src, Register tmp1, Register tmp_thread) {
bool on_oop = type == T_OBJECT || type == T_ARRAY;
+ bool not_in_heap = (decorators & IN_NATIVE) != 0;
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
bool on_reference = on_weak || on_phantom;
+ bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
if (on_oop) {
- load_reference_barrier(masm, dst, tmp1);
-
- if (ShenandoahKeepAliveBarrier && on_reference) {
+ if (not_in_heap) {
+ if (ShenandoahHeap::heap()->is_traversal_mode()) {
+ load_reference_barrier(masm, dst, tmp1);
+ keep_alive = true;
+ } else {
+ load_reference_barrier_native(masm, dst, tmp1);
+ }
+ } else {
+ load_reference_barrier(masm, dst, tmp1);
+ }
+ if (ShenandoahKeepAliveBarrier && on_reference && keep_alive) {
__ enter();
satb_write_barrier_pre(masm /* masm */,
noreg /* obj */,
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Wed Jul 17 04:33:37 2019 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Sat Jul 13 12:14:24 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
@@ -58,6 +58,7 @@
void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg);
void load_reference_barrier(MacroAssembler* masm, Register dst, Register tmp);
void load_reference_barrier_not_null(MacroAssembler* masm, Register dst, Register tmp);
+ void load_reference_barrier_native(MacroAssembler* masm, Register dst, Register tmp);
address generate_shenandoah_lrb(StubCodeGenerator* cgen);
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Wed Jul 17 04:33:37 2019 -0700
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp Sat Jul 13 12:14:24 2019 -0400
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
#include "gc/shenandoah/shenandoahForwarding.hpp"
-#include "gc/shenandoah/shenandoahHeap.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahHeapRegion.hpp"
#include "gc/shenandoah/shenandoahHeuristics.hpp"
#include "gc/shenandoah/shenandoahRuntime.hpp"
@@ -401,6 +401,86 @@
#endif
}
+void ShenandoahBarrierSetAssembler::load_reference_barrier_native(MacroAssembler* masm, Register dst) {
+ if (!ShenandoahLoadRefBarrier) {
+ return;
+ }
+
+ Label done;
+ Label not_null;
+ Label slow_path;
+
+ // null check
+ __ testptr(dst, dst);
+ __ jcc(Assembler::notZero, not_null);
+ __ jmp(done);
+ __ bind(not_null);
+
+
+#ifdef _LP64
+ Register thread = r15_thread;
+#else
+ Register thread = rcx;
+ if (thread == dst) {
+ thread = rbx;
+ }
+ __ push(thread);
+ __ get_thread(thread);
+#endif
+ assert_different_registers(dst, thread);
+
+ Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+ __ testb(gc_state, ShenandoahHeap::EVACUATION);
+#ifndef _LP64
+ __ pop(thread);
+#endif
+ __ jccb(Assembler::notZero, slow_path);
+ __ jmp(done);
+ __ bind(slow_path);
+
+ if (dst != rax) {
+ __ xchgptr(dst, rax); // Move obj into rax and save rax into obj.
+ }
+ __ push(rcx);
+ __ push(rdx);
+ __ push(rdi);
+ __ push(rsi);
+#ifdef _LP64
+ __ push(r8);
+ __ push(r9);
+ __ push(r10);
+ __ push(r11);
+ __ push(r12);
+ __ push(r13);
+ __ push(r14);
+ __ push(r15);
+#endif
+
+ __ movptr(rdi, rax);
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native), rdi);
+
+#ifdef _LP64
+ __ pop(r15);
+ __ pop(r14);
+ __ pop(r13);
+ __ pop(r12);
+ __ pop(r11);
+ __ pop(r10);
+ __ pop(r9);
+ __ pop(r8);
+#endif
+ __ pop(rsi);
+ __ pop(rdi);
+ __ pop(rdx);
+ __ pop(rcx);
+
+ if (dst != rax) {
+ __ xchgptr(rax, dst); // Swap back obj with rax.
+ }
+
+ __ bind(done);
+}
+
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
if (ShenandoahStoreValEnqueueBarrier) {
storeval_barrier_impl(masm, dst, tmp);
@@ -457,12 +537,24 @@
bool on_oop = type == T_OBJECT || type == T_ARRAY;
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+ bool not_in_heap = (decorators & IN_NATIVE) != 0;
bool on_reference = on_weak || on_phantom;
- BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
+ bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+
+ BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
if (on_oop) {
- load_reference_barrier(masm, dst);
+ if (not_in_heap) {
+ if (ShenandoahHeap::heap()->is_traversal_mode()) {
+ load_reference_barrier(masm, dst);
+ keep_alive = true;
+ } else {
+ load_reference_barrier_native(masm, dst);
+ }
+ } else {
+ load_reference_barrier(masm, dst);
+ }
- if (ShenandoahKeepAliveBarrier && on_reference) {
+ if (ShenandoahKeepAliveBarrier && on_reference && keep_alive) {
const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
assert_different_registers(dst, tmp1, tmp_thread);
NOT_LP64(__ get_thread(thread));
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp Wed Jul 17 04:33:37 2019 -0700
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp Sat Jul 13 12:14:24 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
@@ -78,6 +78,7 @@
#endif
void load_reference_barrier(MacroAssembler* masm, Register dst);
+ void load_reference_barrier_native(MacroAssembler* masm, Register dst);
void cmpxchg_oop(MacroAssembler* masm,
Register res, Address addr, Register oldval, Register newval,