1 /*
  2  * Copyright (c) 1997, 2025, 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/globals.hpp"
 33 #include "runtime/handles.inline.hpp"
 34 #include "runtime/javaThread.inline.hpp"
 35 #include "runtime/mutexLocker.hpp"
 36 #include "runtime/orderAccess.hpp"
 37 #include "runtime/os.hpp"
 38 #include "runtime/perfData.hpp"
 39 #include "runtime/safepointMechanism.inline.hpp"
 40 #include "runtime/safepointVerifiers.hpp"
 41 #include "runtime/threadWXSetters.inline.hpp"
 42 #include "runtime/vmOperations.hpp"
 43 #include "utilities/globalDefinitions.hpp"
 44 #include "utilities/macros.hpp"
 45 #include "utilities/preserveException.hpp"
 46 
 47 // Wrapper for all entry points to the virtual machine.
 48 
 49 // InterfaceSupport provides functionality used by the VM_LEAF_BASE and
 50 // VM_ENTRY_BASE macros. These macros are used to guard entry points into
 51 // the VM and perform checks upon leave of the VM.
 52 
 53 
 54 class InterfaceSupport: AllStatic {
 55 # ifdef ASSERT
 56  public:
 57   static unsigned int _scavenge_alot_counter;
 58   static unsigned int _fullgc_alot_counter;
 59   static intx _fullgc_alot_invocation;
 60 
 61   // Helper methods used to implement +ScavengeALot and +FullGCALot
 62   static void check_gc_alot() { if (ScavengeALot || FullGCALot) gc_alot(); }
 63   static void gc_alot();
 64 
 65   static void walk_stack_from(vframe* start_vf);
 66   static void walk_stack();
 67 
 68   static void zombieAll();
 69   static void deoptimizeAll();
 70   static void verify_stack();
 71   static void verify_last_frame();
 72 # endif
 73 };
 74 
 75 
 76 // Basic class for all thread transition classes.
 77 
 78 class ThreadStateTransition : public StackObj {
 79  protected:
 80   JavaThread* _thread;
 81 
 82  public:
 83   ThreadStateTransition(JavaThread *thread) : _thread(thread) {
 84     assert(thread != nullptr, "must be active Java thread");
 85     assert(thread == Thread::current(), "must be current thread");
 86   }
 87 
 88   static inline void transition_from_java(JavaThread *thread, JavaThreadState to) {
 89     assert(thread->thread_state() == _thread_in_Java, "coming from wrong thread state");
 90     assert(to == _thread_in_vm || to == _thread_in_native, "invalid transition");
 91     thread->set_thread_state(to);
 92   }
 93 
 94   // We never install asynchronous exceptions when coming (back) in to the runtime
 95   // from native code because the runtime is not set up to handle exceptions floating
 96   // around at arbitrary points.
 97   static inline void transition_from_native(JavaThread *thread, JavaThreadState to, bool check_asyncs = true) {
 98     assert(thread->thread_state() == _thread_in_native, "coming from wrong thread state");
 99     assert(to == _thread_in_vm || to == _thread_in_Java, "invalid transition");
100     assert(!thread->has_last_Java_frame() || thread->frame_anchor()->walkable(), "Unwalkable stack in native transition");
101 
102     if (!UseSystemMemoryBarrier) {
103       thread->set_thread_state_fence(_thread_in_vm);
104     } else {
105       thread->set_thread_state(_thread_in_vm);
106     }
107     SafepointMechanism::process_if_requested_with_exit_check(thread, to != _thread_in_Java ? false : check_asyncs);
108     thread->set_thread_state(to);
109   }
110 
111   static inline void transition_from_vm(JavaThread *thread, JavaThreadState to, bool check_asyncs = true) {
112     assert(thread->thread_state() == _thread_in_vm, "coming from wrong thread state");
113     if (to == _thread_in_Java) {
114       SafepointMechanism::process_if_requested_with_exit_check(thread, check_asyncs);
115       thread->set_thread_state(to);
116     } else {
117       assert(to == _thread_in_native || to == _thread_blocked, "invalid transition");
118       // Check NoSafepointVerifier. This also clears unhandled oops if CheckUnhandledOops is used.
119       thread->check_possible_safepoint();
120 
121       // Once we are in native/blocked vm expects stack to be walkable
122       thread->frame_anchor()->make_walkable();
123       OrderAccess::storestore(); // Keep thread_state change and make_walkable() separate.
124       thread->set_thread_state(to);
125     }
126   }
127 };
128 
129 class ThreadInVMfromJava : public ThreadStateTransition {
130   bool _check_asyncs;
131  public:
132   ThreadInVMfromJava(JavaThread* thread, bool check_asyncs = true) : ThreadStateTransition(thread), _check_asyncs(check_asyncs) {
133     transition_from_java(thread, _thread_in_vm);
134   }
135   ~ThreadInVMfromJava()  {
136     if (_thread->stack_overflow_state()->stack_yellow_reserved_zone_disabled()) {
137       _thread->stack_overflow_state()->enable_stack_yellow_reserved_zone();
138     }
139     // We prevent asynchronous exceptions from being installed on return to Java in situations
140     // where we can't tolerate them. See bugs: 4324348, 4854693, 4998314, 5040492, 5050705.
141     transition_from_vm(_thread, _thread_in_Java, _check_asyncs);
142   }
143 };
144 
145 
146 class ThreadInVMfromUnknown {
147   JavaThread* _thread;
148  public:
149   ThreadInVMfromUnknown() : _thread(nullptr) {
150     Thread* t = Thread::current();
151     if (t->is_Java_thread()) {
152       JavaThread* t2 = JavaThread::cast(t);
153       if (t2->thread_state() == _thread_in_native) {
154         _thread = t2;
155         ThreadStateTransition::transition_from_native(t2, _thread_in_vm);
156         // Used to have a HandleMarkCleaner but that is dangerous as
157         // it could free a handle in our (indirect, nested) caller.
158         // We expect any handles will be short lived and figure we
159         // don't need an actual HandleMark.
160       }
161     }
162   }
163   ~ThreadInVMfromUnknown()  {
164     if (_thread) {
165       ThreadStateTransition::transition_from_vm(_thread, _thread_in_native);
166     }
167   }
168 };
169 
170 
171 class ThreadInVMfromNative : public ThreadStateTransition {
172   ResetNoHandleMark __rnhm;
173  public:
174   ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) {
175     transition_from_native(thread, _thread_in_vm);
176   }
177   ~ThreadInVMfromNative() {
178     // We cannot assert !_thread->owns_locks() since we have valid cases where
179     // we call known native code using this wrapper holding locks.
180     transition_from_vm(_thread, _thread_in_native);
181   }
182 };
183 
184 
185 class ThreadToNativeFromVM : public ThreadStateTransition {
186  public:
187   ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) {
188     assert(!thread->owns_locks(), "must release all locks when leaving VM");
189     transition_from_vm(thread, _thread_in_native);
190   }
191   ~ThreadToNativeFromVM() {
192     transition_from_native(_thread, _thread_in_vm);
193     assert(!_thread->is_pending_jni_exception_check(), "Pending JNI Exception Check");
194     // We don't need to clear_walkable because it will happen automagically when we return to java
195   }
196 };
197 
198 // Perform a transition to _thread_blocked and take a call-back to be executed before
199 // SafepointMechanism::process_if_requested when returning to the VM. This allows us
200 // to perform an "undo" action if we might block processing a safepoint/handshake operation
201 // (such as thread suspension).
202 template <typename PRE_PROC = void(JavaThread*)>
203 class ThreadBlockInVMPreprocess : public ThreadStateTransition {
204  private:
205   PRE_PROC& _pr;
206   bool _allow_suspend;
207  public:
208   ThreadBlockInVMPreprocess(JavaThread* thread, PRE_PROC& pr, bool allow_suspend = false)
209     : ThreadStateTransition(thread), _pr(pr), _allow_suspend(allow_suspend) {
210     transition_from_vm(thread, _thread_blocked);
211   }
212   ~ThreadBlockInVMPreprocess() {
213     assert(_thread->thread_state() == _thread_blocked, "coming from wrong thread state");
214     // Change back to _thread_in_vm and ensure it is seen by the VM thread.
215     _thread->set_thread_state_fence(_thread_in_vm);
216 
217     if (SafepointMechanism::should_process(_thread, _allow_suspend)) {
218       _pr(_thread);
219       SafepointMechanism::process_if_requested(_thread, _allow_suspend, false /* check_async_exception */);
220     }
221   }
222 };
223 
224 class ThreadBlockInVM  : public ThreadBlockInVMPreprocess<> {
225  public:
226   ThreadBlockInVM(JavaThread* thread, bool allow_suspend = false)
227     : ThreadBlockInVMPreprocess(thread, emptyOp, allow_suspend) {}
228  private:
229   static void emptyOp(JavaThread* current) {}
230 };
231 
232 
233 // Debug class instantiated in JRT_ENTRY macro.
234 // Can be used to verify properties on enter/exit of the VM.
235 
236 #ifdef ASSERT
237 class VMEntryWrapper {
238  public:
239   VMEntryWrapper();
240   ~VMEntryWrapper();
241 };
242 
243 
244 class VMNativeEntryWrapper {
245  public:
246   VMNativeEntryWrapper();
247   ~VMNativeEntryWrapper();
248 };
249 
250 #endif // ASSERT
251 
252 // LEAF routines do not lock, GC or throw exceptions
253 
254 // On macos/aarch64 we need to maintain the W^X state of the thread.  So we
255 // take WXWrite on the enter to VM from the "outside" world, so the rest of JVM
256 // code can assume writing (but not executing) codecache is always possible
257 // without preliminary actions.
258 // JavaThread state should be changed only after taking WXWrite. The state
259 // change may trigger a safepoint, that would need WXWrite to do bookkeeping
260 // in the codecache.
261 
262 #define VM_LEAF_BASE(result_type, header)                            \
263   DEBUG_ONLY(NoHandleMark __hm;)                                     \
264   os::verify_stack_alignment();                                      \
265   /* begin of body */
266 
267 #define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread)         \
268   DEBUG_ONLY(ResetNoHandleMark __rnhm;)                              \
269   HandleMarkCleaner __hm(thread);                                    \
270   JavaThread* THREAD = thread; /* For exception macros. */           \
271   os::verify_stack_alignment();                                      \
272   /* begin of body */
273 
274 
275 // ENTRY routines may lock, GC and throw exceptions
276 
277 #define VM_ENTRY_BASE(result_type, header, thread)                   \
278   HandleMarkCleaner __hm(thread);                                    \
279   JavaThread* THREAD = thread; /* For exception macros. */           \
280   os::verify_stack_alignment();                                      \
281   /* begin of body */
282 
283 #define JRT_ENTRY(result_type, header)                               \
284   result_type header {                                               \
285     assert(current == JavaThread::current(), "Must be");             \
286     ThreadInVMfromJava __tiv(current);                               \
287     MACOS_AARCH64_ONLY(                                              \
288       static WXMode wx_mode = DefaultWXWriteMode;                    \
289       ThreadWXEnable __wx(&wx_mode, current);                        \
290     )                                                                \
291     VM_ENTRY_BASE(result_type, header, current)                      \
292     DEBUG_ONLY(VMEntryWrapper __vew;)
293 
294 // JRT_LEAF currently can be called from either _thread_in_Java or
295 // _thread_in_native mode.
296 //
297 // JRT_LEAF rules:
298 // A JRT_LEAF method may not interfere with safepointing by
299 //   1) acquiring or blocking on a Mutex or JavaLock - checked
300 //   2) allocating heap memory - checked
301 //   3) executing a VM operation - checked
302 //   4) executing a system call (including malloc) that could block or grab a lock
303 //   5) invoking GC
304 //   6) reaching a safepoint
305 //   7) running too long
306 // Nor may any method it calls.
307 
308 #define JRT_LEAF(result_type, header)                                \
309   result_type header {                                               \
310   VM_LEAF_BASE(result_type, header)                                  \
311   DEBUG_ONLY(NoSafepointVerifier __nsv;)
312 
313 
314 #define JRT_ENTRY_NO_ASYNC(result_type, header)                      \
315   result_type header {                                               \
316     assert(current == JavaThread::current(), "Must be");             \
317     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
318     MACOS_AARCH64_ONLY(                                              \
319       static WXMode wx_mode = DefaultWXWriteMode;                    \
320       ThreadWXEnable __wx(&wx_mode, current);                        \
321     )                                                                \
322     VM_ENTRY_BASE(result_type, header, current)                      \
323     DEBUG_ONLY(VMEntryWrapper __vew;)
324 
325 // Same as JRT Entry but allows for return value after the safepoint
326 // to get back into Java from the VM
327 #define JRT_BLOCK_ENTRY(result_type, header)                         \
328   result_type header {                                               \
329     assert(current == JavaThread::current(), "Must be");             \
330     MACOS_AARCH64_ONLY(                                              \
331       static WXMode wx_mode = DefaultWXWriteMode;                    \
332       ThreadWXEnable __wx(&wx_mode, current);                        \
333     )                                                                \
334     HandleMarkCleaner __hm(current);
335 
336 #define JRT_BLOCK                                                    \
337     {                                                                \
338     assert(current == JavaThread::current(), "Must be");             \
339     ThreadInVMfromJava __tiv(current);                               \
340     JavaThread* THREAD = current; /* For exception macros. */        \
341     DEBUG_ONLY(VMEntryWrapper __vew;)
342 
343 #define JRT_BLOCK_NO_ASYNC                                           \
344     {                                                                \
345     assert(current == JavaThread::current(), "Must be");             \
346     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
347     JavaThread* THREAD = current; /* For exception macros. */        \
348     DEBUG_ONLY(VMEntryWrapper __vew;)
349 
350 #define JRT_ENTRY_PROF(result_type, sub, name, header)               \
351   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
352   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
353   result_type header {                                               \
354     assert(current == JavaThread::current(), "Must be");             \
355     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
356     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
357     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
358     ThreadInVMfromJava __tiv(current);                               \
359     VM_ENTRY_BASE(result_type, header, current)                      \
360     DEBUG_ONLY(VMEntryWrapper __vew;)
361 
362 #define JRT_LEAF_PROF(result_type, sub, name, header)                \
363   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
364   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
365   result_type header {                                               \
366     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, \
367                                             current->do_profile_rt_call()); \
368     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
369     VM_LEAF_BASE(result_type, header)                                \
370     DEBUG_ONLY(NoSafepointVerifier __nsv;)
371 
372 #define JRT_LEAF_PROF_NO_THREAD(result_type, sub, name, header)      \
373   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
374   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
375   result_type header {                                               \
376     Thread* current = Thread::current();                             \
377     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, \
378                                             current->do_profile_rt_call()); \
379     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
380     VM_LEAF_BASE(result_type, header)                                \
381     DEBUG_ONLY(NoSafepointVerifier __nsv;)
382 
383 #define JRT_ENTRY_NO_ASYNC_PROF(result_type, sub, name, header)      \
384   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
385   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
386   result_type header {                                               \
387     assert(current == JavaThread::current(), "Must be");             \
388     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
389     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
390     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
391     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
392     VM_ENTRY_BASE(result_type, header, current)                      \
393     DEBUG_ONLY(VMEntryWrapper __vew;)
394 
395 #define JRT_BLOCK_ENTRY_PROF(result_type, sub, name, header)         \
396   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
397   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
398   result_type header {                                               \
399     assert(current == JavaThread::current(), "Must be");             \
400     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
401     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
402     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
403     HandleMarkCleaner __hm(current);
404 
405 #define PROF_ENTRY(result_type, sub, name, header)                   \
406   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
407   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
408   result_type header {                                               \
409     assert(current == JavaThread::current(), "must be");             \
410     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
411     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call());
412 
413 #define JRT_BLOCK_END }
414 #define JRT_END }
415 #define PROF_END }
416 
417 // Definitions for JNI
418 //
419 // As the JNIEnv can be passed from external native code we validate
420 // it in debug builds, primarily for our own testing. In general JNI
421 // does not attempt to detect programming errors and a bad JNIEnv may
422 // not even be readable.
423 
424 #define JNI_ENTRY(result_type, header)                               \
425     JNI_ENTRY_NO_PRESERVE(result_type, header)                       \
426     WeakPreserveExceptionMark __wem(thread);
427 
428 #define JNI_ENTRY_NO_PRESERVE(result_type, header)                   \
429 extern "C" {                                                         \
430   result_type JNICALL header {                                       \
431     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
432     assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \
433     ThreadInVMfromNative __tiv(thread);                              \
434     MACOS_AARCH64_ONLY(                                              \
435       static WXMode wx_mode = DefaultWXWriteMode;                    \
436       ThreadWXEnable __wx(&wx_mode, thread);                         \
437     )                                                                \
438     DEBUG_ONLY(VMNativeEntryWrapper __vew;)                          \
439     VM_ENTRY_BASE(result_type, header, thread)
440 
441 
442 #define JNI_LEAF(result_type, header)                                \
443 extern "C" {                                                         \
444   result_type JNICALL header {                                       \
445     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
446     assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \
447     VM_LEAF_BASE(result_type, header)
448 
449 
450 // Close the routine and the extern "C"
451 #define JNI_END } }
452 
453 
454 
455 // Definitions for JVM
456 
457 #define JVM_ENTRY(result_type, header)                               \
458 extern "C" {                                                         \
459   result_type JNICALL header {                                       \
460     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
461     ThreadInVMfromNative __tiv(thread);                              \
462     MACOS_AARCH64_ONLY(                                              \
463       static WXMode wx_mode = DefaultWXWriteMode;                    \
464       ThreadWXEnable __wx(&wx_mode, thread);                         \
465     )                                                                \
466     DEBUG_ONLY(VMNativeEntryWrapper __vew;)                          \
467     VM_ENTRY_BASE(result_type, header, thread)
468 
469 
470 #define JVM_ENTRY_NO_ENV(result_type, header)                        \
471 extern "C" {                                                         \
472   result_type JNICALL header {                                       \
473     JavaThread* thread = JavaThread::current();                      \
474     ThreadInVMfromNative __tiv(thread);                              \
475     MACOS_AARCH64_ONLY(                                              \
476       static WXMode wx_mode = DefaultWXWriteMode;                    \
477       ThreadWXEnable __wx(&wx_mode, thread);                         \
478     )                                                                \
479     DEBUG_ONLY(VMNativeEntryWrapper __vew;)                          \
480     VM_ENTRY_BASE(result_type, header, thread)
481 
482 
483 #define JVM_LEAF(result_type, header)                                \
484 extern "C" {                                                         \
485   result_type JNICALL header {                                       \
486     VM_Exit::block_if_vm_exited();                                   \
487     VM_LEAF_BASE(result_type, header)
488 
489 
490 #define JVM_ENTRY_PROF(result_type, name, header)                    \
491   PerfTickCounters* _perf_##name##_timer = nullptr;                  \
492   PerfCounter* _perf_##name##_count = nullptr;                       \
493 extern "C" {                                                         \
494   result_type JNICALL header {                                       \
495     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
496     PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, thread->profile_vm_calls()); \
497     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
498     ThreadInVMfromNative __tiv(thread);                              \
499     DEBUG_ONLY(VMNativeEntryWrapper __vew;)                          \
500     VM_ENTRY_BASE(result_type, header, thread)
501 
502 
503 #define JVM_ENTRY_NO_ENV_PROF(result_type, name, header)             \
504   PerfTickCounters* _perf_##name##_timer = nullptr;                  \
505   PerfCounter* _perf_##name##_count = nullptr;                       \
506 extern "C" {                                                         \
507   result_type JNICALL header {                                       \
508     JavaThread* thread = JavaThread::current();                      \
509     PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, thread->profile_vm_calls()); \
510     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
511     ThreadInVMfromNative __tiv(thread);                              \
512     DEBUG_ONLY(VMNativeEntryWrapper __vew;)                          \
513     VM_ENTRY_BASE(result_type, header, thread)
514 
515 
516 #define JVM_LEAF_PROF(result_type, name, header)                     \
517   PerfTickCounters* _perf_##name##_timer = nullptr;                  \
518   PerfCounter* _perf_##name##_count = nullptr;                       \
519 extern "C" {                                                         \
520   result_type JNICALL header {                                       \
521     PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, \
522                                     ProfileVMCalls && Thread::current()->profile_vm_calls()); \
523     VM_Exit::block_if_vm_exited();                                   \
524     VM_LEAF_BASE(result_type, header)
525 
526 #define JVM_END } }
527 
528 #endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP