1 | /* |
2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP |
26 | #define SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP |
27 | |
28 | #include "runtime/handles.inline.hpp" |
29 | #include "runtime/mutexLocker.hpp" |
30 | #include "runtime/orderAccess.hpp" |
31 | #include "runtime/os.hpp" |
32 | #include "runtime/safepointMechanism.inline.hpp" |
33 | #include "runtime/safepointVerifiers.hpp" |
34 | #include "runtime/thread.hpp" |
35 | #include "runtime/vmOperations.hpp" |
36 | #include "utilities/globalDefinitions.hpp" |
37 | #include "utilities/histogram.hpp" |
38 | #include "utilities/macros.hpp" |
39 | #include "utilities/preserveException.hpp" |
40 | |
41 | // Wrapper for all entry points to the virtual machine. |
42 | |
43 | // InterfaceSupport provides functionality used by the VM_LEAF_BASE and |
44 | // VM_ENTRY_BASE macros. These macros are used to guard entry points into |
45 | // the VM and perform checks upon leave of the VM. |
46 | |
47 | |
48 | class InterfaceSupport: AllStatic { |
49 | # ifdef ASSERT |
50 | public: |
51 | static long _scavenge_alot_counter; |
52 | static long _fullgc_alot_counter; |
53 | static long _number_of_calls; |
54 | static long _fullgc_alot_invocation; |
55 | |
56 | // Helper methods used to implement +ScavengeALot and +FullGCALot |
57 | static void check_gc_alot() { if (ScavengeALot || FullGCALot) gc_alot(); } |
58 | static void gc_alot(); |
59 | |
60 | static void walk_stack_from(vframe* start_vf); |
61 | static void walk_stack(); |
62 | |
63 | static void zombieAll(); |
64 | static void deoptimizeAll(); |
65 | static void stress_derived_pointers(); |
66 | static void verify_stack(); |
67 | static void verify_last_frame(); |
68 | # endif |
69 | }; |
70 | |
71 | |
72 | // Basic class for all thread transition classes. |
73 | |
74 | class ThreadStateTransition : public StackObj { |
75 | protected: |
76 | JavaThread* _thread; |
77 | public: |
78 | ThreadStateTransition(JavaThread *thread) { |
79 | _thread = thread; |
80 | assert(thread != NULL && thread->is_Java_thread(), "must be Java thread" ); |
81 | } |
82 | |
83 | // Change threadstate in a manner, so safepoint can detect changes. |
84 | // Time-critical: called on exit from every runtime routine |
85 | static inline void transition(JavaThread *thread, JavaThreadState from, JavaThreadState to) { |
86 | assert(from != _thread_in_Java, "use transition_from_java" ); |
87 | assert(from != _thread_in_native, "use transition_from_native" ); |
88 | assert((from & 1) == 0 && (to & 1) == 0, "odd numbers are transitions states" ); |
89 | assert(thread->thread_state() == from, "coming from wrong thread state" ); |
90 | // Change to transition state and ensure it is seen by the VM thread. |
91 | thread->set_thread_state_fence((JavaThreadState)(from + 1)); |
92 | |
93 | SafepointMechanism::block_if_requested(thread); |
94 | thread->set_thread_state(to); |
95 | |
96 | CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();) |
97 | } |
98 | |
99 | // Same as above, but assumes from = _thread_in_Java. This is simpler, since we |
100 | // never block on entry to the VM. This will break the code, since e.g. preserve arguments |
101 | // have not been setup. |
102 | static inline void transition_from_java(JavaThread *thread, JavaThreadState to) { |
103 | assert(thread->thread_state() == _thread_in_Java, "coming from wrong thread state" ); |
104 | thread->set_thread_state(to); |
105 | } |
106 | |
107 | static inline void transition_from_native(JavaThread *thread, JavaThreadState to) { |
108 | assert((to & 1) == 0, "odd numbers are transitions states" ); |
109 | assert(thread->thread_state() == _thread_in_native, "coming from wrong thread state" ); |
110 | // Change to transition state and ensure it is seen by the VM thread. |
111 | thread->set_thread_state_fence(_thread_in_native_trans); |
112 | |
113 | // We never install asynchronous exceptions when coming (back) in |
114 | // to the runtime from native code because the runtime is not set |
115 | // up to handle exceptions floating around at arbitrary points. |
116 | if (SafepointMechanism::should_block(thread) || thread->is_suspend_after_native()) { |
117 | JavaThread::check_safepoint_and_suspend_for_native_trans(thread); |
118 | } |
119 | |
120 | thread->set_thread_state(to); |
121 | } |
122 | protected: |
123 | void trans(JavaThreadState from, JavaThreadState to) { transition(_thread, from, to); } |
124 | void trans_from_java(JavaThreadState to) { transition_from_java(_thread, to); } |
125 | void trans_from_native(JavaThreadState to) { transition_from_native(_thread, to); } |
126 | }; |
127 | |
128 | class ThreadInVMForHandshake : public ThreadStateTransition { |
129 | const JavaThreadState _original_state; |
130 | |
131 | void transition_back() { |
132 | // This can be invoked from transition states and must return to the original state properly |
133 | assert(_thread->thread_state() == _thread_in_vm, "should only call when leaving VM after handshake" ); |
134 | // Change to transition state and ensure it is seen by the VM thread. |
135 | _thread->set_thread_state_fence(_thread_in_vm_trans); |
136 | |
137 | SafepointMechanism::block_if_requested(_thread); |
138 | |
139 | _thread->set_thread_state(_original_state); |
140 | |
141 | if (_original_state != _thread_blocked_trans && _original_state != _thread_in_vm_trans && |
142 | _thread->has_special_runtime_exit_condition()) { |
143 | _thread->handle_special_runtime_exit_condition( |
144 | !_thread->is_at_poll_safepoint() && (_original_state != _thread_in_native_trans)); |
145 | } |
146 | } |
147 | |
148 | public: |
149 | |
150 | ThreadInVMForHandshake(JavaThread* thread) : ThreadStateTransition(thread), |
151 | _original_state(thread->thread_state()) { |
152 | |
153 | if (thread->has_last_Java_frame()) { |
154 | thread->frame_anchor()->make_walkable(thread); |
155 | } |
156 | |
157 | thread->set_thread_state(_thread_in_vm); |
158 | } |
159 | |
160 | ~ThreadInVMForHandshake() { |
161 | transition_back(); |
162 | } |
163 | |
164 | }; |
165 | |
166 | class ThreadInVMfromJava : public ThreadStateTransition { |
167 | public: |
168 | ThreadInVMfromJava(JavaThread* thread) : ThreadStateTransition(thread) { |
169 | trans_from_java(_thread_in_vm); |
170 | } |
171 | ~ThreadInVMfromJava() { |
172 | if (_thread->stack_yellow_reserved_zone_disabled()) { |
173 | _thread->enable_stack_yellow_reserved_zone(); |
174 | } |
175 | trans(_thread_in_vm, _thread_in_Java); |
176 | // Check for pending. async. exceptions or suspends. |
177 | if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(); |
178 | } |
179 | }; |
180 | |
181 | |
182 | class ThreadInVMfromUnknown { |
183 | JavaThread* _thread; |
184 | public: |
185 | ThreadInVMfromUnknown() : _thread(NULL) { |
186 | Thread* t = Thread::current(); |
187 | if (t->is_Java_thread()) { |
188 | JavaThread* t2 = (JavaThread*) t; |
189 | if (t2->thread_state() == _thread_in_native) { |
190 | _thread = t2; |
191 | ThreadStateTransition::transition_from_native(t2, _thread_in_vm); |
192 | // Used to have a HandleMarkCleaner but that is dangerous as |
193 | // it could free a handle in our (indirect, nested) caller. |
194 | // We expect any handles will be short lived and figure we |
195 | // don't need an actual HandleMark. |
196 | } |
197 | } |
198 | } |
199 | ~ThreadInVMfromUnknown() { |
200 | if (_thread) { |
201 | ThreadStateTransition::transition(_thread, _thread_in_vm, _thread_in_native); |
202 | } |
203 | } |
204 | }; |
205 | |
206 | |
207 | class ThreadInVMfromNative : public ThreadStateTransition { |
208 | public: |
209 | ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) { |
210 | trans_from_native(_thread_in_vm); |
211 | } |
212 | ~ThreadInVMfromNative() { |
213 | trans(_thread_in_vm, _thread_in_native); |
214 | } |
215 | }; |
216 | |
217 | |
218 | class ThreadToNativeFromVM : public ThreadStateTransition { |
219 | public: |
220 | ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) { |
221 | // We are leaving the VM at this point and going directly to native code. |
222 | // Block, if we are in the middle of a safepoint synchronization. |
223 | assert(!thread->owns_locks(), "must release all locks when leaving VM" ); |
224 | thread->frame_anchor()->make_walkable(thread); |
225 | trans(_thread_in_vm, _thread_in_native); |
226 | // Check for pending. async. exceptions or suspends. |
227 | if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(false); |
228 | } |
229 | |
230 | ~ThreadToNativeFromVM() { |
231 | trans_from_native(_thread_in_vm); |
232 | assert(!_thread->is_pending_jni_exception_check(), "Pending JNI Exception Check" ); |
233 | // We don't need to clear_walkable because it will happen automagically when we return to java |
234 | } |
235 | }; |
236 | |
237 | |
238 | class ThreadBlockInVM : public ThreadStateTransition { |
239 | public: |
240 | ThreadBlockInVM(JavaThread *thread) |
241 | : ThreadStateTransition(thread) { |
242 | // Once we are blocked vm expects stack to be walkable |
243 | thread->frame_anchor()->make_walkable(thread); |
244 | trans(_thread_in_vm, _thread_blocked); |
245 | } |
246 | ~ThreadBlockInVM() { |
247 | trans(_thread_blocked, _thread_in_vm); |
248 | OrderAccess::cross_modify_fence(); |
249 | // We don't need to clear_walkable because it will happen automagically when we return to java |
250 | } |
251 | }; |
252 | |
253 | // Unlike ThreadBlockInVM, this class is designed to avoid certain deadlock scenarios while making |
254 | // transitions inside class Monitor in cases where we need to block for a safepoint or handshake. It |
255 | // receives an extra argument compared to ThreadBlockInVM, the address of a pointer to the monitor we |
256 | // are trying to acquire. This will be used to access and release the monitor if needed to avoid |
257 | // said deadlocks. |
258 | // It works like ThreadBlockInVM but differs from it in two ways: |
259 | // - When transitioning in (constructor), it checks for safepoints without blocking, i.e., calls |
260 | // back if needed to allow a pending safepoint to continue but does not block in it. |
261 | // - When transitioning back (destructor), if there is a pending safepoint or handshake it releases |
262 | // the monitor that is only partially acquired. |
263 | class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition { |
264 | private: |
265 | Monitor** _in_flight_monitor_adr; |
266 | |
267 | void release_monitor() { |
268 | assert(_in_flight_monitor_adr != NULL, "_in_flight_monitor_adr should have been set on constructor" ); |
269 | Monitor* in_flight_monitor = *_in_flight_monitor_adr; |
270 | if (in_flight_monitor != NULL) { |
271 | in_flight_monitor->release_for_safepoint(); |
272 | *_in_flight_monitor_adr = NULL; |
273 | } |
274 | } |
275 | public: |
276 | ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Monitor** in_flight_monitor_adr) |
277 | : ThreadStateTransition(thread), _in_flight_monitor_adr(in_flight_monitor_adr) { |
278 | // Once we are blocked vm expects stack to be walkable |
279 | thread->frame_anchor()->make_walkable(thread); |
280 | |
281 | // All unsafe states are treated the same by the VMThread |
282 | // so we can skip the _thread_in_vm_trans state here. Since |
283 | // we don't read poll, it's enough to order the stores. |
284 | OrderAccess::storestore(); |
285 | |
286 | thread->set_thread_state(_thread_blocked); |
287 | } |
288 | ~ThreadBlockInVMWithDeadlockCheck() { |
289 | // Change to transition state and ensure it is seen by the VM thread. |
290 | _thread->set_thread_state_fence((JavaThreadState)(_thread_blocked_trans)); |
291 | |
292 | if (SafepointMechanism::should_block(_thread)) { |
293 | release_monitor(); |
294 | SafepointMechanism::block_if_requested(_thread); |
295 | } |
296 | |
297 | _thread->set_thread_state(_thread_in_vm); |
298 | OrderAccess::cross_modify_fence(); |
299 | } |
300 | }; |
301 | |
302 | |
303 | // This special transition class is only used to prevent asynchronous exceptions |
304 | // from being installed on vm exit in situations where we can't tolerate them. |
305 | // See bugs: 4324348, 4854693, 4998314, 5040492, 5050705. |
306 | class ThreadInVMfromJavaNoAsyncException : public ThreadStateTransition { |
307 | public: |
308 | ThreadInVMfromJavaNoAsyncException(JavaThread* thread) : ThreadStateTransition(thread) { |
309 | trans_from_java(_thread_in_vm); |
310 | } |
311 | ~ThreadInVMfromJavaNoAsyncException() { |
312 | if (_thread->stack_yellow_reserved_zone_disabled()) { |
313 | _thread->enable_stack_yellow_reserved_zone(); |
314 | } |
315 | trans(_thread_in_vm, _thread_in_Java); |
316 | // NOTE: We do not check for pending. async. exceptions. |
317 | // If we did and moved the pending async exception over into the |
318 | // pending exception field, we would need to deopt (currently C2 |
319 | // only). However, to do so would require that we transition back |
320 | // to the _thread_in_vm state. Instead we postpone the handling of |
321 | // the async exception. |
322 | |
323 | |
324 | // Check for pending. suspends only. |
325 | if (_thread->has_special_runtime_exit_condition()) |
326 | _thread->handle_special_runtime_exit_condition(false); |
327 | } |
328 | }; |
329 | |
330 | // Debug class instantiated in JRT_ENTRY and ITR_ENTRY macro. |
331 | // Can be used to verify properties on enter/exit of the VM. |
332 | |
333 | #ifdef ASSERT |
334 | class VMEntryWrapper { |
335 | public: |
336 | VMEntryWrapper(); |
337 | ~VMEntryWrapper(); |
338 | }; |
339 | |
340 | |
341 | class VMNativeEntryWrapper { |
342 | public: |
343 | VMNativeEntryWrapper() { |
344 | if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); |
345 | } |
346 | |
347 | ~VMNativeEntryWrapper() { |
348 | if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); |
349 | } |
350 | }; |
351 | |
352 | #endif |
353 | |
354 | |
355 | // VM-internal runtime interface support |
356 | |
357 | // Definitions for JRT (Java (Compiler/Shared) Runtime) |
358 | |
359 | // JRT_LEAF currently can be called from either _thread_in_Java or |
360 | // _thread_in_native mode. In _thread_in_native, it is ok |
361 | // for another thread to trigger GC. The rest of the JRT_LEAF |
362 | // rules apply. |
363 | class JRTLeafVerifier : public NoSafepointVerifier { |
364 | static bool should_verify_GC(); |
365 | public: |
366 | #ifdef ASSERT |
367 | JRTLeafVerifier(); |
368 | ~JRTLeafVerifier(); |
369 | #else |
370 | JRTLeafVerifier() {} |
371 | ~JRTLeafVerifier() {} |
372 | #endif |
373 | }; |
374 | |
375 | #ifdef ASSERT |
376 | |
377 | class RuntimeHistogramElement : public HistogramElement { |
378 | public: |
379 | RuntimeHistogramElement(const char* name); |
380 | }; |
381 | |
382 | #define TRACE_CALL(result_type, header) \ |
383 | InterfaceSupport::_number_of_calls++; \ |
384 | if (CountRuntimeCalls) { \ |
385 | static RuntimeHistogramElement* e = new RuntimeHistogramElement(#header); \ |
386 | if (e != NULL) e->increment_count(); \ |
387 | } |
388 | #else |
389 | #define TRACE_CALL(result_type, header) \ |
390 | /* do nothing */ |
391 | #endif |
392 | |
393 | |
394 | // LEAF routines do not lock, GC or throw exceptions |
395 | |
396 | #define VM_LEAF_BASE(result_type, header) \ |
397 | TRACE_CALL(result_type, header) \ |
398 | debug_only(NoHandleMark __hm;) \ |
399 | os::verify_stack_alignment(); \ |
400 | /* begin of body */ |
401 | |
402 | #define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \ |
403 | TRACE_CALL(result_type, header) \ |
404 | debug_only(ResetNoHandleMark __rnhm;) \ |
405 | HandleMarkCleaner __hm(thread); \ |
406 | Thread* THREAD = thread; \ |
407 | os::verify_stack_alignment(); \ |
408 | /* begin of body */ |
409 | |
410 | |
411 | // ENTRY routines may lock, GC and throw exceptions |
412 | |
413 | #define VM_ENTRY_BASE(result_type, header, thread) \ |
414 | TRACE_CALL(result_type, header) \ |
415 | HandleMarkCleaner __hm(thread); \ |
416 | Thread* THREAD = thread; \ |
417 | os::verify_stack_alignment(); \ |
418 | /* begin of body */ |
419 | |
420 | |
421 | // QUICK_ENTRY routines behave like ENTRY but without a handle mark |
422 | |
423 | #define VM_QUICK_ENTRY_BASE(result_type, header, thread) \ |
424 | TRACE_CALL(result_type, header) \ |
425 | debug_only(NoHandleMark __hm;) \ |
426 | Thread* THREAD = thread; \ |
427 | os::verify_stack_alignment(); \ |
428 | /* begin of body */ |
429 | |
430 | |
431 | #define JRT_ENTRY(result_type, header) \ |
432 | result_type header { \ |
433 | ThreadInVMfromJava __tiv(thread); \ |
434 | VM_ENTRY_BASE(result_type, header, thread) \ |
435 | debug_only(VMEntryWrapper __vew;) |
436 | |
437 | |
438 | #define JRT_LEAF(result_type, header) \ |
439 | result_type header { \ |
440 | VM_LEAF_BASE(result_type, header) \ |
441 | debug_only(JRTLeafVerifier __jlv;) |
442 | |
443 | |
444 | #define JRT_ENTRY_NO_ASYNC(result_type, header) \ |
445 | result_type header { \ |
446 | ThreadInVMfromJavaNoAsyncException __tiv(thread); \ |
447 | VM_ENTRY_BASE(result_type, header, thread) \ |
448 | debug_only(VMEntryWrapper __vew;) |
449 | |
450 | // Same as JRT Entry but allows for return value after the safepoint |
451 | // to get back into Java from the VM |
452 | #define JRT_BLOCK_ENTRY(result_type, header) \ |
453 | result_type header { \ |
454 | TRACE_CALL(result_type, header) \ |
455 | HandleMarkCleaner __hm(thread); |
456 | |
457 | #define JRT_BLOCK \ |
458 | { \ |
459 | ThreadInVMfromJava __tiv(thread); \ |
460 | Thread* THREAD = thread; \ |
461 | debug_only(VMEntryWrapper __vew;) |
462 | |
463 | #define JRT_BLOCK_NO_ASYNC \ |
464 | { \ |
465 | ThreadInVMfromJavaNoAsyncException __tiv(thread); \ |
466 | Thread* THREAD = thread; \ |
467 | debug_only(VMEntryWrapper __vew;) |
468 | |
469 | #define JRT_BLOCK_END } |
470 | |
471 | #define JRT_END } |
472 | |
473 | // Definitions for JNI |
474 | |
475 | #define JNI_ENTRY(result_type, header) \ |
476 | JNI_ENTRY_NO_PRESERVE(result_type, header) \ |
477 | WeakPreserveExceptionMark __wem(thread); |
478 | |
479 | #define JNI_ENTRY_NO_PRESERVE(result_type, header) \ |
480 | extern "C" { \ |
481 | result_type JNICALL header { \ |
482 | JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ |
483 | assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ |
484 | ThreadInVMfromNative __tiv(thread); \ |
485 | debug_only(VMNativeEntryWrapper __vew;) \ |
486 | VM_ENTRY_BASE(result_type, header, thread) |
487 | |
488 | |
489 | // Ensure that the VMNativeEntryWrapper constructor, which can cause |
490 | // a GC, is called outside the NoHandleMark (set via VM_QUICK_ENTRY_BASE). |
491 | #define JNI_QUICK_ENTRY(result_type, header) \ |
492 | extern "C" { \ |
493 | result_type JNICALL header { \ |
494 | JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ |
495 | assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ |
496 | ThreadInVMfromNative __tiv(thread); \ |
497 | debug_only(VMNativeEntryWrapper __vew;) \ |
498 | VM_QUICK_ENTRY_BASE(result_type, header, thread) |
499 | |
500 | |
501 | #define JNI_LEAF(result_type, header) \ |
502 | extern "C" { \ |
503 | result_type JNICALL header { \ |
504 | JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ |
505 | assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ |
506 | VM_LEAF_BASE(result_type, header) |
507 | |
508 | |
509 | // Close the routine and the extern "C" |
510 | #define JNI_END } } |
511 | |
512 | |
513 | |
514 | // Definitions for JVM |
515 | |
516 | #define JVM_ENTRY(result_type, header) \ |
517 | extern "C" { \ |
518 | result_type JNICALL header { \ |
519 | JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ |
520 | ThreadInVMfromNative __tiv(thread); \ |
521 | debug_only(VMNativeEntryWrapper __vew;) \ |
522 | VM_ENTRY_BASE(result_type, header, thread) |
523 | |
524 | |
525 | #define JVM_ENTRY_NO_ENV(result_type, header) \ |
526 | extern "C" { \ |
527 | result_type JNICALL header { \ |
528 | JavaThread* thread = JavaThread::current(); \ |
529 | ThreadInVMfromNative __tiv(thread); \ |
530 | debug_only(VMNativeEntryWrapper __vew;) \ |
531 | VM_ENTRY_BASE(result_type, header, thread) |
532 | |
533 | |
534 | #define JVM_QUICK_ENTRY(result_type, header) \ |
535 | extern "C" { \ |
536 | result_type JNICALL header { \ |
537 | JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ |
538 | ThreadInVMfromNative __tiv(thread); \ |
539 | debug_only(VMNativeEntryWrapper __vew;) \ |
540 | VM_QUICK_ENTRY_BASE(result_type, header, thread) |
541 | |
542 | |
543 | #define JVM_LEAF(result_type, header) \ |
544 | extern "C" { \ |
545 | result_type JNICALL header { \ |
546 | VM_Exit::block_if_vm_exited(); \ |
547 | VM_LEAF_BASE(result_type, header) |
548 | |
549 | |
550 | #define JVM_ENTRY_FROM_LEAF(env, result_type, header) \ |
551 | { { \ |
552 | JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ |
553 | ThreadInVMfromNative __tiv(thread); \ |
554 | debug_only(VMNativeEntryWrapper __vew;) \ |
555 | VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) |
556 | |
557 | |
558 | #define JVM_END } } |
559 | |
560 | #endif // SHARE_RUNTIME_INTERFACESUPPORT_INLINE_HPP |
561 | |