8198949: Modularize arraycopy stub routine GC barriers
Reviewed-by: rkennke, pliden
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "runtime/thread.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, RegSet saved_regs) {
+ bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ if (!dest_uninitialized) {
+ __ push(saved_regs, sp);
+ if (count == c_rarg0) {
+ if (addr == c_rarg1) {
+ // exactly backwards!!
+ __ mov(rscratch1, c_rarg0);
+ __ mov(c_rarg0, c_rarg1);
+ __ mov(c_rarg1, rscratch1);
+ } else {
+ __ mov(c_rarg1, count);
+ __ mov(c_rarg0, addr);
+ }
+ } else {
+ __ mov(c_rarg0, addr);
+ __ mov(c_rarg1, count);
+ }
+ if (UseCompressedOops) {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry), 2);
+ } else {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), 2);
+ }
+ __ pop(saved_regs, sp);
+ }
+}
+
+void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register start, Register end, Register scratch, RegSet saved_regs) {
+ __ push(saved_regs, sp);
+ // must compute element count unless barrier set interface is changed (other platforms supply count)
+ assert_different_registers(start, end, scratch);
+ __ lea(scratch, Address(end, BytesPerHeapOop));
+ __ sub(scratch, scratch, start); // subtract start to get #bytes
+ __ lsr(scratch, scratch, LogBytesPerHeapOop); // convert to element count
+ __ mov(c_rarg0, start);
+ __ mov(c_rarg1, scratch);
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), 2);
+ __ pop(saved_regs, sp);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH64_GC_G1_G1BARRIERSETASSEMBLER_AARCH64_HPP
+#define CPU_AARCH64_GC_G1_G1BARRIERSETASSEMBLER_AARCH64_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, RegSet saved_regs);
+ void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register start, Register end, Register tmp, RegSet saved_regs);
+};
+
+#endif // CPU_AARCH64_GC_G1_G1BARRIERSETASSEMBLER_AARCH64_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH64_GC_SHARED_BARRIERSETASSEMBLER_AARCH64_HPP
+#define CPU_AARCH64_GC_SHARED_BARRIERSETASSEMBLER_AARCH64_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "memory/allocation.hpp"
+#include "oops/access.hpp"
+
+class BarrierSetAssembler: public CHeapObj<mtGC> {
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, RegSet saved_regs) {}
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register start, Register end, Register tmp, RegSet saved_regs) {}
+};
+
+#endif // CPU_AARCH64_GC_SHARED_BARRIERSETASSEMBLER_AARCH64_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register start, Register end, Register scratch, RegSet saved_regs) {
+
+ BarrierSet* bs = Universe::heap()->barrier_set();
+ CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
+ CardTable* ct = ctbs->card_table();
+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+ Label L_loop;
+
+ __ lsr(start, start, CardTable::card_shift);
+ __ lsr(end, end, CardTable::card_shift);
+ __ sub(end, end, start); // number of bytes to copy
+
+ const Register count = end; // 'end' register contains bytes count now
+ __ load_byte_map_base(scratch);
+ __ add(start, start, scratch);
+ if (UseConcMarkSweepGC) {
+ __ membar(__ StoreStore);
+ }
+ __ bind(L_loop);
+ __ strb(zr, Address(start, count));
+ __ subs(count, count, 1);
+ __ br(Assembler::GE, L_loop);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH64_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_AARCH64_HPP
+#define CPU_AARCH64_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_AARCH64_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register start, Register end, Register tmp, RegSet saved_regs);
+};
+
+#endif // #ifndef CPU_AARCH64_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_AARCH64_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+#define __ masm->
+
+void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, RegSet saved_regs) {
+
+ if (is_oop) {
+ gen_write_ref_array_pre_barrier(masm, decorators, addr, count, saved_regs);
+ }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register start, Register end, Register tmp,
+ RegSet saved_regs) {
+ if (is_oop) {
+ gen_write_ref_array_post_barrier(masm, decorators, start, end, tmp, saved_regs);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_AARCH64_GC_SHARED_MODREFBARRIERSETASSEMBLER_AARCH64_HPP
+#define CPU_AARCH64_GC_SHARED_MODREFBARRIERSETASSEMBLER_AARCH64_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+class ModRefBarrierSetAssembler: public BarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, RegSet saved_regs) {}
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register start, Register end, Register tmp, RegSet saved_regs) {}
+
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, RegSet saved_regs);
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register start, Register end, Register tmp, RegSet saved_regs);
+};
+
+#endif // CPU_AARCH64_GC_SHARED_MODREFBARRIERSETASSEMBLER_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -26,8 +26,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_aarch64.hpp"
#include "oops/instanceOop.hpp"
@@ -620,111 +620,6 @@
void array_overlap_test(Label& L_no_overlap, Address::sxtw sf) { __ b(L_no_overlap); }
- // Generate code for an array write pre barrier
- //
- // addr - starting address
- // count - element count
- // tmp - scratch register
- // saved_regs - registers to be saved before calling static_write_ref_array_pre
- //
- // Callers must specify which registers to preserve in saved_regs.
- // Clobbers: r0-r18, v0-v7, v16-v31, except saved_regs.
- //
- void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized, RegSet saved_regs) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- // With G1, don't generate the call if we statically know that the target in uninitialized
- if (!dest_uninitialized) {
- __ push(saved_regs, sp);
- if (count == c_rarg0) {
- if (addr == c_rarg1) {
- // exactly backwards!!
- __ mov(rscratch1, c_rarg0);
- __ mov(c_rarg0, c_rarg1);
- __ mov(c_rarg1, rscratch1);
- } else {
- __ mov(c_rarg1, count);
- __ mov(c_rarg0, addr);
- }
- } else {
- __ mov(c_rarg0, addr);
- __ mov(c_rarg1, count);
- }
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
- __ pop(saved_regs, sp);
- break;
- case BarrierSet::CardTableBarrierSet:
- break;
- default:
- ShouldNotReachHere();
-
- }
- }
- }
-
- //
- // Generate code for an array write post barrier
- //
- // Input:
- // start - register containing starting address of destination array
- // end - register containing ending address of destination array
- // scratch - scratch register
- // saved_regs - registers to be saved before calling static_write_ref_array_post
- //
- // The input registers are overwritten.
- // The ending address is inclusive.
- // Callers must specify which registers to preserve in saved_regs.
- // Clobbers: r0-r18, v0-v7, v16-v31, except saved_regs.
- void gen_write_ref_array_post_barrier(Register start, Register end, Register scratch, RegSet saved_regs) {
- assert_different_registers(start, end, scratch);
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
-
- {
- __ push(saved_regs, sp);
- // must compute element count unless barrier set interface is changed (other platforms supply count)
- assert_different_registers(start, end, scratch);
- __ lea(scratch, Address(end, BytesPerHeapOop));
- __ sub(scratch, scratch, start); // subtract start to get #bytes
- __ lsr(scratch, scratch, LogBytesPerHeapOop); // convert to element count
- __ mov(c_rarg0, start);
- __ mov(c_rarg1, scratch);
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2);
- __ pop(saved_regs, sp);
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- {
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
- Label L_loop;
-
- __ lsr(start, start, CardTable::card_shift);
- __ lsr(end, end, CardTable::card_shift);
- __ sub(end, end, start); // number of bytes to copy
-
- const Register count = end; // 'end' register contains bytes count now
- __ load_byte_map_base(scratch);
- __ add(start, start, scratch);
- if (UseConcMarkSweepGC) {
- __ membar(__ StoreStore);
- }
- __ BIND(L_loop);
- __ strb(zr, Address(start, count));
- __ subs(count, count, 1);
- __ br(Assembler::GE, L_loop);
- }
- break;
- default:
- ShouldNotReachHere();
-
- }
- }
-
// The inner part of zero_words(). This is the bulk operation,
// zeroing words in blocks, possibly using DC ZVA to do it. The
// caller is responsible for zeroing the last few words.
@@ -1456,20 +1351,33 @@
BLOCK_COMMENT("Entry:");
}
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, is_oop, d, count, saved_reg);
+
if (is_oop) {
- gen_write_ref_array_pre_barrier(d, count, dest_uninitialized, saved_reg);
// save regs before copy_memory
__ push(RegSet::of(d, count), sp);
}
copy_memory(aligned, s, d, count, rscratch1, size);
+
if (is_oop) {
__ pop(RegSet::of(d, count), sp);
if (VerifyOops)
verify_oop_array(size, d, count, r16);
__ sub(count, count, 1); // make an inclusive end pointer
__ lea(count, Address(d, count, Address::lsl(exact_log2(size))));
- gen_write_ref_array_post_barrier(d, count, rscratch1, RegSet());
}
+
+ bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, rscratch1, RegSet());
+
__ leave();
__ mov(r0, zr); // return 0
__ ret(lr);
@@ -1517,8 +1425,18 @@
__ cmp(rscratch1, count, Assembler::LSL, exact_log2(size));
__ br(Assembler::HS, nooverlap_target);
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, is_oop, d, count, saved_regs);
+
if (is_oop) {
- gen_write_ref_array_pre_barrier(d, count, dest_uninitialized, saved_regs);
// save regs before copy_memory
__ push(RegSet::of(d, count), sp);
}
@@ -1529,8 +1447,8 @@
verify_oop_array(size, d, count, r16);
__ sub(count, count, 1); // make an inclusive end pointer
__ lea(count, Address(d, count, Address::lsl(exact_log2(size))));
- gen_write_ref_array_post_barrier(d, count, rscratch1, RegSet());
}
+ bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, rscratch1, RegSet());
__ leave();
__ mov(r0, zr); // return 0
__ ret(lr);
@@ -1871,7 +1789,14 @@
}
#endif //ASSERT
- gen_write_ref_array_pre_barrier(to, count, dest_uninitialized, wb_pre_saved_regs);
+ DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
+ bool is_oop = true;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, is_oop, to, count, wb_pre_saved_regs);
// save the original count
__ mov(count_save, count);
@@ -1915,7 +1840,7 @@
__ BIND(L_do_card_marks);
__ add(to, to, -heapOopSize); // make an inclusive end pointer
- gen_write_ref_array_post_barrier(start_to, to, rscratch1, wb_post_saved_regs);
+ bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, to, rscratch1, wb_post_saved_regs);
__ bind(L_done_pop);
__ pop(RegSet::of(r18, r19, r20, r21), sp);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/macros.hpp"
+
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, int callee_saved_regs) {
+ bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ if (!dest_uninitialized) {
+ assert( addr->encoding() < callee_saved_regs, "addr must be saved");
+ assert(count->encoding() < callee_saved_regs, "count must be saved");
+
+ BLOCK_COMMENT("PreBarrier");
+
+#ifdef AARCH64
+ callee_saved_regs = align_up(callee_saved_regs, 2);
+ for (int i = 0; i < callee_saved_regs; i += 2) {
+ __ raw_push(as_Register(i), as_Register(i+1));
+ }
+#else
+ RegisterSet saved_regs = RegisterSet(R0, as_Register(callee_saved_regs-1));
+ __ push(saved_regs | R9ifScratched);
+#endif // AARCH64
+
+ if (addr != R0) {
+ assert_different_registers(count, R0);
+ __ mov(R0, addr);
+ }
+#ifdef AARCH64
+ __ zero_extend(R1, count, 32); // G1BarrierSet::write_ref_array_pre_*_entry takes size_t
+#else
+ if (count != R1) {
+ __ mov(R1, count);
+ }
+#endif // AARCH64
+
+ if (UseCompressedOops) {
+ __ call(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry));
+ } else {
+ __ call(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry));
+ }
+
+#ifdef AARCH64
+ for (int i = callee_saved_regs - 2; i >= 0; i -= 2) {
+ __ raw_pop(as_Register(i), as_Register(i+1));
+ }
+#else
+ __ pop(saved_regs | R9ifScratched);
+#endif // AARCH64
+ }
+}
+
+void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {
+
+ BLOCK_COMMENT("G1PostBarrier");
+ if (addr != R0) {
+ assert_different_registers(count, R0);
+ __ mov(R0, addr);
+ }
+#ifdef AARCH64
+ __ zero_extend(R1, count, 32); // G1BarrierSet::write_ref_array_post_entry takes size_t
+#else
+ if (count != R1) {
+ __ mov(R1, count);
+ }
+#if R9_IS_SCRATCHED
+ // Safer to save R9 here since callers may have been written
+ // assuming R9 survives. This is suboptimal but is not in
+ // general worth optimizing for the few platforms where R9
+ // is scratched. Note that the optimization might not be to
+ // difficult for this particular call site.
+ __ push(R9);
+#endif // !R9_IS_SCRATCHED
+#endif // !AARCH64
+ __ call(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry));
+#ifndef AARCH64
+#if R9_IS_SCRATCHED
+ __ pop(R9);
+#endif // !R9_IS_SCRATCHED
+#endif // !AARCH64
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ARM_GC_G1_G1BARRIERSETASSEMBLER_ARM_HPP
+#define CPU_ARM_GC_G1_G1BARRIERSETASSEMBLER_ARM_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, , int callee_saved_regs);
+ void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp);
+};
+
+#endif // CPU_ARM_GC_G1_G1BARRIERSETASSEMBLER_ARM_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ARM_GC_SHARED_BARRIERSETASSEMBLER_ARM_HPP
+#define CPU_ARM_GC_SHARED_BARRIERSETASSEMBLER_ARM_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "memory/allocation.hpp"
+#include "oops/access.hpp"
+
+class BarrierSetAssembler: public CHeapObj<mtGC> {
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, , int callee_saved_regs) {}
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, Register tmp) {}
+};
+
+#endif // CPU_ARM_GC_SHARED_BARRIERSETASSEMBLER_ARM_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "runtime/globals.hpp"
+
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {
+ BLOCK_COMMENT("CardTablePostBarrier");
+ CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
+ CardTable* ct = ctbs->card_table();
+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+ Label L_cardtable_loop, L_done;
+
+ __ cbz_32(count, L_done); // zero count - nothing to do
+
+ __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop);
+ __ sub(count, count, BytesPerHeapOop); // last addr
+
+ __ logical_shift_right(addr, addr, CardTable::card_shift);
+ __ logical_shift_right(count, count, CardTable::card_shift);
+ __ sub(count, count, addr); // nb of cards
+
+ // warning: Rthread has not been preserved
+ __ mov_address(tmp, (address) ct->byte_map_base(), symbolic_Relocation::card_table_reference);
+ __ add(addr,tmp, addr);
+
+ Register zero = __ zero_register(tmp);
+
+ __ BIND(L_cardtable_loop);
+ __ strb(zero, Address(addr, 1, post_indexed));
+ __ subs(count, count, 1);
+ __ b(L_cardtable_loop, ge);
+ __ BIND(L_done);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ARM_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_ARM_HPP
+#define CPU_ARM_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_ARM_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp);
+};
+
+#endif // #ifndef CPU_ARM_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_ARM_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/shared/modRefBarrierSetAssembler_arm.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+#define __ masm->
+
+void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, int callee_saved_regs) {
+
+ if (is_oop) {
+ gen_write_ref_array_pre_barrier(masm, decorators, addr, count, callee_saved_regs);
+ }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, Register tmp) {
+ if (is_oop) {
+ gen_write_ref_array_post_barrier(masm, decorators, addr, count, tmp);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/arm/gc/shared/modRefBarrierSetAssembler_arm.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ARM_GC_SHARED_MODREFBARRIERSETASSEMBLER_ARM_HPP
+#define CPU_ARM_GC_SHARED_MODREFBARRIERSETASSEMBLER_ARM_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+class ModRefBarrierSetAssembler: public BarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, , int callee_saved_regs) {}
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {}
+
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, int callee_saved_regs);
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
+ Register addr, Register count, Register tmp);
+};
+
+#endif // CPU_ARM_GC_SHARED_MODREFBARRIERSETASSEMBLER_ARM_HPP
--- a/src/hotspot/cpu/arm/interp_masm_arm.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "jvm.h"
-#include "gc/shared/barrierSet.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/cardTableBarrierSet.inline.hpp"
#include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -25,8 +25,8 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "assembler_arm.inline.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_arm.hpp"
#include "oops/instanceOop.hpp"
@@ -2855,148 +2855,6 @@
return start;
}
-#if INCLUDE_ALL_GCS
- //
- // Generate pre-write barrier for array.
- //
- // Input:
- // addr - register containing starting address
- // count - register containing element count, 32-bit int
- // callee_saved_regs -
- // the call must preserve this number of registers: R0, R1, ..., R[callee_saved_regs-1]
- //
- // callee_saved_regs must include addr and count
- // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR) except for callee_saved_regs.
- void gen_write_ref_array_pre_barrier(Register addr, Register count, int callee_saved_regs) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- {
- assert( addr->encoding() < callee_saved_regs, "addr must be saved");
- assert(count->encoding() < callee_saved_regs, "count must be saved");
-
- BLOCK_COMMENT("PreBarrier");
-
-#ifdef AARCH64
- callee_saved_regs = align_up(callee_saved_regs, 2);
- for (int i = 0; i < callee_saved_regs; i += 2) {
- __ raw_push(as_Register(i), as_Register(i+1));
- }
-#else
- RegisterSet saved_regs = RegisterSet(R0, as_Register(callee_saved_regs-1));
- __ push(saved_regs | R9ifScratched);
-#endif // AARCH64
-
- if (addr != R0) {
- assert_different_registers(count, R0);
- __ mov(R0, addr);
- }
-#ifdef AARCH64
- __ zero_extend(R1, count, 32); // BarrierSet::static_write_ref_array_pre takes size_t
-#else
- if (count != R1) {
- __ mov(R1, count);
- }
-#endif // AARCH64
-
- __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre));
-
-#ifdef AARCH64
- for (int i = callee_saved_regs - 2; i >= 0; i -= 2) {
- __ raw_pop(as_Register(i), as_Register(i+1));
- }
-#else
- __ pop(saved_regs | R9ifScratched);
-#endif // AARCH64
- }
- case BarrierSet::CardTableBarrierSet:
- break;
- default:
- ShouldNotReachHere();
- }
- }
-#endif // INCLUDE_ALL_GCS
-
- //
- // Generate post-write barrier for array.
- //
- // Input:
- // addr - register containing starting address (can be scratched)
- // count - register containing element count, 32-bit int (can be scratched)
- // tmp - scratch register
- //
- // Note: LR can be scratched but might be equal to addr, count or tmp
- // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
- void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp) {
- assert_different_registers(addr, count, tmp);
- BarrierSet* bs = Universe::heap()->barrier_set();
-
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- {
- BLOCK_COMMENT("G1PostBarrier");
- if (addr != R0) {
- assert_different_registers(count, R0);
- __ mov(R0, addr);
- }
-#ifdef AARCH64
- __ zero_extend(R1, count, 32); // BarrierSet::static_write_ref_array_post takes size_t
-#else
- if (count != R1) {
- __ mov(R1, count);
- }
-#if R9_IS_SCRATCHED
- // Safer to save R9 here since callers may have been written
- // assuming R9 survives. This is suboptimal but is not in
- // general worth optimizing for the few platforms where R9
- // is scratched. Note that the optimization might not be to
- // difficult for this particular call site.
- __ push(R9);
-#endif
-#endif // !AARCH64
- __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post));
-#ifndef AARCH64
-#if R9_IS_SCRATCHED
- __ pop(R9);
-#endif
-#endif // !AARCH64
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- {
- BLOCK_COMMENT("CardTablePostBarrier");
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
- Label L_cardtable_loop, L_done;
-
- __ cbz_32(count, L_done); // zero count - nothing to do
-
- __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop);
- __ sub(count, count, BytesPerHeapOop); // last addr
-
- __ logical_shift_right(addr, addr, CardTable::card_shift);
- __ logical_shift_right(count, count, CardTable::card_shift);
- __ sub(count, count, addr); // nb of cards
-
- // warning: Rthread has not been preserved
- __ mov_address(tmp, (address) ct->byte_map_base(), symbolic_Relocation::card_table_reference);
- __ add(addr,tmp, addr);
-
- Register zero = __ zero_register(tmp);
-
- __ BIND(L_cardtable_loop);
- __ strb(zero, Address(addr, 1, post_indexed));
- __ subs(count, count, 1);
- __ b(L_cardtable_loop, ge);
- __ BIND(L_done);
- }
- break;
- default:
- ShouldNotReachHere();
- }
- }
// Generates pattern of code to be placed after raw data copying in generate_oop_copy
// Includes return from arraycopy stub.
@@ -3007,7 +2865,7 @@
// count: total number of copied elements, 32-bit int
//
// Blows all volatile (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR) and 'to', 'count', 'tmp' registers.
- void oop_arraycopy_stub_epilogue_helper(Register to, Register count, Register tmp, bool status, bool forward) {
+ void oop_arraycopy_stub_epilogue_helper(Register to, Register count, Register tmp, bool status, bool forward, DecoratorSet decorators) {
assert_different_registers(to, count, tmp);
if (forward) {
@@ -3018,7 +2876,8 @@
// 'to' is the beginning of the region
- gen_write_ref_array_post_barrier(to, count, tmp);
+ BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->arraycopy_epilogue(this, decorators, true, to, count, tmp);
if (status) {
__ mov(R0, 0); // OK
@@ -3086,9 +2945,16 @@
__ push(LR);
#endif // AARCH64
-#if INCLUDE_ALL_GCS
- gen_write_ref_array_pre_barrier(to, count, callee_saved_regs);
-#endif // INCLUDE_ALL_GCS
+ DecoratorSet decorators = 0;
+ if (disjoint) {
+ decorators |= ARRAYCOPY_DISJOINT;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(this, decorators, true, to, count, callee_saved_regs);
// save arguments for barrier generation (after the pre barrier)
__ mov(saved_count, count);
@@ -3146,12 +3012,12 @@
}
assert(small_copy_limit >= count_required_to_align + min_copy, "first loop might exhaust count");
- oop_arraycopy_stub_epilogue_helper(to, saved_count, /* tmp */ tmp1, status, forward);
+ oop_arraycopy_stub_epilogue_helper(to, saved_count, /* tmp */ tmp1, status, forward, decorators);
{
copy_small_array(from, to, count, tmp1, noreg, bytes_per_count, forward, L_small_array);
- oop_arraycopy_stub_epilogue_helper(to, saved_count, /* tmp */ tmp1, status, forward);
+ oop_arraycopy_stub_epilogue_helper(to, saved_count, /* tmp */ tmp1, status, forward, decorators);
}
if (!to_is_aligned) {
@@ -3165,7 +3031,7 @@
int min_copy_shifted = align_dst_and_generate_shifted_copy_loop(from, to, count, bytes_per_count, forward);
assert (small_copy_limit >= count_required_to_align + min_copy_shifted, "first loop might exhaust count");
- oop_arraycopy_stub_epilogue_helper(to, saved_count, /* tmp */ tmp1, status, forward);
+ oop_arraycopy_stub_epilogue_helper(to, saved_count, /* tmp */ tmp1, status, forward, decorators);
}
return start;
@@ -3336,7 +3202,7 @@
const int callee_saved_regs = AARCH64_ONLY(5) NOT_AARCH64(4); // LR saved differently
- Label load_element, store_element, do_card_marks, fail;
+ Label load_element, store_element, do_epilogue, fail;
BLOCK_COMMENT("Entry:");
@@ -3351,9 +3217,10 @@
pushed+=1;
#endif // AARCH64
-#if INCLUDE_ALL_GCS
- gen_write_ref_array_pre_barrier(to, count, callee_saved_regs);
-#endif // INCLUDE_ALL_GCS
+ DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
+
+ BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(this, decorators, true, to, count, callee_saved_regs);
#ifndef AARCH64
const RegisterSet caller_saved_regs = RegisterSet(R4,R6) | RegisterSet(R8,R9) | altFP_7_11;
@@ -3399,7 +3266,7 @@
__ subs_32(count,count,1);
__ str(R5, Address(to, BytesPerHeapOop, post_indexed)); // store the oop
}
- __ b(do_card_marks, eq); // count exhausted
+ __ b(do_epilogue, eq); // count exhausted
// ======== loop entry is here ========
__ BIND(load_element);
@@ -3421,7 +3288,7 @@
// Note: fail marked by the fact that count differs from saved_count
- __ BIND(do_card_marks);
+ __ BIND(do_epilogue);
Register copied = AARCH64_ONLY(R20) NOT_AARCH64(R4); // saved
Label L_not_copied;
@@ -3431,7 +3298,7 @@
__ sub(to, to, AsmOperand(copied, lsl, LogBytesPerHeapOop)); // initial to value
__ mov(R12, copied); // count arg scratched by post barrier
- gen_write_ref_array_post_barrier(to, R12, R3);
+ bs->arraycopy_epilogue(this, decorators, true, to, R12, R3);
assert_different_registers(R3,R12,LR,copied,saved_count);
inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, R3, R12);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "runtime/thread.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register from, Register to, Register count,
+ Register preserve1, Register preserve2) {
+ bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ // With G1, don't generate the call if we statically know that the target in uninitialized
+ if (!dest_uninitialized) {
+ int spill_slots = 3;
+ if (preserve1 != noreg) { spill_slots++; }
+ if (preserve2 != noreg) { spill_slots++; }
+ const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes);
+ Label filtered;
+
+ // Is marking active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ lwz(R0, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
+ } else {
+ guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ lbz(R0, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
+ }
+ __ cmpdi(CCR0, R0, 0);
+ __ beq(CCR0, filtered);
+
+ __ save_LR_CR(R0);
+ __ push_frame(frame_size, R0);
+ int slot_nr = 0;
+ __ std(from, frame_size - (++slot_nr) * wordSize, R1_SP);
+ __ std(to, frame_size - (++slot_nr) * wordSize, R1_SP);
+ __ std(count, frame_size - (++slot_nr) * wordSize, R1_SP);
+ if (preserve1 != noreg) { __ std(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); }
+ if (preserve2 != noreg) { __ std(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); }
+
+ if (UseCompressedOops) {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry), to, count);
+ } else {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), to, count);
+ }
+
+ slot_nr = 0;
+ __ ld(from, frame_size - (++slot_nr) * wordSize, R1_SP);
+ __ ld(to, frame_size - (++slot_nr) * wordSize, R1_SP);
+ __ ld(count, frame_size - (++slot_nr) * wordSize, R1_SP);
+ if (preserve1 != noreg) { __ ld(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); }
+ if (preserve2 != noreg) { __ ld(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); }
+ __ addi(R1_SP, R1_SP, frame_size); // pop_frame()
+ __ restore_LR_CR(R0);
+
+ __ bind(filtered);
+ }
+}
+
+void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register preserve) {
+ int spill_slots = (preserve != noreg) ? 1 : 0;
+ const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes);
+
+ __ save_LR_CR(R0);
+ __ push_frame(frame_size, R0);
+ if (preserve != noreg) { __ std(preserve, frame_size - 1 * wordSize, R1_SP); }
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), addr, count);
+ if (preserve != noreg) { __ ld(preserve, frame_size - 1 * wordSize, R1_SP); }
+ __ addi(R1_SP, R1_SP, frame_size); // pop_frame();
+ __ restore_LR_CR(R0);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_PPC_GC_G1_G1BARRIERSETASSEMBLER_PPC_HPP
+#define CPU_PPC_GC_G1_G1BARRIERSETASSEMBLER_PPC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register from, Register to, Register count,
+ Register preserve1, Register preserve2);
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register preserve);
+};
+
+#endif // CPU_PPC_GC_G1_G1BARRIERSETASSEMBLER_PPC_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_PPC_GC_SHARED_BARRIERSETASSEMBLER_PPC_HPP
+#define CPU_PPC_GC_SHARED_BARRIERSETASSEMBLER_PPC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "memory/allocation.hpp"
+#include "oops/access.hpp"
+
+class InterpreterMacroAssembler;
+
+class BarrierSetAssembler: public CHeapObj<mtGC> {
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count, Register preserve1, Register preserve2) {}
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count, Register preserve) {}
+};
+
+#endif // CPU_PPC_GC_SHARED_BARRIERSETASSEMBLER_PPC_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr,
+ Register count, Register preserve) {
+ CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+ CardTable* ct = ctbs->card_table();
+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+ assert_different_registers(addr, count, R0);
+
+ Label Lskip_loop, Lstore_loop;
+
+ if (UseConcMarkSweepGC) { __ membar(Assembler::StoreStore); }
+
+ __ 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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_PPC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_PPC_HPP
+#define CPU_PPC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_PPC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr,
+ Register count, Register preserve);
+};
+
+#endif // CPU_PPC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_PPC_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+#define __ masm->
+
+void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count, Register preserve1, Register preserve2) {
+ if (type == T_OBJECT) {
+ gen_write_ref_array_pre_barrier(masm, decorators, src, dst, count, preserve1, preserve2);
+
+ bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
+ if (!checkcast) {
+ assert_different_registers(dst, count, R9_ARG7, R10_ARG8);
+ // Save some arguments for epilogue, e.g. disjoint_long_copy_core destroys them.
+ __ mr(R9_ARG7, dst);
+ __ mr(R10_ARG8, count);
+ }
+ }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count, Register preserve) {
+ if (type == T_OBJECT) {
+ bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
+ if (!checkcast) {
+ gen_write_ref_array_post_barrier(masm, decorators, R9_ARG7, R10_ARG8, preserve);
+ } else {
+ gen_write_ref_array_post_barrier(masm, decorators, dst, count, preserve);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_PPC_GC_SHARED_MODREFBARRIERSETASSEMBLER_PPC_HPP
+#define CPU_PPC_GC_SHARED_MODREFBARRIERSETASSEMBLER_PPC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+class ModRefBarrierSetAssembler: public BarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register from, Register to, Register count,
+ Register preserve1, Register preserve2) {}
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register preserve) {}
+
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count, Register preserve1, Register preserve2);
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count, Register preserve);
+};
+
+#endif // CPU_PPC_GC_SHARED_MODREFBARRIERSETASSEMBLER_PPC_HPP
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -25,8 +25,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_ppc.hpp"
#include "oops/instanceOop.hpp"
@@ -612,137 +612,6 @@
#undef __
#define __ _masm->
- // Generate G1 pre-write barrier for array.
- //
- // Input:
- // from - register containing src address (only needed for spilling)
- // to - register containing starting address
- // count - register containing element count
- // tmp - scratch register
- //
- // Kills:
- // nothing
- //
- void gen_write_ref_array_pre_barrier(Register from, Register to, Register count, bool dest_uninitialized, Register Rtmp1,
- Register preserve1 = noreg, Register preserve2 = noreg) {
- BarrierSet* const bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- // With G1, don't generate the call if we statically know that the target in uninitialized
- if (!dest_uninitialized) {
- int spill_slots = 3;
- if (preserve1 != noreg) { spill_slots++; }
- if (preserve2 != noreg) { spill_slots++; }
- const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes);
- Label filtered;
-
- // Is marking active?
- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
- __ lwz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
- } else {
- guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
- __ lbz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
- }
- __ cmpdi(CCR0, Rtmp1, 0);
- __ beq(CCR0, filtered);
-
- __ save_LR_CR(R0);
- __ push_frame(frame_size, R0);
- int slot_nr = 0;
- __ std(from, frame_size - (++slot_nr) * wordSize, R1_SP);
- __ std(to, frame_size - (++slot_nr) * wordSize, R1_SP);
- __ std(count, frame_size - (++slot_nr) * wordSize, R1_SP);
- if (preserve1 != noreg) { __ std(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); }
- if (preserve2 != noreg) { __ std(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); }
-
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), to, count);
-
- slot_nr = 0;
- __ ld(from, frame_size - (++slot_nr) * wordSize, R1_SP);
- __ ld(to, frame_size - (++slot_nr) * wordSize, R1_SP);
- __ ld(count, frame_size - (++slot_nr) * wordSize, R1_SP);
- if (preserve1 != noreg) { __ ld(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); }
- if (preserve2 != noreg) { __ ld(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); }
- __ addi(R1_SP, R1_SP, frame_size); // pop_frame()
- __ restore_LR_CR(R0);
-
- __ bind(filtered);
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- break;
- default:
- ShouldNotReachHere();
- }
- }
-
- // Generate CMS/G1 post-write barrier for array.
- //
- // Input:
- // addr - register containing starting address
- // count - register containing element count
- // tmp - scratch register
- //
- // The input registers and R0 are overwritten.
- //
- void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp, Register preserve = noreg) {
- BarrierSet* const bs = Universe::heap()->barrier_set();
-
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- {
- int spill_slots = (preserve != noreg) ? 1 : 0;
- const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes);
-
- __ save_LR_CR(R0);
- __ push_frame(frame_size, R0);
- if (preserve != noreg) { __ std(preserve, frame_size - 1 * wordSize, R1_SP); }
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count);
- if (preserve != noreg) { __ ld(preserve, frame_size - 1 * wordSize, R1_SP); }
- __ addi(R1_SP, R1_SP, frame_size); // pop_frame();
- __ restore_LR_CR(R0);
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- {
- Label Lskip_loop, Lstore_loop;
- if (UseConcMarkSweepGC) {
- // TODO PPC port: contribute optimization / requires shared changes
- __ release();
- }
-
- CardTableBarrierSet* const ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* const ct = ctbs->card_table();
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
- assert_different_registers(addr, count, tmp);
-
- __ sldi(count, count, LogBytesPerHeapOop);
- __ 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);
- assert_different_registers(R0, addr, count, tmp);
- __ load_const(tmp, (address)ct->byte_map_base());
- __ addic_(count, count, 1);
- __ beq(CCR0, Lskip_loop);
- __ li(R0, 0);
- __ mtctr(count);
- // Byte store loop
- __ bind(Lstore_loop);
- __ stbx(R0, tmp, addr);
- __ addi(addr, addr, 1);
- __ bdnz(Lstore_loop);
- __ bind(Lskip_loop);
- }
- break;
- case BarrierSet::ModRef:
- break;
- default:
- ShouldNotReachHere();
- }
- }
// Support for void zero_words_aligned8(HeapWord* to, size_t count)
//
@@ -2155,11 +2024,16 @@
STUB_ENTRY(arrayof_oop_disjoint_arraycopy) :
STUB_ENTRY(oop_disjoint_arraycopy);
- gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7);
-
- // Save arguments.
- __ mr(R9_ARG7, R4_ARG2);
- __ mr(R10_ARG8, R5_ARG3);
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, R3_ARG1, R4_ARG2, R5_ARG3, noreg, noreg);
if (UseCompressedOops) {
array_overlap_test(nooverlap_target, 2);
@@ -2169,7 +2043,7 @@
generate_conjoint_long_copy_core(aligned);
}
- gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, R4_ARG2, R5_ARG3, noreg);
__ li(R3_RET, 0); // return 0
__ blr();
return start;
@@ -2188,12 +2062,17 @@
StubCodeMark mark(this, "StubRoutines", name);
address start = __ function_entry();
assert_positive_int(R5_ARG3);
- gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7);
-
- // save some arguments, disjoint_long_copy_core destroys them.
- // needed for post barrier
- __ mr(R9_ARG7, R4_ARG2);
- __ mr(R10_ARG8, R5_ARG3);
+
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, R3_ARG1, R4_ARG2, R5_ARG3, noreg, noreg);
if (UseCompressedOops) {
generate_disjoint_int_copy_core(aligned);
@@ -2201,7 +2080,7 @@
generate_disjoint_long_copy_core(aligned);
}
- gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, R4_ARG2, R5_ARG3, noreg);
__ li(R3_RET, 0); // return 0
__ blr();
@@ -2280,11 +2159,17 @@
}
#endif
- gen_write_ref_array_pre_barrier(R3_from, R4_to, R5_count, dest_uninitialized, R12_tmp, /* preserve: */ R6_ckoff, R7_ckval);
+ DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, R3_from, R4_to, R5_count, /* preserve: */ R6_ckoff, R7_ckval);
//inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, R12_tmp, R3_RET);
- Label load_element, store_element, store_null, success, do_card_marks;
+ Label load_element, store_element, store_null, success, do_epilogue;
__ or_(R9_remain, R5_count, R5_count); // Initialize loop index, and test it.
__ li(R8_offset, 0); // Offset from start of arrays.
__ li(R2_minus1, -1);
@@ -2328,15 +2213,15 @@
// and report their number to the caller.
__ subf_(R5_count, R9_remain, R5_count);
__ nand(R3_RET, R5_count, R5_count); // report (-1^K) to caller
- __ bne(CCR0, do_card_marks);
+ __ bne(CCR0, do_epilogue);
__ blr();
__ bind(success);
__ li(R3_RET, 0);
- __ bind(do_card_marks);
- // Store check on R4_to[0..R5_count-1].
- gen_write_ref_array_post_barrier(R4_to, R5_count, R12_tmp, /* preserve: */ R3_RET);
+ __ bind(do_epilogue);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, R4_to, R5_count, /* preserve */ R3_RET);
+
__ blr();
return start;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "registerSaver_s390.hpp"
+#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "runtime/thread.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+#define BLOCK_COMMENT(str) if (PrintAssembly) __ block_comment(str)
+
+void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count) {
+ bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+
+ // With G1, don't generate the call if we statically know that the target is uninitialized.
+ if (!dest_uninitialized) {
+ // Is marking active?
+ Label filtered;
+ assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame()
+ assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame()
+ Register Rtmp1 = Z_R0_scratch;
+ const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ load_and_test_int(Rtmp1, Address(Z_thread, active_offset));
+ } else {
+ guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ load_and_test_byte(Rtmp1, Address(Z_thread, active_offset));
+ }
+ __ z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently.
+
+ RegisterSaver::save_live_registers(masm, RegisterSaver::arg_registers); // Creates frame.
+
+ if (UseCompressedOops) {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry), addr, count);
+ } else {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), addr, count);
+ }
+
+ RegisterSaver::restore_live_registers(masm, RegisterSaver::arg_registers);
+
+ __ bind(filtered);
+ }
+}
+
+void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, bool do_return) {
+ address entry_point = CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry);
+ if (!do_return) {
+ assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame()
+ assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame()
+ RegisterSaver::save_live_registers(masm, RegisterSaver::arg_registers); // Creates frame.
+ __ call_VM_leaf(entry_point, addr, count);
+ RegisterSaver::restore_live_registers(masm, RegisterSaver::arg_registers);
+ } else {
+ // Tail call: call c and return to stub caller.
+ __ lgr_if_needed(Z_ARG1, addr);
+ __ lgr_if_needed(Z_ARG2, count);
+ __ load_const(Z_R1, entry_point);
+ __ z_br(Z_R1); // Branch without linking, callee will return to stub caller.
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_S390_GC_G1_G1BARRIERSETASSEMBLER_S390_HPP
+#define CPU_S390_GC_G1_G1BARRIERSETASSEMBLER_S390_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
+ protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count);
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, bool do_return);
+};
+
+#endif // CPU_S390_GC_G1_G1BARRIERSETASSEMBLER_S390_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_S390_GC_G1_BARRIERSETASSEMBLER_S390_HPP
+#define CPU_S390_GC_G1_BARRIERSETASSEMBLER_S390_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "memory/allocation.hpp"
+#include "oops/access.hpp"
+
+class InterpreterMacroAssembler;
+
+class BarrierSetAssembler: public CHeapObj<mtGC> {
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {}
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count, bool do_return = false);
+};
+
+#endif // CPU_S390_GC_G1_BARRIERSETASSEMBLER_S390_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8)
+
+void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
+ bool do_return) {
+ CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+ CardTable* ct = ctbs->card_table();
+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+ NearLabel doXC, done;
+ assert_different_registers(Z_R0, Z_R1, addr, count);
+
+ // Nothing to do if count <= 0.
+ if (!do_return) {
+ __ compare64_and_branch(count, (intptr_t) 0, Assembler::bcondNotHigh, done);
+ } else {
+ __ z_ltgr(count, count);
+ __ z_bcr(Assembler::bcondNotPositive, Z_R14);
+ }
+
+ // Note: We can't combine the shifts. We could lose a carry
+ // from calculating the array end address.
+ // count = (count-1)*BytesPerHeapOop + addr
+ // Count holds addr of last oop in array then.
+ __ z_sllg(count, count, LogBytesPerHeapOop);
+ __ add2reg_with_index(count, -BytesPerHeapOop, count, addr);
+
+ // Get base address of card table.
+ __ load_const_optimized(Z_R1, (address)ct->byte_map_base());
+
+ // count = (count>>shift) - (addr>>shift)
+ __ z_srlg(addr, addr, CardTable::card_shift);
+ __ z_srlg(count, count, CardTable::card_shift);
+
+ // Prefetch first elements of card table for update.
+ if (VM_Version::has_Prefetch()) {
+ __ z_pfd(0x02, 0, addr, Z_R1);
+ }
+
+ // Special case: clear just one byte.
+ __ clear_reg(Z_R0, true, false); // Used for doOneByte.
+ __ z_sgr(count, addr); // Count = n-1 now, CC used for brc below.
+ __ z_stc(Z_R0, 0, addr, Z_R1); // Must preserve CC from z_sgr.
+ if (!do_return) {
+ __ z_brz(done);
+ } else {
+ __ z_bcr(Assembler::bcondZero, Z_R14);
+ }
+
+ __ z_cghi(count, 255);
+ __ z_brnh(doXC);
+
+ // MVCLE: clear a long area.
+ // Start addr of card table range = base + addr.
+ // # bytes in card table range = (count + 1)
+ __ add2reg_with_index(Z_R0, 0, Z_R1, addr);
+ __ add2reg(Z_R1, 1, count);
+
+ // dirty hack:
+ // There are just two callers. Both pass
+ // count in Z_ARG3 = Z_R4
+ // addr in Z_ARG2 = Z_R3
+ // ==> use Z_ARG2 as src len reg = 0
+ // Z_ARG1 as src addr (ignored)
+ assert(count == Z_ARG3, "count: unexpected register number");
+ assert(addr == Z_ARG2, "addr: unexpected register number");
+ __ clear_reg(Z_ARG2, true, false);
+
+ __ MacroAssembler::move_long_ext(Z_R0, Z_ARG1, 0);
+
+ if (!do_return) {
+ __ z_bru(done);
+ } else {
+ __ z_bcr(Assembler::bcondAlways, Z_R14);
+ }
+
+ // XC: clear a short area.
+ Label XC_template; // Instr template, never exec directly!
+ __ bind(XC_template);
+ __ z_xc(0, 0, addr, 0, addr);
+
+ __ bind(doXC);
+ // start addr of card table range = base + addr
+ // end addr of card table range = base + addr + count
+ __ add2reg_with_index(addr, 0, Z_R1, addr);
+
+ if (VM_Version::has_ExecuteExtensions()) {
+ __ z_exrl(count, XC_template); // Execute XC with var. len.
+ } else {
+ __ z_larl(Z_R1, XC_template);
+ __ z_ex(count, 0, Z_R0, Z_R1); // Execute XC with var. len.
+ }
+ if (do_return) {
+ __ z_br(Z_R14);
+ }
+
+ __ bind(done);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
+ bool do_return);
+};
+
+#endif // CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+#define __ masm->
+
+void ModRefBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
+ bool do_return) {
+ if (do_return) { __ z_br(Z_R14); }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {
+ if (type == T_OBJECT || type == T_ARRAY) {
+ gen_write_ref_array_pre_barrier(masm, decorators, dst, count);
+ }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count, bool do_return) {
+ if (type == T_OBJECT || type == T_ARRAY) {
+ gen_write_ref_array_post_barrier(masm, decorators, dst, count, do_return);
+ } else {
+ if (do_return) { __ z_br(Z_R14); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+class ModRefBarrierSetAssembler: public BarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count) {}
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
+ bool do_return);
+
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count);
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register dst, Register count, bool do_return = false);
+};
+
+#endif // CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -26,8 +26,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "registerSaver_s390.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interp_masm.hpp"
#include "nativeInst_s390.hpp"
@@ -686,188 +686,6 @@
return start;
}
- // Generate pre-write barrier for array.
- //
- // Input:
- // addr - register containing starting address
- // count - register containing element count
- //
- // The input registers are overwritten.
- void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
-
- BarrierSet* const bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- // With G1, don't generate the call if we statically know that the target is uninitialized.
- if (!dest_uninitialized) {
- // Is marking active?
- Label filtered;
- assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame()
- assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame()
- Register Rtmp1 = Z_R0_scratch;
- const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
- SATBMarkQueue::byte_offset_of_active());
- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
- __ load_and_test_int(Rtmp1, Address(Z_thread, active_offset));
- } else {
- guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
- __ load_and_test_byte(Rtmp1, Address(Z_thread, active_offset));
- }
- __ z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently.
-
- // __ push_frame_abi160(0); // implicitly done in save_live_registers()
- (void) RegisterSaver::save_live_registers(_masm, RegisterSaver::arg_registers);
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), addr, count);
- (void) RegisterSaver::restore_live_registers(_masm, RegisterSaver::arg_registers);
- // __ pop_frame(); // implicitly done in restore_live_registers()
-
- __ bind(filtered);
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- case BarrierSet::ModRef:
- break;
- default:
- ShouldNotReachHere();
- }
- }
-
- // Generate post-write barrier for array.
- //
- // Input:
- // addr - register containing starting address
- // count - register containing element count
- //
- // The input registers are overwritten.
- void gen_write_ref_array_post_barrier(Register addr, Register count, bool branchToEnd) {
- BarrierSet* const bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- {
- if (branchToEnd) {
- assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame()
- assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame()
- // __ push_frame_abi160(0); // implicitly done in save_live_registers()
- (void) RegisterSaver::save_live_registers(_masm, RegisterSaver::arg_registers);
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count);
- (void) RegisterSaver::restore_live_registers(_masm, RegisterSaver::arg_registers);
- // __ pop_frame(); // implicitly done in restore_live_registers()
- } else {
- // Tail call: call c and return to stub caller.
- address entry_point = CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post);
- __ lgr_if_needed(Z_ARG1, addr);
- __ lgr_if_needed(Z_ARG2, count);
- __ load_const(Z_R1, entry_point);
- __ z_br(Z_R1); // Branch without linking, callee will return to stub caller.
- }
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- // These cases formerly known as
- // void array_store_check(Register addr, Register count, bool branchToEnd).
- {
- NearLabel doXC, done;
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
- assert_different_registers(Z_R0, Z_R1, addr, count);
-
- // Nothing to do if count <= 0.
- if (branchToEnd) {
- __ compare64_and_branch(count, (intptr_t) 0, Assembler::bcondNotHigh, done);
- } else {
- __ z_ltgr(count, count);
- __ z_bcr(Assembler::bcondNotPositive, Z_R14);
- }
-
- // Note: We can't combine the shifts. We could lose a carry
- // from calculating the array end address.
- // count = (count-1)*BytesPerHeapOop + addr
- // Count holds addr of last oop in array then.
- __ z_sllg(count, count, LogBytesPerHeapOop);
- __ add2reg_with_index(count, -BytesPerHeapOop, count, addr);
-
- // Get base address of card table.
- __ load_const_optimized(Z_R1, (address)ct->byte_map_base());
-
- // count = (count>>shift) - (addr>>shift)
- __ z_srlg(addr, addr, CardTable::card_shift);
- __ z_srlg(count, count, CardTable::card_shift);
-
- // Prefetch first elements of card table for update.
- if (VM_Version::has_Prefetch()) {
- __ z_pfd(0x02, 0, addr, Z_R1);
- }
-
- // Special case: clear just one byte.
- __ clear_reg(Z_R0, true, false); // Used for doOneByte.
- __ z_sgr(count, addr); // Count = n-1 now, CC used for brc below.
- __ z_stc(Z_R0, 0, addr, Z_R1); // Must preserve CC from z_sgr.
- if (branchToEnd) {
- __ z_brz(done);
- } else {
- __ z_bcr(Assembler::bcondZero, Z_R14);
- }
-
- __ z_cghi(count, 255);
- __ z_brnh(doXC);
-
- // MVCLE: clear a long area.
- // Start addr of card table range = base + addr.
- // # bytes in card table range = (count + 1)
- __ add2reg_with_index(Z_R0, 0, Z_R1, addr);
- __ add2reg(Z_R1, 1, count);
-
- // dirty hack:
- // There are just two callers. Both pass
- // count in Z_ARG3 = Z_R4
- // addr in Z_ARG2 = Z_R3
- // ==> use Z_ARG2 as src len reg = 0
- // Z_ARG1 as src addr (ignored)
- assert(count == Z_ARG3, "count: unexpected register number");
- assert(addr == Z_ARG2, "addr: unexpected register number");
- __ clear_reg(Z_ARG2, true, false);
-
- __ MacroAssembler::move_long_ext(Z_R0, Z_ARG1, 0);
-
- if (branchToEnd) {
- __ z_bru(done);
- } else {
- __ z_bcr(Assembler::bcondAlways, Z_R14);
- }
-
- // XC: clear a short area.
- Label XC_template; // Instr template, never exec directly!
- __ bind(XC_template);
- __ z_xc(0, 0, addr, 0, addr);
-
- __ bind(doXC);
- // start addr of card table range = base + addr
- // end addr of card table range = base + addr + count
- __ add2reg_with_index(addr, 0, Z_R1, addr);
-
- if (VM_Version::has_ExecuteExtensions()) {
- __ z_exrl(count, XC_template); // Execute XC with var. len.
- } else {
- __ z_larl(Z_R1, XC_template);
- __ z_ex(count, 0, Z_R0, Z_R1); // Execute XC with var. len.
- }
- if (!branchToEnd) {
- __ z_br(Z_R14);
- }
-
- __ bind(done);
- }
- break;
- case BarrierSet::ModRef:
- if (!branchToEnd) { __ z_br(Z_R14); }
- break;
- default:
- ShouldNotReachHere();
- }
- }
-
-
// This is to test that the count register contains a positive int value.
// Required because C2 does not respect int to long conversion for stub calls.
void assert_positive_int(Register count) {
@@ -1482,11 +1300,20 @@
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
unsigned int size = UseCompressedOops ? 4 : 8;
- gen_write_ref_array_pre_barrier(Z_ARG2, Z_ARG3, dest_uninitialized);
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, Z_ARG1, Z_ARG2, Z_ARG3);
generate_disjoint_copy(aligned, size, true, true);
- gen_write_ref_array_post_barrier(Z_ARG2, Z_ARG3, false);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, Z_ARG2, Z_ARG3, true);
return __ addr_at(start_off);
}
@@ -1565,11 +1392,20 @@
// Branch to disjoint_copy (if applicable) before pre_barrier to avoid double pre_barrier.
array_overlap_test(nooverlap_target, shift); // Branch away to nooverlap_target if disjoint.
- gen_write_ref_array_pre_barrier(Z_ARG2, Z_ARG3, dest_uninitialized);
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, Z_ARG1, Z_ARG2, Z_ARG3);
generate_conjoint_copy(aligned, size, true); // Must preserve ARG2, ARG3.
- gen_write_ref_array_post_barrier(Z_ARG2, Z_ARG3, false);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, Z_ARG2, Z_ARG3, true);
return __ addr_at(start_off);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/macros.hpp"
+
+#define __ masm->
+
+void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count) {
+ bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ // With G1, don't generate the call if we statically know that the target in uninitialized
+ if (!dest_uninitialized) {
+ Register tmp = O5;
+ assert_different_registers(addr, count, tmp);
+ Label filtered;
+ // Is marking active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ ld(G2, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), tmp);
+ } else {
+ guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
+ "Assumption");
+ __ ldsb(G2, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), tmp);
+ }
+ // Is marking active?
+ __ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
+
+ __ save_frame(0);
+ // Save the necessary global regs... will be used after.
+ if (addr->is_global()) {
+ __ mov(addr, L0);
+ }
+ if (count->is_global()) {
+ __ mov(count, L1);
+ }
+ __ mov(addr->after_save(), O0);
+ // Get the count into O1
+ address slowpath = UseCompressedOops ? CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry)
+ : CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry);
+ __ call(slowpath);
+ __ delayed()->mov(count->after_save(), O1);
+ if (addr->is_global()) {
+ __ mov(L0, addr);
+ }
+ if (count->is_global()) {
+ __ mov(L1, count);
+ }
+ __ restore();
+
+ __ bind(filtered);
+ DEBUG_ONLY(__ set(0xDEADC0DE, tmp);) // we have killed tmp
+ }
+}
+
+void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {
+ // Get some new fresh output registers.
+ __ save_frame(0);
+ __ mov(addr->after_save(), O0);
+ __ call(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry));
+ __ delayed()->mov(count->after_save(), O1);
+ __ restore();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_SPARC_GC_G1_G1BARRIERSETASSEMBLER_SPARC_HPP
+#define CPU_SPARC_GC_G1_G1BARRIERSETASSEMBLER_SPARC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count);
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp);
+};
+
+#endif // CPU_SPARC_GC_G1_G1BARRIERSETASSEMBLER_SPARC_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_SPARC_GC_SHARED_BARRIERSETASSEMBLER_SPARC_HPP
+#define CPU_SPARC_GC_SHARED_BARRIERSETASSEMBLER_SPARC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "memory/allocation.hpp"
+#include "oops/access.hpp"
+
+class InterpreterMacroAssembler;
+
+class BarrierSetAssembler: public CHeapObj<mtGC> {
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {}
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {}
+};
+
+#endif // CPU_SPARC_GC_SHARED_BARRIERSETASSEMBLER_SPARC_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,72 @@
+
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {
+ CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+ CardTable* ct = ctbs->card_table();
+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+ assert_different_registers(addr, count, tmp);
+
+ Label L_loop, L_done;
+
+ __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_done); // zero count - nothing to do
+
+ __ sll_ptr(count, LogBytesPerHeapOop, count);
+ __ sub(count, BytesPerHeapOop, count);
+ __ add(count, addr, count);
+ // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
+ __ srl_ptr(addr, CardTable::card_shift, addr);
+ __ srl_ptr(count, CardTable::card_shift, count);
+ __ sub(count, addr, count);
+ AddressLiteral rs(ct->byte_map_base());
+ __ set(rs, tmp);
+ __ BIND(L_loop);
+ __ stb(G0, tmp, addr);
+ __ subcc(count, 1, count);
+ __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
+ __ delayed()->add(addr, 1, addr);
+
+ __ BIND(L_done);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_SPARC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_SPARC_HPP
+#define CPU_SPARC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_SPARC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp);
+};
+
+#endif // CPU_SPARC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_SPARC_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+#define __ masm->
+
+void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {
+ if (type == T_OBJECT) {
+ bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
+ if (!checkcast) {
+ // save arguments for barrier generation
+ __ mov(dst, G1);
+ __ mov(count, G5);
+ gen_write_ref_array_pre_barrier(masm, decorators, G1, G5);
+ } else {
+ gen_write_ref_array_pre_barrier(masm, decorators, dst, count);
+ }
+ }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {
+ if (type == T_OBJECT) {
+ bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
+ if (!checkcast) {
+ // O0 is used as temp register
+ gen_write_ref_array_post_barrier(masm, decorators, G1, G5, O0);
+ } else {
+ gen_write_ref_array_post_barrier(masm, decorators, dst, count, O3);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_SPARC_GC_SHARED_MODREFBARRIERSETASSEMBLER_SPARC_HPP
+#define CPU_SPARC_GC_SHARED_MODREFBARRIERSETASSEMBLER_SPARC_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+class ModRefBarrierSetAssembler: public BarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count) {}
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) {}
+
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count);
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count);
+};
+
+#endif // CPU_SPARC_GC_SHARED_MODREFBARRIERSETASSEMBLER_SPARC_HPP
--- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -24,8 +24,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_sparc.hpp"
#include "oops/instanceOop.hpp"
@@ -823,125 +823,6 @@
__ delayed()->nop();
}
- //
- // Generate pre-write barrier for array.
- //
- // Input:
- // addr - register containing starting address
- // count - register containing element count
- // tmp - scratch register
- //
- // The input registers are overwritten.
- //
- void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- // With G1, don't generate the call if we statically know that the target in uninitialized
- if (!dest_uninitialized) {
- Register tmp = O5;
- assert_different_registers(addr, count, tmp);
- Label filtered;
- // Is marking active?
- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
- __ ld(G2, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), tmp);
- } else {
- guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
- "Assumption");
- __ ldsb(G2, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), tmp);
- }
- // Is marking active?
- __ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
-
- __ save_frame(0);
- // Save the necessary global regs... will be used after.
- if (addr->is_global()) {
- __ mov(addr, L0);
- }
- if (count->is_global()) {
- __ mov(count, L1);
- }
- __ mov(addr->after_save(), O0);
- // Get the count into O1
- __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre));
- __ delayed()->mov(count->after_save(), O1);
- if (addr->is_global()) {
- __ mov(L0, addr);
- }
- if (count->is_global()) {
- __ mov(L1, count);
- }
- __ restore();
-
- __ bind(filtered);
- DEBUG_ONLY(__ set(0xDEADC0DE, tmp);) // we have killed tmp
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- break;
- default:
- ShouldNotReachHere();
- }
- }
- //
- // Generate post-write barrier for array.
- //
- // Input:
- // addr - register containing starting address
- // count - register containing element count
- // tmp - scratch register
- //
- // The input registers are overwritten.
- //
- void gen_write_ref_array_post_barrier(Register addr, Register count,
- Register tmp) {
- BarrierSet* bs = Universe::heap()->barrier_set();
-
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- {
- // Get some new fresh output registers.
- __ save_frame(0);
- __ mov(addr->after_save(), O0);
- __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post));
- __ delayed()->mov(count->after_save(), O1);
- __ restore();
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- {
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
- assert_different_registers(addr, count, tmp);
-
- Label L_loop, L_done;
-
- __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_done); // zero count - nothing to do
-
- __ sll_ptr(count, LogBytesPerHeapOop, count);
- __ sub(count, BytesPerHeapOop, count);
- __ add(count, addr, count);
- // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
- __ srl_ptr(addr, CardTable::card_shift, addr);
- __ srl_ptr(count, CardTable::card_shift, count);
- __ sub(count, addr, count);
- AddressLiteral rs(ct->byte_map_base());
- __ set(rs, tmp);
- __ BIND(L_loop);
- __ stb(G0, tmp, addr);
- __ subcc(count, 1, count);
- __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
- __ delayed()->add(addr, 1, addr);
- __ BIND(L_done);
- }
- break;
- case BarrierSet::ModRef:
- break;
- default:
- ShouldNotReachHere();
- }
- }
//
// Generate main code for disjoint arraycopy
@@ -2388,18 +2269,25 @@
BLOCK_COMMENT("Entry:");
}
- // save arguments for barrier generation
- __ mov(to, G1);
- __ mov(count, G5);
- gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
+
assert_clean_int(count, O3); // Make sure 'count' is clean int.
if (UseCompressedOops) {
generate_disjoint_int_copy_core(aligned);
} else {
generate_disjoint_long_copy_core(aligned);
}
- // O0 is used as temp register
- gen_write_ref_array_post_barrier(G1, G5, O0);
+
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, from, to, count);
// O3, O4 are used as temp registers
inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
@@ -2438,10 +2326,16 @@
array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
- // save arguments for barrier generation
- __ mov(to, G1);
- __ mov(count, G5);
- gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
if (UseCompressedOops) {
generate_conjoint_int_copy_core(aligned);
@@ -2449,8 +2343,7 @@
generate_conjoint_long_copy_core(aligned);
}
- // O0 is used as temp register
- gen_write_ref_array_post_barrier(G1, G5, O0);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, from, to, count);
// O3, O4 are used as temp registers
inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
@@ -2552,9 +2445,16 @@
// caller can pass a 64-bit byte count here (from generic stub)
BLOCK_COMMENT("Entry:");
}
- gen_write_ref_array_pre_barrier(O1_to, O2_count, dest_uninitialized);
-
- Label load_element, store_element, do_card_marks, fail, done;
+
+ DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
+
+ Label load_element, store_element, do_epilogue, fail, done;
__ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
__ brx(Assembler::notZero, false, Assembler::pt, load_element);
__ delayed()->mov(G0, O5_offset); // offset from start of arrays
@@ -2576,7 +2476,7 @@
__ deccc(G1_remain); // decrement the count
__ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
__ inc(O5_offset, heapOopSize); // step to next offset
- __ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
+ __ brx(Assembler::zero, true, Assembler::pt, do_epilogue);
__ delayed()->set(0, O0); // return -1 on success
// ======== loop entry is here ========
@@ -2600,8 +2500,8 @@
__ brx(Assembler::zero, false, Assembler::pt, done);
__ delayed()->not1(O2_count, O0); // report (-1^K) to caller
- __ BIND(do_card_marks);
- gen_write_ref_array_post_barrier(O1_to, O2_count, O3); // store check on O1[0..O2]
+ __ BIND(do_epilogue);
+ bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
__ BIND(done);
inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "interpreter/interp_masm.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/macros.hpp"
+
+#define __ masm->
+
+void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count) {
+ bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+
+ if (!dest_uninitialized) {
+ Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+#ifndef _LP64
+ __ push(thread);
+ __ get_thread(thread);
+#endif
+
+ Label filtered;
+ Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active()));
+ // Is marking active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ cmpl(in_progress, 0);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ cmpb(in_progress, 0);
+ }
+
+ NOT_LP64(__ pop(thread);)
+
+ __ jcc(Assembler::equal, filtered);
+
+ __ pusha(); // push registers
+#ifdef _LP64
+ if (count == c_rarg0) {
+ if (addr == c_rarg1) {
+ // exactly backwards!!
+ __ xchgptr(c_rarg1, c_rarg0);
+ } else {
+ __ movptr(c_rarg1, count);
+ __ movptr(c_rarg0, addr);
+ }
+ } else {
+ __ movptr(c_rarg0, addr);
+ __ movptr(c_rarg1, count);
+ }
+ if (UseCompressedOops) {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry), 2);
+ } else {
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), 2);
+ }
+#else
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry),
+ addr, count);
+#endif
+ __ popa();
+
+ __ bind(filtered);
+ }
+}
+
+void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {
+ __ pusha(); // push registers (overkill)
+#ifdef _LP64
+ if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
+ assert_different_registers(c_rarg1, addr);
+ __ mov(c_rarg1, count);
+ __ mov(c_rarg0, addr);
+ } else {
+ assert_different_registers(c_rarg0, count);
+ __ mov(c_rarg0, addr);
+ __ mov(c_rarg1, count);
+ }
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), 2);
+#else
+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry),
+ addr, count);
+#endif
+ __ popa();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_GC_G1_G1BARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_G1_G1BARRIERSETASSEMBLER_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
+ protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count);
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp);
+};
+
+#endif // CPU_X86_GC_G1_G1BARRIERSETASSEMBLER_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_GC_G1_BARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_G1_BARRIERSETASSEMBLER_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "memory/allocation.hpp"
+#include "oops/access.hpp"
+
+class InterpreterMacroAssembler;
+
+class BarrierSetAssembler: public CHeapObj<mtGC> {
+protected:
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {}
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {}
+};
+
+#endif // CPU_X86_GC_G1_BARRIERSETASSEMBLER_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
+#include "gc/shared/collectedHeap.hpp"
+
+#define __ masm->
+
+#ifdef PRODUCT
+#define BLOCK_COMMENT(str) /* nothing */
+#else
+#define BLOCK_COMMENT(str) __ block_comment(str)
+#endif
+
+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
+
+#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8)
+
+void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+ Register addr, Register count, Register tmp) {
+ BarrierSet *bs = Universe::heap()->barrier_set();
+ CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
+ CardTable* ct = ctbs->card_table();
+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+ intptr_t disp = (intptr_t) ct->byte_map_base();
+
+ Label L_loop, L_done;
+ const Register end = count;
+ assert_different_registers(addr, end);
+
+ __ testl(count, count);
+ __ jcc(Assembler::zero, L_done); // zero count - nothing to do
+
+
+#ifdef _LP64
+ __ leaq(end, Address(addr, count, TIMES_OOP, 0)); // end == addr+count*oop_size
+ __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
+ __ shrptr(addr, CardTable::card_shift);
+ __ shrptr(end, CardTable::card_shift);
+ __ subptr(end, addr); // end --> cards count
+
+ __ mov64(tmp, disp);
+ __ addptr(addr, tmp);
+__ BIND(L_loop);
+ __ movb(Address(addr, count, Address::times_1), 0);
+ __ decrement(count);
+ __ jcc(Assembler::greaterEqual, L_loop);
+#else
+ __ lea(end, Address(addr, count, Address::times_ptr, -wordSize));
+ __ shrptr(addr, CardTable::card_shift);
+ __ shrptr(end, CardTable::card_shift);
+ __ subptr(end, addr); // end --> count
+__ BIND(L_loop);
+ Address cardtable(addr, count, Address::times_1, disp);
+ __ movb(cardtable, 0);
+ __ decrement(count);
+ __ jcc(Assembler::greaterEqual, L_loop);
+#endif
+
+__ BIND(L_done);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr,
+ Register count, Register tmp);
+};
+
+#endif // CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/modRefBarrierSetAssembler.hpp"
+
+#define __ masm->
+
+void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {
+ bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
+ bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0;
+ bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops);
+
+ if (type == T_OBJECT || type == T_ARRAY) {
+#ifdef _LP64
+ if (!checkcast && !obj_int) {
+ // Save count for barrier
+ __ movptr(r11, count);
+ } else if (disjoint && obj_int) {
+ // Save dst in r11 in the disjoint case
+ __ movq(r11, dst);
+ }
+#else
+ if (disjoint) {
+ __ mov(rdx, dst); // save 'to'
+ }
+#endif
+ gen_write_ref_array_pre_barrier(masm, decorators, dst, count);
+ }
+}
+
+void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count) {
+ bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0;
+ bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0;
+ bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops);
+ Register tmp = rax;
+
+ if (type == T_OBJECT || type == T_ARRAY) {
+#ifdef _LP64
+ if (!checkcast && !obj_int) {
+ // Save count for barrier
+ count = r11;
+ } else if (disjoint && obj_int) {
+ // Use the saved dst in the disjoint case
+ dst = r11;
+ } else if (checkcast) {
+ tmp = rscratch1;
+ }
+#else
+ if (disjoint) {
+ __ mov(dst, rdx); // restore 'to'
+ }
+#endif
+ gen_write_ref_array_post_barrier(masm, decorators, dst, count, tmp);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+class ModRefBarrierSetAssembler: public BarrierSetAssembler {
+protected:
+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count) {}
+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) {}
+
+public:
+ virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count);
+ virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+ Register src, Register dst, Register count);
+};
+
+#endif // CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -25,8 +25,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_x86.hpp"
#include "oops/instanceOop.hpp"
@@ -668,107 +668,6 @@
return start;
}
- //
- // Generate pre-barrier for array stores
- //
- // Input:
- // start - starting address
- // count - element count
- void gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) {
- assert_different_registers(start, count);
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
-#if INCLUDE_ALL_GCS
- case BarrierSet::G1BarrierSet:
- // With G1, don't generate the call if we statically know that the target in uninitialized
- if (!uninitialized_target) {
- Register thread = rax;
- Label filtered;
- __ push(thread);
- __ get_thread(thread);
- Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
- SATBMarkQueue::byte_offset_of_active()));
- // Is marking active?
- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
- __ cmpl(in_progress, 0);
- } else {
- assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
- __ cmpb(in_progress, 0);
- }
- __ pop(thread);
- __ jcc(Assembler::equal, filtered);
-
- __ pusha(); // push registers
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
- start, count);
- __ popa();
-
- __ bind(filtered);
- }
- break;
-#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableBarrierSet:
- break;
- default :
- ShouldNotReachHere();
-
- }
- }
-
-
- //
- // Generate a post-barrier for an array store
- //
- // start - starting address
- // count - element count
- //
- // The two input registers are overwritten.
- //
- void gen_write_ref_array_post_barrier(Register start, Register count) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert_different_registers(start, count);
- switch (bs->kind()) {
-#if INCLUDE_ALL_GCS
- case BarrierSet::G1BarrierSet:
- {
- __ pusha(); // push registers
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post),
- start, count);
- __ popa();
- }
- break;
-#endif // INCLUDE_ALL_GCS
-
- case BarrierSet::CardTableBarrierSet:
- {
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
- Label L_loop;
- const Register end = count; // elements count; end == start+count-1
- assert_different_registers(start, end);
-
- __ lea(end, Address(start, count, Address::times_ptr, -wordSize));
- __ shrptr(start, CardTable::card_shift);
- __ shrptr(end, CardTable::card_shift);
- __ subptr(end, start); // end --> count
- __ BIND(L_loop);
- intptr_t disp = (intptr_t) ct->byte_map_base();
- Address cardtable(start, count, Address::times_1, disp);
- __ movb(cardtable, 0);
- __ decrement(count);
- __ jcc(Assembler::greaterEqual, L_loop);
- }
- break;
- case BarrierSet::ModRef:
- break;
- default :
- ShouldNotReachHere();
-
- }
- }
-
// Copy 64 bytes chunks
//
@@ -936,9 +835,18 @@
if (t == T_OBJECT) {
__ testl(count, count);
__ jcc(Assembler::zero, L_0_count);
- gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
- __ mov(saved_to, to); // save 'to'
+ }
+
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
}
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, t, from, to, count);
__ subptr(to, from); // to --> to_from
__ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
@@ -1024,10 +932,10 @@
__ BIND(L_copy_2_bytes);
}
+ __ movl(count, Address(rsp, 12+12)); // reread 'count'
+ bs->arraycopy_epilogue(_masm, decorators, t, from, to, count);
+
if (t == T_OBJECT) {
- __ movl(count, Address(rsp, 12+12)); // reread 'count'
- __ mov(to, saved_to); // restore 'to'
- gen_write_ref_array_post_barrier(to, count);
__ BIND(L_0_count);
}
inc_copy_counter_np(t);
@@ -1116,8 +1024,18 @@
if (t == T_OBJECT) {
__ testl(count, count);
__ jcc(Assembler::zero, L_0_count);
- gen_write_ref_array_pre_barrier(dst, count, dest_uninitialized);
+ }
+
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
}
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, t, from, to, count);
// copy from high to low
__ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
@@ -1216,9 +1134,11 @@
} else {
__ BIND(L_copy_2_bytes);
}
+
+ __ movl2ptr(count, Address(rsp, 12+12)); // reread count
+ bs->arraycopy_epilogue(_masm, decorators, t, from, to, count);
+
if (t == T_OBJECT) {
- __ movl2ptr(count, Address(rsp, 12+12)); // reread count
- gen_write_ref_array_post_barrier(to, count);
__ BIND(L_0_count);
}
inc_copy_counter_np(t);
@@ -1463,8 +1383,16 @@
Address to_element_addr(end_to, count, Address::times_ptr, 0);
Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes());
+ DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+
+ BasicType type = T_OBJECT;
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
+
// Copy from low to high addresses, indexed from the end of each array.
- gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
__ lea(end_from, end_from_addr);
__ lea(end_to, end_to_addr);
assert(length == count, ""); // else fix next line:
@@ -1521,7 +1449,7 @@
__ BIND(L_post_barrier);
__ movptr(to, to_arg); // reload
- gen_write_ref_array_post_barrier(to, count);
+ bs->arraycopy_epilogue(_masm, decorators, type, from, to, count);
// Common exit point (success or failure).
__ BIND(L_done);
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -26,8 +26,8 @@
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "ci/ciUtilities.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_x86.hpp"
#include "oops/instanceOop.hpp"
@@ -1190,119 +1190,6 @@
#endif
}
- // Generate code for an array write pre barrier
- //
- // addr - starting address
- // count - element count
- // tmp - scratch register
- //
- // Destroy no registers!
- //
- void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- // With G1, don't generate the call if we statically know that the target in uninitialized
- if (!dest_uninitialized) {
- Label filtered;
- Address in_progress(r15_thread, in_bytes(JavaThread::satb_mark_queue_offset() +
- SATBMarkQueue::byte_offset_of_active()));
- // Is marking active?
- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
- __ cmpl(in_progress, 0);
- } else {
- assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
- __ cmpb(in_progress, 0);
- }
- __ jcc(Assembler::equal, filtered);
-
- __ pusha(); // push registers
- if (count == c_rarg0) {
- if (addr == c_rarg1) {
- // exactly backwards!!
- __ xchgptr(c_rarg1, c_rarg0);
- } else {
- __ movptr(c_rarg1, count);
- __ movptr(c_rarg0, addr);
- }
- } else {
- __ movptr(c_rarg0, addr);
- __ movptr(c_rarg1, count);
- }
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
- __ popa();
-
- __ bind(filtered);
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- break;
- default:
- ShouldNotReachHere();
-
- }
- }
-
- //
- // Generate code for an array write post barrier
- //
- // Input:
- // start - register containing starting address of destination array
- // count - elements count
- // scratch - scratch register
- //
- // The input registers are overwritten.
- //
- void gen_write_ref_array_post_barrier(Register start, Register count, Register scratch) {
- assert_different_registers(start, count, scratch);
- BarrierSet* bs = Universe::heap()->barrier_set();
- switch (bs->kind()) {
- case BarrierSet::G1BarrierSet:
- {
- __ pusha(); // push registers (overkill)
- if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
- assert_different_registers(c_rarg1, start);
- __ mov(c_rarg1, count);
- __ mov(c_rarg0, start);
- } else {
- assert_different_registers(c_rarg0, count);
- __ mov(c_rarg0, start);
- __ mov(c_rarg1, count);
- }
- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2);
- __ popa();
- }
- break;
- case BarrierSet::CardTableBarrierSet:
- {
- Label L_loop, L_done;
- const Register end = count;
-
- __ testl(count, count);
- __ jcc(Assembler::zero, L_done); // zero count - nothing to do
-
- __ leaq(end, Address(start, count, TIMES_OOP, 0)); // end == start+count*oop_size
- __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
- __ shrptr(start, CardTable::card_shift);
- __ shrptr(end, CardTable::card_shift);
- __ subptr(end, start); // end --> cards count
-
- int64_t disp = ci_card_table_address_as<int64_t>();
- __ mov64(scratch, disp);
- __ addptr(start, scratch);
- __ BIND(L_loop);
- __ movb(Address(start, count, Address::times_1), 0);
- __ decrement(count);
- __ jcc(Assembler::greaterEqual, L_loop);
- __ BIND(L_done);
- }
- break;
- default:
- ShouldNotReachHere();
-
- }
- }
-
// Copy big chunks forward
//
@@ -1918,7 +1805,6 @@
const Register qword_count = count;
const Register end_from = from; // source array end address
const Register end_to = to; // destination array end address
- const Register saved_to = r11; // saved destination array address
// End pointers are inclusive, and if count is not zero they point
// to the last unit copied: end_to[0] := end_from[0]
@@ -1933,10 +1819,18 @@
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
- if (is_oop) {
- __ movq(saved_to, to);
- gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
+
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
}
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BasicType type = is_oop ? T_OBJECT : T_INT;
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
// 'from', 'to' and 'count' are now valid
__ movptr(dword_count, count);
@@ -1963,9 +1857,7 @@
__ movl(Address(end_to, 8), rax);
__ BIND(L_exit);
- if (is_oop) {
- gen_write_ref_array_post_barrier(saved_to, dword_count, rax);
- }
+ bs->arraycopy_epilogue(_masm, decorators, type, from, to, dword_count);
restore_arg_regs();
inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free
__ vzeroupper();
@@ -2022,10 +1914,18 @@
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
- if (is_oop) {
- // no registers are destroyed by this call
- gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
}
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BasicType type = is_oop ? T_OBJECT : T_INT;
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ // no registers are destroyed by this call
+ bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
assert_clean_int(count, rax); // Make sure 'count' is clean int.
// 'from', 'to' and 'count' are now valid
@@ -2062,9 +1962,7 @@
copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
__ BIND(L_exit);
- if (is_oop) {
- gen_write_ref_array_post_barrier(to, dword_count, rax);
- }
+ bs->arraycopy_epilogue(_masm, decorators, type, from, to, dword_count);
restore_arg_regs();
inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free
__ xorptr(rax, rax); // return 0
@@ -2102,7 +2000,6 @@
const Register qword_count = rdx; // elements count
const Register end_from = from; // source array end address
const Register end_to = rcx; // destination array end address
- const Register saved_to = to;
const Register saved_count = r11;
// End pointers are inclusive, and if count is not zero they point
// to the last unit copied: end_to[0] := end_from[0]
@@ -2120,12 +2017,18 @@
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
// 'from', 'to' and 'qword_count' are now valid
- if (is_oop) {
- // Save to and count for store barrier
- __ movptr(saved_count, qword_count);
- // no registers are destroyed by this call
- gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized);
+
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
}
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BasicType type = is_oop ? T_OBJECT : T_LONG;
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, type, from, to, qword_count);
// Copy from low to high addresses. Use 'to' as scratch.
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
@@ -2154,10 +2057,8 @@
// Copy in multi-bytes chunks
copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
- if (is_oop) {
__ BIND(L_exit);
- gen_write_ref_array_post_barrier(saved_to, saved_count, rax);
- }
+ bs->arraycopy_epilogue(_masm, decorators, type, from, to, qword_count);
restore_arg_regs();
if (is_oop) {
inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free
@@ -2209,12 +2110,18 @@
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
// 'from', 'to' and 'qword_count' are now valid
- if (is_oop) {
- // Save to and count for store barrier
- __ movptr(saved_count, qword_count);
- // No registers are destroyed by this call
- gen_write_ref_array_pre_barrier(to, saved_count, dest_uninitialized);
+
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
}
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+
+ BasicType type = is_oop ? T_OBJECT : T_LONG;
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, type, from, to, qword_count);
__ jmp(L_copy_bytes);
@@ -2239,10 +2146,8 @@
// Copy in multi-bytes chunks
copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
- if (is_oop) {
__ BIND(L_exit);
- gen_write_ref_array_post_barrier(to, saved_count, rax);
- }
+ bs->arraycopy_epilogue(_masm, decorators, type, from, to, qword_count);
restore_arg_regs();
if (is_oop) {
inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free
@@ -2389,7 +2294,14 @@
Address from_element_addr(end_from, count, TIMES_OOP, 0);
Address to_element_addr(end_to, count, TIMES_OOP, 0);
- gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
+ DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+
+ BasicType type = T_OBJECT;
+ BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
// Copy from low to high addresses, indexed from the end of each array.
__ lea(end_from, end_from_addr);
@@ -2442,7 +2354,7 @@
__ xorptr(rax, rax); // return 0 on success
__ BIND(L_post_barrier);
- gen_write_ref_array_post_barrier(to, r14_length, rscratch1);
+ bs->arraycopy_epilogue(_masm, decorators, type, from, to, r14_length);
// Common exit point (success or failure).
__ BIND(L_done);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/zero/gc/g1/g1BarrierSetAssembler_zero.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ZERO_GC_G1_G1BARRIERSETASSEMBLER_ZERO_HPP
+#define CPU_ZERO_GC_G1_G1BARRIERSETASSEMBLER_ZERO_HPP
+
+class G1BarrierSetAssembler;
+
+#endif // CPU_ZERO_GC_G1_G1BARRIERSETASSEMBLER_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/zero/gc/shared/barrierSetAssembler_zero.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ZERO_GC_G1_BARRIERSETASSEMBLER_ZERO_HPP
+#define CPU_ZERO_GC_G1_BARRIERSETASSEMBLER_ZERO_HPP
+
+class BarrierSetAssembler;
+
+#endif // CPU_ZERO_GC_G1_BARRIERSETASSEMBLER_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/zero/gc/shared/cardTableBarrierSetAssembler_zero.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ZERO_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_ZERO_HPP
+#define CPU_ZERO_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_ZERO_HPP
+
+class CardTableBarrierSetAssembler;
+
+#endif // CPU_ZERO_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_ZERO_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/zero/gc/shared/modRefBarrierSetAssembler_zero.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_ZERO_GC_SHARED_MODREFBARRIERSETASSEMBLER_ZERO_HPP
+#define CPU_ZERO_GC_SHARED_MODREFBARRIERSETASSEMBLER_ZERO_HPP
+
+class ModRefBarrierSetAssembler;
+
+#endif // CPU_ZERO_GC_SHARED_MODREFBARRIERSETASSEMBLER_ZERO_HPP
--- a/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "gc/shared/barrierSet.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/cardTableBarrierSet.inline.hpp"
#include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1BarrierSet.inline.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
#include "gc/g1/g1CardTable.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/heapRegion.hpp"
@@ -32,9 +33,12 @@
#include "oops/oop.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.inline.hpp"
+#include "utilities/macros.hpp"
G1BarrierSet::G1BarrierSet(G1CardTable* card_table) :
- CardTableBarrierSet(card_table, BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)),
+ CardTableBarrierSet(make_barrier_set_assembler<G1BarrierSetAssembler>(),
+ card_table,
+ BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)),
_dcqs(JavaThread::dirty_card_queue_set())
{ }
@@ -53,11 +57,26 @@
}
}
+void G1BarrierSet::write_ref_array_pre_oop_entry(oop* dst, size_t length) {
+ G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+ bs->write_ref_array_pre(dst, length, false);
+}
+
+void G1BarrierSet::write_ref_array_pre_narrow_oop_entry(narrowOop* dst, size_t length) {
+ G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+ bs->write_ref_array_pre(dst, length, false);
+}
+
+void G1BarrierSet::write_ref_array_post_entry(HeapWord* dst, size_t length) {
+ G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+ bs->G1BarrierSet::write_ref_array(dst, length);
+}
+
template <class T> void
-G1BarrierSet::write_ref_array_pre_work(T* dst, int count) {
+G1BarrierSet::write_ref_array_pre_work(T* dst, size_t count) {
if (!JavaThread::satb_mark_queue_set().is_active()) return;
T* elem_ptr = dst;
- for (int i = 0; i < count; i++, elem_ptr++) {
+ for (size_t i = 0; i < count; i++, elem_ptr++) {
T heap_oop = oopDesc::load_heap_oop(elem_ptr);
if (!oopDesc::is_null(heap_oop)) {
enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
@@ -65,13 +84,13 @@
}
}
-void G1BarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
+void G1BarrierSet::write_ref_array_pre(oop* dst, size_t count, bool dest_uninitialized) {
if (!dest_uninitialized) {
write_ref_array_pre_work(dst, count);
}
}
-void G1BarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
+void G1BarrierSet::write_ref_array_pre(narrowOop* dst, size_t count, bool dest_uninitialized) {
if (!dest_uninitialized) {
write_ref_array_pre_work(dst, count);
}
--- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -49,9 +49,13 @@
static void enqueue_if_weak_or_archive(DecoratorSet decorators, oop value);
- template <class T> void write_ref_array_pre_work(T* dst, int count);
- virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized);
- virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized);
+ template <class T> void write_ref_array_pre_work(T* dst, size_t count);
+ virtual void write_ref_array_pre(oop* dst, size_t count, bool dest_uninitialized);
+ virtual void write_ref_array_pre(narrowOop* dst, size_t count, bool dest_uninitialized);
+
+ static void write_ref_array_pre_oop_entry(oop* dst, size_t length);
+ static void write_ref_array_pre_narrow_oop_entry(narrowOop* dst, size_t length);
+ static void write_ref_array_post_entry(HeapWord* dst, size_t length);
template <DecoratorSet decorators, typename T>
void write_ref_field_pre(T* field);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1BarrierSetAssembler.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_G1BARRIERSETASSEMBLER_HPP
+#define SHARE_GC_SHARED_G1BARRIERSETASSEMBLER_HPP
+
+#include "utilities/macros.hpp"
+
+#include CPU_HEADER(gc/g1/g1BarrierSetAssembler)
+
+#endif // SHARE_GC_SHARED_G1BARRIERSETASSEMBLER_HPP
--- a/src/hotspot/share/gc/shared/barrierSet.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/barrierSet.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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
@@ -23,24 +23,6 @@
*/
#include "precompiled.hpp"
-#include "gc/shared/barrierSet.inline.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "memory/universe.hpp"
+#include "gc/shared/barrierSet.hpp"
BarrierSet* BarrierSet::_bs = NULL;
-
-// count is number of array elements being written
-void BarrierSet::static_write_ref_array_pre(HeapWord* start, size_t count) {
- assert(count <= (size_t)max_intx, "count too large");
- if (UseCompressedOops) {
- Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count, false);
- } else {
- Universe::heap()->barrier_set()->write_ref_array_pre( (oop*)start, (int)count, false);
- }
-}
-
-// count is number of array elements being written
-void BarrierSet::static_write_ref_array_post(HeapWord* start, size_t count) {
- // simply delegate to instance method
- Universe::heap()->barrier_set()->write_ref_array(start, count);
-}
--- a/src/hotspot/share/gc/shared/barrierSet.hpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -31,8 +31,10 @@
#include "oops/accessBackend.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/fakeRttiSupport.hpp"
+#include "utilities/macros.hpp"
class JavaThread;
+class BarrierSetAssembler;
// This class provides the interface between a barrier implementation and
// the rest of the system.
@@ -67,6 +69,7 @@
private:
FakeRtti _fake_rtti;
+ BarrierSetAssembler* _barrier_set_assembler;
public:
// Metafunction mapping a class derived from BarrierSet to the
@@ -87,28 +90,17 @@
// End of fake RTTI support.
protected:
- BarrierSet(const FakeRtti& fake_rtti) : _fake_rtti(fake_rtti) { }
+ BarrierSet(BarrierSetAssembler* barrier_set_assembler, const FakeRtti& fake_rtti) :
+ _fake_rtti(fake_rtti),
+ _barrier_set_assembler(barrier_set_assembler) { }
~BarrierSet() { }
+ template <class BarrierSetAssemblerT>
+ BarrierSetAssembler* make_barrier_set_assembler() {
+ return NOT_ZERO(new BarrierSetAssemblerT()) ZERO_ONLY(NULL);
+ }
+
public:
- // Operations on arrays, or general regions (e.g., for "clone") may be
- // optimized by some barriers.
-
- // Below length is the # array elements being written
- virtual void write_ref_array_pre(oop* dst, int length,
- bool dest_uninitialized = false) {}
- virtual void write_ref_array_pre(narrowOop* dst, int length,
- bool dest_uninitialized = false) {}
- // Below count is the # array elements being written, starting
- // at the address "start", which may not necessarily be HeapWord-aligned
- inline void write_ref_array(HeapWord* start, size_t count);
-
- // Static versions, suitable for calling from generated code;
- // count is # array elements being written, starting with "start",
- // which may not necessarily be HeapWord-aligned.
- static void static_write_ref_array_pre(HeapWord* start, size_t count);
- static void static_write_ref_array_post(HeapWord* start, size_t count);
-
// Support for optimizing compilers to call the barrier set on slow path allocations
// that did not enter a TLAB. Used for e.g. ReduceInitialCardMarks.
// The allocation is safe to use iff it returns true. If not, the slow-path allocation
@@ -119,15 +111,17 @@
virtual void on_thread_detach(JavaThread* thread) {}
virtual void make_parsable(JavaThread* thread) {}
-protected:
- virtual void write_ref_array_work(MemRegion mr) = 0;
-
public:
// Print a description of the memory for the barrier set
virtual void print_on(outputStream* st) const = 0;
static void set_bs(BarrierSet* bs) { _bs = bs; }
+ BarrierSetAssembler* barrier_set_assembler() {
+ assert(_barrier_set_assembler != NULL, "should be set");
+ return _barrier_set_assembler;
+ }
+
// The AccessBarrier of a BarrierSet subclass is called by the Access API
// (cf. oops/access.hpp) to perform decorated accesses. GC implementations
// may override these default access operations by declaring an
--- a/src/hotspot/share/gc/shared/barrierSet.inline.hpp Thu Mar 22 08:39:51 2018 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_SHARED_BARRIERSET_INLINE_HPP
-#define SHARE_VM_GC_SHARED_BARRIERSET_INLINE_HPP
-
-#include "gc/shared/barrierSet.hpp"
-#include "utilities/align.hpp"
-
-// count is number of array elements being written
-void BarrierSet::write_ref_array(HeapWord* start, size_t count) {
- assert(count <= (size_t)max_intx, "count too large");
- HeapWord* end = (HeapWord*)((char*)start + (count*heapOopSize));
- // In the case of compressed oops, start and end may potentially be misaligned;
- // so we need to conservatively align the first downward (this is not
- // strictly necessary for current uses, but a case of good hygiene and,
- // if you will, aesthetics) and the second upward (this is essential for
- // current uses) to a HeapWord boundary, so we mark all cards overlapping
- // this write. If this evolves in the future to calling a
- // logging barrier of narrow oop granularity, like the pre-barrier for G1
- // (mentioned here merely by way of example), we will need to change this
- // interface, so it is "exactly precise" (if i may be allowed the adverbial
- // redundancy for emphasis) and does not include narrow oop slots not
- // included in the original write interval.
- HeapWord* aligned_start = align_down(start, HeapWordSize);
- HeapWord* aligned_end = align_up (end, HeapWordSize);
- // If compressed oops were not being used, these should already be aligned
- assert(UseCompressedOops || (aligned_start == start && aligned_end == end),
- "Expected heap word alignment of start and end");
- write_ref_array_work(MemRegion(aligned_start, aligned_end));
-}
-
-#endif // SHARE_VM_GC_SHARED_BARRIERSET_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/barrierSetAssembler.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_BARRIERSETASSEMBLER_HPP
+#define SHARE_GC_SHARED_BARRIERSETASSEMBLER_HPP
+
+#include "utilities/macros.hpp"
+
+#include CPU_HEADER(gc/shared/barrierSetAssembler)
+
+#endif // SHARE_GC_SHARED_BARRIERSETASSEMBLER_HPP
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "gc/shared/cardTableBarrierSetAssembler.hpp"
#include "gc/shared/cardTableBarrierSet.inline.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/genCollectedHeap.hpp"
@@ -39,16 +40,18 @@
// enumerate ref fields that have been modified (since the last
// enumeration.)
-CardTableBarrierSet::CardTableBarrierSet(
- CardTable* card_table,
- const BarrierSet::FakeRtti& fake_rtti) :
- ModRefBarrierSet(fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)),
+CardTableBarrierSet::CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler,
+ CardTable* card_table,
+ const BarrierSet::FakeRtti& fake_rtti) :
+ ModRefBarrierSet(barrier_set_assembler,
+ fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)),
_defer_initial_card_mark(false),
_card_table(card_table)
{}
CardTableBarrierSet::CardTableBarrierSet(CardTable* card_table) :
- ModRefBarrierSet(BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)),
+ ModRefBarrierSet(make_barrier_set_assembler<CardTableBarrierSetAssembler>(),
+ BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)),
_defer_initial_card_mark(false),
_card_table(card_table)
{}
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -52,7 +52,9 @@
bool _defer_initial_card_mark;
CardTable* _card_table;
- CardTableBarrierSet(CardTable* card_table, const BarrierSet::FakeRtti& fake_rtti);
+ CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler,
+ CardTable* card_table,
+ const BarrierSet::FakeRtti& fake_rtti);
public:
CardTableBarrierSet(CardTable* card_table);
@@ -66,7 +68,6 @@
invalidate(mr);
}
- protected:
void write_ref_array_work(MemRegion mr);
public:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSetAssembler.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_HPP
+#define SHARE_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_HPP
+
+#include "utilities/macros.hpp"
+
+#include CPU_HEADER(gc/shared/cardTableBarrierSetAssembler)
+
+#endif // SHARE_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_HPP
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Wed Mar 21 14:38:32 2018 +0100
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/allocTracer.hpp"
-#include "gc/shared/barrierSet.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/gcLocker.inline.hpp"
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -32,8 +32,10 @@
class ModRefBarrierSet: public BarrierSet {
protected:
- ModRefBarrierSet(const BarrierSet::FakeRtti& fake_rtti)
- : BarrierSet(fake_rtti.add_tag(BarrierSet::ModRef)) { }
+ ModRefBarrierSet(BarrierSetAssembler* barrier_set_assembler,
+ const BarrierSet::FakeRtti& fake_rtti)
+ : BarrierSet(barrier_set_assembler,
+ fake_rtti.add_tag(BarrierSet::ModRef)) { }
~ModRefBarrierSet() { }
public:
@@ -47,6 +49,22 @@
virtual void invalidate(MemRegion mr) = 0;
virtual void write_region(MemRegion mr) = 0;
+ // Operations on arrays, or general regions (e.g., for "clone") may be
+ // optimized by some barriers.
+
+ // Below length is the # array elements being written
+ virtual void write_ref_array_pre(oop* dst, size_t length,
+ bool dest_uninitialized = false) {}
+ virtual void write_ref_array_pre(narrowOop* dst, size_t length,
+ bool dest_uninitialized = false) {}
+ // Below count is the # array elements being written, starting
+ // at the address "start", which may not necessarily be HeapWord-aligned
+ inline void write_ref_array(HeapWord* start, size_t count);
+
+ protected:
+ virtual void write_ref_array_work(MemRegion mr) = 0;
+
+ public:
// The ModRef abstraction introduces pre and post barriers
template <DecoratorSet decorators, typename BarrierSetT>
class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> {
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp Thu Mar 22 08:39:51 2018 +0100
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -25,12 +25,34 @@
#ifndef SHARE_VM_GC_SHARED_MODREFBARRIERSET_INLINE_HPP
#define SHARE_VM_GC_SHARED_MODREFBARRIERSET_INLINE_HPP
-#include "gc/shared/barrierSet.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
#include "gc/shared/modRefBarrierSet.hpp"
#include "oops/klass.inline.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.hpp"
+// count is number of array elements being written
+void ModRefBarrierSet::write_ref_array(HeapWord* start, size_t count) {
+ HeapWord* end = (HeapWord*)((char*)start + (count*heapOopSize));
+ // In the case of compressed oops, start and end may potentially be misaligned;
+ // so we need to conservatively align the first downward (this is not
+ // strictly necessary for current uses, but a case of good hygiene and,
+ // if you will, aesthetics) and the second upward (this is essential for
+ // current uses) to a HeapWord boundary, so we mark all cards overlapping
+ // this write. If this evolves in the future to calling a
+ // logging barrier of narrow oop granularity, like the pre-barrier for G1
+ // (mentioned here merely by way of example), we will need to change this
+ // interface, so it is "exactly precise" (if i may be allowed the adverbial
+ // redundancy for emphasis) and does not include narrow oop slots not
+ // included in the original write interval.
+ HeapWord* aligned_start = align_down(start, HeapWordSize);
+ HeapWord* aligned_end = align_up (end, HeapWordSize);
+ // If compressed oops were not being used, these should already be aligned
+ assert(UseCompressedOops || (aligned_start == start && aligned_end == end),
+ "Expected heap word alignment of start and end");
+ write_ref_array_work(MemRegion(aligned_start, aligned_end));
+}
+
template <DecoratorSet decorators, typename BarrierSetT>
template <typename T>
inline void ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT>::
@@ -73,7 +95,7 @@
if (!HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) {
// Optimized covariant case
- bs->write_ref_array_pre(dst, (int)length,
+ bs->write_ref_array_pre(dst, length,
HasDecorator<decorators, AS_DEST_NOT_INITIALIZED>::value);
Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length);
bs->write_ref_array((HeapWord*)dst, length);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/modRefBarrierSetAssembler.hpp Wed Mar 21 14:38:32 2018 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_MODREFBARRIERSETASSEMBLER_HPP
+#define SHARE_GC_SHARED_MODREFBARRIERSETASSEMBLER_HPP
+
+#include "utilities/macros.hpp"
+
+#include CPU_HEADER(gc/shared/modRefBarrierSetAssembler)
+
+#endif // SHARE_GC_SHARED_MODREFBARRIERSETASSEMBLER_HPP