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 }