1 /*
   2  * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHHEAP_INLINE_HPP
  25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHHEAP_INLINE_HPP
  26 
  27 #include "gc/shared/cmBitMap.inline.hpp"
  28 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  29 #include "gc/shenandoah/shenandoahHeap.hpp"
  30 #include "runtime/atomic.inline.hpp"
  31 
  32 /*
  33  * Marks the object. Returns true if the object has not been marked before and has
  34  * been marked by this thread. Returns false if the object has already been marked,
  35  * or if a competing thread succeeded in marking this object.
  36  */
  37 inline bool ShenandoahHeap::mark_current(oop obj) const {
  38 #ifdef ASSERT
  39   if (obj != oopDesc::bs()->read_barrier(obj)) {
  40     tty->print_cr("heap region containing obj:");
  41     ShenandoahHeapRegion* obj_region = heap_region_containing(obj);
  42     obj_region->print();
  43     tty->print_cr("heap region containing forwardee:");
  44     ShenandoahHeapRegion* forward_region = heap_region_containing(oopDesc::bs()->read_barrier(obj));
  45     forward_region->print();
  46   }
  47 #endif
  48 
  49   assert(obj == oopDesc::bs()->read_barrier(obj), "only mark forwarded copy of objects");
  50   return mark_current_no_checks(obj);
  51 }
  52 
  53 inline bool ShenandoahHeap::mark_current_no_checks(oop obj) const {
  54   return _next_mark_bit_map->parMark((HeapWord*) obj);
  55 }
  56 
  57 inline bool ShenandoahHeap::is_marked_current(oop obj) const {
  58   return _next_mark_bit_map->isMarked((HeapWord*) obj);
  59 }
  60 
  61 inline bool ShenandoahHeap::need_update_refs() const {
  62   return _need_update_refs;
  63 }
  64 
  65 inline uint ShenandoahHeap::heap_region_index_containing(const void* addr) const {
  66   uintptr_t region_start = ((uintptr_t) addr); // & ~(ShenandoahHeapRegion::RegionSizeBytes - 1);
  67   uintptr_t index = (region_start - (uintptr_t) _first_region_bottom) >> ShenandoahHeapRegion::RegionSizeShift;
  68 #ifdef ASSERT
  69   if (!(index < _num_regions)) {
  70     tty->print_cr("heap region does not contain address, first_region_bottom: "PTR_FORMAT", real bottom of first region: "PTR_FORMAT", num_regions: "SIZE_FORMAT", region_size: "SIZE_FORMAT, p2i(_first_region_bottom), p2i(_ordered_regions[0]->bottom()), _num_regions, ShenandoahHeapRegion::RegionSizeBytes);
  71   }
  72 #endif
  73   assert(index < _num_regions, "heap region index must be in range");
  74   return index;
  75 }
  76 
  77 oop ShenandoahHeap::maybe_update_oop_ref(oop* p) {
  78 
  79   assert((! is_in(p)) || (! heap_region_containing(p)->is_in_collection_set()),
  80          "never update refs in from-space, unless evacuation has been cancelled");
  81 
  82   oop heap_oop = oopDesc::load_heap_oop(p); // read p
  83   if (! oopDesc::is_null(heap_oop)) {
  84 
  85 #ifdef ASSERT
  86     if (! is_in(heap_oop)) {
  87       print_heap_regions();
  88       tty->print_cr("object not in heap: "PTR_FORMAT", referenced by: "PTR_FORMAT, p2i((HeapWord*) heap_oop), p2i(p));
  89       assert(is_in(heap_oop), "object must be in heap");
  90     }
  91 #endif
  92     assert(is_in(heap_oop), "only ever call this on objects in the heap");
  93     assert((! (is_in(p) && heap_region_containing(p)->is_in_collection_set())), "we don't want to update references in from-space");
  94     oop forwarded_oop = ShenandoahBarrierSet::resolve_oop_static_not_null(heap_oop); // read brooks ptr
  95     if (forwarded_oop != heap_oop) {
  96       // tty->print_cr("updating old ref: "PTR_FORMAT" pointing to "PTR_FORMAT" to new ref: "PTR_FORMAT, p2i(p), p2i(heap_oop), p2i(forwarded_oop));
  97       assert(forwarded_oop->is_oop(), "oop required");
  98       assert(is_in(forwarded_oop), "forwardee must be in heap");
  99       assert(! heap_region_containing(forwarded_oop)->is_in_collection_set(), "forwardee must not be in collection set");
 100       // If this fails, another thread wrote to p before us, it will be logged in SATB and the
 101       // reference be updated later.
 102       oop result = (oop) Atomic::cmpxchg_ptr(forwarded_oop, p, heap_oop);
 103 
 104       if (result == heap_oop) { // CAS successful.
 105           return forwarded_oop;
 106       } else {
 107         return result;
 108       }
 109     } else {
 110       return forwarded_oop;
 111     }
 112     /*
 113       else {
 114       tty->print_cr("not updating ref: "PTR_FORMAT, p2i(heap_oop));
 115       }
 116     */
 117   }
 118   return NULL;
 119 }
 120 
 121 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHHEAP_INLINE_HPP