< prev index next > src/hotspot/cpu/s390/stubGenerator_s390.cpp
8198949_arraycopy
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "registerSaver_s390.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableModRefBS.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetCodeGen.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interp_masm.hpp"
#include "nativeInst_s390.hpp"
#include "oops/instanceOop.hpp"
#include "oops/objArrayKlass.hpp"
address start = 0;
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::CardTableModRef:
- 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::CardTableModRef:
- // These cases formerly known as
- // void array_store_check(Register addr, Register count, bool branchToEnd).
- {
- NearLabel doXC, done;
- CardTableModRefBS* ctbs = barrier_set_cast<CardTableModRefBS>(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) {
#ifdef ASSERT
__ z_srag(Z_R0, count, 31); // Just leave the sign (must be zero) in Z_R0.
// This is the zarch specific stub generator for oop array copy.
// Refer to generate_disjoint_copy for a list of prereqs and features.
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);
+ BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
+ DecoratorSet decorators = ARRAYCOPY_DISJOINT;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+ 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);
}
: StubRoutines::oop_disjoint_arraycopy(dest_uninitialized);
// 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);
+ BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
+ DecoratorSet decorators = 0;
+ if (dest_uninitialized) {
+ decorators |= AS_DEST_NOT_INITIALIZED;
+ }
+ if (aligned) {
+ decorators |= ARRAYCOPY_ALIGNED;
+ }
+ 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);
}
< prev index next >