1 /* 2 * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "asm/macroAssembler.inline.hpp" 27 #if INCLUDE_CDS 28 #include "code/SCCache.hpp" 29 #endif 30 #include "gc/g1/g1BarrierSet.hpp" 31 #include "gc/g1/g1BarrierSetAssembler.hpp" 32 #include "gc/g1/g1BarrierSetRuntime.hpp" 33 #include "gc/g1/g1CardTable.hpp" 34 #include "gc/g1/g1HeapRegion.hpp" 35 #include "gc/g1/g1ThreadLocalData.hpp" 36 #include "interpreter/interp_masm.hpp" 37 #include "runtime/sharedRuntime.hpp" 38 #include "utilities/debug.hpp" 39 #include "utilities/macros.hpp" 40 #ifdef COMPILER1 41 #include "c1/c1_LIRAssembler.hpp" 42 #include "c1/c1_MacroAssembler.hpp" 43 #include "gc/g1/c1/g1BarrierSetC1.hpp" 44 #endif // COMPILER1 45 #ifdef COMPILER2 46 #include "gc/g1/c2/g1BarrierSetC2.hpp" 47 #endif // COMPILER2 48 49 #define __ masm-> 50 51 void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, 52 Register addr, Register count) { 53 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; 54 55 if (!dest_uninitialized) { 56 Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); 57 #ifndef _LP64 58 __ push(thread); 59 __ get_thread(thread); 60 #endif 61 62 Label filtered; 63 Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); 64 // Is marking active? 65 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 66 __ cmpl(in_progress, 0); 67 } else { 68 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 69 __ cmpb(in_progress, 0); 70 } 71 72 NOT_LP64(__ pop(thread);) 73 74 __ jcc(Assembler::equal, filtered); 75 76 __ push_call_clobbered_registers(false /* save_fpu */); 77 #ifdef _LP64 78 if (count == c_rarg0) { 79 if (addr == c_rarg1) { 80 // exactly backwards!! 81 __ xchgptr(c_rarg1, c_rarg0); 82 } else { 83 __ movptr(c_rarg1, count); 84 __ movptr(c_rarg0, addr); 85 } 86 } else { 87 __ movptr(c_rarg0, addr); 88 __ movptr(c_rarg1, count); 89 } 90 if (UseCompressedOops) { 91 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_narrow_oop_entry), 2); 92 } else { 93 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), 2); 94 } 95 #else 96 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), 97 addr, count); 98 #endif 99 __ pop_call_clobbered_registers(false /* save_fpu */); 100 101 __ bind(filtered); 102 } 103 } 104 105 void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, 106 Register addr, Register count, Register tmp) { 107 __ push_call_clobbered_registers(false /* save_fpu */); 108 #ifdef _LP64 109 if (c_rarg0 == count) { // On win64 c_rarg0 == rcx 110 assert_different_registers(c_rarg1, addr); 111 __ mov(c_rarg1, count); 112 __ mov(c_rarg0, addr); 113 } else { 114 assert_different_registers(c_rarg0, count); 115 __ mov(c_rarg0, addr); 116 __ mov(c_rarg1, count); 117 } 118 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2); 119 #else 120 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 121 addr, count); 122 #endif 123 __ pop_call_clobbered_registers(false /* save_fpu */); 124 } 125 126 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 127 Register dst, Address src, Register tmp1, Register tmp_thread) { 128 bool on_oop = is_reference_type(type); 129 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; 130 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; 131 bool on_reference = on_weak || on_phantom; 132 ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); 133 if (on_oop && on_reference) { 134 Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); 135 136 #ifndef _LP64 137 // Work around the x86_32 bug that only manifests with Loom for some reason. 138 // MacroAssembler::resolve_weak_handle calls this barrier with tmp_thread == noreg. 139 if (thread == noreg) { 140 if (dst != rcx && tmp1 != rcx) { 141 thread = rcx; 142 } else if (dst != rdx && tmp1 != rdx) { 143 thread = rdx; 144 } else if (dst != rdi && tmp1 != rdi) { 145 thread = rdi; 146 } 147 } 148 assert_different_registers(dst, tmp1, thread); 149 __ push(thread); 150 __ get_thread(thread); 151 #endif 152 153 // Generate the G1 pre-barrier code to log the value of 154 // the referent field in an SATB buffer. 155 g1_write_barrier_pre(masm /* masm */, 156 noreg /* obj */, 157 dst /* pre_val */, 158 thread /* thread */, 159 tmp1 /* tmp */, 160 true /* tosca_live */, 161 true /* expand_call */); 162 163 #ifndef _LP64 164 __ pop(thread); 165 #endif 166 } 167 } 168 169 static void generate_queue_insertion(MacroAssembler* masm, ByteSize index_offset, ByteSize buffer_offset, Label& runtime, 170 const Register thread, const Register value, const Register temp) { 171 // This code assumes that buffer index is pointer sized. 172 STATIC_ASSERT(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t)); 173 // Can we store a value in the given thread's buffer? 174 // (The index field is typed as size_t.) 175 __ movptr(temp, Address(thread, in_bytes(index_offset))); // temp := *(index address) 176 __ testptr(temp, temp); // index == 0? 177 __ jcc(Assembler::zero, runtime); // jump to runtime if index == 0 (full buffer) 178 // The buffer is not full, store value into it. 179 __ subptr(temp, wordSize); // temp := next index 180 __ movptr(Address(thread, in_bytes(index_offset)), temp); // *(index address) := next index 181 __ addptr(temp, Address(thread, in_bytes(buffer_offset))); // temp := buffer address + next index 182 __ movptr(Address(temp, 0), value); // *(buffer address + next index) := value 183 } 184 185 static void generate_pre_barrier_fast_path(MacroAssembler* masm, 186 const Register thread) { 187 Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); 188 // Is marking active? 189 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 190 __ cmpl(in_progress, 0); 191 } else { 192 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 193 __ cmpb(in_progress, 0); 194 } 195 } 196 197 static void generate_pre_barrier_slow_path(MacroAssembler* masm, 198 const Register obj, 199 const Register pre_val, 200 const Register thread, 201 const Register tmp, 202 Label& done, 203 Label& runtime) { 204 // Do we need to load the previous value? 205 if (obj != noreg) { 206 __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); 207 } 208 // Is the previous value null? 209 __ cmpptr(pre_val, NULL_WORD); 210 __ jcc(Assembler::equal, done); 211 generate_queue_insertion(masm, 212 G1ThreadLocalData::satb_mark_queue_index_offset(), 213 G1ThreadLocalData::satb_mark_queue_buffer_offset(), 214 runtime, 215 thread, pre_val, tmp); 216 __ jmp(done); 217 } 218 219 void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, 220 Register obj, 221 Register pre_val, 222 Register thread, 223 Register tmp, 224 bool tosca_live, 225 bool expand_call) { 226 // If expand_call is true then we expand the call_VM_leaf macro 227 // directly to skip generating the check by 228 // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. 229 230 #ifdef _LP64 231 assert(thread == r15_thread, "must be"); 232 #endif // _LP64 233 234 Label done; 235 Label runtime; 236 237 assert(pre_val != noreg, "check this code"); 238 239 if (obj != noreg) { 240 assert_different_registers(obj, pre_val, tmp); 241 assert(pre_val != rax, "check this code"); 242 } 243 244 generate_pre_barrier_fast_path(masm, thread); 245 // If marking is not active (*(mark queue active address) == 0), jump to done 246 __ jcc(Assembler::equal, done); 247 generate_pre_barrier_slow_path(masm, obj, pre_val, thread, tmp, done, runtime); 248 249 __ bind(runtime); 250 251 // Determine and save the live input values 252 __ push_call_clobbered_registers(); 253 254 // Calling the runtime using the regular call_VM_leaf mechanism generates 255 // code (generated by InterpreterMacroAssember::call_VM_leaf_base) 256 // that checks that the *(ebp+frame::interpreter_frame_last_sp) == nullptr. 257 // 258 // If we care generating the pre-barrier without a frame (e.g. in the 259 // intrinsified Reference.get() routine) then ebp might be pointing to 260 // the caller frame and so this check will most likely fail at runtime. 261 // 262 // Expanding the call directly bypasses the generation of the check. 263 // So when we do not have have a full interpreter frame on the stack 264 // expand_call should be passed true. 265 266 if (expand_call) { 267 LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) 268 #ifdef _LP64 269 if (c_rarg1 != thread) { 270 __ mov(c_rarg1, thread); 271 } 272 if (c_rarg0 != pre_val) { 273 __ mov(c_rarg0, pre_val); 274 } 275 #else 276 __ push(thread); 277 __ push(pre_val); 278 #endif 279 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2); 280 } else { 281 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); 282 } 283 284 __ pop_call_clobbered_registers(); 285 286 __ bind(done); 287 } 288 289 // return a register that differs from reg1, reg2, reg3 and is not rcx 290 291 static Register pick_different_reg(Register reg1, Register reg2 = noreg, Register reg3= noreg, Register reg4 = noreg) { 292 RegSet available = (RegSet::of(rscratch1, rscratch2, rax, rbx) + rdx - 293 RegSet::of(reg1, reg2, reg3, reg4)); 294 return *(available.begin()); 295 } 296 297 static void generate_post_barrier_fast_path(MacroAssembler* masm, 298 const Register store_addr, 299 const Register new_val, 300 const Register tmp, 301 const Register tmp2, 302 Label& done, 303 bool new_val_may_be_null) { 304 CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set()); 305 // Does store cross heap regions? 306 #if INCLUDE_CDS 307 // AOT code needs to load the barrier grain shift from the aot 308 // runtime constants area in the code cache otherwise we can compile 309 // it as an immediate operand 310 311 if (SCCache::is_on_for_write()) { 312 address grain_shift_addr = AOTRuntimeConstants::grain_shift_address(); 313 Register save = pick_different_reg(rcx, tmp, new_val, store_addr); 314 __ push(save); 315 __ movptr(save, store_addr); 316 __ xorptr(save, new_val); 317 __ push(rcx); 318 __ lea(rcx, ExternalAddress(grain_shift_addr)); 319 __ movptr(rcx, Address(rcx, 0)); 320 __ shrptr(save); 321 __ pop(rcx); 322 __ mov(tmp, save); 323 __ pop(save); 324 __ jcc(Assembler::equal, done); 325 } else 326 #endif // INCLUDE_CDS 327 { 328 __ movptr(tmp, store_addr); // tmp := store address 329 __ xorptr(tmp, new_val); // tmp := store address ^ new value 330 __ shrptr(tmp, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0? 331 __ jcc(Assembler::equal, done); 332 } 333 334 // Crosses regions, storing null? 335 if (new_val_may_be_null) { 336 __ cmpptr(new_val, NULL_WORD); // new value == null? 337 __ jcc(Assembler::equal, done); 338 } 339 // Storing region crossing non-null, is card young? 340 __ movptr(tmp, store_addr); // tmp := store address 341 #if INCLUDE_CDS 342 // AOT code needs to load the barrier card shift from the aot 343 // runtime constants area in the code cache otherwise we can compile 344 // it as an immediate operand 345 if (SCCache::is_on_for_write()) { 346 address card_shift_addr = AOTRuntimeConstants::card_shift_address(); 347 Register save = pick_different_reg(rcx, tmp); 348 __ push(save); 349 __ mov(save, tmp); 350 __ push(rcx); 351 __ lea(rcx, ExternalAddress(card_shift_addr)); 352 __ movptr(rcx, Address(rcx, 0)); 353 __ shrptr(save); 354 __ pop(rcx); 355 __ mov(tmp, save); 356 __ pop(save); 357 } else 358 #endif // INCLUDE_CDS 359 { 360 __ shrptr(tmp, CardTable::card_shift()); // tmp := card address relative to card table base 361 } 362 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT 363 // a valid address and therefore is not properly handled by the relocation code. 364 if (SCCache::is_on_for_write()) { 365 // SCA needs relocation info for this address 366 __ lea(tmp2, ExternalAddress((address)ct->card_table()->byte_map_base())); // tmp2 := card table base address 367 } else { 368 __ movptr(tmp2, (intptr_t)ct->card_table()->byte_map_base()); // tmp2 := card table base address 369 } 370 __ addptr(tmp, tmp2); // tmp := card address 371 __ cmpb(Address(tmp, 0), G1CardTable::g1_young_card_val()); // *(card address) == young_card_val? 372 } 373 374 static void generate_post_barrier_slow_path(MacroAssembler* masm, 375 const Register thread, 376 const Register tmp, 377 const Register tmp2, 378 Label& done, 379 Label& runtime) { 380 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); // StoreLoad membar 381 __ cmpb(Address(tmp, 0), G1CardTable::dirty_card_val()); // *(card address) == dirty_card_val? 382 __ jcc(Assembler::equal, done); 383 // Storing a region crossing, non-null oop, card is clean. 384 // Dirty card and log. 385 __ movb(Address(tmp, 0), G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val 386 generate_queue_insertion(masm, 387 G1ThreadLocalData::dirty_card_queue_index_offset(), 388 G1ThreadLocalData::dirty_card_queue_buffer_offset(), 389 runtime, 390 thread, tmp, tmp2); 391 __ jmp(done); 392 } 393 394 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, 395 Register store_addr, 396 Register new_val, 397 Register thread, 398 Register tmp, 399 Register tmp2) { 400 #ifdef _LP64 401 assert(thread == r15_thread, "must be"); 402 #endif // _LP64 403 404 Label done; 405 Label runtime; 406 407 generate_post_barrier_fast_path(masm, store_addr, new_val, tmp, tmp2, done, true /* new_val_may_be_null */); 408 // If card is young, jump to done 409 __ jcc(Assembler::equal, done); 410 generate_post_barrier_slow_path(masm, thread, tmp, tmp2, done, runtime); 411 412 __ bind(runtime); 413 // save the live input values 414 RegSet saved = RegSet::of(store_addr NOT_LP64(COMMA thread)); 415 __ push_set(saved); 416 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), tmp, thread); 417 __ pop_set(saved); 418 419 __ bind(done); 420 } 421 422 #if defined(COMPILER2) 423 424 static void generate_c2_barrier_runtime_call(MacroAssembler* masm, G1BarrierStubC2* stub, const Register arg, const address runtime_path) { 425 #ifdef _LP64 426 SaveLiveRegisters save_registers(masm, stub); 427 if (c_rarg0 != arg) { 428 __ mov(c_rarg0, arg); 429 } 430 __ mov(c_rarg1, r15_thread); 431 // rax is a caller-saved, non-argument-passing register, so it does not 432 // interfere with c_rarg0 or c_rarg1. If it contained any live value before 433 // entering this stub, it is saved at this point, and restored after the 434 // call. If it did not contain any live value, it is free to be used. In 435 // either case, it is safe to use it here as a call scratch register. 436 __ call(RuntimeAddress(runtime_path), rax); 437 #else 438 Unimplemented(); 439 #endif // _LP64 440 } 441 442 void G1BarrierSetAssembler::g1_write_barrier_pre_c2(MacroAssembler* masm, 443 Register obj, 444 Register pre_val, 445 Register thread, 446 Register tmp, 447 G1PreBarrierStubC2* stub) { 448 #ifdef _LP64 449 assert(thread == r15_thread, "must be"); 450 #endif // _LP64 451 assert(pre_val != noreg, "check this code"); 452 if (obj != noreg) { 453 assert_different_registers(obj, pre_val, tmp); 454 } 455 456 stub->initialize_registers(obj, pre_val, thread, tmp); 457 458 generate_pre_barrier_fast_path(masm, thread); 459 // If marking is active (*(mark queue active address) != 0), jump to stub (slow path) 460 __ jcc(Assembler::notEqual, *stub->entry()); 461 462 __ bind(*stub->continuation()); 463 } 464 465 void G1BarrierSetAssembler::generate_c2_pre_barrier_stub(MacroAssembler* masm, 466 G1PreBarrierStubC2* stub) const { 467 Assembler::InlineSkippedInstructionsCounter skip_counter(masm); 468 Label runtime; 469 Register obj = stub->obj(); 470 Register pre_val = stub->pre_val(); 471 Register thread = stub->thread(); 472 Register tmp = stub->tmp1(); 473 assert(stub->tmp2() == noreg, "not needed in this platform"); 474 475 __ bind(*stub->entry()); 476 generate_pre_barrier_slow_path(masm, obj, pre_val, thread, tmp, *stub->continuation(), runtime); 477 478 __ bind(runtime); 479 generate_c2_barrier_runtime_call(masm, stub, pre_val, CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry)); 480 __ jmp(*stub->continuation()); 481 } 482 483 void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm, 484 Register store_addr, 485 Register new_val, 486 Register thread, 487 Register tmp, 488 Register tmp2, 489 G1PostBarrierStubC2* stub) { 490 #ifdef _LP64 491 assert(thread == r15_thread, "must be"); 492 #endif // _LP64 493 494 stub->initialize_registers(thread, tmp, tmp2); 495 496 bool new_val_may_be_null = (stub->barrier_data() & G1C2BarrierPostNotNull) == 0; 497 generate_post_barrier_fast_path(masm, store_addr, new_val, tmp, tmp2, *stub->continuation(), new_val_may_be_null); 498 // If card is not young, jump to stub (slow path) 499 __ jcc(Assembler::notEqual, *stub->entry()); 500 501 __ bind(*stub->continuation()); 502 } 503 504 void G1BarrierSetAssembler::generate_c2_post_barrier_stub(MacroAssembler* masm, 505 G1PostBarrierStubC2* stub) const { 506 Assembler::InlineSkippedInstructionsCounter skip_counter(masm); 507 Label runtime; 508 Register thread = stub->thread(); 509 Register tmp = stub->tmp1(); // tmp holds the card address. 510 Register tmp2 = stub->tmp2(); 511 assert(stub->tmp3() == noreg, "not needed in this platform"); 512 513 __ bind(*stub->entry()); 514 generate_post_barrier_slow_path(masm, thread, tmp, tmp2, *stub->continuation(), runtime); 515 516 __ bind(runtime); 517 generate_c2_barrier_runtime_call(masm, stub, tmp, CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry)); 518 __ jmp(*stub->continuation()); 519 } 520 521 #endif // COMPILER2 522 523 void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 524 Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { 525 bool in_heap = (decorators & IN_HEAP) != 0; 526 bool as_normal = (decorators & AS_NORMAL) != 0; 527 528 bool needs_pre_barrier = as_normal; 529 bool needs_post_barrier = val != noreg && in_heap; 530 531 Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); 532 // flatten object address if needed 533 // We do it regardless of precise because we need the registers 534 if (dst.index() == noreg && dst.disp() == 0) { 535 if (dst.base() != tmp1) { 536 __ movptr(tmp1, dst.base()); 537 } 538 } else { 539 __ lea(tmp1, dst); 540 } 541 542 #ifndef _LP64 543 InterpreterMacroAssembler *imasm = static_cast<InterpreterMacroAssembler*>(masm); 544 #endif 545 546 NOT_LP64(__ get_thread(rcx)); 547 NOT_LP64(imasm->save_bcp()); 548 549 if (needs_pre_barrier) { 550 g1_write_barrier_pre(masm /*masm*/, 551 tmp1 /* obj */, 552 tmp2 /* pre_val */, 553 rthread /* thread */, 554 tmp3 /* tmp */, 555 val != noreg /* tosca_live */, 556 false /* expand_call */); 557 } 558 if (val == noreg) { 559 BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg); 560 } else { 561 Register new_val = val; 562 if (needs_post_barrier) { 563 // G1 barrier needs uncompressed oop for region cross check. 564 if (UseCompressedOops) { 565 new_val = tmp2; 566 __ movptr(new_val, val); 567 } 568 } 569 BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg); 570 if (needs_post_barrier) { 571 g1_write_barrier_post(masm /*masm*/, 572 tmp1 /* store_adr */, 573 new_val /* new_val */, 574 rthread /* thread */, 575 tmp3 /* tmp */, 576 tmp2 /* tmp2 */); 577 } 578 } 579 NOT_LP64(imasm->restore_bcp()); 580 } 581 582 #ifdef COMPILER1 583 584 #undef __ 585 #define __ ce->masm()-> 586 587 void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) { 588 G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); 589 // At this point we know that marking is in progress. 590 // If do_load() is true then we have to emit the 591 // load of the previous value; otherwise it has already 592 // been loaded into _pre_val. 593 594 __ bind(*stub->entry()); 595 assert(stub->pre_val()->is_register(), "Precondition."); 596 597 Register pre_val_reg = stub->pre_val()->as_register(); 598 599 if (stub->do_load()) { 600 ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/); 601 } 602 603 __ cmpptr(pre_val_reg, NULL_WORD); 604 __ jcc(Assembler::equal, *stub->continuation()); 605 ce->store_parameter(stub->pre_val()->as_register(), 0); 606 __ call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin())); 607 __ jmp(*stub->continuation()); 608 609 } 610 611 void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) { 612 G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); 613 __ bind(*stub->entry()); 614 assert(stub->addr()->is_register(), "Precondition."); 615 assert(stub->new_val()->is_register(), "Precondition."); 616 Register new_val_reg = stub->new_val()->as_register(); 617 __ cmpptr(new_val_reg, NULL_WORD); 618 __ jcc(Assembler::equal, *stub->continuation()); 619 ce->store_parameter(stub->addr()->as_pointer_register(), 0); 620 __ call(RuntimeAddress(bs->post_barrier_c1_runtime_code_blob()->code_begin())); 621 __ jmp(*stub->continuation()); 622 } 623 624 #undef __ 625 626 #define __ sasm-> 627 628 void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) { 629 // Generated code assumes that buffer index is pointer sized. 630 STATIC_ASSERT(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t)); 631 632 __ prologue("g1_pre_barrier", false); 633 // arg0 : previous value of memory 634 635 __ push(rax); 636 __ push(rdx); 637 638 const Register pre_val = rax; 639 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); 640 const Register tmp = rdx; 641 642 NOT_LP64(__ get_thread(thread);) 643 644 Address queue_active(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); 645 Address queue_index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())); 646 Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())); 647 648 Label done; 649 Label runtime; 650 651 // Is marking still active? 652 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 653 __ cmpl(queue_active, 0); 654 } else { 655 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 656 __ cmpb(queue_active, 0); 657 } 658 __ jcc(Assembler::equal, done); 659 660 // Can we store original value in the thread's buffer? 661 662 __ movptr(tmp, queue_index); 663 __ testptr(tmp, tmp); 664 __ jcc(Assembler::zero, runtime); 665 __ subptr(tmp, wordSize); 666 __ movptr(queue_index, tmp); 667 __ addptr(tmp, buffer); 668 669 // prev_val (rax) 670 __ load_parameter(0, pre_val); 671 __ movptr(Address(tmp, 0), pre_val); 672 __ jmp(done); 673 674 __ bind(runtime); 675 676 __ push_call_clobbered_registers(); 677 678 // load the pre-value 679 __ load_parameter(0, rcx); 680 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), rcx, thread); 681 682 __ pop_call_clobbered_registers(); 683 684 __ bind(done); 685 686 __ pop(rdx); 687 __ pop(rax); 688 689 __ epilogue(); 690 } 691 692 void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) { 693 __ prologue("g1_post_barrier", false); 694 695 CardTableBarrierSet* ct = 696 barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set()); 697 698 Label done; 699 Label enqueued; 700 Label runtime; 701 702 // At this point we know new_value is non-null and the new_value crosses regions. 703 // Must check to see if card is already dirty 704 705 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); 706 707 Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())); 708 Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())); 709 710 __ push(rax); 711 __ push(rcx); 712 713 const Register cardtable = rax; 714 const Register card_addr = rcx; 715 716 __ load_parameter(0, card_addr); 717 __ shrptr(card_addr, CardTable::card_shift()); 718 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT 719 // a valid address and therefore is not properly handled by the relocation code. 720 if (SCCache::is_on()) { 721 // SCA needs relocation info for this address 722 __ lea(cardtable, ExternalAddress((address)ct->card_table()->byte_map_base())); 723 } else { 724 __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); 725 } 726 __ addptr(card_addr, cardtable); 727 728 NOT_LP64(__ get_thread(thread);) 729 730 __ cmpb(Address(card_addr, 0), G1CardTable::g1_young_card_val()); 731 __ jcc(Assembler::equal, done); 732 733 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); 734 __ cmpb(Address(card_addr, 0), CardTable::dirty_card_val()); 735 __ jcc(Assembler::equal, done); 736 737 // storing region crossing non-null, card is clean. 738 // dirty card and log. 739 740 __ movb(Address(card_addr, 0), CardTable::dirty_card_val()); 741 742 const Register tmp = rdx; 743 __ push(rdx); 744 745 __ movptr(tmp, queue_index); 746 __ testptr(tmp, tmp); 747 __ jcc(Assembler::zero, runtime); 748 __ subptr(tmp, wordSize); 749 __ movptr(queue_index, tmp); 750 __ addptr(tmp, buffer); 751 __ movptr(Address(tmp, 0), card_addr); 752 __ jmp(enqueued); 753 754 __ bind(runtime); 755 __ push_call_clobbered_registers(); 756 757 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); 758 759 __ pop_call_clobbered_registers(); 760 761 __ bind(enqueued); 762 __ pop(rdx); 763 764 __ bind(done); 765 __ pop(rcx); 766 __ pop(rax); 767 768 __ epilogue(); 769 } 770 771 #undef __ 772 773 #endif // COMPILER1