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/g1BarrierSetRuntime.hpp"
  30 #include "gc/g1/g1CardTable.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 #include "utilities/macros.hpp"
  36 #ifdef COMPILER1
  37 #include "c1/c1_LIRAssembler.hpp"
  38 #include "c1/c1_MacroAssembler.hpp"
  39 #include "gc/g1/c1/g1BarrierSetC1.hpp"
  40 #endif
  41 
  42 #define __ masm->
  43 
  44 void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
  45                                                             Register addr, Register count) {
  46   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  47   // With G1, don't generate the call if we statically know that the target in uninitialized
  48   if (!dest_uninitialized) {
  49     Register tmp = O5;
  50     assert_different_registers(addr, count, tmp);
  51     Label filtered;
  52     // Is marking active?
  53     if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
  54       __ ld(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
  55     } else {
  56       guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
  57       __ ldsb(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
  58     }
  59     // Is marking active?
  60     __ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
  61 
  62     __ save_frame(0);
  63     // Save the necessary global regs... will be used after.
  64     if (addr->is_global()) {
  65       __ mov(addr, L0);
  66     }
  67     if (count->is_global()) {
  68       __ mov(count, L1);
  69     }
  70     __ mov(addr->after_save(), O0);
  71     // Get the count into O1
  72     address slowpath = UseCompressedOops ? CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_narrow_oop_entry)
  73                                          : CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry);
  74     __ call(slowpath);
  75     __ delayed()->mov(count->after_save(), O1);
  76     if (addr->is_global()) {
  77       __ mov(L0, addr);
  78     }
  79     if (count->is_global()) {
  80       __ mov(L1, count);
  81     }
  82     __ restore();
  83 
  84     __ bind(filtered);
  85     DEBUG_ONLY(__ set(0xDEADC0DE, tmp);) // we have killed tmp
  86   }
  87 }
  88 
  89 void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
  90                                                              Register addr, Register count, Register tmp) {
  91   // Get some new fresh output registers.
  92   __ save_frame(0);
  93   __ mov(addr->after_save(), O0);
  94   __ call(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry));
  95   __ delayed()->mov(count->after_save(), O1);
  96   __ restore();
  97 }
  98 
  99 #undef __
 100 
 101 static address satb_log_enqueue_with_frame = NULL;
 102 static u_char* satb_log_enqueue_with_frame_end = NULL;
 103 
 104 static address satb_log_enqueue_frameless = NULL;
 105 static u_char* satb_log_enqueue_frameless_end = NULL;
 106 
 107 static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions?
 108 
 109 static void generate_satb_log_enqueue(bool with_frame) {
 110   BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize);
 111   CodeBuffer buf(bb);
 112   MacroAssembler masm(&buf);
 113 
 114 #define __ masm.
 115 
 116   address start = __ pc();
 117   Register pre_val;
 118 
 119   Label refill, restart;
 120   if (with_frame) {
 121     __ save_frame(0);
 122     pre_val = I0;  // Was O0 before the save.
 123   } else {
 124     pre_val = O0;
 125   }
 126 
 127   int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
 128   int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
 129 
 130   assert(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t) &&
 131          in_bytes(SATBMarkQueue::byte_width_of_buf()) == sizeof(intptr_t),
 132          "check sizes in assembly below");
 133 
 134   __ bind(restart);
 135 
 136   // Load the index into the SATB buffer. SATBMarkQueue::_index is a size_t
 137   // so ld_ptr is appropriate.
 138   __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0);
 139 
 140   // index == 0?
 141   __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
 142 
 143   __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1);
 144   __ sub(L0, oopSize, L0);
 145 
 146   __ st_ptr(pre_val, L1, L0);  // [_buf + index] := I0
 147   if (!with_frame) {
 148     // Use return-from-leaf
 149     __ retl();
 150     __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset);
 151   } else {
 152     // Not delayed.
 153     __ st_ptr(L0, G2_thread, satb_q_index_byte_offset);
 154   }
 155   if (with_frame) {
 156     __ ret();
 157     __ delayed()->restore();
 158   }
 159   __ bind(refill);
 160 
 161   address handle_zero =
 162     CAST_FROM_FN_PTR(address,
 163                      &SATBMarkQueueSet::handle_zero_index_for_thread);
 164   // This should be rare enough that we can afford to save all the
 165   // scratch registers that the calling context might be using.
 166   __ mov(G1_scratch, L0);
 167   __ mov(G3_scratch, L1);
 168   __ mov(G4, L2);
 169   // We need the value of O0 above (for the write into the buffer), so we
 170   // save and restore it.
 171   __ mov(O0, L3);
 172   // Since the call will overwrite O7, we save and restore that, as well.
 173   __ mov(O7, L4);
 174   __ call_VM_leaf(L5, handle_zero, G2_thread);
 175   __ mov(L0, G1_scratch);
 176   __ mov(L1, G3_scratch);
 177   __ mov(L2, G4);
 178   __ mov(L3, O0);
 179   __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
 180   __ delayed()->mov(L4, O7);
 181 
 182   if (with_frame) {
 183     satb_log_enqueue_with_frame = start;
 184     satb_log_enqueue_with_frame_end = __ pc();
 185   } else {
 186     satb_log_enqueue_frameless = start;
 187     satb_log_enqueue_frameless_end = __ pc();
 188   }
 189 
 190 #undef __
 191 }
 192 
 193 #define __ masm->
 194 
 195 void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
 196                                                  Register obj,
 197                                                  Register index,
 198                                                  int offset,
 199                                                  Register pre_val,
 200                                                  Register tmp,
 201                                                  bool preserve_o_regs) {
 202   Label filtered;
 203 
 204   if (obj == noreg) {
 205     // We are not loading the previous value so make
 206     // sure that we don't trash the value in pre_val
 207     // with the code below.
 208     assert_different_registers(pre_val, tmp);
 209   } else {
 210     // We will be loading the previous value
 211     // in this code so...
 212     assert(offset == 0 || index == noreg, "choose one");
 213     assert(pre_val == noreg, "check this code");
 214   }
 215 
 216   // Is marking active?
 217   if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
 218     __ ld(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
 219   } else {
 220     guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
 221     __ ldsb(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
 222   }
 223 
 224   // Is marking active?
 225   __ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
 226 
 227   // Do we need to load the previous value?
 228   if (obj != noreg) {
 229     // Load the previous value...
 230     if (index == noreg) {
 231       if (Assembler::is_simm13(offset)) {
 232         __ load_heap_oop(obj, offset, tmp);
 233       } else {
 234         __ set(offset, tmp);
 235         __ load_heap_oop(obj, tmp, tmp);
 236       }
 237     } else {
 238       __ load_heap_oop(obj, index, tmp);
 239     }
 240     // Previous value has been loaded into tmp
 241     pre_val = tmp;
 242   }
 243 
 244   assert(pre_val != noreg, "must have a real register");
 245 
 246   // Is the previous value null?
 247   __ cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered);
 248 
 249   // OK, it's not filtered, so we'll need to call enqueue.  In the normal
 250   // case, pre_val will be a scratch G-reg, but there are some cases in
 251   // which it's an O-reg.  In the first case, do a normal call.  In the
 252   // latter, do a save here and call the frameless version.
 253 
 254   guarantee(pre_val->is_global() || pre_val->is_out(),
 255             "Or we need to think harder.");
 256 
 257   if (pre_val->is_global() && !preserve_o_regs) {
 258     __ call(satb_log_enqueue_with_frame);
 259     __ delayed()->mov(pre_val, O0);
 260   } else {
 261     __ save_frame(0);
 262     __ call(satb_log_enqueue_frameless);
 263     __ delayed()->mov(pre_val->after_save(), O0);
 264     __ restore();
 265   }
 266 
 267   __ bind(filtered);
 268 }
 269 
 270 #undef __
 271 
 272 static address dirty_card_log_enqueue = 0;
 273 static u_char* dirty_card_log_enqueue_end = 0;
 274 
 275 // This gets to assume that o0 contains the object address.
 276 static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
 277   BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2);
 278   CodeBuffer buf(bb);
 279   MacroAssembler masm(&buf);
 280 #define __ masm.
 281   address start = __ pc();
 282 
 283   Label not_already_dirty, restart, refill, young_card;
 284 
 285   __ srlx(O0, CardTable::card_shift, O0);
 286   AddressLiteral addrlit(byte_map_base);
 287   __ set(addrlit, O1); // O1 := <card table base>
 288   __ ldub(O0, O1, O2); // O2 := [O0 + O1]
 289 
 290   __ cmp_and_br_short(O2, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
 291 
 292   __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
 293   __ ldub(O0, O1, O2); // O2 := [O0 + O1]
 294 
 295   assert(G1CardTable::dirty_card_val() == 0, "otherwise check this code");
 296   __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
 297 
 298   __ bind(young_card);
 299   // We didn't take the branch, so we're already dirty: return.
 300   // Use return-from-leaf
 301   __ retl();
 302   __ delayed()->nop();
 303 
 304   // Not dirty.
 305   __ bind(not_already_dirty);
 306 
 307   // Get O0 + O1 into a reg by itself
 308   __ add(O0, O1, O3);
 309 
 310   // First, dirty it.
 311   __ stb(G0, O3, G0);  // [cardPtr] := 0  (i.e., dirty).
 312 
 313   int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
 314   int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 315   __ bind(restart);
 316 
 317   // Load the index into the update buffer. DirtyCardQueue::_index is
 318   // a size_t so ld_ptr is appropriate here.
 319   __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0);
 320 
 321   // index == 0?
 322   __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
 323 
 324   __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1);
 325   __ sub(L0, oopSize, L0);
 326 
 327   __ st_ptr(O3, L1, L0);  // [_buf + index] := I0
 328   // Use return-from-leaf
 329   __ retl();
 330   __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset);
 331 
 332   __ bind(refill);
 333   address handle_zero =
 334     CAST_FROM_FN_PTR(address,
 335                      &DirtyCardQueueSet::handle_zero_index_for_thread);
 336   // This should be rare enough that we can afford to save all the
 337   // scratch registers that the calling context might be using.
 338   __ mov(G1_scratch, L3);
 339   __ mov(G3_scratch, L5);
 340   // We need the value of O3 above (for the write into the buffer), so we
 341   // save and restore it.
 342   __ mov(O3, L6);
 343   // Since the call will overwrite O7, we save and restore that, as well.
 344   __ mov(O7, L4);
 345 
 346   __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread);
 347   __ mov(L3, G1_scratch);
 348   __ mov(L5, G3_scratch);
 349   __ mov(L6, O3);
 350   __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
 351   __ delayed()->mov(L4, O7);
 352 
 353   dirty_card_log_enqueue = start;
 354   dirty_card_log_enqueue_end = __ pc();
 355   // XXX Should have a guarantee here about not going off the end!
 356   // Does it already do so?  Do an experiment...
 357 
 358 #undef __
 359 
 360 }
 361 
 362 #define __ masm->
 363 
 364 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp) {
 365   Label filtered;
 366   MacroAssembler* post_filter_masm = masm;
 367 
 368   if (new_val == G0) return;
 369 
 370   G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
 371 
 372   __ xor3(store_addr, new_val, tmp);
 373   __ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp);
 374 
 375   __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
 376 
 377   // If the "store_addr" register is an "in" or "local" register, move it to
 378   // a scratch reg so we can pass it as an argument.
 379   bool use_scr = !(store_addr->is_global() || store_addr->is_out());
 380   // Pick a scratch register different from "tmp".
 381   Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch);
 382   // Make sure we use up the delay slot!
 383   if (use_scr) {
 384     post_filter_masm->mov(store_addr, scr);
 385   } else {
 386     post_filter_masm->nop();
 387   }
 388   __ save_frame(0);
 389   __ call(dirty_card_log_enqueue);
 390   if (use_scr) {
 391     __ delayed()->mov(scr, O0);
 392   } else {
 393     __ delayed()->mov(store_addr->after_save(), O0);
 394   }
 395   __ restore();
 396 
 397   __ bind(filtered);
 398 }
 399 
 400 void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
 401                                          Register val, Address dst, Register tmp) {
 402   bool in_heap = (decorators & IN_HEAP) != 0;
 403   bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0;
 404 
 405   bool needs_pre_barrier = in_heap || in_concurrent_root;
 406   // No need for post barrier if storing NULL
 407   bool needs_post_barrier = val != G0 && in_heap;
 408 
 409   bool is_array = (decorators & IS_ARRAY) != 0;
 410   bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 411   bool precise = is_array || on_anonymous;
 412 
 413   Register index = dst.has_index() ? dst.index() : noreg;
 414   int disp = dst.has_disp() ? dst.disp() : 0;
 415 
 416   if (needs_pre_barrier) {
 417     // Load and record the previous value.
 418     g1_write_barrier_pre(masm, dst.base(), index, disp,
 419                          noreg /* pre_val */,
 420                          tmp, true /*preserve_o_regs*/);
 421   }
 422 
 423   Register new_val = val;
 424   if (needs_post_barrier) {
 425     // G1 barrier needs uncompressed oop for region cross check.
 426     if (UseCompressedOops && val != G0) {
 427       new_val = tmp;
 428       __ mov(val, new_val);
 429     }
 430   }
 431 
 432   BarrierSetAssembler::store_at(masm, decorators, type, val, dst, tmp);
 433 
 434   if (needs_post_barrier) {
 435     Register base = dst.base();
 436     if (precise) {
 437       if (!dst.has_index()) {
 438         __ add(base, disp, base);
 439       } else {
 440         assert(!dst.has_disp(), "not supported yet");
 441         __ add(base, index, base);
 442       }
 443     }
 444     g1_write_barrier_post(masm, base, new_val, tmp);
 445   }
 446 }
 447 
 448 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
 449                                     Address src, Register dst, Register tmp) {
 450   bool on_oop = type == T_OBJECT || type == T_ARRAY;
 451   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
 452   bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
 453   bool on_reference = on_weak || on_phantom;
 454   // Load the value of the referent field.
 455   ModRefBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp);
 456   if (on_oop && on_reference) {
 457     // Generate the G1 pre-barrier code to log the value of
 458     // the referent field in an SATB buffer. Note with
 459     // these parameters the pre-barrier does not generate
 460     // the load of the previous value
 461 
 462     Register pre_val = dst;
 463     bool saved = false;
 464     if (pre_val->is_in()) {
 465       // The g1_write_barrier_pre method assumes that the pre_val
 466       // is not in an input register.
 467       __ save_frame_and_mov(0, pre_val, O0);
 468       pre_val = O0;
 469       saved = true;
 470     }
 471 
 472     g1_write_barrier_pre(masm, noreg /* obj */, noreg /* index */, 0 /* offset */,
 473                          pre_val /* pre_val */,
 474                          tmp /* tmp */,
 475                          true /* preserve_o_regs */);
 476 
 477     if (saved) {
 478       __ restore();
 479     }
 480   }
 481 }
 482 
 483 void G1BarrierSetAssembler::barrier_stubs_init() {
 484   if (dirty_card_log_enqueue == 0) {
 485     G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
 486     CardTable *ct = bs->card_table();
 487     generate_dirty_card_log_enqueue(ct->byte_map_base());
 488     assert(dirty_card_log_enqueue != 0, "postcondition.");
 489   }
 490   if (satb_log_enqueue_with_frame == 0) {
 491     generate_satb_log_enqueue(true);
 492     assert(satb_log_enqueue_with_frame != 0, "postcondition.");
 493   }
 494   if (satb_log_enqueue_frameless == 0) {
 495     generate_satb_log_enqueue(false);
 496     assert(satb_log_enqueue_frameless != 0, "postcondition.");
 497   }
 498 }
 499 
 500 #ifdef COMPILER1
 501 
 502 #undef __
 503 #define __ ce->masm()->
 504 
 505 void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
 506   G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
 507   // At this point we know that marking is in progress.
 508   // If do_load() is true then we have to emit the
 509   // load of the previous value; otherwise it has already
 510   // been loaded into _pre_val.
 511 
 512   __ bind(*stub->entry());
 513 
 514   assert(stub->pre_val()->is_register(), "Precondition.");
 515   Register pre_val_reg = stub->pre_val()->as_register();
 516 
 517   if (stub->do_load()) {
 518     ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
 519   }
 520 
 521   if (__ is_in_wdisp16_range(*stub->continuation())) {
 522     __ br_null(pre_val_reg, /*annul*/false, Assembler::pt, *stub->continuation());
 523   } else {
 524     __ cmp(pre_val_reg, G0);
 525     __ brx(Assembler::equal, false, Assembler::pn, *stub->continuation());
 526   }
 527   __ delayed()->nop();
 528 
 529   __ call(bs->pre_barrier_c1_runtime_code_blob()->code_begin());
 530   __ delayed()->mov(pre_val_reg, G4);
 531   __ br(Assembler::always, false, Assembler::pt, *stub->continuation());
 532   __ delayed()->nop();
 533 }
 534 
 535 void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
 536   G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
 537   __ bind(*stub->entry());
 538 
 539   assert(stub->addr()->is_register(), "Precondition.");
 540   assert(stub->new_val()->is_register(), "Precondition.");
 541   Register addr_reg = stub->addr()->as_pointer_register();
 542   Register new_val_reg = stub->new_val()->as_register();
 543 
 544   if (__ is_in_wdisp16_range(*stub->continuation())) {
 545     __ br_null(new_val_reg, /*annul*/false, Assembler::pt, *stub->continuation());
 546   } else {
 547     __ cmp(new_val_reg, G0);
 548     __ brx(Assembler::equal, false, Assembler::pn, *stub->continuation());
 549   }
 550   __ delayed()->nop();
 551 
 552   __ call(bs->post_barrier_c1_runtime_code_blob()->code_begin());
 553   __ delayed()->mov(addr_reg, G4);
 554   __ br(Assembler::always, false, Assembler::pt, *stub->continuation());
 555   __ delayed()->nop();
 556 }
 557 
 558 #undef __
 559 #define __ sasm->
 560 
 561 void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
 562   __ prologue("g1_pre_barrier", false);
 563 
 564   // G4: previous value of memory
 565 
 566   Register pre_val = G4;
 567   Register tmp  = G1_scratch;
 568   Register tmp2 = G3_scratch;
 569 
 570   Label refill, restart;
 571   int satb_q_active_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
 572   int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
 573   int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
 574 
 575   // Is marking still active?
 576   if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
 577     __ ld(G2_thread, satb_q_active_byte_offset, tmp);
 578   } else {
 579     assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
 580     __ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
 581   }
 582   __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
 583   __ retl();
 584   __ delayed()->nop();
 585 
 586   __ bind(restart);
 587   // Load the index into the SATB buffer. SATBMarkQueue::_index is a
 588   // size_t so ld_ptr is appropriate
 589   __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp);
 590 
 591   // index == 0?
 592   __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill);
 593 
 594   __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2);
 595   __ sub(tmp, oopSize, tmp);
 596 
 597   __ st_ptr(pre_val, tmp2, tmp);  // [_buf + index] := <address_of_card>
 598   // Use return-from-leaf
 599   __ retl();
 600   __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset);
 601 
 602   __ bind(refill);
 603 
 604   __ save_live_registers_no_oop_map(true);
 605 
 606   __ call_VM_leaf(L7_thread_cache,
 607                   CAST_FROM_FN_PTR(address,
 608                                    SATBMarkQueueSet::handle_zero_index_for_thread),
 609                                    G2_thread);
 610 
 611   __ restore_live_registers(true);
 612 
 613   __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
 614   __ epilogue();
 615 }
 616 
 617 void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
 618   __ prologue("g1_post_barrier", false);
 619 
 620   G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
 621 
 622   Register addr = G4;
 623   Register cardtable = G5;
 624   Register tmp  = G1_scratch;
 625   Register tmp2 = G3_scratch;
 626   jbyte* byte_map_base = bs->card_table()->byte_map_base();
 627 
 628   Label not_already_dirty, restart, refill, young_card;
 629 
 630 #ifdef _LP64
 631   __ srlx(addr, CardTable::card_shift, addr);
 632 #else
 633   __ srl(addr, CardTable::card_shift, addr);
 634 #endif
 635 
 636   AddressLiteral rs((address)byte_map_base);
 637   __ set(rs, cardtable);         // cardtable := <card table base>
 638   __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
 639 
 640   __ cmp_and_br_short(tmp, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
 641 
 642   __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
 643   __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
 644 
 645   assert(G1CardTable::dirty_card_val() == 0, "otherwise check this code");
 646   __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
 647 
 648   __ bind(young_card);
 649   // We didn't take the branch, so we're already dirty: return.
 650   // Use return-from-leaf
 651   __ retl();
 652   __ delayed()->nop();
 653 
 654   // Not dirty.
 655   __ bind(not_already_dirty);
 656 
 657   // Get cardtable + tmp into a reg by itself
 658   __ add(addr, cardtable, tmp2);
 659 
 660   // First, dirty it.
 661   __ stb(G0, tmp2, 0);  // [cardPtr] := 0  (i.e., dirty).
 662 
 663   Register tmp3 = cardtable;
 664   Register tmp4 = tmp;
 665 
 666   // these registers are now dead
 667   addr = cardtable = tmp = noreg;
 668 
 669   int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
 670   int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 671 
 672   __ bind(restart);
 673 
 674   // Get the index into the update buffer. DirtyCardQueue::_index is
 675   // a size_t so ld_ptr is appropriate here.
 676   __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3);
 677 
 678   // index == 0?
 679   __ cmp_and_brx_short(tmp3, G0, Assembler::equal,  Assembler::pn, refill);
 680 
 681   __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4);
 682   __ sub(tmp3, oopSize, tmp3);
 683 
 684   __ st_ptr(tmp2, tmp4, tmp3);  // [_buf + index] := <address_of_card>
 685   // Use return-from-leaf
 686   __ retl();
 687   __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset);
 688 
 689   __ bind(refill);
 690 
 691   __ save_live_registers_no_oop_map(true);
 692 
 693   __ call_VM_leaf(L7_thread_cache,
 694                   CAST_FROM_FN_PTR(address,
 695                                    DirtyCardQueueSet::handle_zero_index_for_thread),
 696                                    G2_thread);
 697 
 698   __ restore_live_registers(true);
 699 
 700   __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
 701   __ epilogue();
 702 }
 703 
 704 #undef __
 705 
 706 #endif // COMPILER1