1 /*
  2  * Copyright (c) 2022, Red Hat, Inc. All rights reserved.
  3  * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  4  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  6  *
  7  * This code is free software; you can redistribute it and/or modify it
  8  * under the terms of the GNU General Public License version 2 only, as
  9  * published by the Free Software Foundation.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  *
 25  */
 26 
 27 #ifndef SHARE_RUNTIME_LOCKSTACK_HPP
 28 #define SHARE_RUNTIME_LOCKSTACK_HPP
 29 
 30 #include "oops/oopsHierarchy.hpp"
 31 #include "utilities/globalDefinitions.hpp"
 32 #include "utilities/sizes.hpp"
 33 
 34 class JavaThread;
 35 class OopClosure;
 36 class outputStream;
 37 template<typename>
 38 class GrowableArray;
 39 
 40 class LockStack {
 41   friend class LockStackTest;
 42   friend class VMStructs;
 43   JVMCI_ONLY(friend class JVMCIVMStructs;)
 44 public:
 45   static const int CAPACITY = 8;
 46 private:
 47 
 48   // TODO: It would be very useful if JavaThread::lock_stack_offset() and friends were constexpr,
 49   // but this is currently not the case because we're using offset_of() which is non-constexpr,
 50   // GCC would warn about non-standard-layout types if we were using offsetof() (which *is* constexpr).
 51   static const int lock_stack_offset;
 52   static const int lock_stack_top_offset;
 53   static const int lock_stack_base_offset;
 54 
 55   // The offset of the next element, in bytes, relative to the JavaThread structure.
 56   // We do this instead of a simple index into the array because this allows for
 57   // efficient addressing in generated code.
 58   uint32_t _top;
 59   // The _bad_oop_sentinel acts as a sentinel value to elide underflow checks in generated code.
 60   // The correct layout is statically asserted in the constructor.
 61   const uintptr_t _bad_oop_sentinel = badOopVal;
 62   oop _base[CAPACITY];
 63 
 64   // Get the owning thread of this lock-stack.
 65   inline JavaThread* get_thread() const;
 66 
 67   // Tests if the calling thread is the thread that owns this lock-stack.
 68   bool is_owning_thread() const;
 69 
 70   // Verifies consistency of the lock-stack.
 71   void verify(const char* msg) const PRODUCT_RETURN;
 72 
 73   // Given an offset (in bytes) calculate the index into the lock-stack.
 74   static inline int to_index(uint32_t offset);
 75 
 76 public:
 77   static ByteSize top_offset()  { return byte_offset_of(LockStack, _top); }
 78   static ByteSize base_offset() { return byte_offset_of(LockStack, _base); }
 79 
 80   LockStack(JavaThread* jt);
 81 
 82   // The boundary indicies of the lock-stack.
 83   static uint32_t start_offset();
 84   static uint32_t end_offset();
 85 
 86   // Returns true if the lock-stack is full. False otherwise.
 87   inline bool is_full() const;
 88 
 89   // Pushes an oop on this lock-stack.
 90   inline void push(oop o);
 91 
 92   // Get the oldest oop from this lock-stack.
 93   // Precondition: This lock-stack must not be empty.
 94   inline oop bottom() const;
 95 
 96   // Is the lock-stack empty.
 97   inline bool is_empty() const;
 98 
 99   // Check if object is recursive.
100   // Precondition: This lock-stack must contain the oop.
101   inline bool is_recursive(oop o) const;
102 
103   // Try recursive enter.
104   // Precondition: This lock-stack must not be full.
105   inline bool try_recursive_enter(oop o);
106 
107   // Try recursive exit.
108   // Precondition: This lock-stack must contain the oop.
109   inline bool try_recursive_exit(oop o);
110 
111   // Removes an oop from an arbitrary location of this lock-stack.
112   // Precondition: This lock-stack must contain the oop.
113   // Returns the number of oops removed.
114   inline size_t remove(oop o);
115 
116   // Tests whether the oop is on this lock-stack.
117   inline bool contains(oop o) const;
118 
119   // GC support
120   inline void oops_do(OopClosure* cl);
121 
122   // Printing
123   void print_on(outputStream* st);
124 
125   // Verify Lock Stack consistent with lock order
126   void verify_consistent_lock_order(GrowableArray<oop>& lock_order, bool leaf_frame) const NOT_DEBUG_RETURN;
127 };
128 
129 #endif // SHARE_RUNTIME_LOCKSTACK_HPP