1 /* 2 * Copyright (c) 2019, 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 #include "precompiled.hpp" 25 #include "asm/macroAssembler.inline.hpp" 26 #include "code/codeBlob.hpp" 27 #include "code/vmreg.inline.hpp" 28 #include "gc/z/zBarrier.inline.hpp" 29 #include "gc/z/zBarrierSet.hpp" 30 #include "gc/z/zBarrierSetAssembler.hpp" 31 #include "gc/z/zBarrierSetRuntime.hpp" 32 #include "gc/z/zThreadLocalData.hpp" 33 #include "memory/resourceArea.hpp" 34 #include "runtime/sharedRuntime.hpp" 35 #include "utilities/macros.hpp" 36 #ifdef COMPILER1 37 #include "c1/c1_LIRAssembler.hpp" 38 #include "c1/c1_MacroAssembler.hpp" 39 #include "gc/z/c1/zBarrierSetC1.hpp" 40 #endif // COMPILER1 41 #ifdef COMPILER2 42 #include "gc/z/c2/zBarrierSetC2.hpp" 43 #endif // COMPILER2 44 45 #ifdef PRODUCT 46 #define BLOCK_COMMENT(str) /* nothing */ 47 #else 48 #define BLOCK_COMMENT(str) __ block_comment(str) 49 #endif 50 51 #undef __ 52 #define __ masm-> 53 54 void ZBarrierSetAssembler::load_at(MacroAssembler* masm, 55 DecoratorSet decorators, 56 BasicType type, 57 Register dst, 58 Address src, 59 Register tmp1, 60 Register tmp_thread) { 61 if (!ZBarrierSet::barrier_needed(decorators, type)) { 62 // Barrier not needed 63 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); 64 return; 65 } 66 67 assert_different_registers(rscratch1, rscratch2, src.base()); 68 assert_different_registers(rscratch1, rscratch2, dst); 69 70 RegSet savedRegs = RegSet::range(r0, r28) - RegSet::of(dst, rscratch1, rscratch2); 71 72 Label done; 73 74 // Load bad mask into scratch register. 75 __ ldr(rscratch1, address_bad_mask_from_thread(rthread)); 76 __ lea(rscratch2, src); 77 __ ldr(dst, src); 78 79 // Test reference against bad mask. If mask bad, then we need to fix it up. 80 __ tst(dst, rscratch1); 81 __ br(Assembler::EQ, done); 82 83 __ enter(); 84 85 __ push(savedRegs, sp); 86 87 if (c_rarg0 != dst) { 88 __ mov(c_rarg0, dst); 89 } 90 __ mov(c_rarg1, rscratch2); 91 92 int step = 4 * wordSize; 93 __ mov(rscratch2, -step); 94 __ sub(sp, sp, step); 95 96 for (int i = 28; i >= 4; i -= 4) { 97 __ st1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2), 98 as_FloatRegister(i+3), __ T1D, Address(__ post(sp, rscratch2))); 99 } 100 __ st1(as_FloatRegister(0), as_FloatRegister(1), as_FloatRegister(2), 101 as_FloatRegister(3), __ T1D, Address(sp)); 102 103 __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); 104 105 for (int i = 0; i <= 28; i += 4) { 106 __ ld1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2), 107 as_FloatRegister(i+3), __ T1D, Address(__ post(sp, step))); 108 } 109 110 // Make sure dst has the return value. 111 if (dst != r0) { 112 __ mov(dst, r0); 113 } 114 115 __ pop(savedRegs, sp); 116 __ leave(); 117 118 __ bind(done); 119 } 120 121 #ifdef ASSERT 122 123 void ZBarrierSetAssembler::store_at(MacroAssembler* masm, 124 DecoratorSet decorators, 125 BasicType type, 126 Address dst, 127 Register val, 128 Register tmp1, 129 Register tmp2) { 130 // Verify value 131 if (is_reference_type(type)) { 132 // Note that src could be noreg, which means we 133 // are storing null and can skip verification. 134 if (val != noreg) { 135 Label done; 136 137 // tmp1 and tmp2 are often set to noreg. 138 RegSet savedRegs = RegSet::of(rscratch1); 139 __ push(savedRegs, sp); 140 141 __ ldr(rscratch1, address_bad_mask_from_thread(rthread)); 142 __ tst(val, rscratch1); 143 __ br(Assembler::EQ, done); 144 __ stop("Verify oop store failed"); 145 __ should_not_reach_here(); 146 __ bind(done); 147 __ pop(savedRegs, sp); 148 } 149 } 150 151 // Store value 152 BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); 153 } 154 155 #endif // ASSERT 156 157 void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, 158 DecoratorSet decorators, 159 bool is_oop, 160 Register src, 161 Register dst, 162 Register count, 163 RegSet saved_regs) { 164 if (!is_oop) { 165 // Barrier not needed 166 return; 167 } 168 169 BLOCK_COMMENT("ZBarrierSetAssembler::arraycopy_prologue {"); 170 171 assert_different_registers(src, count, rscratch1); 172 173 __ pusha(); 174 175 if (count == c_rarg0) { 176 if (src == c_rarg1) { 177 // exactly backwards!! 178 __ mov(rscratch1, c_rarg0); 179 __ mov(c_rarg0, c_rarg1); 180 __ mov(c_rarg1, rscratch1); 181 } else { 182 __ mov(c_rarg1, count); 183 __ mov(c_rarg0, src); 184 } 185 } else { 186 __ mov(c_rarg0, src); 187 __ mov(c_rarg1, count); 188 } 189 190 __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_array_addr(), 2); 191 192 __ popa(); 193 BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue"); 194 } 195 196 void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, 197 Register jni_env, 198 Register robj, 199 Register tmp, 200 Label& slowpath) { 201 BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_jobject_in_native {"); 202 203 assert_different_registers(jni_env, robj, tmp); 204 205 // Resolve jobject 206 BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, robj, tmp, slowpath); 207 208 // The Address offset is too large to direct load - -784. Our range is +127, -128. 209 __ mov(tmp, (long int)(in_bytes(ZThreadLocalData::address_bad_mask_offset()) - 210 in_bytes(JavaThread::jni_environment_offset()))); 211 212 // Load address bad mask 213 __ add(tmp, jni_env, tmp); 214 __ ldr(tmp, Address(tmp)); 215 216 // Check address bad mask 217 __ tst(robj, tmp); 218 __ br(Assembler::NE, slowpath); 219 220 BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native"); 221 } 222 223 #ifdef COMPILER1 224 225 #undef __ 226 #define __ ce->masm()-> 227 228 void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce, 229 LIR_Opr ref) const { 230 assert_different_registers(rscratch1, rthread, ref->as_register()); 231 232 __ ldr(rscratch1, address_bad_mask_from_thread(rthread)); 233 __ tst(ref->as_register(), rscratch1); 234 } 235 236 void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce, 237 ZLoadBarrierStubC1* stub) const { 238 // Stub entry 239 __ bind(*stub->entry()); 240 241 Register ref = stub->ref()->as_register(); 242 Register ref_addr = noreg; 243 Register tmp = noreg; 244 245 if (stub->tmp()->is_valid()) { 246 // Load address into tmp register 247 ce->leal(stub->ref_addr(), stub->tmp()); 248 ref_addr = tmp = stub->tmp()->as_pointer_register(); 249 } else { 250 // Address already in register 251 ref_addr = stub->ref_addr()->as_address_ptr()->base()->as_pointer_register(); 252 } 253 254 assert_different_registers(ref, ref_addr, noreg); 255 256 // Save r0 unless it is the result or tmp register 257 // Set up SP to accomodate parameters and maybe r0.. 258 if (ref != r0 && tmp != r0) { 259 __ sub(sp, sp, 32); 260 __ str(r0, Address(sp, 16)); 261 } else { 262 __ sub(sp, sp, 16); 263 } 264 265 // Setup arguments and call runtime stub 266 ce->store_parameter(ref_addr, 1); 267 ce->store_parameter(ref, 0); 268 269 __ far_call(stub->runtime_stub()); 270 271 // Verify result 272 __ verify_oop(r0, "Bad oop"); 273 274 // Move result into place 275 if (ref != r0) { 276 __ mov(ref, r0); 277 } 278 279 // Restore r0 unless it is the result or tmp register 280 if (ref != r0 && tmp != r0) { 281 __ ldr(r0, Address(sp, 16)); 282 __ add(sp, sp, 32); 283 } else { 284 __ add(sp, sp, 16); 285 } 286 287 // Stub exit 288 __ b(*stub->continuation()); 289 } 290 291 #undef __ 292 #define __ sasm-> 293 294 void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, 295 DecoratorSet decorators) const { 296 __ prologue("zgc_load_barrier stub", false); 297 298 // We don't use push/pop_clobbered_registers() - we need to pull out the result from r0. 299 for (int i = 0; i < 32; i += 2) { 300 __ stpd(as_FloatRegister(i), as_FloatRegister(i + 1), Address(__ pre(sp,-16))); 301 } 302 303 const RegSet save_regs = RegSet::range(r1, r28); 304 __ push(save_regs, sp); 305 306 // Setup arguments 307 __ load_parameter(0, c_rarg0); 308 __ load_parameter(1, c_rarg1); 309 310 __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); 311 312 __ pop(save_regs, sp); 313 314 for (int i = 30; i >= 0; i -= 2) { 315 __ ldpd(as_FloatRegister(i), as_FloatRegister(i + 1), Address(__ post(sp, 16))); 316 } 317 318 __ epilogue(); 319 } 320 #endif // COMPILER1 321 322 #ifdef COMPILER2 323 324 OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { 325 if (!OptoReg::is_reg(opto_reg)) { 326 return OptoReg::Bad; 327 } 328 329 const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); 330 if (vm_reg->is_FloatRegister()) { 331 return opto_reg & ~1; 332 } 333 334 return opto_reg; 335 } 336 337 #undef __ 338 #define __ _masm-> 339 340 class ZSaveLiveRegisters { 341 private: 342 MacroAssembler* const _masm; 343 RegSet _gp_regs; 344 RegSet _fp_regs; 345 346 public: 347 void initialize(ZLoadBarrierStubC2* stub) { 348 // Create mask of live registers 349 RegMask live = stub->live(); 350 351 // Record registers that needs to be saved/restored 352 while (live.is_NotEmpty()) { 353 const OptoReg::Name opto_reg = live.find_first_elem(); 354 live.Remove(opto_reg); 355 if (OptoReg::is_reg(opto_reg)) { 356 const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); 357 if (vm_reg->is_Register()) { 358 _gp_regs += RegSet::of(vm_reg->as_Register()); 359 } else if (vm_reg->is_FloatRegister()) { 360 _fp_regs += RegSet::of((Register)vm_reg->as_FloatRegister()); 361 } else { 362 fatal("Unknown register type"); 363 } 364 } 365 } 366 367 // Remove C-ABI SOE registers, scratch regs and _ref register that will be updated 368 _gp_regs -= RegSet::range(r19, r30) + RegSet::of(r8, r9, stub->ref()); 369 } 370 371 ZSaveLiveRegisters(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : 372 _masm(masm), 373 _gp_regs(), 374 _fp_regs() { 375 376 // Figure out what registers to save/restore 377 initialize(stub); 378 379 // Save registers 380 __ push(_gp_regs, sp); 381 __ push_fp(_fp_regs, sp); 382 } 383 384 ~ZSaveLiveRegisters() { 385 // Restore registers 386 __ pop_fp(_fp_regs, sp); 387 __ pop(_gp_regs, sp); 388 } 389 }; 390 391 #undef __ 392 #define __ _masm-> 393 394 class ZSetupArguments { 395 private: 396 MacroAssembler* const _masm; 397 const Register _ref; 398 const Address _ref_addr; 399 400 public: 401 ZSetupArguments(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : 402 _masm(masm), 403 _ref(stub->ref()), 404 _ref_addr(stub->ref_addr()) { 405 406 // Setup arguments 407 if (_ref_addr.base() == noreg) { 408 // No self healing 409 if (_ref != c_rarg0) { 410 __ mov(c_rarg0, _ref); 411 } 412 __ mov(c_rarg1, 0); 413 } else { 414 // Self healing 415 if (_ref == c_rarg0) { 416 // _ref is already at correct place 417 __ lea(c_rarg1, _ref_addr); 418 } else if (_ref != c_rarg1) { 419 // _ref is in wrong place, but not in c_rarg1, so fix it first 420 __ lea(c_rarg1, _ref_addr); 421 __ mov(c_rarg0, _ref); 422 } else if (_ref_addr.base() != c_rarg0 && _ref_addr.index() != c_rarg0) { 423 assert(_ref == c_rarg1, "Mov ref first, vacating c_rarg0"); 424 __ mov(c_rarg0, _ref); 425 __ lea(c_rarg1, _ref_addr); 426 } else { 427 assert(_ref == c_rarg1, "Need to vacate c_rarg1 and _ref_addr is using c_rarg0"); 428 if (_ref_addr.base() == c_rarg0 || _ref_addr.index() == c_rarg0) { 429 __ mov(rscratch2, c_rarg1); 430 __ lea(c_rarg1, _ref_addr); 431 __ mov(c_rarg0, rscratch2); 432 } else { 433 ShouldNotReachHere(); 434 } 435 } 436 } 437 } 438 439 ~ZSetupArguments() { 440 // Transfer result 441 if (_ref != r0) { 442 __ mov(_ref, r0); 443 } 444 } 445 }; 446 447 #undef __ 448 #define __ masm-> 449 450 void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { 451 BLOCK_COMMENT("ZLoadBarrierStubC2"); 452 453 // Stub entry 454 __ bind(*stub->entry()); 455 456 { 457 ZSaveLiveRegisters save_live_registers(masm, stub); 458 ZSetupArguments setup_arguments(masm, stub); 459 __ mov(rscratch1, stub->slow_path()); 460 __ blr(rscratch1); 461 } 462 463 // Stub exit 464 __ b(*stub->continuation()); 465 } 466 467 #undef __ 468 469 #endif // COMPILER2