8227635: Shenandoah: SHBSA::load_at() needs to deal IN_NATIVE load

Reviewed-by: rkennke, roland
This commit is contained in:
Zhengyu Gu 2019-07-13 12:14:24 -04:00
parent f08a9de3b2
commit cb37e2f821
4 changed files with 149 additions and 11 deletions

View File

@ -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 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembl
__ 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_reference_barrier(MacroAssembler* masm,
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 */,

View File

@ -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 @@ private:
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);

View File

@ -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 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembl
#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 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d
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);
if (on_oop) {
load_reference_barrier(masm, dst);
bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
if (ShenandoahKeepAliveBarrier && on_reference) {
BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
if (on_oop) {
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 && 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));

View File

@ -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 @@ public:
#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,