Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/runtime/interfaceSupport.inline.hpp
64440 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();
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();
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();
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
bool _allow_suspend;
247
public:
248
ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr, bool allow_suspend = true)
249
: ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) {
250
assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state");
251
thread->check_possible_safepoint();
252
// Once we are blocked vm expects stack to be walkable
253
thread->frame_anchor()->make_walkable();
254
OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.
255
thread->set_thread_state(_thread_blocked);
256
}
257
~ThreadBlockInVMPreprocess() {
258
assert(_thread->thread_state() == _thread_blocked, "coming from wrong thread state");
259
// Change to transition state and ensure it is seen by the VM thread.
260
_thread->set_thread_state_fence(_thread_blocked_trans);
261
262
if (SafepointMechanism::should_process(_thread, _allow_suspend)) {
263
_pr(_thread);
264
SafepointMechanism::process_if_requested(_thread, _allow_suspend);
265
}
266
267
_thread->set_thread_state(_thread_in_vm);
268
}
269
};
270
271
class InFlightMutexRelease {
272
private:
273
Mutex** _in_flight_mutex_addr;
274
public:
275
InFlightMutexRelease(Mutex** in_flight_mutex_addr) : _in_flight_mutex_addr(in_flight_mutex_addr) {}
276
void operator()(JavaThread* current) {
277
if (_in_flight_mutex_addr != NULL && *_in_flight_mutex_addr != NULL) {
278
(*_in_flight_mutex_addr)->release_for_safepoint();
279
*_in_flight_mutex_addr = NULL;
280
}
281
}
282
};
283
284
// Parameter in_flight_mutex_addr is only used by class Mutex to avoid certain deadlock
285
// scenarios while making transitions that might block for a safepoint or handshake.
286
// It's the address of a pointer to the mutex we are trying to acquire. This will be used to
287
// access and release said mutex when transitioning back from blocked to vm (destructor) in
288
// case we need to stop for a safepoint or handshake.
289
class ThreadBlockInVM {
290
InFlightMutexRelease _ifmr;
291
ThreadBlockInVMPreprocess<InFlightMutexRelease> _tbivmpp;
292
public:
293
ThreadBlockInVM(JavaThread* thread, Mutex** in_flight_mutex_addr = NULL)
294
: _ifmr(in_flight_mutex_addr), _tbivmpp(thread, _ifmr, /* allow_suspend= */ false) {}
295
};
296
297
// Debug class instantiated in JRT_ENTRY macro.
298
// Can be used to verify properties on enter/exit of the VM.
299
300
#ifdef ASSERT
301
class VMEntryWrapper {
302
public:
303
VMEntryWrapper();
304
~VMEntryWrapper();
305
};
306
307
308
class VMNativeEntryWrapper {
309
public:
310
VMNativeEntryWrapper();
311
~VMNativeEntryWrapper();
312
};
313
314
#endif // ASSERT
315
316
// LEAF routines do not lock, GC or throw exceptions
317
318
// On macos/aarch64 we need to maintain the W^X state of the thread. So we
319
// take WXWrite on the enter to VM from the "outside" world, so the rest of JVM
320
// code can assume writing (but not executing) codecache is always possible
321
// without preliminary actions.
322
// JavaThread state should be changed only after taking WXWrite. The state
323
// change may trigger a safepoint, that would need WXWrite to do bookkeeping
324
// in the codecache.
325
326
#define VM_LEAF_BASE(result_type, header) \
327
debug_only(NoHandleMark __hm;) \
328
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, \
329
JavaThread::current())); \
330
os::verify_stack_alignment(); \
331
/* begin of body */
332
333
#define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \
334
debug_only(ResetNoHandleMark __rnhm;) \
335
HandleMarkCleaner __hm(thread); \
336
JavaThread* THREAD = thread; /* For exception macros. */ \
337
os::verify_stack_alignment(); \
338
/* begin of body */
339
340
341
// ENTRY routines may lock, GC and throw exceptions
342
343
#define VM_ENTRY_BASE(result_type, header, thread) \
344
HandleMarkCleaner __hm(thread); \
345
JavaThread* THREAD = thread; /* For exception macros. */ \
346
os::verify_stack_alignment(); \
347
/* begin of body */
348
349
350
#define JRT_ENTRY(result_type, header) \
351
result_type header { \
352
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
353
ThreadInVMfromJava __tiv(current); \
354
VM_ENTRY_BASE(result_type, header, current) \
355
debug_only(VMEntryWrapper __vew;)
356
357
// JRT_LEAF currently can be called from either _thread_in_Java or
358
// _thread_in_native mode.
359
//
360
// JRT_LEAF rules:
361
// A JRT_LEAF method may not interfere with safepointing by
362
// 1) acquiring or blocking on a Mutex or JavaLock - checked
363
// 2) allocating heap memory - checked
364
// 3) executing a VM operation - checked
365
// 4) executing a system call (including malloc) that could block or grab a lock
366
// 5) invoking GC
367
// 6) reaching a safepoint
368
// 7) running too long
369
// Nor may any method it calls.
370
371
#define JRT_LEAF(result_type, header) \
372
result_type header { \
373
VM_LEAF_BASE(result_type, header) \
374
debug_only(NoSafepointVerifier __nsv;)
375
376
377
#define JRT_ENTRY_NO_ASYNC(result_type, header) \
378
result_type header { \
379
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
380
ThreadInVMfromJava __tiv(current, false /* check asyncs */); \
381
VM_ENTRY_BASE(result_type, header, current) \
382
debug_only(VMEntryWrapper __vew;)
383
384
// Same as JRT Entry but allows for return value after the safepoint
385
// to get back into Java from the VM
386
#define JRT_BLOCK_ENTRY(result_type, header) \
387
result_type header { \
388
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
389
HandleMarkCleaner __hm(current);
390
391
#define JRT_BLOCK \
392
{ \
393
ThreadInVMfromJava __tiv(current); \
394
JavaThread* THREAD = current; /* For exception macros. */ \
395
debug_only(VMEntryWrapper __vew;)
396
397
#define JRT_BLOCK_NO_ASYNC \
398
{ \
399
ThreadInVMfromJava __tiv(current, false /* check asyncs */); \
400
JavaThread* THREAD = current; /* For exception macros. */ \
401
debug_only(VMEntryWrapper __vew;)
402
403
#define JRT_BLOCK_END }
404
405
#define JRT_END }
406
407
// Definitions for JNI
408
409
#define JNI_ENTRY(result_type, header) \
410
JNI_ENTRY_NO_PRESERVE(result_type, header) \
411
WeakPreserveExceptionMark __wem(thread);
412
413
#define JNI_ENTRY_NO_PRESERVE(result_type, header) \
414
extern "C" { \
415
result_type JNICALL header { \
416
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
417
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
418
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
419
ThreadInVMfromNative __tiv(thread); \
420
debug_only(VMNativeEntryWrapper __vew;) \
421
VM_ENTRY_BASE(result_type, header, thread)
422
423
424
#define JNI_LEAF(result_type, header) \
425
extern "C" { \
426
result_type JNICALL header { \
427
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
428
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
429
VM_LEAF_BASE(result_type, header)
430
431
432
// Close the routine and the extern "C"
433
#define JNI_END } }
434
435
436
437
// Definitions for JVM
438
439
#define JVM_ENTRY(result_type, header) \
440
extern "C" { \
441
result_type JNICALL header { \
442
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
443
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
444
ThreadInVMfromNative __tiv(thread); \
445
debug_only(VMNativeEntryWrapper __vew;) \
446
VM_ENTRY_BASE(result_type, header, thread)
447
448
449
#define JVM_ENTRY_NO_ENV(result_type, header) \
450
extern "C" { \
451
result_type JNICALL header { \
452
JavaThread* thread = JavaThread::current(); \
453
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
454
ThreadInVMfromNative __tiv(thread); \
455
debug_only(VMNativeEntryWrapper __vew;) \
456
VM_ENTRY_BASE(result_type, header, thread)
457
458
459
#define JVM_LEAF(result_type, header) \
460
extern "C" { \
461
result_type JNICALL header { \
462
VM_Exit::block_if_vm_exited(); \
463
VM_LEAF_BASE(result_type, header)
464
465
466
#define JVM_ENTRY_FROM_LEAF(env, result_type, header) \
467
{ { \
468
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
469
ThreadInVMfromNative __tiv(thread); \
470
debug_only(VMNativeEntryWrapper __vew;) \
471
VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread)
472
473
474
#define JVM_END } }
475
476
#endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP
477
478