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   // Returns true if the lock-stack is full. False otherwise.
 89   inline bool is_full() const;
 90 
 91   // Pushes an oop on this lock-stack.
 92   inline void push(oop o);
 93 
 94   // Get the oldest oop from this lock-stack.
 95   // Precondition: This lock-stack must not be empty.
 96   inline oop bottom() const;
 97 
 98   // Is the lock-stack empty.
 99   inline bool is_empty() const;
100 
101   // Check if object is recursive.
102   // Precondition: This lock-stack must contain the oop.
103   inline bool is_recursive(oop o) const;
104 
105   // Try recursive enter.
106   // Precondition: This lock-stack must not be full.
107   inline bool try_recursive_enter(oop o);
108 
109   // Try recursive exit.
110   // Precondition: This lock-stack must contain the oop.
111   inline bool try_recursive_exit(oop o);
112 
113   // Removes an oop from an arbitrary location of this lock-stack.
114   // Precondition: This lock-stack must contain the oop.
115   // Returns the number of oops removed.
116   inline size_t remove(oop o);
117 
118   // Tests whether the oop is on this lock-stack.
119   inline bool contains(oop o) const;
120 
121   // GC support
122   inline void oops_do(OopClosure* cl);
123 
124   // Printing
125   void print_on(outputStream* st);
126 };
127 
128 class OMCache {
129   friend class VMStructs;
130 public:
131   static constexpr int CAPACITY = 8;
132 
133 private:
134   struct OMCacheEntry {
135     oop _oop = nullptr;
136     ObjectMonitor* _monitor = nullptr;
137   } _entries[CAPACITY];
138   const oop _null_sentinel = nullptr;
139 
140 public:
141   static ByteSize entries_offset() { return byte_offset_of(OMCache, _entries); }
142   static constexpr ByteSize oop_to_oop_difference() { return in_ByteSize(sizeof(OMCacheEntry)); }
143   static constexpr ByteSize oop_to_monitor_difference() { return in_ByteSize(sizeof(oop)); }
144 
145   explicit OMCache(JavaThread* jt);
146 
147   inline ObjectMonitor* get_monitor(oop o);
148   inline void set_monitor(ObjectMonitor* monitor);
149   inline void clear();
150 
151 };
152 
153 #endif // SHARE_RUNTIME_LOCKSTACK_HPP