1 /* 2 * Copyright (c) 2022, Red Hat, Inc. All rights reserved. 3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #ifndef SHARE_RUNTIME_LOCKSTACK_INLINE_HPP 27 #define SHARE_RUNTIME_LOCKSTACK_INLINE_HPP 28 29 #include "memory/iterator.hpp" 30 #include "runtime/lockStack.hpp" 31 #include "runtime/safepoint.hpp" 32 #include "runtime/stackWatermark.hpp" 33 #include "runtime/stackWatermarkSet.inline.hpp" 34 #include "runtime/thread.hpp" 35 36 inline int LockStack::to_index(uint32_t offset) { 37 return (offset - lock_stack_base_offset) / oopSize; 38 } 39 40 JavaThread* LockStack::get_thread() const { 41 char* addr = reinterpret_cast<char*>(const_cast<LockStack*>(this)); 42 return reinterpret_cast<JavaThread*>(addr - lock_stack_offset); 43 } 44 45 inline bool LockStack::can_push() const { 46 return to_index(_top) < CAPACITY; 47 } 48 49 inline bool LockStack::is_owning_thread() const { 50 JavaThread* thread = JavaThread::current(); 51 bool is_owning = &thread->lock_stack() == this; 52 assert(is_owning == (get_thread() == thread), "is_owning sanity"); 53 return is_owning; 54 } 55 56 inline void LockStack::push(oop o) { 57 verify("pre-push"); 58 assert(oopDesc::is_oop(o), "must be"); 59 assert(!contains(o), "entries must be unique"); 60 assert(can_push(), "must have room"); 61 assert(_base[to_index(_top)] == NULL, "expect zapped entry"); 62 _base[to_index(_top)] = o; 63 _top += oopSize; 64 verify("post-push"); 65 } 66 67 inline oop LockStack::pop() { 68 verify("pre-pop"); 69 assert(to_index(_top) > 0, "underflow, probably unbalanced push/pop"); 70 _top -= oopSize; 71 oop o = _base[to_index(_top)]; 72 #ifdef ASSERT 73 _base[to_index(_top)] = NULL; 74 #endif 75 assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o)); 76 verify("post-pop"); 77 return o; 78 } 79 80 inline void LockStack::remove(oop o) { 81 verify("pre-remove"); 82 assert(contains(o), "entry must be present: " PTR_FORMAT, p2i(o)); 83 int end = to_index(_top); 84 for (int i = 0; i < end; i++) { 85 if (_base[i] == o) { 86 int last = end - 1; 87 for (; i < last; i++) { 88 _base[i] = _base[i + 1]; 89 } 90 _top -= oopSize; 91 #ifdef ASSERT 92 _base[to_index(_top)] = NULL; 93 #endif 94 break; 95 } 96 } 97 assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o)); 98 verify("post-remove"); 99 } 100 101 inline bool LockStack::contains(oop o) const { 102 verify("pre-contains"); 103 if (!SafepointSynchronize::is_at_safepoint() && !is_owning_thread()) { 104 // When a foreign thread inspects this thread's lock-stack, it may see 105 // bad references here when a concurrent collector has not gotten 106 // to processing the lock-stack, yet. Call StackWaterMark::start_processing() 107 // to ensure that all references are valid. 108 StackWatermark* watermark = StackWatermarkSet::get(get_thread(), StackWatermarkKind::gc); 109 if (watermark != NULL) { 110 watermark->start_processing(); 111 } 112 } 113 int end = to_index(_top); 114 for (int i = end - 1; i >= 0; i--) { 115 if (_base[i] == o) { 116 verify("post-contains"); 117 return true; 118 } 119 } 120 verify("post-contains"); 121 return false; 122 } 123 124 inline void LockStack::oops_do(OopClosure* cl) { 125 verify("pre-oops-do"); 126 int end = to_index(_top); 127 for (int i = 0; i < end; i++) { 128 cl->do_oop(&_base[i]); 129 } 130 verify("post-oops-do"); 131 } 132 133 #endif // SHARE_RUNTIME_LOCKSTACK_INLINE_HPP