< prev index next >
src/hotspot/cpu/arm/macroAssembler_arm.cpp
Print this page
rev 49916 : 8201786: Modularize interpreter GC barriers: leftovers for ARM32
Reviewed-by: enevill
*** 29,38 ****
--- 29,39 ----
#include "ci/ciEnv.hpp"
#include "code/nativeInst.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/cardTable.hpp"
+ #include "gc/shared/barrierSetAssembler.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/resourceArea.hpp"
#include "oops/klass.inline.hpp"
*** 2124,2338 ****
void MacroAssembler::resolve_jobject(Register value,
Register tmp1,
Register tmp2) {
assert_different_registers(value, tmp1, tmp2);
Label done, not_weak;
cbz(value, done); // Use NULL as-is.
STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
tbz(value, 0, not_weak); // Test for jweak tag.
// Resolve jweak.
! ldr(value, Address(value, -JNIHandles::weak_tag_value));
! verify_oop(value);
! #if INCLUDE_ALL_GCS
! if (UseG1GC) {
! g1_write_barrier_pre(noreg, // store_addr
! noreg, // new_val
! value, // pre_val
! tmp1, // tmp1
! tmp2); // tmp2
! }
! #endif // INCLUDE_ALL_GCS
b(done);
bind(not_weak);
// Resolve (untagged) jobject.
! ldr(value, Address(value));
verify_oop(value);
bind(done);
}
//////////////////////////////////////////////////////////////////////////////////
- #if INCLUDE_ALL_GCS
-
- // G1 pre-barrier.
- // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
- // If store_addr != noreg, then previous value is loaded from [store_addr];
- // in such case store_addr and new_val registers are preserved;
- // otherwise pre_val register is preserved.
- void MacroAssembler::g1_write_barrier_pre(Register store_addr,
- Register new_val,
- Register pre_val,
- Register tmp1,
- Register tmp2) {
- Label done;
- Label runtime;
-
- if (store_addr != noreg) {
- assert_different_registers(store_addr, new_val, pre_val, tmp1, tmp2, noreg);
- } else {
- assert (new_val == noreg, "should be");
- assert_different_registers(pre_val, tmp1, tmp2, noreg);
- }
-
- Address in_progress(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
- Address index(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
- Address buffer(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
-
- // Is marking active?
- assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "adjust this code");
- ldrb(tmp1, in_progress);
- cbz(tmp1, done);
-
- // Do we need to load the previous value?
- if (store_addr != noreg) {
- load_heap_oop(pre_val, Address(store_addr, 0));
- }
-
- // Is the previous value null?
- cbz(pre_val, done);
-
- // Can we store original value in the thread's buffer?
- // Is index == 0?
- // (The index field is typed as size_t.)
-
- ldr(tmp1, index); // tmp1 := *index_adr
- ldr(tmp2, buffer);
-
- subs(tmp1, tmp1, wordSize); // tmp1 := tmp1 - wordSize
- b(runtime, lt); // If negative, goto runtime
-
- str(tmp1, index); // *index_adr := tmp1
-
- // Record the previous value
- str(pre_val, Address(tmp2, tmp1));
- b(done);
-
- bind(runtime);
-
- // save the live input values
- #ifdef AARCH64
- if (store_addr != noreg) {
- raw_push(store_addr, new_val);
- } else {
- raw_push(pre_val, ZR);
- }
- #else
- if (store_addr != noreg) {
- // avoid raw_push to support any ordering of store_addr and new_val
- push(RegisterSet(store_addr) | RegisterSet(new_val));
- } else {
- push(pre_val);
- }
- #endif // AARCH64
-
- if (pre_val != R0) {
- mov(R0, pre_val);
- }
- mov(R1, Rthread);
-
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), R0, R1);
-
- #ifdef AARCH64
- if (store_addr != noreg) {
- raw_pop(store_addr, new_val);
- } else {
- raw_pop(pre_val, ZR);
- }
- #else
- if (store_addr != noreg) {
- pop(RegisterSet(store_addr) | RegisterSet(new_val));
- } else {
- pop(pre_val);
- }
- #endif // AARCH64
-
- bind(done);
- }
-
- // G1 post-barrier.
- // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR).
- void MacroAssembler::g1_write_barrier_post(Register store_addr,
- Register new_val,
- Register tmp1,
- Register tmp2,
- Register tmp3) {
-
- Address queue_index(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
- Address buffer(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
-
- BarrierSet* bs = BarrierSet::barrier_set();
- CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
- CardTable* ct = ctbs->card_table();
- Label done;
- Label runtime;
-
- // Does store cross heap regions?
-
- eor(tmp1, store_addr, new_val);
- #ifdef AARCH64
- logical_shift_right(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes);
- cbz(tmp1, done);
- #else
- movs(tmp1, AsmOperand(tmp1, lsr, HeapRegion::LogOfHRGrainBytes));
- b(done, eq);
- #endif
-
- // crosses regions, storing NULL?
-
- cbz(new_val, done);
-
- // storing region crossing non-NULL, is card already dirty?
- const Register card_addr = tmp1;
- assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
- mov_address(tmp2, (address)ct->byte_map_base(), symbolic_Relocation::card_table_reference);
- add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift));
-
- ldrb(tmp2, Address(card_addr));
- cmp(tmp2, (int)G1CardTable::g1_young_card_val());
- b(done, eq);
-
- membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp2);
-
- assert(CardTable::dirty_card_val() == 0, "adjust this code");
- ldrb(tmp2, Address(card_addr));
- cbz(tmp2, done);
-
- // storing a region crossing, non-NULL oop, card is clean.
- // dirty card and log.
-
- strb(zero_register(tmp2), Address(card_addr));
-
- ldr(tmp2, queue_index);
- ldr(tmp3, buffer);
-
- subs(tmp2, tmp2, wordSize);
- b(runtime, lt); // go to runtime if now negative
-
- str(tmp2, queue_index);
-
- str(card_addr, Address(tmp3, tmp2));
- b(done);
-
- bind(runtime);
-
- if (card_addr != R0) {
- mov(R0, card_addr);
- }
- mov(R1, Rthread);
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), R0, R1);
-
- bind(done);
- }
-
- #endif // INCLUDE_ALL_GCS
-
- //////////////////////////////////////////////////////////////////////////////////
-
#ifdef AARCH64
void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed) {
switch (size_in_bytes) {
case 8: ldr(dst, src); break;
--- 2125,2157 ----
void MacroAssembler::resolve_jobject(Register value,
Register tmp1,
Register tmp2) {
+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+
assert_different_registers(value, tmp1, tmp2);
Label done, not_weak;
cbz(value, done); // Use NULL as-is.
STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
tbz(value, 0, not_weak); // Test for jweak tag.
+
// Resolve jweak.
! bs->load_at(this, IN_ROOT | ON_PHANTOM_OOP_REF, T_OBJECT,
! value, Address(value, -JNIHandles::weak_tag_value), tmp1, tmp2, noreg);
b(done);
bind(not_weak);
// Resolve (untagged) jobject.
! bs->load_at(this, IN_ROOT | IN_CONCURRENT_ROOT, T_OBJECT,
! value, Address(value, 0), tmp1, tmp2, noreg);
verify_oop(value);
bind(done);
}
//////////////////////////////////////////////////////////////////////////////////
#ifdef AARCH64
void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed) {
switch (size_in_bytes) {
case 8: ldr(dst, src); break;
*** 2871,2912 ****
}
#endif // AARCH64
! void MacroAssembler::load_heap_oop(Register dst, Address src) {
! #ifdef AARCH64
! if (UseCompressedOops) {
! ldr_w(dst, src);
! decode_heap_oop(dst);
! return;
! }
! #endif // AARCH64
! ldr(dst, src);
}
// Blows src and flags.
! void MacroAssembler::store_heap_oop(Register src, Address dst) {
! #ifdef AARCH64
! if (UseCompressedOops) {
! assert(!dst.uses(src), "not enough registers");
! encode_heap_oop(src);
! str_w(src, dst);
! return;
}
- #endif // AARCH64
- str(src, dst);
}
! void MacroAssembler::store_heap_oop_null(Register src, Address dst) {
! #ifdef AARCH64
! if (UseCompressedOops) {
! str_w(src, dst);
! return;
}
- #endif // AARCH64
- str(src, dst);
}
#ifdef AARCH64
--- 2690,2732 ----
}
#endif // AARCH64
! void MacroAssembler::load_heap_oop(Register dst, Address src, Register tmp1, Register tmp2, Register tmp3, DecoratorSet decorators) {
! access_load_at(T_OBJECT, IN_HEAP | decorators, src, dst, tmp1, tmp2, tmp3);
}
// Blows src and flags.
! void MacroAssembler::store_heap_oop(Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, DecoratorSet decorators) {
! access_store_at(T_OBJECT, IN_HEAP | decorators, obj, new_val, tmp1, tmp2, tmp3, false);
! }
!
! void MacroAssembler::store_heap_oop_null(Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, DecoratorSet decorators) {
! access_store_at(T_OBJECT, IN_HEAP, obj, new_val, tmp1, tmp2, tmp3, true);
! }
!
! void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators,
! Address src, Register dst, Register tmp1, Register tmp2, Register tmp3) {
! BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
! bool as_raw = (decorators & AS_RAW) != 0;
! if (as_raw) {
! bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3);
! } else {
! bs->load_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3);
}
}
! void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
! Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) {
! BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
! bool as_raw = (decorators & AS_RAW) != 0;
! if (as_raw) {
! bs->BarrierSetAssembler::store_at(this, decorators, type, obj, new_val, tmp1, tmp2, tmp3, is_null);
! } else {
! bs->store_at(this, decorators, type, obj, new_val, tmp1, tmp2, tmp3, is_null);
}
}
#ifdef AARCH64
< prev index next >