Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/runtime/interfaceSupport.inline.hpp
40951 views
1
/*
2
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2021, Azul Systems, Inc. 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_INTERFACESUPPORT_INLINE_HPP
27
#define SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP
28
29
// No interfaceSupport.hpp
30
31
#include "gc/shared/gc_globals.hpp"
32
#include "runtime/handles.inline.hpp"
33
#include "runtime/mutexLocker.hpp"
34
#include "runtime/orderAccess.hpp"
35
#include "runtime/os.hpp"
36
#include "runtime/safepointMechanism.inline.hpp"
37
#include "runtime/safepointVerifiers.hpp"
38
#include "runtime/thread.hpp"
39
#include "runtime/threadWXSetters.inline.hpp"
40
#include "runtime/vmOperations.hpp"
41
#include "utilities/globalDefinitions.hpp"
42
#include "utilities/macros.hpp"
43
#include "utilities/preserveException.hpp"
44
45
// Wrapper for all entry points to the virtual machine.
46
47
// InterfaceSupport provides functionality used by the VM_LEAF_BASE and
48
// VM_ENTRY_BASE macros. These macros are used to guard entry points into
49
// the VM and perform checks upon leave of the VM.
50
51
52
class InterfaceSupport: AllStatic {
53
# ifdef ASSERT
54
public:
55
static unsigned int _scavenge_alot_counter;
56
static unsigned int _fullgc_alot_counter;
57
static int _fullgc_alot_invocation;
58
59
// Helper methods used to implement +ScavengeALot and +FullGCALot
60
static void check_gc_alot() { if (ScavengeALot || FullGCALot) gc_alot(); }
61
static void gc_alot();
62
63
static void walk_stack_from(vframe* start_vf);
64
static void walk_stack();
65
66
static void zombieAll();
67
static void deoptimizeAll();
68
static void verify_stack();
69
static void verify_last_frame();
70
# endif
71
};
72
73
74
// Basic class for all thread transition classes.
75
76
class ThreadStateTransition : public StackObj {
77
protected:
78
JavaThread* _thread;
79
public:
80
ThreadStateTransition(JavaThread *thread) {
81
_thread = thread;
82
assert(thread != NULL, "must be active Java thread");
83
assert(thread == Thread::current(), "must be current thread");
84
}
85
86
// Change threadstate in a manner, so safepoint can detect changes.
87
// Time-critical: called on exit from every runtime routine
88
static inline void transition(JavaThread *thread, JavaThreadState from, JavaThreadState to) {
89
assert(from != _thread_in_Java, "use transition_from_java");
90
assert(from != _thread_in_native, "use transition_from_native");
91
assert((from & 1) == 0 && (to & 1) == 0, "odd numbers are transitions states");
92
assert(thread->thread_state() == from, "coming from wrong thread state");
93
94
// Check NoSafepointVerifier
95
// This also clears unhandled oops if CheckUnhandledOops is used.
96
thread->check_possible_safepoint();
97
98
// Change to transition state and ensure it is seen by the VM thread.
99
thread->set_thread_state_fence((JavaThreadState)(from + 1));
100
101
SafepointMechanism::process_if_requested(thread);
102
thread->set_thread_state(to);
103
}
104
105
// Same as above, but assumes from = _thread_in_Java. This is simpler, since we
106
// never block on entry to the VM. This will break the code, since e.g. preserve arguments
107
// have not been setup.
108
static inline void transition_from_java(JavaThread *thread, JavaThreadState to) {
109
assert(thread->thread_state() == _thread_in_Java, "coming from wrong thread state");
110
thread->set_thread_state(to);
111
}
112
113
static inline void transition_from_native(JavaThread *thread, JavaThreadState to) {
114
assert((to & 1) == 0, "odd numbers are transitions states");
115
assert(thread->thread_state() == _thread_in_native, "coming from wrong thread state");
116
assert(!thread->has_last_Java_frame() || thread->frame_anchor()->walkable(), "Unwalkable stack in native->vm transition");
117
118
// Change to transition state and ensure it is seen by the VM thread.
119
thread->set_thread_state_fence(_thread_in_native_trans);
120
121
// We never install asynchronous exceptions when coming (back) in
122
// to the runtime from native code because the runtime is not set
123
// up to handle exceptions floating around at arbitrary points.
124
SafepointMechanism::process_if_requested_with_exit_check(thread, false /* check asyncs */);
125
thread->set_thread_state(to);
126
}
127
128
protected:
129
void trans(JavaThreadState from, JavaThreadState to) { transition(_thread, from, to); }
130
void trans_from_java(JavaThreadState to) { transition_from_java(_thread, to); }
131
void trans_from_native(JavaThreadState to) { transition_from_native(_thread, to); }
132
};
133
134
class ThreadInVMForHandshake : public ThreadStateTransition {
135
const JavaThreadState _original_state;
136
public:
137
ThreadInVMForHandshake(JavaThread* thread) : ThreadStateTransition(thread),
138
_original_state(thread->thread_state()) {
139
140
if (thread->has_last_Java_frame()) {
141
thread->frame_anchor()->make_walkable(thread);
142
}
143
144
thread->set_thread_state(_thread_in_vm);
145
146
// Threads shouldn't block if they are in the middle of printing, but...
147
ttyLocker::break_tty_lock_for_safepoint(os::current_thread_id());
148
}
149
150
~ThreadInVMForHandshake() {
151
assert(_thread->thread_state() == _thread_in_vm, "should only call when leaving VM after handshake");
152
_thread->set_thread_state(_original_state);
153
}
154
155
};
156
157
class ThreadInVMfromJava : public ThreadStateTransition {
158
bool _check_asyncs;
159
public:
160
ThreadInVMfromJava(JavaThread* thread, bool check_asyncs = true) : ThreadStateTransition(thread), _check_asyncs(check_asyncs) {
161
trans_from_java(_thread_in_vm);
162
}
163
~ThreadInVMfromJava() {
164
if (_thread->stack_overflow_state()->stack_yellow_reserved_zone_disabled()) {
165
_thread->stack_overflow_state()->enable_stack_yellow_reserved_zone();
166
}
167
trans(_thread_in_vm, _thread_in_Java);
168
// We prevent asynchronous exceptions from being installed on return to Java in situations
169
// where we can't tolerate them. See bugs: 4324348, 4854693, 4998314, 5040492, 5050705.
170
if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(_check_asyncs);
171
}
172
};
173
174
175
class ThreadInVMfromUnknown {
176
JavaThread* _thread;
177
public:
178
ThreadInVMfromUnknown() : _thread(NULL) {
179
Thread* t = Thread::current();
180
if (t->is_Java_thread()) {
181
JavaThread* t2 = t->as_Java_thread();
182
if (t2->thread_state() == _thread_in_native) {
183
_thread = t2;
184
ThreadStateTransition::transition_from_native(t2, _thread_in_vm);
185
// Used to have a HandleMarkCleaner but that is dangerous as
186
// it could free a handle in our (indirect, nested) caller.
187
// We expect any handles will be short lived and figure we
188
// don't need an actual HandleMark.
189
}
190
}
191
}
192
~ThreadInVMfromUnknown() {
193
if (_thread) {
194
ThreadStateTransition::transition(_thread, _thread_in_vm, _thread_in_native);
195
}
196
}
197
};
198
199
200
class ThreadInVMfromNative : public ThreadStateTransition {
201
ResetNoHandleMark __rnhm;
202
public:
203
ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) {
204
trans_from_native(_thread_in_vm);
205
}
206
~ThreadInVMfromNative() {
207
assert(_thread->thread_state() == _thread_in_vm, "coming from wrong thread state");
208
// We cannot assert !_thread->owns_locks() since we have valid cases where
209
// we call known native code using this wrapper holding locks.
210
_thread->check_possible_safepoint();
211
// Once we are in native vm expects stack to be walkable
212
_thread->frame_anchor()->make_walkable(_thread);
213
OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.
214
_thread->set_thread_state(_thread_in_native);
215
}
216
};
217
218
219
class ThreadToNativeFromVM : public ThreadStateTransition {
220
public:
221
ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) {
222
// We are leaving the VM at this point and going directly to native code.
223
// Block, if we are in the middle of a safepoint synchronization.
224
assert(!thread->owns_locks(), "must release all locks when leaving VM");
225
thread->frame_anchor()->make_walkable(thread);
226
trans(_thread_in_vm, _thread_in_native);
227
// Check for pending. async. exceptions or suspends.
228
if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(false);
229
}
230
231
~ThreadToNativeFromVM() {
232
trans_from_native(_thread_in_vm);
233
assert(!_thread->is_pending_jni_exception_check(), "Pending JNI Exception Check");
234
// We don't need to clear_walkable because it will happen automagically when we return to java
235
}
236
};
237
238
// Perform a transition to _thread_blocked and take a call-back to be executed before
239
// SafepointMechanism::process_if_requested when returning to the VM. This allows us
240
// to perform an "undo" action if we might block processing a safepoint/handshake operation
241
// (such as thread suspension).
242
template <typename PRE_PROC>
243
class ThreadBlockInVMPreprocess : public ThreadStateTransition {
244
private:
245
PRE_PROC& _pr;
246
public:
247
ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr) : ThreadStateTransition(thread), _pr(pr) {
248
assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state");
249
thread->check_possible_safepoint();
250
// Once we are blocked vm expects stack to be walkable
251
thread->frame_anchor()->make_walkable(thread);
252
OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.
253
thread->set_thread_state(_thread_blocked);
254
}
255
~ThreadBlockInVMPreprocess() {
256
assert(_thread->thread_state() == _thread_blocked, "coming from wrong thread state");
257
// Change to transition state and ensure it is seen by the VM thread.
258
_thread->set_thread_state_fence(_thread_blocked_trans);
259
260
if (SafepointMechanism::should_process(_thread)) {
261
_pr(_thread);
262
SafepointMechanism::process_if_requested(_thread);
263
}
264
265
_thread->set_thread_state(_thread_in_vm);
266
}
267
};
268
269
class InFlightMutexRelease {
270
private:
271
Mutex** _in_flight_mutex_addr;
272
public:
273
InFlightMutexRelease(Mutex** in_flight_mutex_addr) : _in_flight_mutex_addr(in_flight_mutex_addr) {}
274
void operator()(JavaThread* current) {
275
if (_in_flight_mutex_addr != NULL && *_in_flight_mutex_addr != NULL) {
276
(*_in_flight_mutex_addr)->release_for_safepoint();
277
*_in_flight_mutex_addr = NULL;
278
}
279
}
280
};
281
282
// Parameter in_flight_mutex_addr is only used by class Mutex to avoid certain deadlock
283
// scenarios while making transitions that might block for a safepoint or handshake.
284
// It's the address of a pointer to the mutex we are trying to acquire. This will be used to
285
// access and release said mutex when transitioning back from blocked to vm (destructor) in
286
// case we need to stop for a safepoint or handshake.
287
class ThreadBlockInVM {
288
InFlightMutexRelease _ifmr;
289
ThreadBlockInVMPreprocess<InFlightMutexRelease> _tbivmpp;
290
public:
291
ThreadBlockInVM(JavaThread* thread, Mutex** in_flight_mutex_addr = NULL)
292
: _ifmr(in_flight_mutex_addr), _tbivmpp(thread, _ifmr) {}
293
};
294
295
// Debug class instantiated in JRT_ENTRY macro.
296
// Can be used to verify properties on enter/exit of the VM.
297
298
#ifdef ASSERT
299
class VMEntryWrapper {
300
public:
301
VMEntryWrapper();
302
~VMEntryWrapper();
303
};
304
305
306
class VMNativeEntryWrapper {
307
public:
308
VMNativeEntryWrapper();
309
~VMNativeEntryWrapper();
310
};
311
312
#endif // ASSERT
313
314
// LEAF routines do not lock, GC or throw exceptions
315
316
// On macos/aarch64 we need to maintain the W^X state of the thread. So we
317
// take WXWrite on the enter to VM from the "outside" world, so the rest of JVM
318
// code can assume writing (but not executing) codecache is always possible
319
// without preliminary actions.
320
// JavaThread state should be changed only after taking WXWrite. The state
321
// change may trigger a safepoint, that would need WXWrite to do bookkeeping
322
// in the codecache.
323
324
#define VM_LEAF_BASE(result_type, header) \
325
debug_only(NoHandleMark __hm;) \
326
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, \
327
JavaThread::current())); \
328
os::verify_stack_alignment(); \
329
/* begin of body */
330
331
#define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \
332
debug_only(ResetNoHandleMark __rnhm;) \
333
HandleMarkCleaner __hm(thread); \
334
JavaThread* THREAD = thread; /* For exception macros. */ \
335
os::verify_stack_alignment(); \
336
/* begin of body */
337
338
339
// ENTRY routines may lock, GC and throw exceptions
340
341
#define VM_ENTRY_BASE(result_type, header, thread) \
342
HandleMarkCleaner __hm(thread); \
343
JavaThread* THREAD = thread; /* For exception macros. */ \
344
os::verify_stack_alignment(); \
345
/* begin of body */
346
347
348
#define JRT_ENTRY(result_type, header) \
349
result_type header { \
350
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
351
ThreadInVMfromJava __tiv(current); \
352
VM_ENTRY_BASE(result_type, header, current) \
353
debug_only(VMEntryWrapper __vew;)
354
355
// JRT_LEAF currently can be called from either _thread_in_Java or
356
// _thread_in_native mode.
357
//
358
// JRT_LEAF rules:
359
// A JRT_LEAF method may not interfere with safepointing by
360
// 1) acquiring or blocking on a Mutex or JavaLock - checked
361
// 2) allocating heap memory - checked
362
// 3) executing a VM operation - checked
363
// 4) executing a system call (including malloc) that could block or grab a lock
364
// 5) invoking GC
365
// 6) reaching a safepoint
366
// 7) running too long
367
// Nor may any method it calls.
368
369
#define JRT_LEAF(result_type, header) \
370
result_type header { \
371
VM_LEAF_BASE(result_type, header) \
372
debug_only(NoSafepointVerifier __nsv;)
373
374
375
#define JRT_ENTRY_NO_ASYNC(result_type, header) \
376
result_type header { \
377
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
378
ThreadInVMfromJava __tiv(current, false /* check asyncs */); \
379
VM_ENTRY_BASE(result_type, header, current) \
380
debug_only(VMEntryWrapper __vew;)
381
382
// Same as JRT Entry but allows for return value after the safepoint
383
// to get back into Java from the VM
384
#define JRT_BLOCK_ENTRY(result_type, header) \
385
result_type header { \
386
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
387
HandleMarkCleaner __hm(current);
388
389
#define JRT_BLOCK \
390
{ \
391
ThreadInVMfromJava __tiv(current); \
392
JavaThread* THREAD = current; /* For exception macros. */ \
393
debug_only(VMEntryWrapper __vew;)
394
395
#define JRT_BLOCK_NO_ASYNC \
396
{ \
397
ThreadInVMfromJava __tiv(current, false /* check asyncs */); \
398
JavaThread* THREAD = current; /* For exception macros. */ \
399
debug_only(VMEntryWrapper __vew;)
400
401
#define JRT_BLOCK_END }
402
403
#define JRT_END }
404
405
// Definitions for JNI
406
407
#define JNI_ENTRY(result_type, header) \
408
JNI_ENTRY_NO_PRESERVE(result_type, header) \
409
WeakPreserveExceptionMark __wem(thread);
410
411
#define JNI_ENTRY_NO_PRESERVE(result_type, header) \
412
extern "C" { \
413
result_type JNICALL header { \
414
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
415
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
416
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
417
ThreadInVMfromNative __tiv(thread); \
418
debug_only(VMNativeEntryWrapper __vew;) \
419
VM_ENTRY_BASE(result_type, header, thread)
420
421
422
#define JNI_LEAF(result_type, header) \
423
extern "C" { \
424
result_type JNICALL header { \
425
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
426
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
427
VM_LEAF_BASE(result_type, header)
428
429
430
// Close the routine and the extern "C"
431
#define JNI_END } }
432
433
434
435
// Definitions for JVM
436
437
#define JVM_ENTRY(result_type, header) \
438
extern "C" { \
439
result_type JNICALL header { \
440
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
441
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
442
ThreadInVMfromNative __tiv(thread); \
443
debug_only(VMNativeEntryWrapper __vew;) \
444
VM_ENTRY_BASE(result_type, header, thread)
445
446
447
#define JVM_ENTRY_NO_ENV(result_type, header) \
448
extern "C" { \
449
result_type JNICALL header { \
450
JavaThread* thread = JavaThread::current(); \
451
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
452
ThreadInVMfromNative __tiv(thread); \
453
debug_only(VMNativeEntryWrapper __vew;) \
454
VM_ENTRY_BASE(result_type, header, thread)
455
456
457
#define JVM_LEAF(result_type, header) \
458
extern "C" { \
459
result_type JNICALL header { \
460
VM_Exit::block_if_vm_exited(); \
461
VM_LEAF_BASE(result_type, header)
462
463
464
#define JVM_ENTRY_FROM_LEAF(env, result_type, header) \
465
{ { \
466
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
467
ThreadInVMfromNative __tiv(thread); \
468
debug_only(VMNativeEntryWrapper __vew;) \
469
VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread)
470
471
472
#define JVM_END } }
473
474
#endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP
475
476