1 /*
  2  * Copyright (c) 1997, 2023, 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 
284 #define JRT_ENTRY(result_type, header)                               \
285   result_type header {                                               \
286     assert(current == JavaThread::current(), "Must be");             \
287     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
288     ThreadInVMfromJava __tiv(current);                               \
289     VM_ENTRY_BASE(result_type, header, current)                      \
290     debug_only(VMEntryWrapper __vew;)
291 
292 // JRT_LEAF currently can be called from either _thread_in_Java or
293 // _thread_in_native mode.
294 //
295 // JRT_LEAF rules:
296 // A JRT_LEAF method may not interfere with safepointing by
297 //   1) acquiring or blocking on a Mutex or JavaLock - checked
298 //   2) allocating heap memory - checked
299 //   3) executing a VM operation - checked
300 //   4) executing a system call (including malloc) that could block or grab a lock
301 //   5) invoking GC
302 //   6) reaching a safepoint
303 //   7) running too long
304 // Nor may any method it calls.
305 
306 #define JRT_LEAF(result_type, header)                                \
307   result_type header {                                               \
308   VM_LEAF_BASE(result_type, header)                                  \
309   debug_only(NoSafepointVerifier __nsv;)
310 
311 
312 #define JRT_ENTRY_NO_ASYNC(result_type, header)                      \
313   result_type header {                                               \
314     assert(current == JavaThread::current(), "Must be");             \
315     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
316     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
317     VM_ENTRY_BASE(result_type, header, current)                      \
318     debug_only(VMEntryWrapper __vew;)
319 
320 // Same as JRT Entry but allows for return value after the safepoint
321 // to get back into Java from the VM
322 #define JRT_BLOCK_ENTRY(result_type, header)                         \
323   result_type header {                                               \
324     assert(current == JavaThread::current(), "Must be");             \
325     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
326     HandleMarkCleaner __hm(current);
327 
328 #define JRT_BLOCK                                                    \
329     {                                                                \
330     assert(current == JavaThread::current(), "Must be");             \
331     ThreadInVMfromJava __tiv(current);                               \
332     JavaThread* THREAD = current; /* For exception macros. */        \
333     debug_only(VMEntryWrapper __vew;)
334 
335 #define JRT_BLOCK_NO_ASYNC                                           \
336     {                                                                \
337     assert(current == JavaThread::current(), "Must be");             \
338     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
339     JavaThread* THREAD = current; /* For exception macros. */        \
340     debug_only(VMEntryWrapper __vew;)
341 
342 #define JRT_ENTRY_PROF(result_type, sub, name, header)               \
343   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
344   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
345   result_type header {                                               \
346     assert(current == JavaThread::current(), "Must be");             \
347     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
348     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
349     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
350     ThreadInVMfromJava __tiv(current);                               \
351     VM_ENTRY_BASE(result_type, header, current)                      \
352     debug_only(VMEntryWrapper __vew;)
353 
354 #define JRT_LEAF_PROF(result_type, sub, name, header)                \
355   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
356   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
357   result_type header {                                               \
358     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, \
359                                             current->do_profile_rt_call()); \
360     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
361     VM_LEAF_BASE(result_type, header)                                \
362     debug_only(NoSafepointVerifier __nsv;)
363 
364 #define JRT_LEAF_PROF_NO_THREAD(result_type, sub, name, header)      \
365   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
366   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
367   result_type header {                                               \
368     Thread* current = Thread::current();                             \
369     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, \
370                                             current->do_profile_rt_call()); \
371     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
372     VM_LEAF_BASE(result_type, header)                                \
373     debug_only(NoSafepointVerifier __nsv;)
374 
375 #define JRT_ENTRY_NO_ASYNC_PROF(result_type, sub, name, header)      \
376   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
377   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
378   result_type header {                                               \
379     assert(current == JavaThread::current(), "Must be");             \
380     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
381     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
382     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
383     ThreadInVMfromJava __tiv(current, false /* check asyncs */);     \
384     VM_ENTRY_BASE(result_type, header, current)                      \
385     debug_only(VMEntryWrapper __vew;)
386 
387 #define JRT_BLOCK_ENTRY_PROF(result_type, sub, name, header)         \
388   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
389   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
390   result_type header {                                               \
391     assert(current == JavaThread::current(), "Must be");             \
392     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
393     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call()); \
394     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current));       \
395     HandleMarkCleaner __hm(current);
396 
397 #define PROF_ENTRY(result_type, sub, name, header)                   \
398   PerfTickCounters* _perf_##sub##_##name##_timer = nullptr;          \
399   PerfCounter* _perf_##sub##_##name##_count = nullptr;               \
400   result_type header {                                               \
401     assert(current == JavaThread::current(), "must be");             \
402     PerfTraceTimedEvent perf_##sub##_##name(_perf_##sub##_##name##_timer, _perf_##sub##_##name##_count, current->do_profile_rt_call()); \
403     ProfileVMCallContext pctx(current, &(perf_##sub##_##name), current->do_profile_rt_call());
404 
405 #define JRT_BLOCK_END }
406 #define JRT_END }
407 #define PROF_END }
408 
409 // Definitions for JNI
410 //
411 // As the JNIEnv can be passed from external native code we validate
412 // it in debug builds, primarily for our own testing. In general JNI
413 // does not attempt to detect programming errors and a bad JNIEnv may
414 // not even be readable.
415 
416 #define JNI_ENTRY(result_type, header)                               \
417     JNI_ENTRY_NO_PRESERVE(result_type, header)                       \
418     WeakPreserveExceptionMark __wem(thread);
419 
420 #define JNI_ENTRY_NO_PRESERVE(result_type, header)                   \
421 extern "C" {                                                         \
422   result_type JNICALL header {                                       \
423     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
424     assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \
425     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
426     ThreadInVMfromNative __tiv(thread);                              \
427     debug_only(VMNativeEntryWrapper __vew;)                          \
428     VM_ENTRY_BASE(result_type, header, thread)
429 
430 
431 #define JNI_LEAF(result_type, header)                                \
432 extern "C" {                                                         \
433   result_type JNICALL header {                                       \
434     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
435     assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \
436     VM_LEAF_BASE(result_type, header)
437 
438 
439 // Close the routine and the extern "C"
440 #define JNI_END } }
441 
442 
443 
444 // Definitions for JVM
445 
446 #define JVM_ENTRY(result_type, header)                               \
447 extern "C" {                                                         \
448   result_type JNICALL header {                                       \
449     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
450     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
451     ThreadInVMfromNative __tiv(thread);                              \
452     debug_only(VMNativeEntryWrapper __vew;)                          \
453     VM_ENTRY_BASE(result_type, header, thread)
454 
455 
456 #define JVM_ENTRY_NO_ENV(result_type, header)                        \
457 extern "C" {                                                         \
458   result_type JNICALL header {                                       \
459     JavaThread* thread = JavaThread::current();                      \
460     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
461     ThreadInVMfromNative __tiv(thread);                              \
462     debug_only(VMNativeEntryWrapper __vew;)                          \
463     VM_ENTRY_BASE(result_type, header, thread)
464 
465 
466 #define JVM_LEAF(result_type, header)                                \
467 extern "C" {                                                         \
468   result_type JNICALL header {                                       \
469     VM_Exit::block_if_vm_exited();                                   \
470     VM_LEAF_BASE(result_type, header)
471 
472 
473 #define JVM_ENTRY_PROF(result_type, name, header)                    \
474   PerfTickCounters* _perf_##name##_timer = nullptr;                  \
475   PerfCounter* _perf_##name##_count = nullptr;                       \
476 extern "C" {                                                         \
477   result_type JNICALL header {                                       \
478     JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
479     PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, thread->profile_vm_calls()); \
480     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
481     ThreadInVMfromNative __tiv(thread);                              \
482     debug_only(VMNativeEntryWrapper __vew;)                          \
483     VM_ENTRY_BASE(result_type, header, thread)
484 
485 
486 #define JVM_ENTRY_NO_ENV_PROF(result_type, name, header)             \
487   PerfTickCounters* _perf_##name##_timer = nullptr;                  \
488   PerfCounter* _perf_##name##_count = nullptr;                       \
489 extern "C" {                                                         \
490   result_type JNICALL header {                                       \
491     JavaThread* thread = JavaThread::current();                      \
492     PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, thread->profile_vm_calls()); \
493     MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));        \
494     ThreadInVMfromNative __tiv(thread);                              \
495     debug_only(VMNativeEntryWrapper __vew;)                          \
496     VM_ENTRY_BASE(result_type, header, thread)
497 
498 
499 #define JVM_LEAF_PROF(result_type, name, header)                     \
500   PerfTickCounters* _perf_##name##_timer = nullptr;                  \
501   PerfCounter* _perf_##name##_count = nullptr;                       \
502 extern "C" {                                                         \
503   result_type JNICALL header {                                       \
504     PerfTraceTimedEvent perf_##name(_perf_##name##_timer, _perf_##name##_count, \
505                                     ProfileVMCalls && Thread::current()->profile_vm_calls()); \
506     VM_Exit::block_if_vm_exited();                                   \
507     VM_LEAF_BASE(result_type, header)
508 
509 #define JVM_END } }
510 
511 #endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP