1 /*
   2  * Copyright (c) 2017, 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 "opto/arraycopynode.hpp"
  27 #include "opto/graphKit.hpp"
  28 #include "opto/idealKit.hpp"
  29 #include "opto/macro.hpp"
  30 #include "gc/shared/c2CardTableModRefBSCodeGen.hpp"
  31 #include "utilities/macros.hpp"
  32 
  33 #define __ ideal.
  34 
  35 Node* C2CardTableModRefBSCodeGen::byte_map_base_node(GraphKit* kit) {
  36   // Get base of card map
  37   CardTableModRefBS* ct =
  38     barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
  39   assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust users of this code");
  40   if (ct->card_table()->byte_map_base() != NULL) {
  41     return kit->makecon(TypeRawPtr::make((address)ct->card_table()->byte_map_base()));
  42   } else {
  43     return kit->null();
  44   }
  45 }
  46 
  47 // vanilla/CMS post barrier
  48 // Insert a write-barrier store.  This is to let generational GC work; we have
  49 // to flag all oop-stores before the next GC point.
  50 void C2CardTableModRefBSCodeGen::post_barrier(GraphKit* kit,
  51                                               Node* ctl,
  52                                               Node* oop_store,
  53                                               Node* obj,
  54                                               Node* adr,
  55                                               uint  adr_idx,
  56                                               Node* val,
  57                                               BasicType bt,
  58                                               bool use_precise) {
  59   // No store check needed if we're storing a NULL or an old object
  60   // (latter case is probably a string constant). The concurrent
  61   // mark sweep garbage collector, however, needs to have all nonNull
  62   // oop updates flagged via card-marks.
  63   if (val != NULL && val->is_Con()) {
  64     // must be either an oop or NULL
  65     const Type* t = val->bottom_type();
  66     if (t == TypePtr::NULL_PTR || t == Type::TOP)
  67       // stores of null never (?) need barriers
  68       return;
  69   }
  70 
  71   if (use_ReduceInitialCardMarks()
  72       && obj == kit->just_allocated_object(kit->control())) {
  73     // We can skip marks on a freshly-allocated object in Eden.
  74     // Keep this code in sync with new_deferred_store_barrier() in runtime.cpp.
  75     // That routine informs GC to take appropriate compensating steps,
  76     // upon a slow-path allocation, so as to make this card-mark
  77     // elision safe.
  78     return;
  79   }
  80 
  81   if (!use_precise) {
  82     // All card marks for a (non-array) instance are in one place:
  83     adr = obj;
  84   }
  85   // (Else it's an array (or unknown), and we want more precise card marks.)
  86   assert(adr != NULL, "");
  87 
  88   IdealKit ideal(kit, true);
  89 
  90   // Convert the pointer to an int prior to doing math on it
  91   Node* cast = __ CastPX(__ ctrl(), adr);
  92 
  93   // Divide by card size
  94   assert(Universe::heap()->barrier_set()->is_a(BarrierSet::CardTableModRef),
  95          "Only one we handle so far.");
  96   Node* card_offset = __ URShiftX( cast, __ ConI(CardTable::card_shift) );
  97 
  98   // Combine card table base and card offset
  99   Node* card_adr = __ AddP(__ top(), byte_map_base_node(kit), card_offset );
 100 
 101   // Get the alias_index for raw card-mark memory
 102   int adr_type = Compile::AliasIdxRaw;
 103   Node*   zero = __ ConI(0); // Dirty card value
 104 
 105   if (UseConcMarkSweepGC && UseCondCardMark) {
 106     kit->insert_mem_bar(Op_MemBarVolatile, oop_store);
 107     __ sync_kit(kit);
 108   }
 109 
 110   if (UseCondCardMark) {
 111     // The classic GC reference write barrier is typically implemented
 112     // as a store into the global card mark table.  Unfortunately
 113     // unconditional stores can result in false sharing and excessive
 114     // coherence traffic as well as false transactional aborts.
 115     // UseCondCardMark enables MP "polite" conditional card mark
 116     // stores.  In theory we could relax the load from ctrl() to
 117     // no_ctrl, but that doesn't buy much latitude.
 118     Node* card_val = __ load( __ ctrl(), card_adr, TypeInt::BYTE, T_BYTE, adr_type);
 119     __ if_then(card_val, BoolTest::ne, zero);
 120   }
 121 
 122   // Smash zero into card
 123   if( !UseConcMarkSweepGC ) {
 124     __ store(__ ctrl(), card_adr, zero, T_BYTE, adr_type, MemNode::unordered);
 125   } else {
 126     // Specialized path for CM store barrier
 127     __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, T_BYTE, adr_type);
 128   }
 129 
 130   if (UseCondCardMark) {
 131     __ end_if();
 132   }
 133 
 134   // Final sync IdealKit and GraphKit.
 135   kit->final_sync(ideal);
 136 }
 137 
 138 void C2CardTableModRefBSCodeGen::clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) {
 139   C2BarrierSetCodeGen::clone(kit, src, dst, size, is_array);
 140   const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
 141 
 142   // If necessary, emit some card marks afterwards.  (Non-arrays only.)
 143   bool card_mark = !is_array && !use_ReduceInitialCardMarks();
 144   if (card_mark) {
 145     assert(!is_array, "");
 146     // Put in store barrier for any and all oops we are sticking
 147     // into this object.  (We could avoid this if we could prove
 148     // that the object type contains no oop fields at all.)
 149     Node* no_particular_value = NULL;
 150     Node* no_particular_field = NULL;
 151     int raw_adr_idx = Compile::AliasIdxRaw;
 152     post_barrier(kit, kit->control(),
 153                  kit->memory(raw_adr_type),
 154                  dst,
 155                  no_particular_field,
 156                  raw_adr_idx,
 157                  no_particular_value,
 158                  T_OBJECT,
 159                  false);
 160   }
 161 }
 162 
 163 bool C2CardTableModRefBSCodeGen::use_ReduceInitialCardMarks() {
 164   BarrierSet *bs = Universe::heap()->barrier_set();
 165   return barrier_set_cast<CardTableModRefBS>(bs)->can_elide_tlab_store_barriers()
 166          && ReduceInitialCardMarks;
 167 }
 168 
 169 bool C2CardTableModRefBSCodeGen::is_gc_barrier_node(Node* node) {
 170   return C2ModRefBSCodeGen::is_gc_barrier_node(node) || node->Opcode() == Op_StoreCM;
 171 }
 172 
 173 void C2CardTableModRefBSCodeGen::eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) {
 174   assert(node->Opcode() == Op_CastP2X, "ConvP2XNode required");
 175   Node *shift = node->unique_out();
 176   Node *addp = shift->unique_out();
 177   for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
 178     Node *mem = addp->last_out(j);
 179     if (UseCondCardMark && mem->is_Load()) {
 180       assert(mem->Opcode() == Op_LoadB, "unexpected code shape");
 181       // The load is checking if the card has been written so
 182       // replace it with zero to fold the test.
 183       macro->replace_node(mem, macro->intcon(0));
 184       continue;
 185     }
 186     assert(mem->is_Store(), "store required");
 187     macro->replace_node(mem, mem->in(MemNode::Memory));
 188   }
 189 }
 190 
 191 bool C2CardTableModRefBSCodeGen::array_copy_requires_gc_barriers(BasicType type) {
 192   return !use_ReduceInitialCardMarks();
 193 }