1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018, SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "asm/macroAssembler.inline.hpp" 28 #include "gc/g1/g1BarrierSet.hpp" 29 #include "gc/g1/g1CardTable.hpp" 30 #include "gc/g1/g1BarrierSetAssembler.hpp" 31 #include "gc/g1/g1ThreadLocalData.hpp" 32 #include "gc/g1/heapRegion.hpp" 33 #include "interpreter/interp_masm.hpp" 34 #include "runtime/sharedRuntime.hpp" 35 36 #define __ masm-> 37 38 void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, 39 Register from, Register to, Register count, 40 Register preserve1, Register preserve2) { 41 bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0; 42 // With G1, don't generate the call if we statically know that the target in uninitialized 43 if (!dest_uninitialized) { 44 int spill_slots = 3; 45 if (preserve1 != noreg) { spill_slots++; } 46 if (preserve2 != noreg) { spill_slots++; } 47 const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); 48 Label filtered; 49 50 // Is marking active? 51 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 52 __ lwz(R0, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread); 53 } else { 54 guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 55 __ lbz(R0, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread); 56 } 57 __ cmpdi(CCR0, R0, 0); 58 __ beq(CCR0, filtered); 59 60 __ save_LR_CR(R0); 61 __ push_frame(frame_size, R0); 62 int slot_nr = 0; 63 __ std(from, frame_size - (++slot_nr) * wordSize, R1_SP); 64 __ std(to, frame_size - (++slot_nr) * wordSize, R1_SP); 65 __ std(count, frame_size - (++slot_nr) * wordSize, R1_SP); 66 if (preserve1 != noreg) { __ std(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); } 67 if (preserve2 != noreg) { __ std(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); } 68 69 if (UseCompressedOops) { 70 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_narrow_oop_entry), to, count); 71 } else { 72 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_pre_oop_entry), to, count); 73 } 74 75 slot_nr = 0; 76 __ ld(from, frame_size - (++slot_nr) * wordSize, R1_SP); 77 __ ld(to, frame_size - (++slot_nr) * wordSize, R1_SP); 78 __ ld(count, frame_size - (++slot_nr) * wordSize, R1_SP); 79 if (preserve1 != noreg) { __ ld(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); } 80 if (preserve2 != noreg) { __ ld(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); } 81 __ addi(R1_SP, R1_SP, frame_size); // pop_frame() 82 __ restore_LR_CR(R0); 83 84 __ bind(filtered); 85 } 86 } 87 88 void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, 89 Register addr, Register count, Register preserve) { 90 int spill_slots = (preserve != noreg) ? 1 : 0; 91 const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); 92 93 __ save_LR_CR(R0); 94 __ push_frame(frame_size, R0); 95 if (preserve != noreg) { __ std(preserve, frame_size - 1 * wordSize, R1_SP); } 96 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), addr, count); 97 if (preserve != noreg) { __ ld(preserve, frame_size - 1 * wordSize, R1_SP); } 98 __ addi(R1_SP, R1_SP, frame_size); // pop_frame(); 99 __ restore_LR_CR(R0); 100 } 101 102 void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, DecoratorSet decorators, Register obj, RegisterOrConstant ind_or_offs, Register pre_val, 103 Register tmp1, Register tmp2, bool needs_frame) { 104 bool not_null = (decorators & OOP_NOT_NULL) != 0, 105 preloaded = obj == noreg; 106 Register nv_save = noreg; 107 108 if (preloaded) { 109 // We are not loading the previous value so make 110 // sure that we don't trash the value in pre_val 111 // with the code below. 112 assert_different_registers(pre_val, tmp1, tmp2); 113 if (pre_val->is_volatile()) { 114 nv_save = !tmp1->is_volatile() ? tmp1 : tmp2; 115 assert(!nv_save->is_volatile(), "need one nv temp register if pre_val lives in volatile register"); 116 } 117 } 118 119 Label runtime, filtered; 120 121 // Is marking active? 122 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 123 __ lwz(tmp1, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread); 124 } else { 125 guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 126 __ lbz(tmp1, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread); 127 } 128 __ cmpdi(CCR0, tmp1, 0); 129 __ beq(CCR0, filtered); 130 131 // Do we need to load the previous value? 132 if (!preloaded) { 133 // Load the previous value... 134 if (UseCompressedOops) { 135 __ lwz(pre_val, ind_or_offs, obj); 136 } else { 137 __ ld(pre_val, ind_or_offs, obj); 138 } 139 // Previous value has been loaded into Rpre_val. 140 } 141 assert(pre_val != noreg, "must have a real register"); 142 143 // Is the previous value null? 144 if (preloaded && not_null) { 145 #ifdef ASSERT 146 __ cmpdi(CCR0, pre_val, 0); 147 __ asm_assert_ne("null oop not allowed (G1 pre)", 0x321); // Checked by caller. 148 #endif 149 } else { 150 __ cmpdi(CCR0, pre_val, 0); 151 __ beq(CCR0, filtered); 152 } 153 154 if (!preloaded && UseCompressedOops) { 155 __ decode_heap_oop_not_null(pre_val); 156 } 157 158 // OK, it's not filtered, so we'll need to call enqueue. In the normal 159 // case, pre_val will be a scratch G-reg, but there are some cases in 160 // which it's an O-reg. In the first case, do a normal call. In the 161 // latter, do a save here and call the frameless version. 162 163 // Can we store original value in the thread's buffer? 164 // Is index == 0? 165 // (The index field is typed as size_t.) 166 const Register Rbuffer = tmp1, Rindex = tmp2; 167 168 __ ld(Rindex, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()), R16_thread); 169 __ cmpdi(CCR0, Rindex, 0); 170 __ beq(CCR0, runtime); // If index == 0, goto runtime. 171 __ ld(Rbuffer, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()), R16_thread); 172 173 __ addi(Rindex, Rindex, -wordSize); // Decrement index. 174 __ std(Rindex, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()), R16_thread); 175 176 // Record the previous value. 177 __ stdx(pre_val, Rbuffer, Rindex); 178 __ b(filtered); 179 180 __ bind(runtime); 181 182 // May need to preserve LR. Also needed if current frame is not compatible with C calling convention. 183 if (needs_frame) { 184 __ save_LR_CR(tmp1); 185 __ push_frame_reg_args(0, tmp2); 186 } 187 188 if (pre_val->is_volatile() && preloaded) { __ mr(nv_save, pre_val); } // Save pre_val across C call if it was preloaded. 189 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, R16_thread); 190 if (pre_val->is_volatile() && preloaded) { __ mr(pre_val, nv_save); } // restore 191 192 if (needs_frame) { 193 __ pop_frame(); 194 __ restore_LR_CR(tmp1); 195 } 196 197 __ bind(filtered); 198 } 199 200 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register store_addr, Register new_val, 201 Register tmp1, Register tmp2, Register tmp3) { 202 bool not_null = (decorators & OOP_NOT_NULL) != 0; 203 204 Label runtime, filtered; 205 assert_different_registers(store_addr, new_val, tmp1, tmp2); 206 207 CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set()); 208 assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code"); 209 210 // Does store cross heap regions? 211 if (G1RSBarrierRegionFilter) { 212 __ xorr(tmp1, store_addr, new_val); 213 __ srdi_(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes); 214 __ beq(CCR0, filtered); 215 } 216 217 // Crosses regions, storing NULL? 218 if (not_null) { 219 #ifdef ASSERT 220 __ cmpdi(CCR0, new_val, 0); 221 __ asm_assert_ne("null oop not allowed (G1 post)", 0x322); // Checked by caller. 222 #endif 223 } else { 224 __ cmpdi(CCR0, new_val, 0); 225 __ beq(CCR0, filtered); 226 } 227 228 // Storing region crossing non-NULL, is card already dirty? 229 const Register Rcard_addr = tmp1; 230 Register Rbase = tmp2; 231 __ load_const_optimized(Rbase, (address)(ct->card_table()->byte_map_base()), /*temp*/ tmp3); 232 233 __ srdi(Rcard_addr, store_addr, CardTable::card_shift); 234 235 // Get the address of the card. 236 __ lbzx(/*card value*/ tmp3, Rbase, Rcard_addr); 237 __ cmpwi(CCR0, tmp3, (int)G1CardTable::g1_young_card_val()); 238 __ beq(CCR0, filtered); 239 240 __ membar(Assembler::StoreLoad); 241 __ lbzx(/*card value*/ tmp3, Rbase, Rcard_addr); // Reload after membar. 242 __ cmpwi(CCR0, tmp3 /* card value */, (int)G1CardTable::dirty_card_val()); 243 __ beq(CCR0, filtered); 244 245 // Storing a region crossing, non-NULL oop, card is clean. 246 // Dirty card and log. 247 __ li(tmp3, (int)G1CardTable::dirty_card_val()); 248 //release(); // G1: oops are allowed to get visible after dirty marking. 249 __ stbx(tmp3, Rbase, Rcard_addr); 250 251 __ add(Rcard_addr, Rbase, Rcard_addr); // This is the address which needs to get enqueued. 252 Rbase = noreg; // end of lifetime 253 254 const Register Rqueue_index = tmp2, 255 Rqueue_buf = tmp3; 256 __ ld(Rqueue_index, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()), R16_thread); 257 __ cmpdi(CCR0, Rqueue_index, 0); 258 __ beq(CCR0, runtime); // index == 0 then jump to runtime 259 __ ld(Rqueue_buf, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()), R16_thread); 260 261 __ addi(Rqueue_index, Rqueue_index, -wordSize); // decrement index 262 __ std(Rqueue_index, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()), R16_thread); 263 264 __ stdx(Rcard_addr, Rqueue_buf, Rqueue_index); // store card 265 __ b(filtered); 266 267 __ bind(runtime); 268 269 // Save the live input values. 270 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, R16_thread); 271 272 __ bind(filtered); 273 } 274 275 void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 276 Register base, RegisterOrConstant ind_or_offs, Register val, 277 Register tmp1, Register tmp2, Register tmp3, bool needs_frame) { 278 bool on_array = (decorators & IN_HEAP_ARRAY) != 0; 279 bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0; 280 bool precise = on_array || on_anonymous; 281 // Load and record the previous value. 282 g1_write_barrier_pre(masm, decorators, base, ind_or_offs, 283 tmp1, tmp2, tmp3, needs_frame); 284 285 BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame); 286 287 // No need for post barrier if storing NULL 288 if (val != noreg) { 289 if (precise) { 290 if (ind_or_offs.is_constant()) { 291 __ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp1); 292 } else { 293 __ add(base, ind_or_offs.as_register(), base); 294 } 295 } 296 g1_write_barrier_post(masm, decorators, base, val, tmp1, tmp2, tmp3); 297 } 298 } 299 300 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, 301 Register base, RegisterOrConstant ind_or_offs, Register dst, 302 Register tmp1, Register tmp2, bool needs_frame, Label *is_null) { 303 bool on_oop = type == T_OBJECT || type == T_ARRAY; 304 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; 305 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; 306 bool on_reference = on_weak || on_phantom; 307 Label done; 308 if (on_oop && on_reference && is_null == NULL) { is_null = &done; } 309 // Load the value of the referent field. 310 ModRefBarrierSetAssembler::load_at(masm, decorators, type, base, ind_or_offs, dst, tmp1, tmp2, needs_frame, is_null); 311 if (on_oop && on_reference) { 312 // Generate the G1 pre-barrier code to log the value of 313 // the referent field in an SATB buffer. Note with 314 // these parameters the pre-barrier does not generate 315 // the load of the previous value 316 // We only reach here if value is not null. 317 g1_write_barrier_pre(masm, decorators | OOP_NOT_NULL, noreg /* obj */, (intptr_t)0, dst /* pre_val */, 318 tmp1, tmp2, needs_frame); 319 } 320 __ bind(done); 321 } 322 323 void G1BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2, bool needs_frame) { 324 Label done, not_weak; 325 __ cmpdi(CCR0, value, 0); 326 __ beq(CCR0, done); // Use NULL as-is. 327 328 __ clrrdi(tmp1, value, JNIHandles::weak_tag_size); 329 __ andi_(tmp2, value, JNIHandles::weak_tag_mask); 330 __ ld(value, 0, tmp1); // Resolve (untagged) jobject. 331 332 __ beq(CCR0, not_weak); // Test for jweak tag. 333 __ verify_oop(value); 334 g1_write_barrier_pre(masm, IN_ROOT | ON_PHANTOM_OOP_REF, 335 noreg, noreg, value, 336 tmp1, tmp2, needs_frame); 337 __ bind(not_weak); 338 __ verify_oop(value); 339 __ bind(done); 340 } 341 342 #undef __