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 "classfile/classLoaderData.hpp" 27 #include "gc/shared/barrierSet.hpp" 28 #include "gc/shared/barrierSetAssembler.hpp" 29 #include "gc/shared/barrierSetNMethod.hpp" 30 #include "gc/shared/barrierSetRuntime.hpp" 31 #include "gc/shared/collectedHeap.hpp" 32 #include "interpreter/interp_masm.hpp" 33 #include "memory/universe.hpp" 34 #include "runtime/javaThread.hpp" 35 #include "runtime/jniHandles.hpp" 36 #include "runtime/sharedRuntime.hpp" 37 #include "runtime/stubRoutines.hpp" 38 39 40 #define __ masm-> 41 42 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 43 Register dst, Address src, Register tmp1, Register tmp2) { 44 45 // LR is live. It must be saved around calls. 46 47 bool in_heap = (decorators & IN_HEAP) != 0; 48 bool in_native = (decorators & IN_NATIVE) != 0; 49 bool is_not_null = (decorators & IS_NOT_NULL) != 0; 50 51 switch (type) { 52 case T_OBJECT: 53 case T_ARRAY: { 54 if (in_heap) { 55 if (UseCompressedOops) { 56 __ ldrw(dst, src); 57 if (is_not_null) { 58 __ decode_heap_oop_not_null(dst); 59 } else { 60 __ decode_heap_oop(dst); 61 } 62 } else { 63 __ ldr(dst, src); 64 } 65 } else { 66 assert(in_native, "why else?"); 67 __ ldr(dst, src); 68 } 69 break; 70 } 71 case T_BOOLEAN: __ load_unsigned_byte (dst, src); break; 72 case T_BYTE: __ load_signed_byte (dst, src); break; 73 case T_CHAR: __ load_unsigned_short(dst, src); break; 74 case T_SHORT: __ load_signed_short (dst, src); break; 75 case T_INT: __ ldrw (dst, src); break; 76 case T_LONG: __ ldr (dst, src); break; 77 case T_ADDRESS: __ ldr (dst, src); break; 78 case T_FLOAT: __ ldrs (v0, src); break; 79 case T_DOUBLE: __ ldrd (v0, src); break; 80 default: Unimplemented(); 81 } 82 } 83 84 void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 85 Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { 86 bool in_heap = (decorators & IN_HEAP) != 0; 87 bool in_native = (decorators & IN_NATIVE) != 0; 88 bool is_not_null = (decorators & IS_NOT_NULL) != 0; 89 90 switch (type) { 91 case T_OBJECT: 92 case T_ARRAY: { 93 if (in_heap) { 94 if (val == noreg) { 95 assert(!is_not_null, "inconsistent access"); 96 if (UseCompressedOops) { 97 __ strw(zr, dst); 98 } else { 99 __ str(zr, dst); 100 } 101 } else { 102 if (UseCompressedOops) { 103 assert(!dst.uses(val), "not enough registers"); 104 if (is_not_null) { 105 __ encode_heap_oop_not_null(val); 106 } else { 107 __ encode_heap_oop(val); 108 } 109 __ strw(val, dst); 110 } else { 111 __ str(val, dst); 112 } 113 } 114 } else { 115 assert(in_native, "why else?"); 116 assert(val != noreg, "not supported"); 117 __ str(val, dst); 118 } 119 break; 120 } 121 case T_BOOLEAN: 122 __ andw(val, val, 0x1); // boolean is true if LSB is 1 123 __ strb(val, dst); 124 break; 125 case T_BYTE: __ strb(val, dst); break; 126 case T_CHAR: __ strh(val, dst); break; 127 case T_SHORT: __ strh(val, dst); break; 128 case T_INT: __ strw(val, dst); break; 129 case T_LONG: __ str (val, dst); break; 130 case T_ADDRESS: __ str (val, dst); break; 131 case T_FLOAT: __ strs(v0, dst); break; 132 case T_DOUBLE: __ strd(v0, dst); break; 133 default: Unimplemented(); 134 } 135 } 136 137 void BarrierSetAssembler::value_copy(MacroAssembler* masm, DecoratorSet decorators, 138 Register src, Register dst, Register value_klass) { 139 // value_copy implementation is fairly complex, and there are not any 140 // "short-cuts" to be made from asm. What there is, appears to have the same 141 // cost in C++, so just "call_VM_leaf" for now rather than maintain hundreds 142 // of hand-rolled instructions... 143 if (decorators & IS_DEST_UNINITIALIZED) { 144 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetRuntime::value_copy_is_dest_uninitialized), src, dst, value_klass); 145 } else { 146 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetRuntime::value_copy), src, dst, value_klass); 147 } 148 } 149 150 void BarrierSetAssembler::copy_load_at(MacroAssembler* masm, 151 DecoratorSet decorators, 152 BasicType type, 153 size_t bytes, 154 Register dst1, 155 Register dst2, 156 Address src, 157 Register tmp) { 158 if (bytes == 1) { 159 assert(dst2 == noreg, "invariant"); 160 __ ldrb(dst1, src); 161 } else if (bytes == 2) { 162 assert(dst2 == noreg, "invariant"); 163 __ ldrh(dst1, src); 164 } else if (bytes == 4) { 165 assert(dst2 == noreg, "invariant"); 166 __ ldrw(dst1, src); 167 } else if (bytes == 8) { 168 assert(dst2 == noreg, "invariant"); 169 __ ldr(dst1, src); 170 } else if (bytes == 16) { 171 assert(dst2 != noreg, "invariant"); 172 assert(dst2 != dst1, "invariant"); 173 __ ldp(dst1, dst2, src); 174 } else { 175 // Not the right size 176 ShouldNotReachHere(); 177 } 178 if ((decorators & ARRAYCOPY_CHECKCAST) != 0 && UseCompressedOops) { 179 __ decode_heap_oop(dst1); 180 } 181 } 182 183 void BarrierSetAssembler::copy_store_at(MacroAssembler* masm, 184 DecoratorSet decorators, 185 BasicType type, 186 size_t bytes, 187 Address dst, 188 Register src1, 189 Register src2, 190 Register tmp1, 191 Register tmp2, 192 Register tmp3) { 193 if ((decorators & ARRAYCOPY_CHECKCAST) != 0 && UseCompressedOops) { 194 __ encode_heap_oop(src1); 195 } 196 if (bytes == 1) { 197 assert(src2 == noreg, "invariant"); 198 __ strb(src1, dst); 199 } else if (bytes == 2) { 200 assert(src2 == noreg, "invariant"); 201 __ strh(src1, dst); 202 } else if (bytes == 4) { 203 assert(src2 == noreg, "invariant"); 204 __ strw(src1, dst); 205 } else if (bytes == 8) { 206 assert(src2 == noreg, "invariant"); 207 __ str(src1, dst); 208 } else if (bytes == 16) { 209 assert(src2 != noreg, "invariant"); 210 assert(src2 != src1, "invariant"); 211 __ stp(src1, src2, dst); 212 } else { 213 // Not the right size 214 ShouldNotReachHere(); 215 } 216 } 217 218 void BarrierSetAssembler::copy_load_at(MacroAssembler* masm, 219 DecoratorSet decorators, 220 BasicType type, 221 size_t bytes, 222 FloatRegister dst1, 223 FloatRegister dst2, 224 Address src, 225 Register tmp1, 226 Register tmp2, 227 FloatRegister vec_tmp) { 228 if (bytes == 32) { 229 __ ldpq(dst1, dst2, src); 230 } else { 231 ShouldNotReachHere(); 232 } 233 } 234 235 void BarrierSetAssembler::copy_store_at(MacroAssembler* masm, 236 DecoratorSet decorators, 237 BasicType type, 238 size_t bytes, 239 Address dst, 240 FloatRegister src1, 241 FloatRegister src2, 242 Register tmp1, 243 Register tmp2, 244 Register tmp3, 245 FloatRegister vec_tmp1, 246 FloatRegister vec_tmp2, 247 FloatRegister vec_tmp3) { 248 if (bytes == 32) { 249 __ stpq(src1, src2, dst); 250 } else { 251 ShouldNotReachHere(); 252 } 253 } 254 255 void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, 256 Register obj, Register tmp, Label& slowpath) { 257 // If mask changes we need to ensure that the inverse is still encodable as an immediate 258 STATIC_ASSERT(JNIHandles::tag_mask == 0b11); 259 __ andr(obj, obj, ~JNIHandles::tag_mask); 260 __ ldr(obj, Address(obj, 0)); // *obj 261 } 262 263 // Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes. 264 void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj, 265 Register var_size_in_bytes, 266 int con_size_in_bytes, 267 Register t1, 268 Register t2, 269 Label& slow_case) { 270 assert_different_registers(obj, t2); 271 assert_different_registers(obj, var_size_in_bytes); 272 Register end = t2; 273 274 // verify_tlab(); 275 276 __ ldr(obj, Address(rthread, JavaThread::tlab_top_offset())); 277 if (var_size_in_bytes == noreg) { 278 __ lea(end, Address(obj, con_size_in_bytes)); 279 } else { 280 __ lea(end, Address(obj, var_size_in_bytes)); 281 } 282 __ ldr(rscratch1, Address(rthread, JavaThread::tlab_end_offset())); 283 __ cmp(end, rscratch1); 284 __ br(Assembler::HI, slow_case); 285 286 // update the tlab top pointer 287 __ str(end, Address(rthread, JavaThread::tlab_top_offset())); 288 289 // recover var_size_in_bytes if necessary 290 if (var_size_in_bytes == end) { 291 __ sub(var_size_in_bytes, var_size_in_bytes, obj); 292 } 293 // verify_tlab(); 294 } 295 296 void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, 297 Register var_size_in_bytes, 298 int con_size_in_bytes, 299 Register t1) { 300 assert(t1->is_valid(), "need temp reg"); 301 302 __ ldr(t1, Address(rthread, in_bytes(JavaThread::allocated_bytes_offset()))); 303 if (var_size_in_bytes->is_valid()) { 304 __ add(t1, t1, var_size_in_bytes); 305 } else { 306 __ add(t1, t1, con_size_in_bytes); 307 } 308 __ str(t1, Address(rthread, in_bytes(JavaThread::allocated_bytes_offset()))); 309 } 310 311 static volatile uint32_t _patching_epoch = 0; 312 313 address BarrierSetAssembler::patching_epoch_addr() { 314 return (address)&_patching_epoch; 315 } 316 317 void BarrierSetAssembler::increment_patching_epoch() { 318 Atomic::inc(&_patching_epoch); 319 } 320 321 void BarrierSetAssembler::clear_patching_epoch() { 322 _patching_epoch = 0; 323 } 324 325 void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Label* slow_path, Label* continuation, Label* guard) { 326 BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); 327 328 if (bs_nm == nullptr) { 329 return; 330 } 331 332 Label local_guard; 333 Label skip_barrier; 334 NMethodPatchingType patching_type = nmethod_patching_type(); 335 336 if (slow_path == nullptr) { 337 guard = &local_guard; 338 } 339 340 // If the slow path is out of line in a stub, we flip the condition 341 Assembler::Condition condition = slow_path == nullptr ? Assembler::EQ : Assembler::NE; 342 Label& barrier_target = slow_path == nullptr ? skip_barrier : *slow_path; 343 344 __ ldrw(rscratch1, *guard); 345 346 if (patching_type == NMethodPatchingType::stw_instruction_and_data_patch) { 347 // With STW patching, no data or instructions are updated concurrently, 348 // which means there isn't really any need for any fencing for neither 349 // data nor instruction modifications happening concurrently. The 350 // instruction patching is handled with isb fences on the way back 351 // from the safepoint to Java. So here we can do a plain conditional 352 // branch with no fencing. 353 Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); 354 __ ldrw(rscratch2, thread_disarmed_addr); 355 __ cmp(rscratch1, rscratch2); 356 } else if (patching_type == NMethodPatchingType::conc_instruction_and_data_patch) { 357 // If we patch code we need both a code patching and a loadload 358 // fence. It's not super cheap, so we use a global epoch mechanism 359 // to hide them in a slow path. 360 // The high level idea of the global epoch mechanism is to detect 361 // when any thread has performed the required fencing, after the 362 // last nmethod was disarmed. This implies that the required 363 // fencing has been performed for all preceding nmethod disarms 364 // as well. Therefore, we do not need any further fencing. 365 __ lea(rscratch2, ExternalAddress((address)&_patching_epoch)); 366 // Embed an artificial data dependency to order the guard load 367 // before the epoch load. 368 __ orr(rscratch2, rscratch2, rscratch1, Assembler::LSR, 32); 369 // Read the global epoch value. 370 __ ldrw(rscratch2, rscratch2); 371 // Combine the guard value (low order) with the epoch value (high order). 372 __ orr(rscratch1, rscratch1, rscratch2, Assembler::LSL, 32); 373 // Compare the global values with the thread-local values. 374 Address thread_disarmed_and_epoch_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); 375 __ ldr(rscratch2, thread_disarmed_and_epoch_addr); 376 __ cmp(rscratch1, rscratch2); 377 } else { 378 assert(patching_type == NMethodPatchingType::conc_data_patch, "must be"); 379 // Subsequent loads of oops must occur after load of guard value. 380 // BarrierSetNMethod::disarm sets guard with release semantics. 381 __ membar(__ LoadLoad); 382 Address thread_disarmed_addr(rthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset())); 383 __ ldrw(rscratch2, thread_disarmed_addr); 384 __ cmpw(rscratch1, rscratch2); 385 } 386 __ br(condition, barrier_target); 387 388 if (slow_path == nullptr) { 389 __ lea(rscratch1, RuntimeAddress(StubRoutines::method_entry_barrier())); 390 __ blr(rscratch1); 391 __ b(skip_barrier); 392 393 __ bind(local_guard); 394 395 __ emit_int32(0); // nmethod guard value. Skipped over in common case. 396 } else { 397 __ bind(*continuation); 398 } 399 400 __ bind(skip_barrier); 401 } 402 403 void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { 404 BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod(); 405 if (bs == nullptr) { 406 return; 407 } 408 409 Label bad_call; 410 __ cbz(rmethod, bad_call); 411 412 // Pointer chase to the method holder to find out if the method is concurrently unloading. 413 Label method_live; 414 __ load_method_holder_cld(rscratch1, rmethod); 415 416 // Is it a strong CLD? 417 __ ldrw(rscratch2, Address(rscratch1, ClassLoaderData::keep_alive_offset())); 418 __ cbnz(rscratch2, method_live); 419 420 // Is it a weak but alive CLD? 421 __ push(RegSet::of(r10), sp); 422 __ ldr(r10, Address(rscratch1, ClassLoaderData::holder_offset())); 423 424 __ resolve_weak_handle(r10, rscratch1, rscratch2); 425 __ mov(rscratch1, r10); 426 __ pop(RegSet::of(r10), sp); 427 __ cbnz(rscratch1, method_live); 428 429 __ bind(bad_call); 430 431 __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); 432 __ bind(method_live); 433 } 434 435 void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error) { 436 // Check if the oop is in the right area of memory 437 __ mov(tmp2, (intptr_t) Universe::verify_oop_mask()); 438 __ andr(tmp1, obj, tmp2); 439 __ mov(tmp2, (intptr_t) Universe::verify_oop_bits()); 440 441 // Compare tmp1 and tmp2. We don't use a compare 442 // instruction here because the flags register is live. 443 __ eor(tmp1, tmp1, tmp2); 444 __ cbnz(tmp1, error); 445 446 // make sure klass is 'reasonable', which is not zero. 447 __ load_klass(obj, obj); // get klass 448 __ cbz(obj, error); // if klass is null it is broken 449 }