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 ObjectMonitor;
 36 class OopClosure;
 37 class outputStream;
 38 template<typename>
 39 class GrowableArray;
 40 class Thread;
 41 
 42 class LockStack {
 43   friend class LockStackTest;
 44   friend class VMStructs;
 45   JVMCI_ONLY(friend class JVMCIVMStructs;)
 46 public:
 47   static const int CAPACITY = 8;
 48 private:
 49 
 50   // TODO: It would be very useful if JavaThread::lock_stack_offset() and friends were constexpr,
 51   // but this is currently not the case because we're using offset_of() which is non-constexpr,
 52   // GCC would warn about non-standard-layout types if we were using offsetof() (which *is* constexpr).
 53   static const int lock_stack_offset;
 54   static const int lock_stack_top_offset;
 55   static const int lock_stack_base_offset;
 56 
 57   // The offset of the next element, in bytes, relative to the JavaThread structure.
 58   // We do this instead of a simple index into the array because this allows for
 59   // efficient addressing in generated code.
 60   uint32_t _top;
 61   // The _bad_oop_sentinel acts as a sentinel value to elide underflow checks in generated code.
 62   // The correct layout is statically asserted in the constructor.
 63   const uintptr_t _bad_oop_sentinel = badOopVal;
 64   oop _base[CAPACITY];
 65 
 66   // Get the owning thread of this lock-stack.
 67   inline JavaThread* get_thread() const;
 68 
 69   // Tests if the calling thread is the thread that owns this lock-stack.
 70   bool is_owning_thread() const;
 71 
 72   // Verifies consistency of the lock-stack.
 73   void verify(const char* msg) const PRODUCT_RETURN;
 74 
 75   // Given an offset (in bytes) calculate the index into the lock-stack.
 76   static inline int to_index(uint32_t offset);
 77 
 78 public:
 79   static ByteSize top_offset()  { return byte_offset_of(LockStack, _top); }
 80   static ByteSize base_offset() { return byte_offset_of(LockStack, _base); }
 81 
 82   LockStack(JavaThread* jt);
 83 
 84   // The boundary indicies of the lock-stack.
 85   static uint32_t start_offset();
 86   static uint32_t end_offset();
 87 
 88   // Return true if we have room to push n oops onto this lock-stack, false otherwise.
 89   inline bool can_push(int n = 1) const;
 90 
 91   // Returns true if the lock-stack is full. False otherwise.
 92   inline bool is_full() const;
 93 
 94   // Pushes an oop on this lock-stack.
 95   inline void push(oop o);
 96 
 97   // Get the oldest oop from this lock-stack.
 98   // Precondition: This lock-stack must not be empty.
 99   inline oop bottom() const;
100 
101   // Is the lock-stack empty.
102   inline bool is_empty() const;
103 
104   // Get the oldest oop in the stack
105   inline oop top();
106 
107   // Check if object is recursive.
108   // Precondition: This lock-stack must contain the oop.
109   inline bool is_recursive(oop o) const;
110 
111   // Try recursive enter.
112   // Precondition: This lock-stack must not be full.
113   inline bool try_recursive_enter(oop o);
114 
115   // Try recursive exit.
116   // Precondition: This lock-stack must contain the oop.
117   inline bool try_recursive_exit(oop o);
118 
119   // Removes an oop from an arbitrary location of this lock-stack.
120   // Precondition: This lock-stack must contain the oop.
121   // Returns the number of oops removed.
122   inline size_t remove(oop o);
123 
124   // Tests whether the oop is on this lock-stack.
125   inline bool contains(oop o) const;
126 
127   // GC support
128   inline void oops_do(OopClosure* cl);
129 
130   // Printing
131   void print_on(outputStream* st);
132 
133   // Verify Lock Stack consistent with lock order
134   void verify_consistent_lock_order(GrowableArray<oop>& lock_order, bool leaf_frame) const NOT_DEBUG_RETURN;
135 };
136 
137 class OMCache {
138   friend class VMStructs;
139 public:
140   static constexpr int CAPACITY = 8;
141 
142 private:
143   struct OMCacheEntry {
144     oop _oop = nullptr;
145     ObjectMonitor* _monitor = nullptr;
146   } _entries[CAPACITY];
147   const oop _null_sentinel = nullptr;
148 
149 public:
150   static ByteSize entries() { return byte_offset_of(OMCache, _entries); }
151   static constexpr ByteSize oop_to_oop_difference() { return in_ByteSize(sizeof(OMCacheEntry)); }
152   static constexpr ByteSize oop_to_monitor_difference() { return in_ByteSize(sizeof(oop)); }
153 
154   explicit OMCache(JavaThread* jt);
155 
156   inline ObjectMonitor* get_monitor(oop o);
157   inline void set_monitor(ObjectMonitor* monitor);
158   inline void clear();
159 
160 };
161 
162 #endif // SHARE_RUNTIME_LOCKSTACK_HPP