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 ObjectSynchronizer::stable_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 for (;;) { 44 assert(heap->is_in(obj), "object not in heap: " PTR_FORMAT, p2i(obj)); 45 markWord mark = obj->mark_acquire(); 46 47 // The mark can be in one of the following states: 48 // * Inflated - just return mark from inflated monitor 49 // * Stack-locked - coerce it to inflating, and then return displaced mark 50 // * INFLATING - busy wait for conversion to complete 51 // * Neutral - return mark 52 // * Marked - object is forwarded, try again on forwardee 53 54 // Most common case first. 55 if (mark.is_neutral() || mark.is_fast_locked()) { 56 return mark; 57 } 58 59 // If object is already forwarded, then resolve it, and try again. 60 if (mark.is_marked()) { 61 if (heap->is_full_gc_move_in_progress()) { 62 // In these cases, we want to return the header as-is: the Klass* would not be overloaded. 63 return mark; 64 } 65 obj = cast_to_oop(mark.decode_pointer()); 66 continue; 67 } 68 69 // CASE: inflated 70 if (mark.has_monitor()) { 71 // It is safe to access the object monitor because all Java and GC worker threads 72 // participate in the monitor deflation protocol (i.e, they react to handshakes and STS requests). 73 ObjectMonitor* inf = mark.monitor(); 74 markWord dmw = inf->header(); 75 assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT ", original mark: " INTPTR_FORMAT, dmw.value(), mark.value()); 76 return dmw; 77 } 78 79 // CASE: inflating 80 if (mark.is_being_inflated()) { 81 // Interference, try again. 82 continue; 83 } 84 85 // CASE: stack-locked 86 if (mark.has_locker()) { 87 if (Thread::current()->is_lock_owned((address)mark.locker())) { 88 // This thread owns the lock. We can safely access it. 89 markWord dmw = mark.displaced_mark_helper(); 90 assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT ", original mark: " INTPTR_FORMAT, dmw.value(), mark.value()); 91 return dmw; 92 } 93 94 // Else we try to install INFLATING into the header. This will (temporarily) prevent other 95 // threads from stack-locking or evacuating the object. 96 markWord cmp = obj->cas_set_mark(markWord::INFLATING(), mark); 97 if (cmp != mark) { 98 continue; // Interference -- just retry 99 } 100 101 // We've successfully installed INFLATING (0) into the mark-word. 102 // This is the only case where 0 will appear in a mark-word. 103 // Only the singular thread that successfully swings the mark-word 104 // to 0 can fetch the stack-lock and safely read the displaced header. 105 106 // fetch the displaced mark from the owner's stack. 107 // The owner can't die or unwind past the lock while our INFLATING 108 // object is in the mark. Furthermore the owner can't complete 109 // an unlock on the object, either. No other thread can do evacuation, either. 110 markWord dmw = mark.displaced_mark_helper(); 111 // Catch if the object's header is not neutral (not locked and 112 // not marked is what we care about here). 113 assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); 114 115 // Must preserve store ordering. The monitor state must 116 // be stable at the time of publishing the monitor address. 117 guarantee(obj->mark() == markWord::INFLATING(), "invariant"); 118 // Release semantics so that above set_object() is seen first. 119 obj->release_set_mark(mark); 120 121 return dmw; 122 } 123 } 124 } 125 #endif 126 127 Klass* ShenandoahObjectUtils::klass(oop obj) { 128 if (!UseCompactObjectHeaders) { 129 return obj->klass(); 130 } 131 #ifdef _LP64 132 markWord header = stable_mark(obj); 133 assert(header.narrow_klass() != 0, "klass must not be NULL: " INTPTR_FORMAT, header.value()); 134 return header.klass(); 135 #else 136 return obj->klass(); 137 #endif 138 } 139 140 size_t ShenandoahObjectUtils::size(oop obj) { 141 if (!UseCompactObjectHeaders) { 142 return obj->size(); 143 } 144 Klass* kls = klass(obj); 145 return obj->size_given_klass(kls); 146 } 147 148 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTUTILS_HPP