< prev index next > src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp
Print this page
/*
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
- * Copyright (c) 2012, 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2022 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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
* published by the Free Software Foundation.
#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);
__ 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 (ShenandoahCardBarrier && 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.
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) {
+ assert(ShenandoahCardBarrier, "Should have been checked by caller");
+
+ 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 (ShenandoahCardBarrier && 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) {
+ assert(ShenandoahCardBarrier, "Should have been checked by caller");
+
+ ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
+ CardTable* ct = bs->card_table();
+ assert_different_registers(addr, count, R0);
+
+ Label L_skip_loop, L_store_loop;
+
+ __ sldi_(count, count, LogBytesPerHeapOop);
+
+ // Zero length? Skip.
+ __ beq(CCR0, L_skip_loop);
+
+ __ 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(L_store_loop);
+ __ stb(R0, 0, addr);
+ __ addi(addr, addr, 1);
+ __ bdnz(L_store_loop);
+ __ bind(L_skip_loop);
+ }
+
#undef __
#ifdef COMPILER1
#define __ ce->masm()->
< prev index next >