1 /* 2 * Copyright (c) 2018, 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 #include "gc/g1/g1BarrierSet.hpp" 28 #include "gc/g1/g1BarrierSetAssembler.hpp" 29 #include "gc/g1/g1CardTable.hpp" 30 #include "gc/g1/g1ThreadLocalData.hpp" 31 #include "gc/g1/heapRegion.hpp" 32 #include "interpreter/interp_masm.hpp" 33 #include "runtime/sharedRuntime.hpp" 34 #include "utilities/macros.hpp" 35 36 #define __ masm-> 37 38 void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, 39 Register addr, Register count) { 40 bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0; 41 42 if (!dest_uninitialized) { 43 Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); 44 #ifndef _LP64 45 __ push(thread); 46 __ get_thread(thread); 47 #endif 48 49 Label filtered; 50 Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); 51 // Is marking active? 52 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 53 __ cmpl(in_progress, 0); 54 } else { 55 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 56 __ cmpb(in_progress, 0); 57 } 58 59 NOT_LP64(__ pop(thread);) 60 61 __ jcc(Assembler::equal, filtered); 62 63 __ pusha(); // push registers 64 #ifdef _LP64 65 if (count == c_rarg0) { 66 if (addr == c_rarg1) { 67 // exactly backwards!! 68 __ xchgptr(c_rarg1, c_rarg0); 69 } else { 70 __ movptr(c_rarg1, count); 71 __ movptr(c_rarg0, addr); 72 } 73 } else { 74 __ movptr(c_rarg0, addr); 75 __ movptr(c_rarg1, count); 76 } 77 if (UseCompressedOops) { 78 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry), 2); 79 } else { 80 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), 2); 81 } 82 #else 83 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), 84 addr, count); 85 #endif 86 __ popa(); 87 88 __ bind(filtered); 89 } 90 } 91 92 void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, 93 Register addr, Register count, Register tmp) { 94 __ pusha(); // push registers (overkill) 95 #ifdef _LP64 96 if (c_rarg0 == count) { // On win64 c_rarg0 == rcx 97 assert_different_registers(c_rarg1, addr); 98 __ mov(c_rarg1, count); 99 __ mov(c_rarg0, addr); 100 } else { 101 assert_different_registers(c_rarg0, count); 102 __ mov(c_rarg0, addr); 103 __ mov(c_rarg1, count); 104 } 105 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), 2); 106 #else 107 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), 108 addr, count); 109 #endif 110 __ popa(); 111 } 112 113 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 114 Register dst, Address src, Register tmp1, Register tmp_thread) { 115 bool on_oop = type == T_OBJECT || type == T_ARRAY; 116 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; 117 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; 118 bool on_reference = on_weak || on_phantom; 119 ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); 120 if (on_oop && on_reference) { 121 const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); 122 NOT_LP64(__ get_thread(thread)); 123 124 // Generate the G1 pre-barrier code to log the value of 125 // the referent field in an SATB buffer. 126 g1_write_barrier_pre(masm /* masm */, 127 noreg /* obj */, 128 dst /* pre_val */, 129 thread /* thread */, 130 tmp1 /* tmp */, 131 true /* tosca_live */, 132 true /* expand_call */); 133 } 134 } 135 136 void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, 137 Register obj, 138 Register pre_val, 139 Register thread, 140 Register tmp, 141 bool tosca_live, 142 bool expand_call) { 143 // If expand_call is true then we expand the call_VM_leaf macro 144 // directly to skip generating the check by 145 // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. 146 147 #ifdef _LP64 148 assert(thread == r15_thread, "must be"); 149 #endif // _LP64 150 151 Label done; 152 Label runtime; 153 154 assert(pre_val != noreg, "check this code"); 155 156 if (obj != noreg) { 157 assert_different_registers(obj, pre_val, tmp); 158 assert(pre_val != rax, "check this code"); 159 } 160 161 Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); 162 Address index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())); 163 Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())); 164 165 // Is marking active? 166 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 167 __ cmpl(in_progress, 0); 168 } else { 169 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 170 __ cmpb(in_progress, 0); 171 } 172 __ jcc(Assembler::equal, done); 173 174 // Do we need to load the previous value? 175 if (obj != noreg) { 176 __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW); 177 } 178 179 // Is the previous value null? 180 __ cmpptr(pre_val, (int32_t) NULL_WORD); 181 __ jcc(Assembler::equal, done); 182 183 // Can we store original value in the thread's buffer? 184 // Is index == 0? 185 // (The index field is typed as size_t.) 186 187 __ movptr(tmp, index); // tmp := *index_adr 188 __ cmpptr(tmp, 0); // tmp == 0? 189 __ jcc(Assembler::equal, runtime); // If yes, goto runtime 190 191 __ subptr(tmp, wordSize); // tmp := tmp - wordSize 192 __ movptr(index, tmp); // *index_adr := tmp 193 __ addptr(tmp, buffer); // tmp := tmp + *buffer_adr 194 195 // Record the previous value 196 __ movptr(Address(tmp, 0), pre_val); 197 __ jmp(done); 198 199 __ bind(runtime); 200 // save the live input values 201 if(tosca_live) __ push(rax); 202 203 if (obj != noreg && obj != rax) 204 __ push(obj); 205 206 if (pre_val != rax) 207 __ push(pre_val); 208 209 // Calling the runtime using the regular call_VM_leaf mechanism generates 210 // code (generated by InterpreterMacroAssember::call_VM_leaf_base) 211 // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL. 212 // 213 // If we care generating the pre-barrier without a frame (e.g. in the 214 // intrinsified Reference.get() routine) then ebp might be pointing to 215 // the caller frame and so this check will most likely fail at runtime. 216 // 217 // Expanding the call directly bypasses the generation of the check. 218 // So when we do not have have a full interpreter frame on the stack 219 // expand_call should be passed true. 220 221 NOT_LP64( __ push(thread); ) 222 223 if (expand_call) { 224 LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) 225 #ifdef _LP64 226 if (c_rarg1 != thread) { 227 __ mov(c_rarg1, thread); 228 } 229 if (c_rarg0 != pre_val) { 230 __ mov(c_rarg0, pre_val); 231 } 232 #else 233 __ push(thread); 234 __ push(pre_val); 235 #endif 236 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2); 237 } else { 238 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread); 239 } 240 241 NOT_LP64( __ pop(thread); ) 242 243 // save the live input values 244 if (pre_val != rax) 245 __ pop(pre_val); 246 247 if (obj != noreg && obj != rax) 248 __ pop(obj); 249 250 if(tosca_live) __ pop(rax); 251 252 __ bind(done); 253 } 254 255 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, 256 Register store_addr, 257 Register new_val, 258 Register thread, 259 Register tmp, 260 Register tmp2) { 261 #ifdef _LP64 262 assert(thread == r15_thread, "must be"); 263 #endif // _LP64 264 265 Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())); 266 Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())); 267 268 CardTableBarrierSet* ct = 269 barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set()); 270 assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code"); 271 272 Label done; 273 Label runtime; 274 275 // Does store cross heap regions? 276 277 __ movptr(tmp, store_addr); 278 __ xorptr(tmp, new_val); 279 __ shrptr(tmp, HeapRegion::LogOfHRGrainBytes); 280 __ jcc(Assembler::equal, done); 281 282 // crosses regions, storing NULL? 283 284 __ cmpptr(new_val, (int32_t) NULL_WORD); 285 __ jcc(Assembler::equal, done); 286 287 // storing region crossing non-NULL, is card already dirty? 288 289 const Register card_addr = tmp; 290 const Register cardtable = tmp2; 291 292 __ movptr(card_addr, store_addr); 293 __ shrptr(card_addr, CardTable::card_shift); 294 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT 295 // a valid address and therefore is not properly handled by the relocation code. 296 __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); 297 __ addptr(card_addr, cardtable); 298 299 __ cmpb(Address(card_addr, 0), (int)G1CardTable::g1_young_card_val()); 300 __ jcc(Assembler::equal, done); 301 302 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); 303 __ cmpb(Address(card_addr, 0), (int)G1CardTable::dirty_card_val()); 304 __ jcc(Assembler::equal, done); 305 306 307 // storing a region crossing, non-NULL oop, card is clean. 308 // dirty card and log. 309 310 __ movb(Address(card_addr, 0), (int)G1CardTable::dirty_card_val()); 311 312 __ cmpl(queue_index, 0); 313 __ jcc(Assembler::equal, runtime); 314 __ subl(queue_index, wordSize); 315 __ movptr(tmp2, buffer); 316 #ifdef _LP64 317 __ movslq(rscratch1, queue_index); 318 __ addq(tmp2, rscratch1); 319 __ movq(Address(tmp2, 0), card_addr); 320 #else 321 __ addl(tmp2, queue_index); 322 __ movl(Address(tmp2, 0), card_addr); 323 #endif 324 __ jmp(done); 325 326 __ bind(runtime); 327 // save the live input values 328 __ push(store_addr); 329 __ push(new_val); 330 #ifdef _LP64 331 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, r15_thread); 332 #else 333 __ push(thread); 334 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); 335 __ pop(thread); 336 #endif 337 __ pop(new_val); 338 __ pop(store_addr); 339 340 __ bind(done); 341 } 342 343 void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 344 Address dst, Register val, Register tmp1, Register tmp2) { 345 bool in_heap = (decorators & IN_HEAP) != 0; 346 bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0; 347 348 bool needs_pre_barrier = in_heap || in_concurrent_root; 349 bool needs_post_barrier = val != noreg && in_heap; 350 351 Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi); 352 Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); 353 // flatten object address if needed 354 // We do it regardless of precise because we need the registers 355 if (dst.index() == noreg && dst.disp() == 0) { 356 if (dst.base() != tmp1) { 357 __ movptr(tmp1, dst.base()); 358 } 359 } else { 360 __ lea(tmp1, dst); 361 } 362 363 #ifndef _LP64 364 InterpreterMacroAssembler *imasm = static_cast<InterpreterMacroAssembler*>(masm); 365 #endif 366 367 NOT_LP64(__ get_thread(rcx)); 368 NOT_LP64(imasm->save_bcp()); 369 370 if (needs_pre_barrier) { 371 g1_write_barrier_pre(masm /*masm*/, 372 tmp1 /* obj */, 373 tmp2 /* pre_val */, 374 rthread /* thread */, 375 tmp3 /* tmp */, 376 val != noreg /* tosca_live */, 377 false /* expand_call */); 378 } 379 if (val == noreg) { 380 BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); 381 } else { 382 Register new_val = val; 383 if (needs_post_barrier) { 384 // G1 barrier needs uncompressed oop for region cross check. 385 if (UseCompressedOops) { 386 new_val = tmp2; 387 __ movptr(new_val, val); 388 } 389 } 390 BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); 391 if (needs_post_barrier) { 392 g1_write_barrier_post(masm /*masm*/, 393 tmp1 /* store_adr */, 394 new_val /* new_val */, 395 rthread /* thread */, 396 tmp3 /* tmp */, 397 tmp2 /* tmp2 */); 398 } 399 } 400 NOT_LP64(imasm->restore_bcp()); 401 }