1
1
/*
2
2
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
3
3
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
4
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
4
5
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
6
*
6
7
* This code is free software; you can redistribute it and/or modify it
26
27
#ifndef SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
27
28
#define SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
28
29
30
+ #include " runtime/lockStack.hpp"
31
+
29
32
#include " memory/iterator.hpp"
30
33
#include " runtime/javaThread.hpp"
31
- #include " runtime/lockStack.hpp"
32
34
#include " runtime/safepoint.hpp"
33
35
#include " runtime/stackWatermark.hpp"
34
36
#include " runtime/stackWatermarkSet.inline.hpp"
37
+ #include " utilities/align.hpp"
38
+ #include " utilities/globalDefinitions.hpp"
35
39
36
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 ());
37
44
return (offset - lock_stack_base_offset) / oopSize;
38
45
}
39
46
@@ -42,8 +49,8 @@ JavaThread* LockStack::get_thread() const {
42
49
return reinterpret_cast <JavaThread*>(addr - lock_stack_offset);
43
50
}
44
51
45
- inline bool LockStack::can_push () const {
46
- return to_index (_top) < CAPACITY;
52
+ inline bool LockStack::is_full () const {
53
+ return to_index (_top) == CAPACITY;
47
54
}
48
55
49
56
inline bool LockStack::is_owning_thread () const {
@@ -61,32 +68,132 @@ inline void LockStack::push(oop o) {
61
68
verify (" pre-push" );
62
69
assert (oopDesc::is_oop (o), " must be" );
63
70
assert (!contains (o), " entries must be unique" );
64
- assert (can_push (), " must have room" );
71
+ assert (! is_full (), " must have room" );
65
72
assert (_base[to_index (_top)] == nullptr , " expect zapped entry" );
66
73
_base[to_index (_top)] = o;
67
74
_top += oopSize;
68
75
verify (" post-push" );
69
76
}
70
77
71
- inline void LockStack::remove (oop o) {
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) {
72
172
verify (" pre-remove" );
73
173
assert (contains (o), " entry must be present: " PTR_FORMAT, p2i (o));
174
+
74
175
int end = to_index (_top);
176
+ int inserted = 0 ;
75
177
for (int i = 0 ; i < end; i++) {
76
- if (_base[i] == o) {
77
- int last = end - 1 ;
78
- for (; i < last; i++) {
79
- _base[i] = _base[i + 1 ];
178
+ if (_base[i] != o) {
179
+ if (inserted != i) {
180
+ _base[inserted] = _base[i];
80
181
}
81
- _top -= oopSize;
82
- #ifdef ASSERT
83
- _base[to_index (_top)] = nullptr ;
84
- #endif
85
- break ;
182
+ inserted++;
86
183
}
87
184
}
88
- assert (!contains (o), " entries must be unique: " PTR_FORMAT, p2i (o));
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));
89
195
verify (" post-remove" );
196
+ return removed;
90
197
}
91
198
92
199
inline bool LockStack::contains (oop o) const {
0 commit comments