8078438: Interpreter should support conditional card marks (UseCondCardMark) on x86 and aarch64
Summary: Add interpreter support for conditional card marks on x86 and aarch64
Reviewed-by: tschatzl, aph
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Jun 18 10:47:34 2015 -0400
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Fri Jun 19 09:41:49 2015 +0200
@@ -2888,41 +2888,40 @@
cmp(src1, rscratch1);
}
-void MacroAssembler::store_check(Register obj) {
- // Does a store check for the oop in register obj. The content of
- // register obj is destroyed afterwards.
- store_check_part_1(obj);
- store_check_part_2(obj);
-}
-
void MacroAssembler::store_check(Register obj, Address dst) {
store_check(obj);
}
-
-// split the store check operation so that other instructions can be scheduled inbetween
-void MacroAssembler::store_check_part_1(Register obj) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
- lsr(obj, obj, CardTableModRefBS::card_shift);
-}
-
-void MacroAssembler::store_check_part_2(Register obj) {
+void MacroAssembler::store_check(Register obj) {
+ // Does a store check for the oop in register obj. The content of
+ // register obj is destroyed afterwards.
+
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
- CardTableModRefBS* ct = (CardTableModRefBS*)bs;
+
+ CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
- // The calculation for byte_map_base is as follows:
- // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
- // So this essentially converts an address to a displacement and
- // it will never need to be relocated.
-
- // FIXME: It's not likely that disp will fit into an offset so we
- // don't bother to check, but it could save an instruction.
- intptr_t disp = (intptr_t) ct->byte_map_base;
- mov(rscratch1, disp);
- strb(zr, Address(obj, rscratch1));
+ lsr(obj, obj, CardTableModRefBS::card_shift);
+
+ assert(CardTableModRefBS::dirty_card_val() == 0, "must be");
+
+ {
+ ExternalAddress cardtable((address) ct->byte_map_base);
+ unsigned long offset;
+ adrp(rscratch1, cardtable, offset);
+ assert(offset == 0, "byte_map_base is misaligned");
+ }
+
+ if (UseCondCardMark) {
+ Label L_already_dirty;
+ ldrb(rscratch2, Address(obj, rscratch1));
+ cbz(rscratch2, L_already_dirty);
+ strb(zr, Address(obj, rscratch1));
+ bind(L_already_dirty);
+ } else {
+ strb(zr, Address(obj, rscratch1));
+ }
}
void MacroAssembler::load_klass(Register dst, Register src) {
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Jun 18 10:47:34 2015 -0400
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Fri Jun 19 09:41:49 2015 +0200
@@ -756,10 +756,6 @@
#endif // INCLUDE_ALL_GCS
- // split store_check(Register obj) to enhance instruction interleaving
- void store_check_part_1(Register obj);
- void store_check_part_2(Register obj);
-
// oop manipulations
void load_klass(Register dst, Register src);
void store_klass(Register dst, Register src);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Jun 18 10:47:34 2015 -0400
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Jun 19 09:41:49 2015 +0200
@@ -4260,31 +4260,24 @@
//////////////////////////////////////////////////////////////////////////////////
+void MacroAssembler::store_check(Register obj, Address dst) {
+ store_check(obj);
+}
+
void MacroAssembler::store_check(Register obj) {
// Does a store check for the oop in register obj. The content of
// register obj is destroyed afterwards.
- store_check_part_1(obj);
- store_check_part_2(obj);
-}
-
-void MacroAssembler::store_check(Register obj, Address dst) {
- store_check(obj);
-}
-
-
-// split the store check operation so that other instructions can be scheduled inbetween
-void MacroAssembler::store_check_part_1(Register obj) {
+
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
- shrptr(obj, CardTableModRefBS::card_shift);
-}
-
-void MacroAssembler::store_check_part_2(Register obj) {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
+
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
+ shrptr(obj, CardTableModRefBS::card_shift);
+
+ Address card_addr;
+
// The calculation for byte_map_base is as follows:
// byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
// So this essentially converts an address to a displacement and it will
@@ -4292,8 +4285,7 @@
// large for a 32bit displacement.
intptr_t disp = (intptr_t) ct->byte_map_base;
if (is_simm32(disp)) {
- Address cardtable(noreg, obj, Address::times_1, disp);
- movb(cardtable, 0);
+ card_addr = Address(noreg, obj, Address::times_1, disp);
} else {
// By doing it as an ExternalAddress 'disp' could be converted to a rip-relative
// displacement and done in a single instruction given favorable mapping and a
@@ -4301,7 +4293,18 @@
// entry and that entry is not properly handled by the relocation code.
AddressLiteral cardtable((address)ct->byte_map_base, relocInfo::none);
Address index(noreg, obj, Address::times_1);
- movb(as_Address(ArrayAddress(cardtable, index)), 0);
+ card_addr = as_Address(ArrayAddress(cardtable, index));
+ }
+
+ int dirty = CardTableModRefBS::dirty_card_val();
+ if (UseCondCardMark) {
+ Label L_already_dirty;
+ cmpb(card_addr, dirty);
+ jcc(Assembler::equal, L_already_dirty);
+ movb(card_addr, dirty);
+ bind(L_already_dirty);
+ } else {
+ movb(card_addr, dirty);
}
}
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Jun 18 10:47:34 2015 -0400
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Jun 19 09:41:49 2015 +0200
@@ -315,10 +315,6 @@
#endif // INCLUDE_ALL_GCS
- // split store_check(Register obj) to enhance instruction interleaving
- void store_check_part_1(Register obj);
- void store_check_part_2(Register obj);
-
// C 'boolean' to Java boolean: x == 0 ? 0 : 1
void c2bool(Register x);