1 /*
2 * Copyright (c) 2022, Red Hat, Inc. All rights reserved.
3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #ifndef SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
27 #define SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
28
29 #include "memory/iterator.hpp"
30 #include "runtime/javaThread.hpp"
31 #include "runtime/lockStack.hpp"
32 #include "runtime/safepoint.hpp"
33 #include "runtime/stackWatermark.hpp"
34 #include "runtime/stackWatermarkSet.inline.hpp"
35
36 inline int LockStack::to_index(uint32_t offset) {
37 return (offset - lock_stack_base_offset) / oopSize;
38 }
39
40 JavaThread* LockStack::get_thread() const {
41 char* addr = reinterpret_cast<char*>(const_cast<LockStack*>(this));
42 return reinterpret_cast<JavaThread*>(addr - lock_stack_offset);
43 }
44
45 inline bool LockStack::can_push() const {
46 return to_index(_top) < CAPACITY;
47 }
48
49 inline bool LockStack::is_owning_thread() const {
50 Thread* current = Thread::current();
51 if (current->is_Java_thread()) {
52 JavaThread* thread = JavaThread::cast(current);
53 bool is_owning = &thread->lock_stack() == this;
54 assert(is_owning == (get_thread() == thread), "is_owning sanity");
55 return is_owning;
56 }
57 return false;
58 }
59
60 inline void LockStack::push(oop o) {
61 verify("pre-push");
62 assert(oopDesc::is_oop(o), "must be");
63 assert(!contains(o), "entries must be unique");
64 assert(can_push(), "must have room");
65 assert(_base[to_index(_top)] == nullptr, "expect zapped entry");
66 _base[to_index(_top)] = o;
67 _top += oopSize;
68 verify("post-push");
69 }
70
71 inline oop LockStack::pop() {
72 verify("pre-pop");
73 assert(to_index(_top) > 0, "underflow, probably unbalanced push/pop");
74 _top -= oopSize;
75 oop o = _base[to_index(_top)];
76 #ifdef ASSERT
77 _base[to_index(_top)] = nullptr;
78 #endif
79 assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o));
80 verify("post-pop");
81 return o;
82 }
83
84 inline void LockStack::remove(oop o) {
85 verify("pre-remove");
86 assert(contains(o), "entry must be present: " PTR_FORMAT, p2i(o));
87 int end = to_index(_top);
88 for (int i = 0; i < end; i++) {
89 if (_base[i] == o) {
90 int last = end - 1;
91 for (; i < last; i++) {
92 _base[i] = _base[i + 1];
93 }
94 _top -= oopSize;
95 #ifdef ASSERT
96 _base[to_index(_top)] = nullptr;
97 #endif
98 break;
99 }
100 }
101 assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o));
102 verify("post-remove");
103 }
104
105 inline bool LockStack::contains(oop o) const {
106 verify("pre-contains");
107
108 // Can't poke around in thread oops without having started stack watermark processing.
109 assert(StackWatermarkSet::processing_started(get_thread()), "Processing must have started!");
110
111 int end = to_index(_top);
112 for (int i = end - 1; i >= 0; i--) {
113 if (_base[i] == o) {
114 verify("post-contains");
115 return true;
116 }
117 }
118 verify("post-contains");
119 return false;
120 }
121
122 inline void LockStack::oops_do(OopClosure* cl) {
|
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_INLINE_HPP
28 #define SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
29
30 #include "runtime/lockStack.hpp"
31
32 #include "memory/iterator.hpp"
33 #include "runtime/javaThread.hpp"
34 #include "runtime/safepoint.hpp"
35 #include "runtime/stackWatermark.hpp"
36 #include "runtime/stackWatermarkSet.inline.hpp"
37 #include "utilities/align.hpp"
38 #include "utilities/globalDefinitions.hpp"
39
40 inline int LockStack::to_index(uint32_t offset) {
41 assert(is_aligned(offset, oopSize), "Bad alignment: %u", offset);
42 assert((offset <= end_offset()), "lockstack overflow: offset %d end_offset %d", offset, end_offset());
43 assert((offset >= start_offset()), "lockstack underflow: offset %d start_offset %d", offset, start_offset());
44 return (offset - lock_stack_base_offset) / oopSize;
45 }
46
47 JavaThread* LockStack::get_thread() const {
48 char* addr = reinterpret_cast<char*>(const_cast<LockStack*>(this));
49 return reinterpret_cast<JavaThread*>(addr - lock_stack_offset);
50 }
51
52 inline bool LockStack::is_full() const {
53 return to_index(_top) == CAPACITY;
54 }
55
56 inline bool LockStack::is_owning_thread() const {
57 Thread* current = Thread::current();
58 if (current->is_Java_thread()) {
59 JavaThread* thread = JavaThread::cast(current);
60 bool is_owning = &thread->lock_stack() == this;
61 assert(is_owning == (get_thread() == thread), "is_owning sanity");
62 return is_owning;
63 }
64 return false;
65 }
66
67 inline void LockStack::push(oop o) {
68 verify("pre-push");
69 assert(oopDesc::is_oop(o), "must be");
70 assert(!contains(o), "entries must be unique");
71 assert(!is_full(), "must have room");
72 assert(_base[to_index(_top)] == nullptr, "expect zapped entry");
73 _base[to_index(_top)] = o;
74 _top += oopSize;
75 verify("post-push");
76 }
77
78 inline oop LockStack::bottom() const {
79 assert(to_index(_top) > 0, "must contain an oop");
80 return _base[0];
81 }
82
83 inline bool LockStack::is_empty() const {
84 return to_index(_top) == 0;
85 }
86
87 inline bool LockStack::is_recursive(oop o) const {
88 if (!VM_Version::supports_recursive_lightweight_locking()) {
89 return false;
90 }
91 verify("pre-is_recursive");
92
93 // This will succeed iff there is a consecutive run of oops on the
94 // lock-stack with a length of at least 2.
95
96 assert(contains(o), "at least one entry must exist");
97 int end = to_index(_top);
98 // Start iterating from the top because the runtime code is more
99 // interested in the balanced locking case when the top oop on the
100 // lock-stack matches o. This will cause the for loop to break out
101 // in the first loop iteration if it is non-recursive.
102 for (int i = end - 1; i > 0; i--) {
103 if (_base[i - 1] == o && _base[i] == o) {
104 verify("post-is_recursive");
105 return true;
106 }
107 if (_base[i] == o) {
108 // o can only occur in one consecutive run on the lock-stack.
109 // Only one of the two oops checked matched o, so this run
110 // must be of length 1 and thus not be recursive. Stop the search.
111 break;
112 }
113 }
114
115 verify("post-is_recursive");
116 return false;
117 }
118
119 inline bool LockStack::try_recursive_enter(oop o) {
120 if (!VM_Version::supports_recursive_lightweight_locking()) {
121 return false;
122 }
123 verify("pre-try_recursive_enter");
124
125 // This will succeed iff the top oop on the stack matches o.
126 // When successful o will be pushed to the lock-stack creating
127 // a consecutive run at least 2 oops that matches o on top of
128 // the lock-stack.
129
130 assert(!is_full(), "precond");
131
132 int end = to_index(_top);
133 if (end == 0 || _base[end - 1] != o) {
134 // Topmost oop does not match o.
135 verify("post-try_recursive_enter");
136 return false;
137 }
138
139 _base[end] = o;
140 _top += oopSize;
141 verify("post-try_recursive_enter");
142 return true;
143 }
144
145 inline bool LockStack::try_recursive_exit(oop o) {
146 if (!VM_Version::supports_recursive_lightweight_locking()) {
147 return false;
148 }
149 verify("pre-try_recursive_exit");
150
151 // This will succeed iff the top two oops on the stack matches o.
152 // When successful the top oop will be popped of the lock-stack.
153 // When unsuccessful the lock may still be recursive, in which
154 // case the locking is unbalanced. This case is handled externally.
155
156 assert(contains(o), "entries must exist");
157
158 int end = to_index(_top);
159 if (end <= 1 || _base[end - 1] != o || _base[end - 2] != o) {
160 // The two topmost oops do not match o.
161 verify("post-try_recursive_exit");
162 return false;
163 }
164
165 _top -= oopSize;
166 DEBUG_ONLY(_base[to_index(_top)] = nullptr;)
167 verify("post-try_recursive_exit");
168 return true;
169 }
170
171 inline size_t LockStack::remove(oop o) {
172 verify("pre-remove");
173 assert(contains(o), "entry must be present: " PTR_FORMAT, p2i(o));
174
175 int end = to_index(_top);
176 int inserted = 0;
177 for (int i = 0; i < end; i++) {
178 if (_base[i] != o) {
179 if (inserted != i) {
180 _base[inserted] = _base[i];
181 }
182 inserted++;
183 }
184 }
185
186 #ifdef ASSERT
187 for (int i = inserted; i < end; i++) {
188 _base[i] = nullptr;
189 }
190 #endif
191
192 uint32_t removed = end - inserted;
193 _top -= removed * oopSize;
194 assert(!contains(o), "entry must have been removed: " PTR_FORMAT, p2i(o));
195 verify("post-remove");
196 return removed;
197 }
198
199 inline bool LockStack::contains(oop o) const {
200 verify("pre-contains");
201
202 // Can't poke around in thread oops without having started stack watermark processing.
203 assert(StackWatermarkSet::processing_started(get_thread()), "Processing must have started!");
204
205 int end = to_index(_top);
206 for (int i = end - 1; i >= 0; i--) {
207 if (_base[i] == o) {
208 verify("post-contains");
209 return true;
210 }
211 }
212 verify("post-contains");
213 return false;
214 }
215
216 inline void LockStack::oops_do(OopClosure* cl) {
|