Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/runtime/escapeBarrier.cpp
40951 views
1
/*
2
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2020 SAP SE. 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
#include "precompiled.hpp"
27
#include "code/scopeDesc.hpp"
28
#include "memory/allocation.hpp"
29
#include "prims/jvmtiDeferredUpdates.hpp"
30
#include "runtime/deoptimization.hpp"
31
#include "runtime/escapeBarrier.hpp"
32
#include "runtime/frame.inline.hpp"
33
#include "runtime/handles.hpp"
34
#include "runtime/handshake.hpp"
35
#include "runtime/interfaceSupport.inline.hpp"
36
#include "runtime/keepStackGCProcessed.hpp"
37
#include "runtime/mutexLocker.hpp"
38
#include "runtime/registerMap.hpp"
39
#include "runtime/stackFrameStream.inline.hpp"
40
#include "runtime/stackValue.hpp"
41
#include "runtime/stackValueCollection.hpp"
42
#include "runtime/threadSMR.hpp"
43
#include "runtime/vframe.hpp"
44
#include "runtime/vframe_hp.hpp"
45
#include "utilities/debug.hpp"
46
#include "utilities/globalDefinitions.hpp"
47
#include "utilities/macros.hpp"
48
49
#if COMPILER2_OR_JVMCI
50
51
// Returns true iff objects were reallocated and relocked because of access through JVMTI
52
bool EscapeBarrier::objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id) {
53
// first/oldest update holds the flag
54
GrowableArray<jvmtiDeferredLocalVariableSet*>* list = JvmtiDeferredUpdates::deferred_locals(thread);
55
bool result = false;
56
if (list != NULL) {
57
for (int i = 0; i < list->length(); i++) {
58
if (list->at(i)->matches(fr_id)) {
59
result = list->at(i)->objects_are_deoptimized();
60
break;
61
}
62
}
63
}
64
return result;
65
}
66
67
// Deoptimize objects of frames of the target thread at depth >= d1 and depth <= d2.
68
// Deoptimize objects of caller frames if they passed references to ArgEscape objects as arguments.
69
// Return false in the case of a reallocation failure and true otherwise.
70
bool EscapeBarrier::deoptimize_objects(int d1, int d2) {
71
if (!barrier_active()) return true;
72
if (d1 < deoptee_thread()->frames_to_pop_failed_realloc()) {
73
// The deoptee thread has frames with reallocation failures on top of its stack.
74
// These frames are about to be removed. We must not interfere with that and signal failure.
75
return false;
76
}
77
if (deoptee_thread()->has_last_Java_frame()) {
78
assert(calling_thread() == Thread::current(), "should be");
79
KeepStackGCProcessedMark ksgcpm(deoptee_thread());
80
ResourceMark rm(calling_thread());
81
HandleMark hm(calling_thread());
82
RegisterMap reg_map(deoptee_thread(), false /* update_map */, false /* process_frames */);
83
vframe* vf = deoptee_thread()->last_java_vframe(&reg_map);
84
int cur_depth = 0;
85
86
// Skip frames at depth < d1
87
while (vf != NULL && cur_depth < d1) {
88
cur_depth++;
89
vf = vf->sender();
90
}
91
92
while (vf != NULL && ((cur_depth <= d2) || !vf->is_entry_frame())) {
93
if (vf->is_compiled_frame()) {
94
compiledVFrame* cvf = compiledVFrame::cast(vf);
95
// Deoptimize frame and local objects if any exist.
96
// If cvf is deeper than depth, then we deoptimize iff local objects are passed as args.
97
bool should_deopt = cur_depth <= d2 ? cvf->has_ea_local_in_scope() : cvf->arg_escape();
98
if (should_deopt && !deoptimize_objects(cvf->fr().id())) {
99
// reallocation of scalar replaced objects failed because heap is exhausted
100
return false;
101
}
102
103
// move to top frame
104
while(!vf->is_top()) {
105
cur_depth++;
106
vf = vf->sender();
107
}
108
}
109
110
// move to next physical frame
111
cur_depth++;
112
vf = vf->sender();
113
}
114
}
115
return true;
116
}
117
118
bool EscapeBarrier::deoptimize_objects_all_threads() {
119
if (!barrier_active()) return true;
120
ResourceMark rm(calling_thread());
121
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
122
if (jt->frames_to_pop_failed_realloc() > 0) {
123
// The deoptee thread jt has frames with reallocation failures on top of its stack.
124
// These frames are about to be removed. We must not interfere with that and signal failure.
125
return false;
126
}
127
if (jt->has_last_Java_frame()) {
128
KeepStackGCProcessedMark ksgcpm(jt);
129
RegisterMap reg_map(jt, false /* update_map */, false /* process_frames */);
130
vframe* vf = jt->last_java_vframe(&reg_map);
131
assert(jt->frame_anchor()->walkable(),
132
"The stack of JavaThread " PTR_FORMAT " is not walkable. Thread state is %d",
133
p2i(jt), jt->thread_state());
134
while (vf != NULL) {
135
if (vf->is_compiled_frame()) {
136
compiledVFrame* cvf = compiledVFrame::cast(vf);
137
if ((cvf->has_ea_local_in_scope() || cvf->arg_escape()) &&
138
!deoptimize_objects_internal(jt, cvf->fr().id())) {
139
return false; // reallocation failure
140
}
141
// move to top frame
142
while(!vf->is_top()) {
143
vf = vf->sender();
144
}
145
}
146
// move to next physical frame
147
vf = vf->sender();
148
}
149
}
150
}
151
return true; // success
152
}
153
154
bool EscapeBarrier::_deoptimizing_objects_for_all_threads = false;
155
bool EscapeBarrier::_self_deoptimization_in_progress = false;
156
157
class EscapeBarrierSuspendHandshake : public HandshakeClosure {
158
public:
159
EscapeBarrierSuspendHandshake(const char* name) :
160
HandshakeClosure(name) { }
161
void do_thread(Thread* th) { }
162
};
163
164
void EscapeBarrier::sync_and_suspend_one() {
165
assert(_calling_thread != NULL, "calling thread must not be NULL");
166
assert(_deoptee_thread != NULL, "deoptee thread must not be NULL");
167
assert(barrier_active(), "should not call");
168
169
// Sync with other threads that might be doing deoptimizations
170
{
171
// Need to switch to _thread_blocked for the wait() call
172
ThreadBlockInVM tbivm(_calling_thread);
173
MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
174
while (_self_deoptimization_in_progress || _deoptee_thread->is_obj_deopt_suspend()) {
175
ml.wait();
176
}
177
178
if (self_deopt()) {
179
_self_deoptimization_in_progress = true;
180
return;
181
}
182
183
// set suspend flag for target thread
184
_deoptee_thread->set_obj_deopt_flag();
185
}
186
187
// Use a handshake to synchronize with the target thread.
188
EscapeBarrierSuspendHandshake sh("EscapeBarrierSuspendOne");
189
Handshake::execute(&sh, _deoptee_thread);
190
assert(!_deoptee_thread->has_last_Java_frame() || _deoptee_thread->frame_anchor()->walkable(),
191
"stack should be walkable now");
192
}
193
194
void EscapeBarrier::sync_and_suspend_all() {
195
assert(barrier_active(), "should not call");
196
assert(_calling_thread != NULL, "calling thread must not be NULL");
197
assert(all_threads(), "sanity");
198
199
// Sync with other threads that might be doing deoptimizations
200
{
201
// Need to switch to _thread_blocked for the wait() call
202
ThreadBlockInVM tbivm(_calling_thread);
203
MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
204
205
bool deopt_in_progress;
206
do {
207
deopt_in_progress = _self_deoptimization_in_progress;
208
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
209
deopt_in_progress = (deopt_in_progress || jt->is_obj_deopt_suspend());
210
if (deopt_in_progress) {
211
break;
212
}
213
}
214
if (deopt_in_progress) {
215
ml.wait(); // then check again
216
}
217
} while(deopt_in_progress);
218
219
_self_deoptimization_in_progress = true;
220
_deoptimizing_objects_for_all_threads = true;
221
222
// We set the suspend flags before executing the handshake because then the
223
// setting will be visible after leaving the _thread_blocked state in
224
// JavaThread::wait_for_object_deoptimization(). If we set the flags in the
225
// handshake then the read must happen after the safepoint/handshake poll.
226
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
227
if (jt->is_Java_thread() && !jt->is_hidden_from_external_view() && (jt != _calling_thread)) {
228
jt->set_obj_deopt_flag();
229
}
230
}
231
}
232
233
// Use a handshake to synchronize with the other threads.
234
EscapeBarrierSuspendHandshake sh("EscapeBarrierSuspendAll");
235
Handshake::execute(&sh);
236
#ifdef ASSERT
237
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
238
if (jt->is_hidden_from_external_view()) continue;
239
assert(!jt->has_last_Java_frame() || jt->frame_anchor()->walkable(),
240
"The stack of JavaThread " PTR_FORMAT " is not walkable. Thread state is %d",
241
p2i(jt), jt->thread_state());
242
}
243
#endif // ASSERT
244
}
245
246
void EscapeBarrier::resume_one() {
247
assert(barrier_active(), "should not call");
248
assert(!all_threads(), "use resume_all()");
249
MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
250
if (self_deopt()) {
251
assert(_self_deoptimization_in_progress, "incorrect synchronization");
252
_self_deoptimization_in_progress = false;
253
} else {
254
_deoptee_thread->clear_obj_deopt_flag();
255
}
256
ml.notify_all();
257
}
258
259
void EscapeBarrier::resume_all() {
260
assert(barrier_active(), "should not call");
261
assert(all_threads(), "use resume_one()");
262
MonitorLocker ml(_calling_thread, EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
263
assert(_self_deoptimization_in_progress, "incorrect synchronization");
264
_deoptimizing_objects_for_all_threads = false;
265
_self_deoptimization_in_progress = false;
266
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
267
jt->clear_obj_deopt_flag();
268
}
269
ml.notify_all();
270
}
271
272
void EscapeBarrier::thread_added(JavaThread* jt) {
273
if (!jt->is_hidden_from_external_view()) {
274
MutexLocker ml(EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
275
if (_deoptimizing_objects_for_all_threads) {
276
jt->set_obj_deopt_flag();
277
}
278
}
279
}
280
281
void EscapeBarrier::thread_removed(JavaThread* jt) {
282
MonitorLocker ml(EscapeBarrier_lock, Mutex::_no_safepoint_check_flag);
283
if (jt->is_obj_deopt_suspend()) {
284
// jt terminated before it self suspended.
285
// Other threads might be waiting to perform deoptimizations for it.
286
jt->clear_obj_deopt_flag();
287
ml.notify_all();
288
}
289
}
290
291
// Remember that objects were reallocated and relocked for the compiled frame with the given id
292
static void set_objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id) {
293
// set in first/oldest update
294
GrowableArray<jvmtiDeferredLocalVariableSet*>* list =
295
JvmtiDeferredUpdates::deferred_locals(thread);
296
DEBUG_ONLY(bool found = false);
297
if (list != NULL) {
298
for (int i = 0; i < list->length(); i++) {
299
if (list->at(i)->matches(fr_id)) {
300
DEBUG_ONLY(found = true);
301
list->at(i)->set_objs_are_deoptimized();
302
break;
303
}
304
}
305
}
306
assert(found, "variable set should exist at least for one vframe");
307
}
308
309
// Deoptimize the given frame and deoptimize objects with optimizations based on
310
// escape analysis, i.e. reallocate scalar replaced objects on the heap and
311
// relock objects if locking has been eliminated.
312
// Deoptimized objects are kept as JVMTI deferred updates until the compiled
313
// frame is replaced with interpreter frames. Returns false iff at least one
314
// reallocation failed.
315
bool EscapeBarrier::deoptimize_objects_internal(JavaThread* deoptee, intptr_t* fr_id) {
316
assert(barrier_active(), "should not call");
317
318
JavaThread* ct = calling_thread();
319
bool realloc_failures = false;
320
321
if (!objs_are_deoptimized(deoptee, fr_id)) {
322
// Make sure the frame identified by fr_id is deoptimized and fetch its last vframe
323
compiledVFrame* last_cvf;
324
bool fr_is_deoptimized;
325
do {
326
StackFrameStream fst(deoptee, true /* update */, false /* process_frames */);
327
while (fst.current()->id() != fr_id && !fst.is_done()) {
328
fst.next();
329
}
330
assert(fst.current()->id() == fr_id, "frame not found");
331
assert(fst.current()->is_compiled_frame(),
332
"only compiled frames can contain stack allocated objects");
333
fr_is_deoptimized = fst.current()->is_deoptimized_frame();
334
if (!fr_is_deoptimized) {
335
// Execution must not continue in the compiled method, so we deoptimize the frame.
336
Deoptimization::deoptimize_frame(deoptee, fr_id);
337
} else {
338
last_cvf = compiledVFrame::cast(vframe::new_vframe(fst.current(), fst.register_map(), deoptee));
339
}
340
} while(!fr_is_deoptimized);
341
342
// collect inlined frames
343
compiledVFrame* cvf = last_cvf;
344
GrowableArray<compiledVFrame*>* vfs = new GrowableArray<compiledVFrame*>(10);
345
while (!cvf->is_top()) {
346
vfs->push(cvf);
347
cvf = compiledVFrame::cast(cvf->sender());
348
}
349
vfs->push(cvf);
350
351
// reallocate and relock optimized objects
352
bool deoptimized_objects = Deoptimization::deoptimize_objects_internal(ct, vfs, realloc_failures);
353
if (!realloc_failures && deoptimized_objects) {
354
// now do the updates
355
for (int frame_index = 0; frame_index < vfs->length(); frame_index++) {
356
cvf = vfs->at(frame_index);
357
cvf->create_deferred_updates_after_object_deoptimization();
358
}
359
set_objs_are_deoptimized(deoptee, fr_id);
360
}
361
}
362
return !realloc_failures;
363
}
364
365
#endif // COMPILER2_OR_JVMCI
366
367