1 /*
   2  * Copyright (c) 2015, 2019, 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 #include "precompiled.hpp"
  25 #include "gc/z/zBarrier.inline.hpp"
  26 #include "gc/z/zHeap.inline.hpp"
  27 #include "gc/z/zOop.inline.hpp"
  28 #include "gc/z/zOopClosures.inline.hpp"
  29 #include "memory/iterator.inline.hpp"
  30 #include "oops/oop.inline.hpp"
  31 #include "runtime/safepoint.hpp"
  32 #include "utilities/debug.hpp"
  33 
  34 bool ZBarrier::during_mark() {
  35   return ZGlobalPhase == ZPhaseMark;
  36 }
  37 
  38 bool ZBarrier::during_relocate() {
  39   return ZGlobalPhase == ZPhaseRelocate;
  40 }
  41 
  42 template <bool finalizable>
  43 bool ZBarrier::should_mark_through(uintptr_t addr) {
  44   // Finalizable marked oops can still exists on the heap after marking
  45   // has completed, in which case we just want to convert this into a
  46   // good oop and not push it on the mark stack.
  47   if (!during_mark()) {
  48     assert(ZAddress::is_marked(addr), "Should be marked");
  49     assert(ZAddress::is_finalizable(addr), "Should be finalizable");
  50     return false;
  51   }
  52 
  53   // During marking, we mark through already marked oops to avoid having
  54   // some large part of the object graph hidden behind a pushed, but not
  55   // yet flushed, entry on a mutator mark stack. Always marking through
  56   // allows the GC workers to proceed through the object graph even if a
  57   // mutator touched an oop first, which in turn will reduce the risk of
  58   // having to flush mark stacks multiple times to terminate marking.
  59   //
  60   // However, when doing finalizable marking we don't always want to mark
  61   // through. First, marking through an already strongly marked oop would
  62   // be wasteful, since we will then proceed to do finalizable marking on
  63   // an object which is, or will be, marked strongly. Second, marking
  64   // through an already finalizable marked oop would also be wasteful,
  65   // since such oops can never end up on a mutator mark stack and can
  66   // therefore not hide some part of the object graph from GC workers.
  67   if (finalizable) {
  68     return !ZAddress::is_marked(addr);
  69   }
  70 
  71   // Mark through
  72   return true;
  73 }
  74 
  75 template <bool finalizable, bool publish>
  76 uintptr_t ZBarrier::mark(uintptr_t addr) {
  77   uintptr_t good_addr;
  78 
  79   if (ZAddress::is_marked(addr)) {
  80     // Already marked, but try to mark though anyway
  81     good_addr = ZAddress::good(addr);
  82   } else if (ZAddress::is_remapped(addr)) {
  83     // Already remapped, but also needs to be marked
  84     good_addr = ZAddress::good(addr);
  85   } else {
  86     // Needs to be both remapped and marked
  87     good_addr = remap(addr);
  88   }
  89 
  90   // Mark
  91   if (should_mark_through<finalizable>(addr)) {
  92     ZHeap::heap()->mark_object<finalizable, publish>(good_addr);
  93   }
  94 
  95   return good_addr;
  96 }
  97 
  98 uintptr_t ZBarrier::remap(uintptr_t addr) {
  99   assert(!ZAddress::is_good(addr), "Should not be good");
 100   assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
 101   return ZHeap::heap()->remap_object(addr);
 102 }
 103 
 104 uintptr_t ZBarrier::relocate(uintptr_t addr) {
 105   assert(!ZAddress::is_good(addr), "Should not be good");
 106   assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
 107   return ZHeap::heap()->relocate_object(addr);
 108 }
 109 
 110 uintptr_t ZBarrier::relocate_or_mark(uintptr_t addr) {
 111   return during_relocate() ? relocate(addr) : mark<Strong, Publish>(addr);
 112 }
 113 
 114 uintptr_t ZBarrier::relocate_or_remap(uintptr_t addr) {
 115   return during_relocate() ? relocate(addr) : remap(addr);
 116 }
 117 
 118 //
 119 // Load barrier
 120 //
 121 uintptr_t ZBarrier::load_barrier_on_oop_slow_path(uintptr_t addr) {
 122   return relocate_or_mark(addr);
 123 }
 124 
 125 void ZBarrier::load_barrier_on_oop_fields(oop o) {
 126   assert(ZAddress::is_good(ZOop::to_address(o)), "Should be good");
 127   ZLoadBarrierOopClosure cl;
 128   o->oop_iterate(&cl);
 129 }
 130 
 131 //
 132 // Weak load barrier
 133 //
 134 uintptr_t ZBarrier::weak_load_barrier_on_oop_slow_path(uintptr_t addr) {
 135   return ZAddress::is_weak_good(addr) ? ZAddress::good(addr) : relocate_or_remap(addr);
 136 }
 137 
 138 uintptr_t ZBarrier::weak_load_barrier_on_weak_oop_slow_path(uintptr_t addr) {
 139   const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
 140   if (ZHeap::heap()->is_object_strongly_live(good_addr)) {
 141     return good_addr;
 142   }
 143 
 144   // Not strongly live
 145   return 0;
 146 }
 147 
 148 uintptr_t ZBarrier::weak_load_barrier_on_phantom_oop_slow_path(uintptr_t addr) {
 149   const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
 150   if (ZHeap::heap()->is_object_live(good_addr)) {
 151     return good_addr;
 152   }
 153 
 154   // Not live
 155   return 0;
 156 }
 157 
 158 //
 159 // Keep alive barrier
 160 //
 161 uintptr_t ZBarrier::keep_alive_barrier_on_weak_oop_slow_path(uintptr_t addr) {
 162   const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
 163   assert(ZHeap::heap()->is_object_strongly_live(good_addr), "Should be live");
 164   return good_addr;
 165 }
 166 
 167 uintptr_t ZBarrier::keep_alive_barrier_on_phantom_oop_slow_path(uintptr_t addr) {
 168   const uintptr_t good_addr = weak_load_barrier_on_oop_slow_path(addr);
 169   assert(ZHeap::heap()->is_object_live(good_addr), "Should be live");
 170   return good_addr;
 171 }
 172 
 173 //
 174 // Mark barrier
 175 //
 176 uintptr_t ZBarrier::mark_barrier_on_oop_slow_path(uintptr_t addr) {
 177   return mark<Strong, Overflow>(addr);
 178 }
 179 
 180 uintptr_t ZBarrier::mark_barrier_on_finalizable_oop_slow_path(uintptr_t addr) {
 181   const uintptr_t good_addr = mark<Finalizable, Overflow>(addr);
 182   if (ZAddress::is_good(addr)) {
 183     // If the oop was already strongly marked/good, then we do
 184     // not want to downgrade it to finalizable marked/good.
 185     return good_addr;
 186   }
 187 
 188   // Make the oop finalizable marked/good, instead of normal marked/good.
 189   // This is needed because an object might first becomes finalizable
 190   // marked by the GC, and then loaded by a mutator thread. In this case,
 191   // the mutator thread must be able to tell that the object needs to be
 192   // strongly marked. The finalizable bit in the oop exists to make sure
 193   // that a load of a finalizable marked oop will fall into the barrier
 194   // slow path so that we can mark the object as strongly reachable.
 195   return ZAddress::finalizable_good(good_addr);
 196 }
 197 
 198 uintptr_t ZBarrier::mark_barrier_on_root_oop_slow_path(uintptr_t addr) {
 199   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
 200   assert(during_mark(), "Invalid phase");
 201 
 202   // Mark
 203   return mark<Strong, Publish>(addr);
 204 }
 205 
 206 //
 207 // Relocate barrier
 208 //
 209 uintptr_t ZBarrier::relocate_barrier_on_root_oop_slow_path(uintptr_t addr) {
 210   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
 211   assert(during_relocate(), "Invalid phase");
 212 
 213   // Relocate
 214   return relocate(addr);
 215 }
 216 
 217 //
 218 // Narrow oop variants, never used.
 219 //
 220 oop ZBarrier::load_barrier_on_oop_field(volatile narrowOop* p) {
 221   ShouldNotReachHere();
 222   return NULL;
 223 }
 224 
 225 oop ZBarrier::load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o) {
 226   ShouldNotReachHere();
 227   return NULL;
 228 }
 229 
 230 void ZBarrier::load_barrier_on_oop_array(volatile narrowOop* p, size_t length) {
 231   ShouldNotReachHere();
 232 }
 233 
 234 oop ZBarrier::load_barrier_on_weak_oop_field_preloaded(volatile narrowOop* p, oop o) {
 235   ShouldNotReachHere();
 236   return NULL;
 237 }
 238 
 239 oop ZBarrier::load_barrier_on_phantom_oop_field_preloaded(volatile narrowOop* p, oop o) {
 240   ShouldNotReachHere();
 241   return NULL;
 242 }
 243 
 244 oop ZBarrier::weak_load_barrier_on_oop_field_preloaded(volatile narrowOop* p, oop o) {
 245   ShouldNotReachHere();
 246   return NULL;
 247 }
 248 
 249 oop ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(volatile narrowOop* p, oop o) {
 250   ShouldNotReachHere();
 251   return NULL;
 252 }
 253 
 254 oop ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(volatile narrowOop* p, oop o) {
 255   ShouldNotReachHere();
 256   return NULL;
 257 }
--- EOF ---