8227635: Shenandoah: SHBSA::load_at() needs to deal IN_NATIVE load
Reviewed-by: rkennke, roland
This commit is contained in:
parent
f08a9de3b2
commit
cb37e2f821
@ -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 */,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user