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 
 38 class LockStack {
 39   friend class LockStackTest;
 40   friend class VMStructs;
 41   JVMCI_ONLY(friend class JVMCIVMStructs;)
 42 public:
 43   static const int CAPACITY = 8;
 44 private:
 45 
 46   // TODO: It would be very useful if JavaThread::lock_stack_offset() and friends were constexpr,
 47   // but this is currently not the case because we're using offset_of() which is non-constexpr,
 48   // GCC would warn about non-standard-layout types if we were using offsetof() (which *is* constexpr).
 49   static const int lock_stack_offset;
 50   static const int lock_stack_top_offset;
 51   static const int lock_stack_base_offset;
 52 
 53   // The offset of the next element, in bytes, relative to the JavaThread structure.
 54   // We do this instead of a simple index into the array because this allows for
 55   // efficient addressing in generated code.
 56   uint32_t _top;
 57   // The _bad_oop_sentinel acts as a sentinel value to elide underflow checks in generated code.
 58   // The correct layout is statically asserted in the constructor.
 59   const uintptr_t _bad_oop_sentinel = badOopVal;
 60   oop _base[CAPACITY];
 61 
 62   // Get the owning thread of this lock-stack.
 63   inline JavaThread* get_thread() const;
 64 
 65   // Tests if the calling thread is the thread that owns this lock-stack.
 66   bool is_owning_thread() const;
 67 
 68   // Verifies consistency of the lock-stack.
 69   void verify(const char* msg) const PRODUCT_RETURN;
 70 
 71   // Given an offset (in bytes) calculate the index into the lock-stack.
 72   static inline int to_index(uint32_t offset);
 73 
 74 public:
 75   static ByteSize top_offset()  { return byte_offset_of(LockStack, _top); }
 76   static ByteSize base_offset() { return byte_offset_of(LockStack, _base); }
 77 
 78   LockStack(JavaThread* jt);
 79 
 80   // The boundary indicies of the lock-stack.
 81   static uint32_t start_offset();
 82   static uint32_t end_offset();
 83 
 84   // Returns true if the lock-stack is full. False otherwise.
 85   inline bool is_full() const;
 86 
 87   // Pushes an oop on this lock-stack.
 88   inline void push(oop o);
 89 
 90   // Get the oldest oop from this lock-stack.
 91   // Precondition: This lock-stack must not be empty.
 92   inline oop bottom() const;
 93 
 94   // Is the lock-stack empty.
 95   inline bool is_empty() const;
 96 
 97   // Check if object is recursive.
 98   // Precondition: This lock-stack must contain the oop.
 99   inline bool is_recursive(oop o) const;
100 
101   // Try recursive enter.
102   // Precondition: This lock-stack must not be full.
103   inline bool try_recursive_enter(oop o);
104 
105   // Try recursive exit.
106   // Precondition: This lock-stack must contain the oop.
107   inline bool try_recursive_exit(oop o);
108 
109   // Removes an oop from an arbitrary location of this lock-stack.
110   // Precondition: This lock-stack must contain the oop.
111   // Returns the number of oops removed.
112   inline size_t remove(oop o);
113 
114   // Tests whether the oop is on this lock-stack.
115   inline bool contains(oop o) const;
116 
117   // GC support
118   inline void oops_do(OopClosure* cl);
119 
120   // Printing
121   void print_on(outputStream* st);
122 };
123 
124 #endif // SHARE_RUNTIME_LOCKSTACK_HPP