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