0
|
1 /*
|
|
2 * Copyright 1997-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 // Wrapper for all entry points to the virtual machine.
|
|
26 // The HandleMarkCleaner is a faster version of HandleMark.
|
|
27 // It relies on the fact that there is a HandleMark further
|
|
28 // down the stack (in JavaCalls::call_helper), and just resets
|
|
29 // to the saved values in that HandleMark.
|
|
30
|
|
31 class HandleMarkCleaner: public StackObj {
|
|
32 private:
|
|
33 Thread* _thread;
|
|
34 public:
|
|
35 HandleMarkCleaner(Thread* thread) {
|
|
36 _thread = thread;
|
|
37 _thread->last_handle_mark()->push();
|
|
38 }
|
|
39 ~HandleMarkCleaner() {
|
|
40 _thread->last_handle_mark()->pop_and_restore();
|
|
41 }
|
|
42
|
|
43 private:
|
|
44 inline void* operator new(size_t size, void* ptr) {
|
|
45 return ptr;
|
|
46 }
|
|
47 };
|
|
48
|
|
49 // InterfaceSupport provides functionality used by the __LEAF and __ENTRY
|
|
50 // macros. These macros are used to guard entry points into the VM and
|
|
51 // perform checks upon leave of the VM.
|
|
52
|
|
53
|
|
54 class InterfaceSupport: AllStatic {
|
|
55 # ifdef ASSERT
|
|
56 public:
|
|
57 static long _scavenge_alot_counter;
|
|
58 static long _fullgc_alot_counter;
|
|
59 static long _number_of_calls;
|
|
60 static long _fullgc_alot_invocation;
|
|
61
|
|
62 // tracing
|
|
63 static void trace(const char* result_type, const char* header);
|
|
64
|
|
65 // Helper methods used to implement +ScavengeALot and +FullGCALot
|
|
66 static void check_gc_alot() { if (ScavengeALot || FullGCALot) gc_alot(); }
|
|
67 static void gc_alot();
|
|
68
|
|
69 static void walk_stack_from(vframe* start_vf);
|
|
70 static void walk_stack();
|
|
71
|
|
72 # ifdef ENABLE_ZAP_DEAD_LOCALS
|
|
73 static void zap_dead_locals_old();
|
|
74 # endif
|
|
75
|
|
76 static void zombieAll();
|
|
77 static void deoptimizeAll();
|
|
78 static void stress_derived_pointers();
|
|
79 static void verify_stack();
|
|
80 static void verify_last_frame();
|
|
81 # endif
|
|
82
|
|
83 public:
|
|
84 // OS dependent stuff
|
|
85 #include "incls/_interfaceSupport_pd.hpp.incl"
|
|
86 };
|
|
87
|
|
88
|
|
89 // Basic class for all thread transition classes.
|
|
90
|
|
91 class ThreadStateTransition : public StackObj {
|
|
92 protected:
|
|
93 JavaThread* _thread;
|
|
94 public:
|
|
95 ThreadStateTransition(JavaThread *thread) {
|
|
96 _thread = thread;
|
|
97 assert(thread != NULL && thread->is_Java_thread(), "must be Java thread");
|
|
98 }
|
|
99
|
|
100 // Change threadstate in a manner, so safepoint can detect changes.
|
|
101 // Time-critical: called on exit from every runtime routine
|
|
102 static inline void transition(JavaThread *thread, JavaThreadState from, JavaThreadState to) {
|
|
103 assert(from != _thread_in_Java, "use transition_from_java");
|
|
104 assert(from != _thread_in_native, "use transition_from_native");
|
|
105 assert((from & 1) == 0 && (to & 1) == 0, "odd numbers are transitions states");
|
|
106 assert(thread->thread_state() == from, "coming from wrong thread state");
|
|
107 // Change to transition state (assumes total store ordering! -Urs)
|
|
108 thread->set_thread_state((JavaThreadState)(from + 1));
|
|
109
|
|
110 // Make sure new state is seen by VM thread
|
|
111 if (os::is_MP()) {
|
|
112 if (UseMembar) {
|
|
113 // Force a fence between the write above and read below
|
|
114 OrderAccess::fence();
|
|
115 } else {
|
|
116 // store to serialize page so VM thread can do pseudo remote membar
|
|
117 os::write_memory_serialize_page(thread);
|
|
118 }
|
|
119 }
|
|
120
|
|
121 if (SafepointSynchronize::do_call_back()) {
|
|
122 SafepointSynchronize::block(thread);
|
|
123 }
|
|
124 thread->set_thread_state(to);
|
|
125
|
|
126 CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
|
|
127 }
|
|
128
|
|
129 // transition_and_fence must be used on any thread state transition
|
|
130 // where there might not be a Java call stub on the stack, in
|
|
131 // particular on Windows where the Structured Exception Handler is
|
|
132 // set up in the call stub. os::write_memory_serialize_page() can
|
|
133 // fault and we can't recover from it on Windows without a SEH in
|
|
134 // place.
|
|
135 static inline void transition_and_fence(JavaThread *thread, JavaThreadState from, JavaThreadState to) {
|
|
136 assert(thread->thread_state() == from, "coming from wrong thread state");
|
|
137 assert((from & 1) == 0 && (to & 1) == 0, "odd numbers are transitions states");
|
|
138 // Change to transition state (assumes total store ordering! -Urs)
|
|
139 thread->set_thread_state((JavaThreadState)(from + 1));
|
|
140
|
|
141 // Make sure new state is seen by VM thread
|
|
142 if (os::is_MP()) {
|
|
143 if (UseMembar) {
|
|
144 // Force a fence between the write above and read below
|
|
145 OrderAccess::fence();
|
|
146 } else {
|
|
147 // Must use this rather than serialization page in particular on Windows
|
|
148 InterfaceSupport::serialize_memory(thread);
|
|
149 }
|
|
150 }
|
|
151
|
|
152 if (SafepointSynchronize::do_call_back()) {
|
|
153 SafepointSynchronize::block(thread);
|
|
154 }
|
|
155 thread->set_thread_state(to);
|
|
156
|
|
157 CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
|
|
158 }
|
|
159
|
|
160 // Same as above, but assumes from = _thread_in_Java. This is simpler, since we
|
|
161 // never block on entry to the VM. This will break the code, since e.g. preserve arguments
|
|
162 // have not been setup.
|
|
163 static inline void transition_from_java(JavaThread *thread, JavaThreadState to) {
|
|
164 assert(thread->thread_state() == _thread_in_Java, "coming from wrong thread state");
|
|
165 thread->set_thread_state(to);
|
|
166 }
|
|
167
|
|
168 static inline void transition_from_native(JavaThread *thread, JavaThreadState to) {
|
|
169 assert((to & 1) == 0, "odd numbers are transitions states");
|
|
170 assert(thread->thread_state() == _thread_in_native, "coming from wrong thread state");
|
|
171 // Change to transition state (assumes total store ordering! -Urs)
|
|
172 thread->set_thread_state(_thread_in_native_trans);
|
|
173
|
|
174 // Make sure new state is seen by GC thread
|
|
175 if (os::is_MP()) {
|
|
176 if (UseMembar) {
|
|
177 // Force a fence between the write above and read below
|
|
178 OrderAccess::fence();
|
|
179 } else {
|
|
180 // Must use this rather than serialization page in particular on Windows
|
|
181 InterfaceSupport::serialize_memory(thread);
|
|
182 }
|
|
183 }
|
|
184
|
|
185 // We never install asynchronous exceptions when coming (back) in
|
|
186 // to the runtime from native code because the runtime is not set
|
|
187 // up to handle exceptions floating around at arbitrary points.
|
|
188 if (SafepointSynchronize::do_call_back() || thread->is_suspend_after_native()) {
|
|
189 JavaThread::check_safepoint_and_suspend_for_native_trans(thread);
|
|
190
|
|
191 // Clear unhandled oops anywhere where we could block, even if we don't.
|
|
192 CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)
|
|
193 }
|
|
194
|
|
195 thread->set_thread_state(to);
|
|
196 }
|
|
197 protected:
|
|
198 void trans(JavaThreadState from, JavaThreadState to) { transition(_thread, from, to); }
|
|
199 void trans_from_java(JavaThreadState to) { transition_from_java(_thread, to); }
|
|
200 void trans_from_native(JavaThreadState to) { transition_from_native(_thread, to); }
|
|
201 void trans_and_fence(JavaThreadState from, JavaThreadState to) { transition_and_fence(_thread, from, to); }
|
|
202 };
|
|
203
|
|
204
|
|
205 class ThreadInVMfromJava : public ThreadStateTransition {
|
|
206 public:
|
|
207 ThreadInVMfromJava(JavaThread* thread) : ThreadStateTransition(thread) {
|
|
208 trans_from_java(_thread_in_vm);
|
|
209 }
|
|
210 ~ThreadInVMfromJava() {
|
|
211 trans(_thread_in_vm, _thread_in_Java);
|
|
212 // Check for pending. async. exceptions or suspends.
|
|
213 if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition();
|
|
214 }
|
|
215 };
|
|
216
|
|
217
|
|
218 class ThreadInVMfromUnknown {
|
|
219 private:
|
|
220 JavaThread* _thread;
|
|
221 public:
|
|
222 ThreadInVMfromUnknown() : _thread(NULL) {
|
|
223 Thread* t = Thread::current();
|
|
224 if (t->is_Java_thread()) {
|
|
225 JavaThread* t2 = (JavaThread*) t;
|
|
226 if (t2->thread_state() == _thread_in_native) {
|
|
227 _thread = t2;
|
|
228 ThreadStateTransition::transition_from_native(t2, _thread_in_vm);
|
|
229 // Used to have a HandleMarkCleaner but that is dangerous as
|
|
230 // it could free a handle in our (indirect, nested) caller.
|
|
231 // We expect any handles will be short lived and figure we
|
|
232 // don't need an actual HandleMark.
|
|
233 }
|
|
234 }
|
|
235 }
|
|
236 ~ThreadInVMfromUnknown() {
|
|
237 if (_thread) {
|
|
238 ThreadStateTransition::transition_and_fence(_thread, _thread_in_vm, _thread_in_native);
|
|
239 }
|
|
240 }
|
|
241 };
|
|
242
|
|
243
|
|
244 class ThreadInVMfromNative : public ThreadStateTransition {
|
|
245 public:
|
|
246 ThreadInVMfromNative(JavaThread* thread) : ThreadStateTransition(thread) {
|
|
247 trans_from_native(_thread_in_vm);
|
|
248 }
|
|
249 ~ThreadInVMfromNative() {
|
|
250 trans_and_fence(_thread_in_vm, _thread_in_native);
|
|
251 }
|
|
252 };
|
|
253
|
|
254
|
|
255 class ThreadToNativeFromVM : public ThreadStateTransition {
|
|
256 public:
|
|
257 ThreadToNativeFromVM(JavaThread *thread) : ThreadStateTransition(thread) {
|
|
258 // We are leaving the VM at this point and going directly to native code.
|
|
259 // Block, if we are in the middle of a safepoint synchronization.
|
|
260 assert(!thread->owns_locks(), "must release all locks when leaving VM");
|
|
261 thread->frame_anchor()->make_walkable(thread);
|
|
262 trans_and_fence(_thread_in_vm, _thread_in_native);
|
|
263 // Check for pending. async. exceptions or suspends.
|
|
264 if (_thread->has_special_runtime_exit_condition()) _thread->handle_special_runtime_exit_condition(false);
|
|
265 }
|
|
266
|
|
267 ~ThreadToNativeFromVM() {
|
|
268 trans_from_native(_thread_in_vm);
|
|
269 // We don't need to clear_walkable because it will happen automagically when we return to java
|
|
270 }
|
|
271 };
|
|
272
|
|
273
|
|
274 class ThreadBlockInVM : public ThreadStateTransition {
|
|
275 public:
|
|
276 ThreadBlockInVM(JavaThread *thread)
|
|
277 : ThreadStateTransition(thread) {
|
|
278 // Once we are blocked vm expects stack to be walkable
|
|
279 thread->frame_anchor()->make_walkable(thread);
|
|
280 trans_and_fence(_thread_in_vm, _thread_blocked);
|
|
281 }
|
|
282 ~ThreadBlockInVM() {
|
|
283 trans_and_fence(_thread_blocked, _thread_in_vm);
|
|
284 // We don't need to clear_walkable because it will happen automagically when we return to java
|
|
285 }
|
|
286 };
|
|
287
|
|
288
|
|
289 // This special transition class is only used to prevent asynchronous exceptions
|
|
290 // from being installed on vm exit in situations where we can't tolerate them.
|
|
291 // See bugs: 4324348, 4854693, 4998314, 5040492, 5050705.
|
|
292 class ThreadInVMfromJavaNoAsyncException : public ThreadStateTransition {
|
|
293 public:
|
|
294 ThreadInVMfromJavaNoAsyncException(JavaThread* thread) : ThreadStateTransition(thread) {
|
|
295 trans_from_java(_thread_in_vm);
|
|
296 }
|
|
297 ~ThreadInVMfromJavaNoAsyncException() {
|
|
298 trans(_thread_in_vm, _thread_in_Java);
|
|
299 // NOTE: We do not check for pending. async. exceptions.
|
|
300 // If we did and moved the pending async exception over into the
|
|
301 // pending exception field, we would need to deopt (currently C2
|
|
302 // only). However, to do so would require that we transition back
|
|
303 // to the _thread_in_vm state. Instead we postpone the handling of
|
|
304 // the async exception.
|
|
305
|
|
306 // Check for pending. suspends only.
|
|
307 if (_thread->has_special_runtime_exit_condition())
|
|
308 _thread->handle_special_runtime_exit_condition(false);
|
|
309 }
|
|
310 };
|
|
311
|
|
312 // Debug class instantiated in JRT_ENTRY and ITR_ENTRY macro.
|
|
313 // Can be used to verify properties on enter/exit of the VM.
|
|
314
|
|
315 #ifdef ASSERT
|
|
316 class VMEntryWrapper {
|
|
317 public:
|
|
318 VMEntryWrapper() {
|
|
319 if (VerifyLastFrame) {
|
|
320 InterfaceSupport::verify_last_frame();
|
|
321 }
|
|
322 }
|
|
323
|
|
324 ~VMEntryWrapper() {
|
|
325 InterfaceSupport::check_gc_alot();
|
|
326 if (WalkStackALot) {
|
|
327 InterfaceSupport::walk_stack();
|
|
328 }
|
|
329 #ifdef ENABLE_ZAP_DEAD_LOCALS
|
|
330 if (ZapDeadLocalsOld) {
|
|
331 InterfaceSupport::zap_dead_locals_old();
|
|
332 }
|
|
333 #endif
|
|
334 #ifdef COMPILER2
|
|
335 // This option is not used by Compiler 1
|
|
336 if (StressDerivedPointers) {
|
|
337 InterfaceSupport::stress_derived_pointers();
|
|
338 }
|
|
339 #endif
|
|
340 if (DeoptimizeALot || DeoptimizeRandom) {
|
|
341 InterfaceSupport::deoptimizeAll();
|
|
342 }
|
|
343 if (ZombieALot) {
|
|
344 InterfaceSupport::zombieAll();
|
|
345 }
|
|
346 // do verification AFTER potential deoptimization
|
|
347 if (VerifyStack) {
|
|
348 InterfaceSupport::verify_stack();
|
|
349 }
|
|
350
|
|
351 }
|
|
352 };
|
|
353
|
|
354
|
|
355 class VMNativeEntryWrapper {
|
|
356 public:
|
|
357 VMNativeEntryWrapper() {
|
|
358 if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
|
|
359 }
|
|
360
|
|
361 ~VMNativeEntryWrapper() {
|
|
362 if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
|
|
363 }
|
|
364 };
|
|
365
|
|
366 #endif
|
|
367
|
|
368
|
|
369 // VM-internal runtime interface support
|
|
370
|
|
371 #ifdef ASSERT
|
|
372
|
|
373 class RuntimeHistogramElement : public HistogramElement {
|
|
374 public:
|
|
375 RuntimeHistogramElement(const char* name);
|
|
376 };
|
|
377
|
|
378 #define TRACE_CALL(result_type, header) \
|
|
379 InterfaceSupport::_number_of_calls++; \
|
|
380 if (TraceRuntimeCalls) \
|
|
381 InterfaceSupport::trace(#result_type, #header); \
|
|
382 if (CountRuntimeCalls) { \
|
|
383 static RuntimeHistogramElement* e = new RuntimeHistogramElement(#header); \
|
|
384 if (e != NULL) e->increment_count(); \
|
|
385 }
|
|
386 #else
|
|
387 #define TRACE_CALL(result_type, header) \
|
|
388 /* do nothing */
|
|
389 #endif
|
|
390
|
|
391
|
|
392 // LEAF routines do not lock, GC or throw exceptions
|
|
393
|
|
394 #define __LEAF(result_type, header) \
|
|
395 TRACE_CALL(result_type, header) \
|
|
396 debug_only(NoHandleMark __hm;) \
|
|
397 /* begin of body */
|
|
398
|
|
399
|
|
400 // ENTRY routines may lock, GC and throw exceptions
|
|
401
|
|
402 #define __ENTRY(result_type, header, thread) \
|
|
403 TRACE_CALL(result_type, header) \
|
|
404 HandleMarkCleaner __hm(thread); \
|
|
405 Thread* THREAD = thread; \
|
|
406 /* begin of body */
|
|
407
|
|
408
|
|
409 // QUICK_ENTRY routines behave like ENTRY but without a handle mark
|
|
410
|
|
411 #define __QUICK_ENTRY(result_type, header, thread) \
|
|
412 TRACE_CALL(result_type, header) \
|
|
413 debug_only(NoHandleMark __hm;) \
|
|
414 Thread* THREAD = thread; \
|
|
415 /* begin of body */
|
|
416
|
|
417
|
|
418 // Definitions for IRT (Interpreter Runtime)
|
|
419 // (thread is an argument passed in to all these routines)
|
|
420
|
|
421 #define IRT_ENTRY(result_type, header) \
|
|
422 result_type header { \
|
|
423 ThreadInVMfromJava __tiv(thread); \
|
|
424 __ENTRY(result_type, header, thread) \
|
|
425 debug_only(VMEntryWrapper __vew;)
|
|
426
|
|
427
|
|
428 #define IRT_LEAF(result_type, header) \
|
|
429 result_type header { \
|
|
430 __LEAF(result_type, header) \
|
|
431 debug_only(No_Safepoint_Verifier __nspv(true);)
|
|
432
|
|
433
|
|
434 #define IRT_ENTRY_NO_ASYNC(result_type, header) \
|
|
435 result_type header { \
|
|
436 ThreadInVMfromJavaNoAsyncException __tiv(thread); \
|
|
437 __ENTRY(result_type, header, thread) \
|
|
438 debug_only(VMEntryWrapper __vew;)
|
|
439
|
|
440 // Another special case for nmethod_entry_point so the nmethod that the
|
|
441 // interpreter is about to branch to doesn't get flushed before as we
|
|
442 // branch to it's interpreter_entry_point. Skip stress testing here too.
|
|
443 // Also we don't allow async exceptions because it is just too painful.
|
|
444 #define IRT_ENTRY_FOR_NMETHOD(result_type, header) \
|
|
445 result_type header { \
|
|
446 nmethodLocker _nmlock(nm); \
|
|
447 ThreadInVMfromJavaNoAsyncException __tiv(thread); \
|
|
448 __ENTRY(result_type, header, thread)
|
|
449
|
|
450 #define IRT_END }
|
|
451
|
|
452
|
|
453 // Definitions for JRT (Java (Compiler/Shared) Runtime)
|
|
454
|
|
455 #define JRT_ENTRY(result_type, header) \
|
|
456 result_type header { \
|
|
457 ThreadInVMfromJava __tiv(thread); \
|
|
458 __ENTRY(result_type, header, thread) \
|
|
459 debug_only(VMEntryWrapper __vew;)
|
|
460
|
|
461
|
|
462 #define JRT_LEAF(result_type, header) \
|
|
463 result_type header { \
|
|
464 __LEAF(result_type, header) \
|
|
465 debug_only(JRT_Leaf_Verifier __jlv;)
|
|
466
|
|
467
|
|
468 #define JRT_ENTRY_NO_ASYNC(result_type, header) \
|
|
469 result_type header { \
|
|
470 ThreadInVMfromJavaNoAsyncException __tiv(thread); \
|
|
471 __ENTRY(result_type, header, thread) \
|
|
472 debug_only(VMEntryWrapper __vew;)
|
|
473
|
|
474 // Same as JRT Entry but allows for return value after the safepoint
|
|
475 // to get back into Java from the VM
|
|
476 #define JRT_BLOCK_ENTRY(result_type, header) \
|
|
477 result_type header { \
|
|
478 TRACE_CALL(result_type, header) \
|
|
479 HandleMarkCleaner __hm(thread);
|
|
480
|
|
481 #define JRT_BLOCK \
|
|
482 { \
|
|
483 ThreadInVMfromJava __tiv(thread); \
|
|
484 Thread* THREAD = thread; \
|
|
485 debug_only(VMEntryWrapper __vew;)
|
|
486
|
|
487 #define JRT_BLOCK_END }
|
|
488
|
|
489 #define JRT_END }
|
|
490
|
|
491 // Definitions for JNI
|
|
492
|
|
493 #define JNI_ENTRY(result_type, header) \
|
|
494 JNI_ENTRY_NO_PRESERVE(result_type, header) \
|
|
495 WeakPreserveExceptionMark __wem(thread);
|
|
496
|
|
497 #define JNI_ENTRY_NO_PRESERVE(result_type, header) \
|
|
498 extern "C" { \
|
|
499 result_type JNICALL header { \
|
|
500 JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
|
|
501 assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
|
|
502 ThreadInVMfromNative __tiv(thread); \
|
|
503 debug_only(VMNativeEntryWrapper __vew;) \
|
|
504 __ENTRY(result_type, header, thread)
|
|
505
|
|
506
|
|
507 // Ensure that the VMNativeEntryWrapper constructor, which can cause
|
|
508 // a GC, is called outside the NoHandleMark (set via __QUICK_ENTRY).
|
|
509 #define JNI_QUICK_ENTRY(result_type, header) \
|
|
510 extern "C" { \
|
|
511 result_type JNICALL header { \
|
|
512 JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
|
|
513 assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
|
|
514 ThreadInVMfromNative __tiv(thread); \
|
|
515 debug_only(VMNativeEntryWrapper __vew;) \
|
|
516 __QUICK_ENTRY(result_type, header, thread)
|
|
517
|
|
518
|
|
519 #define JNI_LEAF(result_type, header) \
|
|
520 extern "C" { \
|
|
521 result_type JNICALL header { \
|
|
522 JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
|
|
523 assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
|
|
524 __LEAF(result_type, header)
|
|
525
|
|
526
|
|
527 // Close the routine and the extern "C"
|
|
528 #define JNI_END } }
|
|
529
|
|
530
|
|
531
|
|
532 // Definitions for JVM
|
|
533
|
|
534 #define JVM_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 __ENTRY(result_type, header, thread)
|
|
541
|
|
542
|
|
543 #define JVM_ENTRY_NO_ENV(result_type, header) \
|
|
544 extern "C" { \
|
|
545 result_type JNICALL header { \
|
|
546 JavaThread* thread = (JavaThread*)ThreadLocalStorage::thread(); \
|
|
547 ThreadInVMfromNative __tiv(thread); \
|
|
548 debug_only(VMNativeEntryWrapper __vew;) \
|
|
549 __ENTRY(result_type, header, thread)
|
|
550
|
|
551
|
|
552 #define JVM_QUICK_ENTRY(result_type, header) \
|
|
553 extern "C" { \
|
|
554 result_type JNICALL header { \
|
|
555 JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
|
|
556 ThreadInVMfromNative __tiv(thread); \
|
|
557 debug_only(VMNativeEntryWrapper __vew;) \
|
|
558 __QUICK_ENTRY(result_type, header, thread)
|
|
559
|
|
560
|
|
561 #define JVM_LEAF(result_type, header) \
|
|
562 extern "C" { \
|
|
563 result_type JNICALL header { \
|
|
564 VM_Exit::block_if_vm_exited(); \
|
|
565 __LEAF(result_type, header)
|
|
566
|
|
567
|
|
568 #define JVM_END } }
|