1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2015-2018, Azul Systems, Inc. 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/shared/barrierSet.hpp"
  29 #include "gc/shared/cardTable.hpp"
  30 #include "gc/shared/cardTableBarrierSet.hpp"
  31 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
  32 #include "interpreter/interp_masm.hpp"
  33 
  34 #define __ masm->
  35 
  36 void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst) {
  37 
  38   // Does a store check for the oop in register obj. The content of
  39   // register obj is destroyed afterwards.
  40 
  41   BarrierSet* bs = BarrierSet::barrier_set();
  42   assert(bs->kind() == BarrierSet::CardTableBarrierSet,
  43          "Wrong barrier set kind");
  44 
  45   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
  46   CardTable* ct = ctbs->card_table();
  47   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
  48 
  49   assert(CardTable::dirty_card_val() == 0, "must be");
  50 
  51   jbyte *byte_map_base =
  52     ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
  53   __ mov(rscratch1, (uint32_t)byte_map_base);
  54   assert((p2i(byte_map_base) & 0xff) == 0, "fix store char 0 below");
  55 
  56   if (UseCondCardMark) {
  57     __ membar(Assembler::StoreLoad);
  58     __ ldrb(rscratch2,  Address(rscratch1, obj, lsr((int) CardTable::card_shift)));
  59     __ cmp(rscratch2, 0);
  60     __ strb(rscratch1, Address(rscratch1, obj, lsr((int) CardTable::card_shift)), Assembler::NE);
  61   } else {
  62     if (ct->scanned_concurrently()) {
  63       __ membar(Assembler::StoreStore);
  64     }
  65     __ strb(rscratch1, Address(rscratch1, obj, lsr((int) CardTable::card_shift)));
  66   }
  67 }
  68 
  69 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
  70                                                                     Register start, Register end, Register scratch) {
  71   BarrierSet* bs = BarrierSet::barrier_set();
  72   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
  73   CardTable* ct = ctbs->card_table();
  74   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
  75 
  76   Label L_loop;
  77 
  78   __ lsr(start, start, CardTable::card_shift);
  79   __ lsr(end, end, CardTable::card_shift);
  80   __ sub(end, end, start); // number of bytes to copy
  81 
  82   const Register count = end; // 'end' register contains bytes count now
  83   __ mov(scratch, (address)ct->byte_map_base());
  84   __ add(start, start, scratch);
  85   if (ct->scanned_concurrently()) {
  86     __ membar(__ StoreStore);
  87   }
  88   __ bind(L_loop);
  89   __ mov(scratch, 0);
  90   __ strb(scratch, Address(start, count));
  91   __ subs(count, count, 1);
  92   __ b(L_loop, Assembler::HS);
  93 }
  94 
  95 void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
  96                                                 Address dst, Register val, Register tmp1, Register tmp2) {
  97   bool in_heap = (decorators & IN_HEAP) != 0;
  98   bool is_array = (decorators & IS_ARRAY) != 0;
  99   bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 100   bool precise = is_array || on_anonymous;
 101 
 102   bool needs_post_barrier = val != noreg && in_heap;
 103   BarrierSetAssembler::store_word_at(masm, decorators, type, dst, val, tmp1, noreg);
 104   if (needs_post_barrier) {
 105     // flatten object address if needed
 106     if (!precise || (dst.index() == noreg && dst.offset() == 0)) {
 107       store_check(masm, dst.base(), dst);
 108     } else {
 109       __ lea(tmp1, dst);
 110       store_check(masm, tmp1, dst);
 111     }
 112   }
 113 }