1 /*
  2  * Copyright (c) 2022, Red Hat, Inc. 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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTUTILS_INLINE_HPP
 26 #define SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTUTILS_INLINE_HPP
 27 
 28 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 29 #include "gc/shenandoah/shenandoahObjectUtils.hpp"
 30 #include "oops/klass.hpp"
 31 #include "oops/markWord.inline.hpp"
 32 #include "oops/oop.inline.hpp"
 33 #include "runtime/objectMonitor.inline.hpp"
 34 #include "runtime/thread.hpp"
 35 
 36 // This is a variant of oopDesc::actual_mark(), which does the same thing, but also
 37 // handles forwarded objects. This is intended to be used by concurrent evacuation only. No other
 38 // code is supposed to observe from-space objects.
 39 #ifdef _LP64
 40 markWord ShenandoahObjectUtils::stable_mark(oop obj) {
 41   assert(UseCompactObjectHeaders, "only used with compact object headers");
 42   ShenandoahHeap* heap = ShenandoahHeap::heap();
 43   assert(heap->is_in(obj), "object not in heap: " PTR_FORMAT, p2i(obj));
 44   markWord mark = obj->mark_acquire();
 45 
 46   assert(!mark.is_being_inflated(), "can not be inflating");
 47   assert(!mark.has_locker(), "can not be stack-locked");
 48 
 49   // The mark can be in one of the following states:
 50   // *  Marked       - object is forwarded, try again on forwardee
 51   // *  Inflated     - just return mark from inflated monitor
 52   // *  Fast-locked  - return mark
 53   // *  Neutral      - return mark
 54 
 55   // Most common cases first.
 56   if (mark.is_neutral() || mark.is_fast_locked()) {
 57     return mark;
 58   }
 59 
 60   // If object is already forwarded, then resolve it, and try again.
 61   if (mark.is_marked()) {
 62     if (heap->is_full_gc_move_in_progress()) {
 63       // In these cases, we want to return the header as-is: the Klass* would not be overloaded.
 64       return mark;
 65     }
 66     obj = cast_to_oop(mark.decode_pointer());
 67     return stable_mark(obj);
 68   }
 69 
 70   // CASE: inflated
 71   assert(mark.has_monitor(), "must be monitor-locked at this point");
 72   // It is safe to access the object monitor because all Java and GC worker threads
 73   // participate in the monitor deflation protocol (i.e, they react to handshakes and STS requests).
 74   ObjectMonitor* inf = mark.monitor();
 75   markWord dmw = inf->header();
 76   assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT ", original mark: " INTPTR_FORMAT, dmw.value(), mark.value());
 77   return dmw;
 78 }
 79 #endif
 80 
 81 Klass* ShenandoahObjectUtils::klass(oop obj) {
 82   if (!UseCompactObjectHeaders) {
 83     return obj->klass();
 84   }
 85 #ifdef _LP64
 86   markWord header = stable_mark(obj);
 87   assert(header.narrow_klass() != 0, "klass must not be NULL: " INTPTR_FORMAT, header.value());
 88   return header.klass();
 89 #else
 90   return obj->klass();
 91 #endif
 92 }
 93 
 94 size_t ShenandoahObjectUtils::size(oop obj) {
 95   if (!UseCompactObjectHeaders) {
 96     return obj->size();
 97   }
 98  Klass* kls = klass(obj);
 99   return obj->size_given_klass(kls);
100 }
101 
102 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTUTILS_HPP