1 /*
  2  * Copyright (c) 2015, 2019, 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_SHENANDOAHFORWARDING_INLINE_HPP
 26 #define SHARE_GC_SHENANDOAH_SHENANDOAHFORWARDING_INLINE_HPP
 27 
 28 #include "gc/shenandoah/shenandoahForwarding.hpp"
 29 
 30 #include "gc/shenandoah/shenandoahAsserts.hpp"
 31 #include "oops/klass.hpp"
 32 #include "oops/markWord.hpp"
 33 #include "runtime/javaThread.hpp"
 34 
 35 inline oop ShenandoahForwarding::get_forwardee_raw(oop obj) {
 36   shenandoah_assert_in_heap_bounds(nullptr, obj);
 37   return get_forwardee_raw_unchecked(obj);
 38 }
 39 
 40 static HeapWord* to_forwardee(markWord mark) {
 41   return reinterpret_cast<HeapWord*>(mark.value() & ~(markWord::lock_mask_in_place | markWord::self_fwd_mask_in_place));
 42 }
 43 inline oop ShenandoahForwarding::get_forwardee_raw_unchecked(oop obj) {
 44   // JVMTI and JFR code use mark words for marking objects for their needs.
 45   // On this path, we can encounter the "marked" object, but with null
 46   // fwdptr. That object is still not forwarded, and we need to return
 47   // the object itself.
 48   markWord mark = obj->mark();
 49   if (mark.is_marked()) {
 50     HeapWord* fwdptr = to_forwardee(mark);
 51     if (fwdptr != nullptr) {
 52       return cast_to_oop(fwdptr);
 53     }
 54   }
 55   return obj;
 56 }
 57 
 58 inline oop ShenandoahForwarding::get_forwardee_mutator(oop obj) {
 59   // Same as above, but mutator thread cannot ever see null forwardee.
 60   shenandoah_assert_correct(nullptr, obj);
 61   assert(Thread::current()->is_Java_thread(), "Must be a mutator thread");
 62 
 63   markWord mark = obj->mark();
 64   if (mark.is_marked()) {
 65     HeapWord* fwdptr = to_forwardee(mark);
 66     assert(fwdptr != nullptr, "Forwarding pointer is never null here");
 67     return cast_to_oop(fwdptr);
 68   } else {
 69     return obj;
 70   }
 71 }
 72 
 73 inline oop ShenandoahForwarding::get_forwardee(oop obj) {
 74   shenandoah_assert_correct(nullptr, obj);
 75   return get_forwardee_raw_unchecked(obj);
 76 }
 77 
 78 inline bool ShenandoahForwarding::is_forwarded(markWord m) {
 79   return (m.value() & (markWord::lock_mask_in_place | markWord::self_fwd_mask_in_place)) > markWord::monitor_value;
 80 }
 81 
 82 inline bool ShenandoahForwarding::is_forwarded(oop obj) {
 83   return is_forwarded(obj->mark());
 84 }
 85 
 86 inline oop ShenandoahForwarding::try_update_forwardee(oop obj, oop update) {
 87   markWord old_mark = obj->mark();
 88   if (is_forwarded(old_mark)) {
 89     return cast_to_oop(to_forwardee(old_mark));
 90   }
 91 
 92   markWord new_mark = markWord::encode_pointer_as_mark(update);
 93   if (UseCompactObjectHeaders && old_mark.is_hashed_not_expanded()) {
 94     new_mark = markWord(new_mark.value() | FWDED_HASH_TRANSITION);
 95   }
 96   markWord prev_mark = obj->cas_set_mark(new_mark, old_mark, memory_order_conservative);
 97   if (prev_mark == old_mark) {
 98     return update;
 99   } else {
100     return cast_to_oop(to_forwardee(prev_mark));
101   }
102 }
103 
104 inline Klass* ShenandoahForwarding::klass(oop obj) {
105   if (UseCompactObjectHeaders) {
106     markWord mark = obj->mark();
107     if (mark.is_marked()) {
108       oop fwd = cast_to_oop(to_forwardee(mark));
109       mark = fwd->mark();
110     }
111     return mark.klass();
112   } else {
113     return obj->klass();
114   }
115 }
116 
117 inline size_t ShenandoahForwarding::size(oop obj) {
118   markWord mark = obj->mark();
119   if (is_forwarded(mark)) {
120     oop fwd = cast_to_oop(to_forwardee(mark));
121     markWord fwd_mark = fwd->mark();
122     Klass* klass = UseCompactObjectHeaders ? fwd_mark.klass() : fwd->klass();
123     size_t size = fwd->base_size_given_klass(fwd_mark, klass);
124     if (UseCompactObjectHeaders) {
125       if ((mark.value() & FWDED_HASH_TRANSITION) != FWDED_HASH_TRANSITION) {
126         if (fwd_mark.is_expanded() && klass->expand_for_hash(fwd)) {
127           size = align_object_size(size + 1);
128         }
129       }
130     }
131     return size;
132   } else {
133     Klass* klass = UseCompactObjectHeaders ? mark.klass() : obj->klass();
134     return obj->size_given_mark_and_klass(mark, klass);
135   }
136 }
137 
138 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHFORWARDING_INLINE_HPP