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/javaThread.hpp"
 31 #include "runtime/lockStack.hpp"
 32 #include "runtime/safepoint.hpp"
 33 #include "runtime/stackWatermark.hpp"
 34 #include "runtime/stackWatermarkSet.inline.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   Thread* current = Thread::current();
 51   if (current->is_Java_thread()) {
 52     JavaThread* thread = JavaThread::cast(current);
 53     bool is_owning = &thread->lock_stack() == this;
 54     assert(is_owning == (get_thread() == thread), "is_owning sanity");
 55     return is_owning;
 56   }
 57   return false;
 58 }
 59 
 60 inline void LockStack::push(oop o) {
 61   verify("pre-push");
 62   assert(oopDesc::is_oop(o), "must be");
 63   assert(!contains(o), "entries must be unique");
 64   assert(can_push(), "must have room");
 65   assert(_base[to_index(_top)] == nullptr, "expect zapped entry");
 66   _base[to_index(_top)] = o;
 67   _top += oopSize;
 68   verify("post-push");
 69 }
 70 
 71 inline oop LockStack::pop() {
 72   verify("pre-pop");
 73   assert(to_index(_top) > 0, "underflow, probably unbalanced push/pop");
 74   _top -= oopSize;
 75   oop o = _base[to_index(_top)];
 76 #ifdef ASSERT
 77   _base[to_index(_top)] = nullptr;
 78 #endif
 79   assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o));
 80   verify("post-pop");
 81   return o;
 82 }
 83 
 84 inline void LockStack::remove(oop o) {
 85   verify("pre-remove");
 86   assert(contains(o), "entry must be present: " PTR_FORMAT, p2i(o));
 87   int end = to_index(_top);
 88   for (int i = 0; i < end; i++) {
 89     if (_base[i] == o) {
 90       int last = end - 1;
 91       for (; i < last; i++) {
 92         _base[i] = _base[i + 1];
 93       }
 94       _top -= oopSize;
 95 #ifdef ASSERT
 96       _base[to_index(_top)] = nullptr;
 97 #endif
 98       break;
 99     }
100   }
101   assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o));
102   verify("post-remove");
103 }
104 
105 inline bool LockStack::contains(oop o) const {
106   verify("pre-contains");
107 
108   // Can't poke around in thread oops without having started stack watermark processing.
109   assert(StackWatermarkSet::processing_started(get_thread()), "Processing must have started!");
110 
111   int end = to_index(_top);
112   for (int i = end - 1; i >= 0; i--) {
113     if (_base[i] == o) {
114       verify("post-contains");
115       return true;
116     }
117   }
118   verify("post-contains");
119   return false;
120 }
121 
122 inline void LockStack::oops_do(OopClosure* cl) {
123   verify("pre-oops-do");
124   int end = to_index(_top);
125   for (int i = 0; i < end; i++) {
126     cl->do_oop(&_base[i]);
127   }
128   verify("post-oops-do");
129 }
130 
131 #endif // SHARE_RUNTIME_LOCKSTACK_INLINE_HPP