8227635: Shenandoah: SHBSA::load_at() needs to deal IN_NATIVE load
Reviewed-by: rkennke, roland
This commit is contained in:
parent
f08a9de3b2
commit
cb37e2f821
src/hotspot/cpu
@ -24,7 +24,7 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
|
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
|
||||||
#include "gc/shenandoah/shenandoahForwarding.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/shenandoahHeapRegion.hpp"
|
||||||
#include "gc/shenandoah/shenandoahHeuristics.hpp"
|
#include "gc/shenandoah/shenandoahHeuristics.hpp"
|
||||||
#include "gc/shenandoah/shenandoahRuntime.hpp"
|
#include "gc/shenandoah/shenandoahRuntime.hpp"
|
||||||
@ -282,6 +282,40 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembl
|
|||||||
__ leave();
|
__ 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) {
|
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
|
||||||
if (ShenandoahStoreValEnqueueBarrier) {
|
if (ShenandoahStoreValEnqueueBarrier) {
|
||||||
// Save possibly live regs.
|
// 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,
|
void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||||
Register dst, Address src, Register tmp1, Register tmp_thread) {
|
Register dst, Address src, Register tmp1, Register tmp_thread) {
|
||||||
bool on_oop = type == T_OBJECT || type == T_ARRAY;
|
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_weak = (decorators & ON_WEAK_OOP_REF) != 0;
|
||||||
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
|
bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
|
||||||
bool on_reference = on_weak || on_phantom;
|
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);
|
BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
|
||||||
if (on_oop) {
|
if (on_oop) {
|
||||||
load_reference_barrier(masm, dst, tmp1);
|
if (not_in_heap) {
|
||||||
|
if (ShenandoahHeap::heap()->is_traversal_mode()) {
|
||||||
if (ShenandoahKeepAliveBarrier && on_reference) {
|
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();
|
__ enter();
|
||||||
satb_write_barrier_pre(masm /* masm */,
|
satb_write_barrier_pre(masm /* masm */,
|
||||||
noreg /* obj */,
|
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
|
* 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
|
* 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 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(MacroAssembler* masm, Register dst, Register tmp);
|
||||||
void load_reference_barrier_not_null(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);
|
address generate_shenandoah_lrb(StubCodeGenerator* cgen);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
|
#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
|
||||||
#include "gc/shenandoah/shenandoahForwarding.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/shenandoahHeapRegion.hpp"
|
||||||
#include "gc/shenandoah/shenandoahHeuristics.hpp"
|
#include "gc/shenandoah/shenandoahHeuristics.hpp"
|
||||||
#include "gc/shenandoah/shenandoahRuntime.hpp"
|
#include "gc/shenandoah/shenandoahRuntime.hpp"
|
||||||
@ -401,6 +401,86 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembl
|
|||||||
#endif
|
#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) {
|
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
|
||||||
if (ShenandoahStoreValEnqueueBarrier) {
|
if (ShenandoahStoreValEnqueueBarrier) {
|
||||||
storeval_barrier_impl(masm, dst, tmp);
|
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_oop = type == T_OBJECT || type == T_ARRAY;
|
||||||
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
|
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
|
||||||
bool on_phantom = (decorators & ON_PHANTOM_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;
|
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;
|
||||||
if (on_oop) {
|
|
||||||
load_reference_barrier(masm, dst);
|
|
||||||
|
|
||||||
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);
|
const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
|
||||||
assert_different_registers(dst, tmp1, tmp_thread);
|
assert_different_registers(dst, tmp1, tmp_thread);
|
||||||
NOT_LP64(__ get_thread(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
|
* 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
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
@ -78,6 +78,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void load_reference_barrier(MacroAssembler* masm, Register dst);
|
void load_reference_barrier(MacroAssembler* masm, Register dst);
|
||||||
|
void load_reference_barrier_native(MacroAssembler* masm, Register dst);
|
||||||
|
|
||||||
void cmpxchg_oop(MacroAssembler* masm,
|
void cmpxchg_oop(MacroAssembler* masm,
|
||||||
Register res, Address addr, Register oldval, Register newval,
|
Register res, Address addr, Register oldval, Register newval,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user