55
56 __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop);
57 __ sub(count, count, BytesPerHeapOop); // last addr
58
59 __ logical_shift_right(addr, addr, CardTable::card_shift);
60 __ logical_shift_right(count, count, CardTable::card_shift);
61 __ sub(count, count, addr); // nb of cards
62
63 // warning: Rthread has not been preserved
64 __ mov_address(tmp, (address) ct->byte_map_base(), symbolic_Relocation::card_table_reference);
65 __ add(addr,tmp, addr);
66
67 Register zero = __ zero_register(tmp);
68
69 __ BIND(L_cardtable_loop);
70 __ strb(zero, Address(addr, 1, post_indexed));
71 __ subs(count, count, 1);
72 __ b(L_cardtable_loop, ge);
73 __ BIND(L_done);
74 }
|
55
56 __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop);
57 __ sub(count, count, BytesPerHeapOop); // last addr
58
59 __ logical_shift_right(addr, addr, CardTable::card_shift);
60 __ logical_shift_right(count, count, CardTable::card_shift);
61 __ sub(count, count, addr); // nb of cards
62
63 // warning: Rthread has not been preserved
64 __ mov_address(tmp, (address) ct->byte_map_base(), symbolic_Relocation::card_table_reference);
65 __ add(addr,tmp, addr);
66
67 Register zero = __ zero_register(tmp);
68
69 __ BIND(L_cardtable_loop);
70 __ strb(zero, Address(addr, 1, post_indexed));
71 __ subs(count, count, 1);
72 __ b(L_cardtable_loop, ge);
73 __ BIND(L_done);
74 }
75
76 void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
77 Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) {
78 bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
79 bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
80 bool precise = on_array || on_anonymous;
81
82 if (is_null) {
83 BarrierSetAssembler::store_at(masm, decorators, type, obj, new_val, tmp1, tmp2, tmp3, true);
84 } else {
85 assert (!precise || (obj.index() == noreg && obj.disp() == 0),
86 "store check address should be calculated beforehand");
87
88 store_check_part1(masm, tmp1);
89 BarrierSetAssembler::store_at(masm, decorators, type, obj, new_val, tmp1, tmp2, tmp3, false);
90 new_val = noreg;
91 store_check_part2(masm, obj.base(), tmp1, tmp2);
92 }
93 }
94
95 // The 1st part of the store check.
96 // Sets card_table_base register.
97 void CardTableBarrierSetAssembler::store_check_part1(MacroAssembler* masm, Register card_table_base) {
98 // Check barrier set type (should be card table) and element size
99 BarrierSet* bs = BarrierSet::barrier_set();
100 assert(bs->kind() == BarrierSet::CardTableBarrierSet,
101 "Wrong barrier set kind");
102
103 CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
104 CardTable* ct = ctbs->card_table();
105 assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "Adjust store check code");
106
107 // Load card table base address.
108
109 /* Performance note.
110
111 There is an alternative way of loading card table base address
112 from thread descriptor, which may look more efficient:
113
114 ldr(card_table_base, Address(Rthread, JavaThread::card_table_base_offset()));
115
116 However, performance measurements of micro benchmarks and specJVM98
117 showed that loading of card table base from thread descriptor is
118 7-18% slower compared to loading of literal embedded into the code.
119 Possible cause is a cache miss (card table base address resides in a
120 rarely accessed area of thread descriptor).
121 */
122 // TODO-AARCH64 Investigate if mov_slow is faster than ldr from Rthread on AArch64
123 __ mov_address(card_table_base, (address)ct->byte_map_base(), symbolic_Relocation::card_table_reference);
124 }
125
126 // The 2nd part of the store check.
127 void CardTableBarrierSetAssembler::store_check_part2(MacroAssembler* masm, Register obj, Register card_table_base, Register tmp) {
128 assert_different_registers(obj, card_table_base, tmp);
129
130 assert(CardTable::dirty_card_val() == 0, "Dirty card value must be 0 due to optimizations.");
131 #ifdef AARCH64
132 add(card_table_base, card_table_base, AsmOperand(obj, lsr, CardTable::card_shift));
133 Address card_table_addr(card_table_base);
134 #else
135 Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift);
136 #endif
137
138 if (UseCondCardMark) {
139 #if INCLUDE_ALL_GCS
140 if (UseConcMarkSweepGC) {
141 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), noreg);
142 }
143 #endif
144 Label already_dirty;
145
146 __ ldrb(tmp, card_table_addr);
147 __ cbz(tmp, already_dirty);
148
149 set_card(masm, card_table_base, card_table_addr, tmp);
150 __ bind(already_dirty);
151
152 } else {
153 #if INCLUDE_ALL_GCS
154 if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
155 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
156 }
157 #endif
158 set_card(masm, card_table_base, card_table_addr, tmp);
159 }
160 }
161
162 void CardTableBarrierSetAssembler::set_card(MacroAssembler* masm, Register card_table_base, Address card_table_addr, Register tmp) {
163 #ifdef AARCH64
164 strb(ZR, card_table_addr);
165 #else
166 CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
167 CardTable* ct = ctbs->card_table();
168 if ((((uintptr_t)ct->byte_map_base() & 0xff) == 0)) {
169 // Card table is aligned so the lowest byte of the table address base is zero.
170 // This works only if the code is not saved for later use, possibly
171 // in a context where the base would no longer be aligned.
172 __ strb(card_table_base, card_table_addr);
173 } else {
174 __ mov(tmp, 0);
175 __ strb(tmp, card_table_addr);
176 }
177 #endif // AARCH64
178 }
|