diff a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp
--- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp
+++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp
@@ -33,10 +33,11 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaThread.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
+#include "runtime/perfData.hpp"
 #include "runtime/safepointMechanism.inline.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/threadWXSetters.inline.hpp"
 #include "runtime/vmOperations.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -336,13 +337,76 @@
     assert(current == JavaThread::current(), "Must be");             \
     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
     JavaThread* THREAD = current; /* For exception macros. */        \
     debug_only(VMEntryWrapper __vew;)
 
-#define JRT_BLOCK_END }
+#define JRT_ENTRY_PROF(result_type, sub, name, header)               \
+  PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
+  PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
+  result_type header {                                               \
+    assert(current == JavaThread::current(), "Must be");             \
+    PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
+    ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
+    MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
+    ThreadInVMfromJava __tiv(current);                               \
+    VM_ENTRY_BASE(result_type, header, current)                      \
+    debug_only(VMEntryWrapper __vew;)
+
+#define JRT_LEAF_PROF(result_type, sub, name, header)                \
+  PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
+  PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
+  result_type header {                                               \
+    PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, \
+                                            current->do_profile_rt_call()); \
+    ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
+    VM_LEAF_BASE(result_type, header)                                \
+    debug_only(NoSafepointVerifier __nsv;)
+
+#define JRT_LEAF_PROF_NO_THREAD(result_type, sub, name, header)      \
+  PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
+  PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
+  result_type header {                                               \
+    Thread* current = Thread::current();                             \
+    PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, \
+                                            current->do_profile_rt_call()); \
+    ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
+    VM_LEAF_BASE(result_type, header)                                \
+    debug_only(NoSafepointVerifier __nsv;)
+
+#define JRT_ENTRY_NO_ASYNC_PROF(result_type, sub, name, header)      \
+  PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
+  PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
+  result_type header {                                               \
+    assert(current == JavaThread::current(), "Must be");             \
+    PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
+    ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
+    MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
+    ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
+    VM_ENTRY_BASE(result_type, header, current)                      \
+    debug_only(VMEntryWrapper __vew;)
+
+#define JRT_BLOCK_ENTRY_PROF(result_type, sub, name, header)         \
+  PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
+  PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
+  result_type header {                                               \
+    assert(current == JavaThread::current(), "Must be");             \
+    PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
+    ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
+    MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
+    HandleMarkCleaner __hm(current);
 
+#define PROF_ENTRY(result_type, sub, name, header)                   \
+  PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
+  PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
+  result_type header {                                               \
+    assert(current == JavaThread::current(), "must be");             \
+    PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
+    ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call());
+
+#define JRT_BLOCK_END }
 #define JRT_END }
+#define PROF_END }
 
 // Definitions for JNI
 //
 // As the JNIEnv can be passed from external native code we validate
 // it in debug builds, primarily for our own testing. In general JNI
@@ -404,8 +468,44 @@
   result_type JNICALL header {                                       \
     VM_Exit::block_if_vm_exited();                                   \
     VM_LEAF_BASE(result_type, header)
 
 
+#define JVM_ENTRY_PROF(result_type, name, header)                    \
+  PerfTickCounters* _perf_##name##_timer = nullptr;                  \
+  PerfCounter* _perf_##name##_count = nullptr;                       \
+extern "C" {                                                         \
+  result_type JNICALL header {                                       \
+    JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
+    PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, thread->profile_vm_calls()); \
+    MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
+    ThreadInVMfromNative __tiv(thread);                              \
+    debug_only(VMNativeEntryWrapper __vew;)                          \
+    VM_ENTRY_BASE(result_type, header, thread)
+
+
+#define JVM_ENTRY_NO_ENV_PROF(result_type, name, header)             \
+  PerfTickCounters* _perf_##name##_timer = nullptr;                  \
+  PerfCounter* _perf_##name##_count = nullptr;                       \
+extern "C" {                                                         \
+  result_type JNICALL header {                                       \
+    JavaThread* thread = JavaThread::current();                      \
+    PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, thread->profile_vm_calls()); \
+    MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
+    ThreadInVMfromNative __tiv(thread);                              \
+    debug_only(VMNativeEntryWrapper __vew;)                          \
+    VM_ENTRY_BASE(result_type, header, thread)
+
+
+#define JVM_LEAF_PROF(result_type, name, header)                     \
+  PerfTickCounters* _perf_##name##_timer = nullptr;                  \
+  PerfCounter* _perf_##name##_count = nullptr;                       \
+extern "C" {                                                         \
+  result_type JNICALL header {                                       \
+    PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, \
+                                    ProfileVMCalls && Thread::current()->profile_vm_calls()); \
+    VM_Exit::block_if_vm_exited();                                   \
+    VM_LEAF_BASE(result_type, header)
+
 #define JVM_END } }
 
 #endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP
