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