102 #else
103 if (count != R1) {
104 __ mov(R1, count);
105 }
106 #if R9_IS_SCRATCHED
107 // Safer to save R9 here since callers may have been written
108 // assuming R9 survives. This is suboptimal but is not in
109 // general worth optimizing for the few platforms where R9
110 // is scratched. Note that the optimization might not be to
111 // difficult for this particular call site.
112 __ push(R9);
113 #endif // !R9_IS_SCRATCHED
114 #endif // !AARCH64
115 __ call(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry));
116 #ifndef AARCH64
117 #if R9_IS_SCRATCHED
118 __ pop(R9);
119 #endif // !R9_IS_SCRATCHED
120 #endif // !AARCH64
121 }
|
102 #else
103 if (count != R1) {
104 __ mov(R1, count);
105 }
106 #if R9_IS_SCRATCHED
107 // Safer to save R9 here since callers may have been written
108 // assuming R9 survives. This is suboptimal but is not in
109 // general worth optimizing for the few platforms where R9
110 // is scratched. Note that the optimization might not be to
111 // difficult for this particular call site.
112 __ push(R9);
113 #endif // !R9_IS_SCRATCHED
114 #endif // !AARCH64
115 __ call(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry));
116 #ifndef AARCH64
117 #if R9_IS_SCRATCHED
118 __ pop(R9);
119 #endif // !R9_IS_SCRATCHED
120 #endif // !AARCH64
121 }
122
123 #undef __
124 #define __ ce->masm()->
125
126 void G1BarrierSetAssembler::gen_g1_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
127 // At this point we know that marking is in progress.
128 // If do_load() is true then we have to emit the
129 // load of the previous value; otherwise it has already
130 // been loaded into _pre_val.
131
132 __ bind(*stub->entry());
133 assert(stub->pre_val()->is_register(), "Precondition.");
134
135 Register pre_val_reg = stub->pre_val()->as_register();
136
137 if (stub->do_load()) {
138 ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
139 }
140
141 __ cbz(pre_val_reg, *stub->continuation());
142 ce->verify_reserved_argument_area_size(1);
143 __ str(pre_val_reg, Address(SP));
144 __ call(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id), relocInfo::runtime_call_type);
145
146 __ b(*stub->continuation());
147 }
148
149 void G1BarrierSetAssembler::gen_g1_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
150 __ bind(*stub->entry());
151 assert(stub->addr()->is_register(), "Precondition.");
152 assert(stub->new_val()->is_register(), "Precondition.");
153 Register new_val_reg = stub->new_val()->as_register();
154 __ cbz(new_val_reg, *stub->continuation());
155 ce->verify_reserved_argument_area_size(1);
156 __ str(stub->addr()->as_pointer_register(), Address(SP));
157 __ call(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id), relocInfo::runtime_call_type);
158 __ b(*stub->continuation());
159 }
160
161 #undef __
162 #define __ sasm->
163
164 void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
165 // Input:
166 // - pre_val pushed on the stack
167
168 __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
169
170 BarrierSet* bs = BarrierSet::barrier_set();
171 if (bs->kind() != BarrierSet::G1BarrierSet) {
172 __ mov(R0, (int)id);
173 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), R0);
174 __ should_not_reach_here();
175 break;
176 }
177
178 // save at least the registers that need saving if the runtime is called
179 #ifdef AARCH64
180 __ raw_push(R0, R1);
181 __ raw_push(R2, R3);
182 const int nb_saved_regs = 4;
183 #else // AARCH64
184 const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
185 const int nb_saved_regs = 6;
186 assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
187 __ push(saved_regs);
188 #endif // AARCH64
189
190 const Register r_pre_val_0 = R0; // must be R0, to be ready for the runtime call
191 const Register r_index_1 = R1;
192 const Register r_buffer_2 = R2;
193
194 Address queue_active(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
195 Address queue_index(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
196 Address buffer(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
197
198 Label done;
199 Label runtime;
200
201 // Is marking still active?
202 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
203 __ ldrb(R1, queue_active);
204 __ cbz(R1, done);
205
206 __ ldr(r_index_1, queue_index);
207 __ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
208 __ ldr(r_buffer_2, buffer);
209
210 __ subs(r_index_1, r_index_1, wordSize);
211 __ b(runtime, lt);
212
213 __ str(r_index_1, queue_index);
214 __ str(r_pre_val_0, Address(r_buffer_2, r_index_1));
215
216 __ bind(done);
217
218 #ifdef AARCH64
219 __ raw_pop(R2, R3);
220 __ raw_pop(R0, R1);
221 #else // AARCH64
222 __ pop(saved_regs);
223 #endif // AARCH64
224
225 __ ret();
226
227 __ bind(runtime);
228
229 __ save_live_registers();
230
231 assert(r_pre_val_0 == c_rarg0, "pre_val should be in R0");
232 __ mov(c_rarg1, Rthread);
233 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), c_rarg0, c_rarg1);
234
235 __ restore_live_registers_without_return();
236
237 __ b(done);
238 }
239
240 void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
241 // Input:
242 // - store_addr, pushed on the stack
243
244 __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
245
246 BarrierSet* bs = BarrierSet::barrier_set();
247 if (bs->kind() != BarrierSet::G1BarrierSet) {
248 __ mov(R0, (int)id);
249 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), R0);
250 __ should_not_reach_here();
251 break;
252 }
253
254 Label done;
255 Label recheck;
256 Label runtime;
257
258 Address queue_index(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
259 Address buffer(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
260
261 AddressLiteral cardtable(ci_card_table_address_as<address>(), relocInfo::none);
262
263 // save at least the registers that need saving if the runtime is called
264 #ifdef AARCH64
265 __ raw_push(R0, R1);
266 __ raw_push(R2, R3);
267 const int nb_saved_regs = 4;
268 #else // AARCH64
269 const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
270 const int nb_saved_regs = 6;
271 assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
272 __ push(saved_regs);
273 #endif // AARCH64
274
275 const Register r_card_addr_0 = R0; // must be R0 for the slow case
276 const Register r_obj_0 = R0;
277 const Register r_card_base_1 = R1;
278 const Register r_tmp2 = R2;
279 const Register r_index_2 = R2;
280 const Register r_buffer_3 = R3;
281 const Register tmp1 = Rtemp;
282
283 __ ldr(r_obj_0, Address(SP, nb_saved_regs*wordSize));
284 // Note: there is a comment in x86 code about not using
285 // ExternalAddress / lea, due to relocation not working
286 // properly for that address. Should be OK for arm, where we
287 // explicitly specify that 'cardtable' has a relocInfo::none
288 // type.
289 __ lea(r_card_base_1, cardtable);
290 __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift));
291
292 // first quick check without barrier
293 __ ldrb(r_tmp2, Address(r_card_addr_0));
294
295 __ cmp(r_tmp2, (int)G1CardTable::g1_young_card_val());
296 __ b(recheck, ne);
297
298 __ bind(done);
299
300 #ifdef AARCH64
301 __ raw_pop(R2, R3);
302 __ raw_pop(R0, R1);
303 #else // AARCH64
304 __ pop(saved_regs);
305 #endif // AARCH64
306
307 __ ret();
308
309 __ bind(recheck);
310
311 __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp1);
312
313 // reload card state after the barrier that ensures the stored oop was visible
314 __ ldrb(r_tmp2, Address(r_card_addr_0));
315
316 assert(CardTable::dirty_card_val() == 0, "adjust this code");
317 __ cbz(r_tmp2, done);
318
319 // storing region crossing non-NULL, card is clean.
320 // dirty card and log.
321
322 assert(0 == (int)CardTable::dirty_card_val(), "adjust this code");
323 if ((ci_card_table_address_as<intptr_t>() & 0xff) == 0) {
324 // Card table is aligned so the lowest byte of the table address base is zero.
325 __ strb(r_card_base_1, Address(r_card_addr_0));
326 } else {
327 __ strb(__ zero_register(r_tmp2), Address(r_card_addr_0));
328 }
329
330 __ ldr(r_index_2, queue_index);
331 __ ldr(r_buffer_3, buffer);
332
333 __ subs(r_index_2, r_index_2, wordSize);
334 __ b(runtime, lt); // go to runtime if now negative
335
336 __ str(r_index_2, queue_index);
337
338 __ str(r_card_addr_0, Address(r_buffer_3, r_index_2));
339
340 __ b(done);
341
342 __ bind(runtime);
343
344 __ save_live_registers();
345
346 assert(r_card_addr_0 == c_rarg0, "card_addr should be in R0");
347 __ mov(c_rarg1, Rthread);
348 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), c_rarg0, c_rarg1);
349
350 __ restore_live_registers_without_return();
351
352 __ b(done);
353 }
354
355 #undef __
|