< prev index next > src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp
Print this page
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahHeapRegion.hpp"
#include "gc/shenandoah/shenandoahRuntime.hpp"
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
+ #include "gc/shenandoah/mode/shenandoahMode.hpp"
#include "interpreter/interpreter.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/globalDefinitions.hpp"
#include "vm_version_ppc.hpp"
}
void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
Register src, Register dst, Register count,
Register preserve1, Register preserve2) {
- __ block_comment("arraycopy_prologue (shenandoahgc) {");
-
Register R11_tmp = R11_scratch1;
assert_different_registers(src, dst, count, R11_tmp, noreg);
if (preserve1 != noreg) {
// Technically not required, but likely to indicate an error.
// any useful information.
if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahIUBarrier && !ShenandoahLoadRefBarrier) {
return;
}
+ __ block_comment("arraycopy_prologue (shenandoahgc) {");
Label skip_prologue;
// Fast path: Array is of length zero.
__ cmpdi(CCR0, count, 0);
__ beq(CCR0, skip_prologue);
// type of the reference in question.
// For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant
// for the garbage collector.
const int required_states = ShenandoahSATBBarrier && dest_uninitialized
? ShenandoahHeap::HAS_FORWARDED
- : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING;
+ : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::YOUNG_MARKING | ShenandoahHeap::OLD_MARKING;
__ andi_(R11_tmp, R11_tmp, required_states);
__ beq(CCR0, skip_prologue);
/* ==== Invoke runtime ==== */
__ bind(skip_prologue);
__ block_comment("} arraycopy_prologue (shenandoahgc)");
}
+ void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count,
+ Register preserve) {
+ if (is_reference_type(type)) {
+ __ block_comment("arraycopy_epilogue (shenandoahgc) {");
+ gen_write_ref_array_post_barrier(masm, decorators, dst, count, preserve);
+ __ block_comment("} arraycopy_epilogue (shenandoahgc)");
+ }
+ }
+
// The to-be-enqueued value can either be determined
// - dynamically by passing the reference's address information (load mode) or
// - statically by passing a register the value is stored in (preloaded mode)
// - for performance optimizations in cases where the previous value is known (currently not implemented) and
// - for incremental-update barriers.
const bool preserve_fp_registers = preservation_level >= MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS;
// Check whether marking is active.
__ lbz(tmp1, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread);
- __ andi_(tmp1, tmp1, ShenandoahHeap::MARKING);
+ __ andi_(tmp1, tmp1, ShenandoahHeap::YOUNG_MARKING | ShenandoahHeap::OLD_MARKING);
__ beq(CCR0, skip_barrier);
/* ==== Determine the reference's previous value ==== */
bool preloaded_mode = base == noreg;
Register pre_val_save = noreg;
if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
iu_barrier(masm, dst, tmp1, tmp2, preservation_level);
}
}
+ void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register base, RegisterOrConstant ind_or_offs, Register tmp) {
+ if (!ShenandoahHeap::heap()->mode()->is_generational()) {
+ return;
+ }
+
+ ShenandoahBarrierSet* ctbs = ShenandoahBarrierSet::barrier_set();
+ CardTable* ct = ctbs->card_table();
+ assert_different_registers(base, tmp, R0);
+
+ if (ind_or_offs.is_constant()) {
+ __ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp);
+ } else {
+ __ add(base, ind_or_offs.as_register(), base);
+ }
+
+ __ load_const_optimized(tmp, (address)ct->byte_map_base(), R0);
+ __ srdi(base, base, CardTable::card_shift());
+ __ li(R0, CardTable::dirty_card_val());
+ __ stbx(R0, tmp, base);
+ }
+
// base: Base register of the reference's address.
// ind_or_offs: Index or offset of the reference's address.
// val: To-be-stored value/reference's new value.
void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
BarrierSetAssembler::store_at(masm, decorators, type,
base, ind_or_offs,
val,
tmp1, tmp2, tmp3,
preservation_level);
+
+ // No need for post barrier if storing NULL
+ if (is_reference_type(type) && val != noreg) {
+ store_check(masm, base, ind_or_offs, tmp1);
+ }
}
void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
Register dst, Register jni_env, Register obj,
Register tmp, Label &slowpath) {
__ bind(done);
__ block_comment("} cmpxchg_oop (shenandoahgc)");
}
+ void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register preserve) {
+ if (!ShenandoahHeap::heap()->mode()->is_generational()) {
+ return;
+ }
+
+ ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
+ CardTable* ct = bs->card_table();
+ assert_different_registers(addr, count, R0);
+
+ Label Lskip_loop, Lstore_loop;
+
+ __ sldi_(count, count, LogBytesPerHeapOop);
+ __ beq(CCR0, Lskip_loop); // zero length
+ __ addi(count, count, -BytesPerHeapOop);
+ __ add(count, addr, count);
+ // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
+ __ srdi(addr, addr, CardTable::card_shift());
+ __ srdi(count, count, CardTable::card_shift());
+ __ subf(count, addr, count);
+ __ add_const_optimized(addr, addr, (address)ct->byte_map_base(), R0);
+ __ addi(count, count, 1);
+ __ li(R0, 0);
+ __ mtctr(count);
+ // Byte store loop
+ __ bind(Lstore_loop);
+ __ stb(R0, 0, addr);
+ __ addi(addr, addr, 1);
+ __ bdnz(Lstore_loop);
+ __ bind(Lskip_loop);
+ }
+
#undef __
#ifdef COMPILER1
#define __ ce->masm()->
/* ==== Check whether marking is active ==== */
// Even though gc status was checked in 'ShenandoahBarrierSetAssembler::gen_pre_barrier_stub',
// another check is required as a safepoint might have been reached in the meantime (JDK-8140588).
__ lbz(R12_tmp2, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread);
- __ andi_(R12_tmp2, R12_tmp2, ShenandoahHeap::MARKING);
+ __ andi_(R12_tmp2, R12_tmp2, ShenandoahHeap::YOUNG_MARKING | ShenandoahHeap::OLD_MARKING);
__ beq(CCR0, skip_barrier);
/* ==== Add previous value directly to thread-local SATB mark queue ==== */
// Check queue's capacity. Jump to runtime if no free slot is available.
__ ld(R12_tmp2, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread);
< prev index next >