1 
   2 /*
   3  * Copyright (c) 2016, Oracle and/or its affiliates. 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/cardTableModRefBS.hpp"
  31 #include "gc/shared/cardTableModRefBSCodeGen.hpp"
  32 #include "gc/shared/collectedHeap.hpp"
  33 #include "interpreter/interp_masm.hpp"
  34 
  35 #define __ masm->
  36 
  37 #ifdef PRODUCT
  38 #define BLOCK_COMMENT(str) /* nothing */
  39 #else
  40 #define BLOCK_COMMENT(str) __ block_comment(str)
  41 #endif
  42 
  43 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
  44 
  45 #define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8)
  46 
  47 void CardTableModRefBSCodeGen::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) {
  48   BarrierSet *bs = Universe::heap()->barrier_set();
  49   CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
  50   assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
  51 
  52   Label L_loop;
  53   const Register end = count;
  54 
  55   __ leaq(end, Address(addr, count, TIMES_OOP, 0));  // end == addr+count*oop_size
  56   __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
  57   __ shrptr(addr, CardTable::card_shift);
  58   __ shrptr(end,   CardTable::card_shift);
  59   __ subptr(end, addr); // end --> cards count
  60 
  61   int64_t disp = (int64_t) ct->card_table()->byte_map_base();
  62   __ mov64(tmp, disp);
  63   __ addptr(addr, tmp);
  64 __ BIND(L_loop);
  65   __ movb(Address(addr, count, Address::times_1), 0);
  66   __ decrement(count);
  67   __ jcc(Assembler::greaterEqual, L_loop);
  68 }
  69 
  70 void CardTableModRefBSCodeGen::store_check(MacroAssembler* masm, Register obj, Address dst) {
  71   // Does a store check for the oop in register obj. The content of
  72   // register obj is destroyed afterwards.
  73   BarrierSet* bs = Universe::heap()->barrier_set();
  74 
  75   CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
  76   assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
  77 
  78   __ shrptr(obj, CardTable::card_shift);
  79 
  80   Address card_addr;
  81 
  82   // The calculation for byte_map_base is as follows:
  83   // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
  84   // So this essentially converts an address to a displacement and it will
  85   // never need to be relocated. On 64bit however the value may be too
  86   // large for a 32bit displacement.
  87   intptr_t disp = (intptr_t) ct->card_table()->byte_map_base();
  88   if (__ is_simm32(disp)) {
  89     card_addr = Address(noreg, obj, Address::times_1, disp);
  90   } else {
  91     // By doing it as an ExternalAddress 'disp' could be converted to a rip-relative
  92     // displacement and done in a single instruction given favorable mapping and a
  93     // smarter version of as_Address. However, 'ExternalAddress' generates a relocation
  94     // entry and that entry is not properly handled by the relocation code.
  95     AddressLiteral cardtable((address)ct->card_table()->byte_map_base(), relocInfo::none);
  96     Address index(noreg, obj, Address::times_1);
  97     card_addr = __ as_Address(ArrayAddress(cardtable, index));
  98   }
  99 
 100   int dirty = CardTable::dirty_card_val();
 101   if (UseCondCardMark) {
 102     Label L_already_dirty;
 103     if (UseConcMarkSweepGC) {
 104       __ membar(Assembler::StoreLoad);
 105     }
 106     __ cmpb(card_addr, dirty);
 107     __ jcc(Assembler::equal, L_already_dirty);
 108     __ movb(card_addr, dirty);
 109     __ bind(L_already_dirty);
 110   } else {
 111     __ movb(card_addr, dirty);
 112   }
 113 }
 114 
 115 void CardTableModRefBSCodeGen::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
 116                                             Address dst, Register val, Register tmp1, Register tmp2) {
 117   bool on_array = (decorators & ACCESS_ON_ARRAY) != 0;
 118   bool on_anonymous = (decorators & ACCESS_ON_ANONYMOUS) != 0;
 119   bool precise = on_array || on_anonymous;
 120   if (val == noreg) {
 121     __ store_heap_oop_null(dst);
 122   } else {
 123     __ store_heap_oop(dst, val);
 124     // flatten object address if needed
 125     if (!precise || (dst.index() == noreg && dst.disp() == 0)) {
 126       store_check(masm, dst.base(), dst);
 127     } else {
 128       __ lea(tmp1, dst);
 129       store_check(masm, tmp1, dst);
 130     }
 131   }
 132 }