--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp Wed Apr 11 10:05:02 2018 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp Wed Apr 11 16:07:42 2018 +0200
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -27,7 +27,8 @@
#include "asm/codeBuffer.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "compiler/disassembler.hpp"
-#include "gc/shared/cardTable.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
@@ -51,11 +52,6 @@
#include "runtime/stubRoutines.hpp"
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/heapRegion.hpp"
-#endif
#include <ucontext.h>
@@ -3502,315 +3498,10 @@
// flag == NE indicates failure
}
-// Write to card table for modification at store_addr - register is destroyed afterwards.
-void MacroAssembler::card_write_barrier_post(Register store_addr, Register tmp) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- assert(bs->kind() == BarrierSet::CardTableBarrierSet, "wrong barrier");
- assert_different_registers(store_addr, tmp);
- z_srlg(store_addr, store_addr, CardTable::card_shift);
- load_absolute_address(tmp, (address)ct->byte_map_base());
- z_agr(store_addr, tmp);
- z_mvi(0, store_addr, 0); // Store byte 0.
-}
-
void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) {
- NearLabel Ldone;
- z_ltgr(tmp1, value);
- z_bre(Ldone); // Use NULL result as-is.
-
- z_nill(value, ~JNIHandles::weak_tag_mask);
- z_lg(value, 0, value); // Resolve (untagged) jobject.
-
-#if INCLUDE_ALL_GCS
- if (UseG1GC) {
- NearLabel Lnot_weak;
- z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag.
- z_braz(Lnot_weak);
- verify_oop(value);
- g1_write_barrier_pre(noreg /* obj */,
- noreg /* offset */,
- value /* pre_val */,
- noreg /* val */,
- tmp1 /* tmp1 */,
- tmp2 /* tmp2 */,
- true /* pre_val_needed */);
- bind(Lnot_weak);
- }
-#endif // INCLUDE_ALL_GCS
- verify_oop(value);
- bind(Ldone);
-}
-
-#if INCLUDE_ALL_GCS
-
-//------------------------------------------------------
-// General G1 pre-barrier generator.
-// Purpose: record the previous value if it is not null.
-// All non-tmps are preserved.
-//------------------------------------------------------
-// Note: Rpre_val needs special attention.
-// The flag pre_val_needed indicated that the caller of this emitter function
-// relies on Rpre_val containing the correct value, that is:
-// either the value it contained on entry to this code segment
-// or the value that was loaded into the register from (Robj+offset).
-//
-// Independent from this requirement, the contents of Rpre_val must survive
-// the push_frame() operation. push_frame() uses Z_R0_scratch by default
-// to temporarily remember the frame pointer.
-// If Rpre_val is assigned Z_R0_scratch by the caller, code must be emitted to
-// save it's value.
-void MacroAssembler::g1_write_barrier_pre(Register Robj,
- RegisterOrConstant offset,
- Register Rpre_val, // Ideally, this is a non-volatile register.
- Register Rval, // Will be preserved.
- Register Rtmp1, // If Rpre_val is volatile, either Rtmp1
- Register Rtmp2, // or Rtmp2 has to be non-volatile..
- bool pre_val_needed // Save Rpre_val across runtime call, caller uses it.
- ) {
- Label callRuntime, filtered;
- const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active());
- const int buffer_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf());
- const int index_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index());
- assert_different_registers(Rtmp1, Rtmp2, Z_R0_scratch); // None of the Rtmp<i> must be Z_R0!!
- assert_different_registers(Robj, Z_R0_scratch); // Used for addressing. Furthermore, push_frame destroys Z_R0!!
- assert_different_registers(Rval, Z_R0_scratch); // push_frame destroys Z_R0!!
-
-#ifdef ASSERT
- // make sure the register is not Z_R0. Used for addressing. Furthermore, would be destroyed by push_frame.
- if (offset.is_register() && offset.as_register()->encoding() == 0) {
- tty->print_cr("Roffset(g1_write_barrier_pre) = %%r%d", offset.as_register()->encoding());
- assert(false, "bad register for offset");
- }
-#endif
-
- BLOCK_COMMENT("g1_write_barrier_pre {");
-
- // Is marking active?
- // Note: value is loaded for test purposes only. No further use here.
- 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.
-
- assert(Rpre_val != noreg, "must have a real register");
-
-
- // If an object is given, we need to load the previous value into Rpre_val.
- if (Robj != noreg) {
- // Load the previous value...
- Register ixReg = offset.is_register() ? offset.register_or_noreg() : Z_R0;
- if (UseCompressedOops) {
- z_llgf(Rpre_val, offset.constant_or_zero(), ixReg, Robj);
- } else {
- z_lg(Rpre_val, offset.constant_or_zero(), ixReg, Robj);
- }
- }
-
- // Is the previous value NULL?
- // If so, we don't need to record it and we're done.
- // Note: pre_val is loaded, decompressed and stored (directly or via runtime call).
- // Register contents is preserved across runtime call if caller requests to do so.
- z_ltgr(Rpre_val, Rpre_val);
- z_bre(filtered); // previous value is NULL, so we don't need to record it.
-
- // Decode the oop now. We know it's not NULL.
- if (Robj != noreg && UseCompressedOops) {
- oop_decoder(Rpre_val, Rpre_val, /*maybeNULL=*/false);
- }
-
- // OK, it's not filtered, so we'll need to call enqueue.
-
- // We can store the original value in the thread's buffer
- // only if index > 0. Otherwise, we need runtime to handle.
- // (The index field is typed as size_t.)
- Register Rbuffer = Rtmp1, Rindex = Rtmp2;
- assert_different_registers(Rbuffer, Rindex, Rpre_val);
-
- z_lg(Rbuffer, buffer_offset, Z_thread);
-
- load_and_test_long(Rindex, Address(Z_thread, index_offset));
- z_bre(callRuntime); // If index == 0, goto runtime.
-
- add2reg(Rindex, -wordSize); // Decrement index.
- z_stg(Rindex, index_offset, Z_thread);
-
- // Record the previous value.
- z_stg(Rpre_val, 0, Rbuffer, Rindex);
- z_bru(filtered); // We are done.
-
- Rbuffer = noreg; // end of life
- Rindex = noreg; // end of life
-
- bind(callRuntime);
-
- // Save some registers (inputs and result) over runtime call
- // by spilling them into the top frame.
- if (Robj != noreg && Robj->is_volatile()) {
- z_stg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
- }
- if (offset.is_register() && offset.as_register()->is_volatile()) {
- Register Roff = offset.as_register();
- z_stg(Roff, Roff->encoding()*BytesPerWord, Z_SP);
- }
- if (Rval != noreg && Rval->is_volatile()) {
- z_stg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
- }
-
- // Save Rpre_val (result) over runtime call.
- Register Rpre_save = Rpre_val;
- if ((Rpre_val == Z_R0_scratch) || (pre_val_needed && Rpre_val->is_volatile())) {
- guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!");
- Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2;
- }
- lgr_if_needed(Rpre_save, Rpre_val);
-
- // Push frame to protect top frame with return pc and spilled register values.
- save_return_pc();
- push_frame_abi160(0); // Will use Z_R0 as tmp.
-
- // Rpre_val may be destroyed by push_frame().
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_save, Z_thread);
-
- pop_frame();
- restore_return_pc();
-
- // Restore spilled values.
- if (Robj != noreg && Robj->is_volatile()) {
- z_lg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
- }
- if (offset.is_register() && offset.as_register()->is_volatile()) {
- Register Roff = offset.as_register();
- z_lg(Roff, Roff->encoding()*BytesPerWord, Z_SP);
- }
- if (Rval != noreg && Rval->is_volatile()) {
- z_lg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
- }
- if (pre_val_needed && Rpre_val->is_volatile()) {
- lgr_if_needed(Rpre_val, Rpre_save);
- }
-
- bind(filtered);
- BLOCK_COMMENT("} g1_write_barrier_pre");
-}
-
-// General G1 post-barrier generator.
-// Purpose: Store cross-region card.
-void MacroAssembler::g1_write_barrier_post(Register Rstore_addr,
- Register Rnew_val,
- Register Rtmp1,
- Register Rtmp2,
- Register Rtmp3) {
- Label callRuntime, filtered;
-
- assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2); // Most probably, Rnew_val == Rtmp3.
-
- G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(Universe::heap()->barrier_set());
- CardTable* ct = bs->card_table();
- assert(bs->kind() == BarrierSet::G1BarrierSet, "wrong barrier");
-
- BLOCK_COMMENT("g1_write_barrier_post {");
-
- // Does store cross heap regions?
- // It does if the two addresses specify different grain addresses.
- if (G1RSBarrierRegionFilter) {
- if (VM_Version::has_DistinctOpnds()) {
- z_xgrk(Rtmp1, Rstore_addr, Rnew_val);
- } else {
- z_lgr(Rtmp1, Rstore_addr);
- z_xgr(Rtmp1, Rnew_val);
- }
- z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes);
- z_bre(filtered);
- }
-
- // Crosses regions, storing NULL?
-#ifdef ASSERT
- z_ltgr(Rnew_val, Rnew_val);
- asm_assert_ne("null oop not allowed (G1)", 0x255); // TODO: also on z? Checked by caller on PPC64, so following branch is obsolete:
- z_bre(filtered); // Safety net: don't break if we have a NULL oop.
-#endif
- Rnew_val = noreg; // end of lifetime
-
- // Storing region crossing non-NULL, is card already dirty?
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
- assert_different_registers(Rtmp1, Rtmp2, Rtmp3);
- // Make sure not to use Z_R0 for any of these registers.
- Register Rcard_addr = (Rtmp1 != Z_R0_scratch) ? Rtmp1 : Rtmp3;
- Register Rbase = (Rtmp2 != Z_R0_scratch) ? Rtmp2 : Rtmp3;
-
- // calculate address of card
- load_const_optimized(Rbase, (address)ct->byte_map_base()); // Card table base.
- z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift); // Index into card table.
- z_algr(Rcard_addr, Rbase); // Explicit calculation needed for cli.
- Rbase = noreg; // end of lifetime
-
- // Filter young.
- assert((unsigned int)G1CardTable::g1_young_card_val() <= 255, "otherwise check this code");
- z_cli(0, Rcard_addr, (int)G1CardTable::g1_young_card_val());
- z_bre(filtered);
-
- // Check the card value. If dirty, we're done.
- // This also avoids false sharing of the (already dirty) card.
- z_sync(); // Required to support concurrent cleaning.
- assert((unsigned int)CardTable::dirty_card_val() <= 255, "otherwise check this code");
- z_cli(0, Rcard_addr, CardTable::dirty_card_val()); // Reload after membar.
- z_bre(filtered);
-
- // Storing a region crossing, non-NULL oop, card is clean.
- // Dirty card and log.
- z_mvi(0, Rcard_addr, CardTable::dirty_card_val());
-
- Register Rcard_addr_x = Rcard_addr;
- Register Rqueue_index = (Rtmp2 != Z_R0_scratch) ? Rtmp2 : Rtmp1;
- Register Rqueue_buf = (Rtmp3 != Z_R0_scratch) ? Rtmp3 : Rtmp1;
- const int qidx_off = in_bytes(JavaThread::dirty_card_queue_offset() + SATBMarkQueue::byte_offset_of_index());
- const int qbuf_off = in_bytes(JavaThread::dirty_card_queue_offset() + SATBMarkQueue::byte_offset_of_buf());
- if ((Rcard_addr == Rqueue_buf) || (Rcard_addr == Rqueue_index)) {
- Rcard_addr_x = Z_R0_scratch; // Register shortage. We have to use Z_R0.
- }
- lgr_if_needed(Rcard_addr_x, Rcard_addr);
-
- load_and_test_long(Rqueue_index, Address(Z_thread, qidx_off));
- z_bre(callRuntime); // Index == 0 then jump to runtime.
-
- z_lg(Rqueue_buf, qbuf_off, Z_thread);
-
- add2reg(Rqueue_index, -wordSize); // Decrement index.
- z_stg(Rqueue_index, qidx_off, Z_thread);
-
- z_stg(Rcard_addr_x, 0, Rqueue_index, Rqueue_buf); // Store card.
- z_bru(filtered);
-
- bind(callRuntime);
-
- // TODO: do we need a frame? Introduced to be on the safe side.
- bool needs_frame = true;
- lgr_if_needed(Rcard_addr, Rcard_addr_x); // copy back asap. push_frame will destroy Z_R0_scratch!
-
- // VM call need frame to access(write) O register.
- if (needs_frame) {
- save_return_pc();
- push_frame_abi160(0); // Will use Z_R0 as tmp on old CPUs.
- }
-
- // Save the live input values.
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, Z_thread);
-
- if (needs_frame) {
- pop_frame();
- restore_return_pc();
- }
-
- bind(filtered);
-
- BLOCK_COMMENT("} g1_write_barrier_post");
-}
-#endif // INCLUDE_ALL_GCS
+ BarrierSetAssembler* bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+ bs->resolve_jobject(this, value, tmp1, tmp2);
+}
// Last_Java_sp must comply to the rules in frame_s390.hpp.
void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc, bool allow_relocation) {