1 | /* |
2 | * Copyright (c) 1997, 2018, 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 | #include "precompiled.hpp" |
26 | #include "classfile/systemDictionary.hpp" |
27 | #include "classfile/vmSymbols.hpp" |
28 | #include "code/nmethod.hpp" |
29 | #include "compiler/compileBroker.hpp" |
30 | #include "interpreter/interpreter.hpp" |
31 | #include "interpreter/linkResolver.hpp" |
32 | #include "memory/universe.hpp" |
33 | #include "oops/method.inline.hpp" |
34 | #include "oops/oop.inline.hpp" |
35 | #include "prims/jniCheck.hpp" |
36 | #include "runtime/compilationPolicy.hpp" |
37 | #include "runtime/handles.inline.hpp" |
38 | #include "runtime/interfaceSupport.inline.hpp" |
39 | #include "runtime/javaCalls.hpp" |
40 | #include "runtime/jniHandles.inline.hpp" |
41 | #include "runtime/mutexLocker.hpp" |
42 | #include "runtime/os.inline.hpp" |
43 | #include "runtime/sharedRuntime.hpp" |
44 | #include "runtime/signature.hpp" |
45 | #include "runtime/stubRoutines.hpp" |
46 | #include "runtime/thread.inline.hpp" |
47 | |
48 | // ----------------------------------------------------- |
49 | // Implementation of JavaCallWrapper |
50 | |
51 | JavaCallWrapper::JavaCallWrapper(const methodHandle& callee_method, Handle receiver, JavaValue* result, TRAPS) { |
52 | JavaThread* thread = (JavaThread *)THREAD; |
53 | bool clear_pending_exception = true; |
54 | |
55 | guarantee(thread->is_Java_thread(), "crucial check - the VM thread cannot and must not escape to Java code" ); |
56 | assert(!thread->owns_locks(), "must release all locks when leaving VM" ); |
57 | guarantee(thread->can_call_java(), "cannot make java calls from the native compiler" ); |
58 | _result = result; |
59 | |
60 | // Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub, |
61 | // since it can potentially block. |
62 | JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread); |
63 | |
64 | // After this, we are official in JavaCode. This needs to be done before we change any of the thread local |
65 | // info, since we cannot find oops before the new information is set up completely. |
66 | ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_Java); |
67 | |
68 | // Make sure that we handle asynchronous stops and suspends _before_ we clear all thread state |
69 | // in JavaCallWrapper::JavaCallWrapper(). This way, we can decide if we need to do any pd actions |
70 | // to prepare for stop/suspend (flush register windows on sparcs, cache sp, or other state). |
71 | if (thread->has_special_runtime_exit_condition()) { |
72 | thread->handle_special_runtime_exit_condition(); |
73 | if (HAS_PENDING_EXCEPTION) { |
74 | clear_pending_exception = false; |
75 | } |
76 | } |
77 | |
78 | |
79 | // Make sure to set the oop's after the thread transition - since we can block there. No one is GC'ing |
80 | // the JavaCallWrapper before the entry frame is on the stack. |
81 | _callee_method = callee_method(); |
82 | _receiver = receiver(); |
83 | |
84 | #ifdef CHECK_UNHANDLED_OOPS |
85 | THREAD->allow_unhandled_oop(&_receiver); |
86 | #endif // CHECK_UNHANDLED_OOPS |
87 | |
88 | _thread = (JavaThread *)thread; |
89 | _handles = _thread->active_handles(); // save previous handle block & Java frame linkage |
90 | |
91 | // For the profiler, the last_Java_frame information in thread must always be in |
92 | // legal state. We have no last Java frame if last_Java_sp == NULL so |
93 | // the valid transition is to clear _last_Java_sp and then reset the rest of |
94 | // the (platform specific) state. |
95 | |
96 | _anchor.copy(_thread->frame_anchor()); |
97 | _thread->frame_anchor()->clear(); |
98 | |
99 | debug_only(_thread->inc_java_call_counter()); |
100 | _thread->set_active_handles(new_handles); // install new handle block and reset Java frame linkage |
101 | |
102 | assert (_thread->thread_state() != _thread_in_native, "cannot set native pc to NULL" ); |
103 | |
104 | // clear any pending exception in thread (native calls start with no exception pending) |
105 | if(clear_pending_exception) { |
106 | _thread->clear_pending_exception(); |
107 | } |
108 | |
109 | if (_anchor.last_Java_sp() == NULL) { |
110 | _thread->record_base_of_stack_pointer(); |
111 | } |
112 | } |
113 | |
114 | |
115 | JavaCallWrapper::~JavaCallWrapper() { |
116 | assert(_thread == JavaThread::current(), "must still be the same thread" ); |
117 | |
118 | // restore previous handle block & Java frame linkage |
119 | JNIHandleBlock *_old_handles = _thread->active_handles(); |
120 | _thread->set_active_handles(_handles); |
121 | |
122 | _thread->frame_anchor()->zap(); |
123 | |
124 | debug_only(_thread->dec_java_call_counter()); |
125 | |
126 | if (_anchor.last_Java_sp() == NULL) { |
127 | _thread->set_base_of_stack_pointer(NULL); |
128 | } |
129 | |
130 | |
131 | // Old thread-local info. has been restored. We are not back in the VM. |
132 | ThreadStateTransition::transition_from_java(_thread, _thread_in_vm); |
133 | |
134 | // State has been restored now make the anchor frame visible for the profiler. |
135 | // Do this after the transition because this allows us to put an assert |
136 | // the Java->vm transition which checks to see that stack is not walkable |
137 | // on sparc/ia64 which will catch violations of the reseting of last_Java_frame |
138 | // invariants (i.e. _flags always cleared on return to Java) |
139 | |
140 | _thread->frame_anchor()->copy(&_anchor); |
141 | |
142 | // Release handles after we are marked as being inside the VM again, since this |
143 | // operation might block |
144 | JNIHandleBlock::release_block(_old_handles, _thread); |
145 | } |
146 | |
147 | |
148 | void JavaCallWrapper::oops_do(OopClosure* f) { |
149 | f->do_oop((oop*)&_receiver); |
150 | handles()->oops_do(f); |
151 | } |
152 | |
153 | |
154 | // Helper methods |
155 | static BasicType runtime_type_from(JavaValue* result) { |
156 | switch (result->get_type()) { |
157 | case T_BOOLEAN: // fall through |
158 | case T_CHAR : // fall through |
159 | case T_SHORT : // fall through |
160 | case T_INT : // fall through |
161 | #ifndef _LP64 |
162 | case T_OBJECT : // fall through |
163 | case T_ARRAY : // fall through |
164 | #endif |
165 | case T_BYTE : // fall through |
166 | case T_VOID : return T_INT; |
167 | case T_LONG : return T_LONG; |
168 | case T_FLOAT : return T_FLOAT; |
169 | case T_DOUBLE : return T_DOUBLE; |
170 | #ifdef _LP64 |
171 | case T_ARRAY : // fall through |
172 | case T_OBJECT: return T_OBJECT; |
173 | #endif |
174 | default: |
175 | ShouldNotReachHere(); |
176 | return T_ILLEGAL; |
177 | } |
178 | } |
179 | |
180 | // ============ Virtual calls ============ |
181 | |
182 | void JavaCalls::call_virtual(JavaValue* result, Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { |
183 | CallInfo callinfo; |
184 | Handle receiver = args->receiver(); |
185 | Klass* recvrKlass = receiver.is_null() ? (Klass*)NULL : receiver->klass(); |
186 | LinkInfo link_info(spec_klass, name, signature); |
187 | LinkResolver::resolve_virtual_call( |
188 | callinfo, receiver, recvrKlass, link_info, true, CHECK); |
189 | methodHandle method = callinfo.selected_method(); |
190 | assert(method.not_null(), "should have thrown exception" ); |
191 | |
192 | // Invoke the method |
193 | JavaCalls::call(result, method, args, CHECK); |
194 | } |
195 | |
196 | |
197 | void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, TRAPS) { |
198 | JavaCallArguments args(receiver); |
199 | call_virtual(result, spec_klass, name, signature, &args, CHECK); |
200 | } |
201 | |
202 | |
203 | void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { |
204 | JavaCallArguments args(receiver); |
205 | args.push_oop(arg1); |
206 | call_virtual(result, spec_klass, name, signature, &args, CHECK); |
207 | } |
208 | |
209 | |
210 | |
211 | void JavaCalls::call_virtual(JavaValue* result, Handle receiver, Klass* spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { |
212 | JavaCallArguments args(receiver); |
213 | args.push_oop(arg1); |
214 | args.push_oop(arg2); |
215 | call_virtual(result, spec_klass, name, signature, &args, CHECK); |
216 | } |
217 | |
218 | |
219 | // ============ Special calls ============ |
220 | |
221 | void JavaCalls::call_special(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { |
222 | CallInfo callinfo; |
223 | LinkInfo link_info(klass, name, signature); |
224 | LinkResolver::resolve_special_call(callinfo, args->receiver(), link_info, CHECK); |
225 | methodHandle method = callinfo.selected_method(); |
226 | assert(method.not_null(), "should have thrown exception" ); |
227 | |
228 | // Invoke the method |
229 | JavaCalls::call(result, method, args, CHECK); |
230 | } |
231 | |
232 | |
233 | void JavaCalls::call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, TRAPS) { |
234 | JavaCallArguments args(receiver); |
235 | call_special(result, klass, name, signature, &args, CHECK); |
236 | } |
237 | |
238 | |
239 | void JavaCalls::call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { |
240 | JavaCallArguments args(receiver); |
241 | args.push_oop(arg1); |
242 | call_special(result, klass, name, signature, &args, CHECK); |
243 | } |
244 | |
245 | |
246 | void JavaCalls::call_special(JavaValue* result, Handle receiver, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { |
247 | JavaCallArguments args(receiver); |
248 | args.push_oop(arg1); |
249 | args.push_oop(arg2); |
250 | call_special(result, klass, name, signature, &args, CHECK); |
251 | } |
252 | |
253 | |
254 | // ============ Static calls ============ |
255 | |
256 | void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { |
257 | CallInfo callinfo; |
258 | LinkInfo link_info(klass, name, signature); |
259 | LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK); |
260 | methodHandle method = callinfo.selected_method(); |
261 | assert(method.not_null(), "should have thrown exception" ); |
262 | |
263 | // Invoke the method |
264 | JavaCalls::call(result, method, args, CHECK); |
265 | } |
266 | |
267 | |
268 | void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, TRAPS) { |
269 | JavaCallArguments args; |
270 | call_static(result, klass, name, signature, &args, CHECK); |
271 | } |
272 | |
273 | |
274 | void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) { |
275 | JavaCallArguments args(arg1); |
276 | call_static(result, klass, name, signature, &args, CHECK); |
277 | } |
278 | |
279 | |
280 | void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) { |
281 | JavaCallArguments args; |
282 | args.push_oop(arg1); |
283 | args.push_oop(arg2); |
284 | call_static(result, klass, name, signature, &args, CHECK); |
285 | } |
286 | |
287 | |
288 | void JavaCalls::call_static(JavaValue* result, Klass* klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS) { |
289 | JavaCallArguments args; |
290 | args.push_oop(arg1); |
291 | args.push_oop(arg2); |
292 | args.push_oop(arg3); |
293 | call_static(result, klass, name, signature, &args, CHECK); |
294 | } |
295 | |
296 | // ============ allocate and initialize new object instance ============ |
297 | |
298 | Handle JavaCalls::construct_new_instance(InstanceKlass* klass, Symbol* constructor_signature, JavaCallArguments* args, TRAPS) { |
299 | klass->initialize(CHECK_NH); // Quick no-op if already initialized. |
300 | Handle obj = klass->allocate_instance_handle(CHECK_NH); |
301 | JavaValue void_result(T_VOID); |
302 | args->set_receiver(obj); // inserts <obj> as the first argument. |
303 | JavaCalls::call_special(&void_result, klass, |
304 | vmSymbols::object_initializer_name(), |
305 | constructor_signature, args, CHECK_NH); |
306 | // Already returned a Null Handle if any exception is pending. |
307 | return obj; |
308 | } |
309 | |
310 | Handle JavaCalls::construct_new_instance(InstanceKlass* klass, Symbol* constructor_signature, TRAPS) { |
311 | JavaCallArguments args; |
312 | return JavaCalls::construct_new_instance(klass, constructor_signature, &args, THREAD); |
313 | } |
314 | |
315 | Handle JavaCalls::construct_new_instance(InstanceKlass* klass, Symbol* constructor_signature, Handle arg1, TRAPS) { |
316 | JavaCallArguments args; |
317 | args.push_oop(arg1); |
318 | return JavaCalls::construct_new_instance(klass, constructor_signature, &args, THREAD); |
319 | } |
320 | |
321 | Handle JavaCalls::construct_new_instance(InstanceKlass* klass, Symbol* constructor_signature, Handle arg1, Handle arg2, TRAPS) { |
322 | JavaCallArguments args; |
323 | args.push_oop(arg1); |
324 | args.push_oop(arg2); |
325 | return JavaCalls::construct_new_instance(klass, constructor_signature, &args, THREAD); |
326 | } |
327 | |
328 | // ------------------------------------------------- |
329 | // Implementation of JavaCalls (low level) |
330 | |
331 | |
332 | void JavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { |
333 | // Check if we need to wrap a potential OS exception handler around thread |
334 | // This is used for e.g. Win32 structured exception handlers |
335 | assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls" ); |
336 | // Need to wrap each and every time, since there might be native code down the |
337 | // stack that has installed its own exception handlers |
338 | os::os_exception_wrapper(call_helper, result, method, args, THREAD); |
339 | } |
340 | |
341 | void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) { |
342 | |
343 | JavaThread* thread = (JavaThread*)THREAD; |
344 | assert(thread->is_Java_thread(), "must be called by a java thread" ); |
345 | assert(method.not_null(), "must have a method to call" ); |
346 | assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation" ); |
347 | assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here" ); |
348 | |
349 | |
350 | CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();) |
351 | |
352 | #if INCLUDE_JVMCI |
353 | // Gets the nmethod (if any) that should be called instead of normal target |
354 | nmethod* alternative_target = args->alternative_target(); |
355 | if (alternative_target == NULL) { |
356 | #endif |
357 | // Verify the arguments |
358 | |
359 | if (CheckJNICalls) { |
360 | args->verify(method, result->get_type()); |
361 | } |
362 | else debug_only(args->verify(method, result->get_type())); |
363 | #if INCLUDE_JVMCI |
364 | } |
365 | #else |
366 | |
367 | // Ignore call if method is empty |
368 | if (method->is_empty_method()) { |
369 | assert(result->get_type() == T_VOID, "an empty method must return a void value" ); |
370 | return; |
371 | } |
372 | #endif |
373 | |
374 | #ifdef ASSERT |
375 | { InstanceKlass* holder = method->method_holder(); |
376 | // A klass might not be initialized since JavaCall's might be used during the executing of |
377 | // the <clinit>. For example, a Thread.start might start executing on an object that is |
378 | // not fully initialized! (bad Java programming style) |
379 | assert(holder->is_linked(), "rewriting must have taken place" ); |
380 | } |
381 | #endif |
382 | |
383 | CompilationPolicy::compile_if_required(method, CHECK); |
384 | |
385 | // Since the call stub sets up like the interpreter we call the from_interpreted_entry |
386 | // so we can go compiled via a i2c. Otherwise initial entry method will always |
387 | // run interpreted. |
388 | address entry_point = method->from_interpreted_entry(); |
389 | if (JvmtiExport::can_post_interpreter_events() && thread->is_interp_only_mode()) { |
390 | entry_point = method->interpreter_entry(); |
391 | } |
392 | |
393 | // Figure out if the result value is an oop or not (Note: This is a different value |
394 | // than result_type. result_type will be T_INT of oops. (it is about size) |
395 | BasicType result_type = runtime_type_from(result); |
396 | bool oop_result_flag = (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY); |
397 | |
398 | // NOTE: if we move the computation of the result_val_address inside |
399 | // the call to call_stub, the optimizer produces wrong code. |
400 | intptr_t* result_val_address = (intptr_t*)(result->get_value_addr()); |
401 | |
402 | // Find receiver |
403 | Handle receiver = (!method->is_static()) ? args->receiver() : Handle(); |
404 | |
405 | // When we reenter Java, we need to reenable the reserved/yellow zone which |
406 | // might already be disabled when we are in VM. |
407 | if (!thread->stack_guards_enabled()) { |
408 | thread->reguard_stack(); |
409 | } |
410 | |
411 | // Check that there are shadow pages available before changing thread state |
412 | // to Java. Calculate current_stack_pointer here to make sure |
413 | // stack_shadow_pages_available() and bang_stack_shadow_pages() use the same sp. |
414 | address sp = os::current_stack_pointer(); |
415 | if (!os::stack_shadow_pages_available(THREAD, method, sp)) { |
416 | // Throw stack overflow exception with preinitialized exception. |
417 | Exceptions::throw_stack_overflow_exception(THREAD, __FILE__, __LINE__, method); |
418 | return; |
419 | } else { |
420 | // Touch pages checked if the OS needs them to be touched to be mapped. |
421 | os::map_stack_shadow_pages(sp); |
422 | } |
423 | |
424 | #if INCLUDE_JVMCI |
425 | if (alternative_target != NULL) { |
426 | if (alternative_target->is_alive() && !alternative_target->is_unloading()) { |
427 | thread->set_jvmci_alternate_call_target(alternative_target->verified_entry_point()); |
428 | entry_point = method->adapter()->get_i2c_entry(); |
429 | } else { |
430 | THROW(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException()); |
431 | } |
432 | } |
433 | #endif |
434 | |
435 | // do call |
436 | { JavaCallWrapper link(method, receiver, result, CHECK); |
437 | { HandleMark hm(thread); // HandleMark used by HandleMarkCleaner |
438 | |
439 | StubRoutines::call_stub()( |
440 | (address)&link, |
441 | // (intptr_t*)&(result->_value), // see NOTE above (compiler problem) |
442 | result_val_address, // see NOTE above (compiler problem) |
443 | result_type, |
444 | method(), |
445 | entry_point, |
446 | args->parameters(), |
447 | args->size_of_parameters(), |
448 | CHECK |
449 | ); |
450 | |
451 | result = link.result(); // circumvent MS C++ 5.0 compiler bug (result is clobbered across call) |
452 | // Preserve oop return value across possible gc points |
453 | if (oop_result_flag) { |
454 | thread->set_vm_result((oop) result->get_jobject()); |
455 | } |
456 | } |
457 | } // Exit JavaCallWrapper (can block - potential return oop must be preserved) |
458 | |
459 | // Check if a thread stop or suspend should be executed |
460 | // The following assert was not realistic. Thread.stop can set that bit at any moment. |
461 | //assert(!thread->has_special_runtime_exit_condition(), "no async. exceptions should be installed"); |
462 | |
463 | // Restore possible oop return |
464 | if (oop_result_flag) { |
465 | result->set_jobject((jobject)thread->vm_result()); |
466 | thread->set_vm_result(NULL); |
467 | } |
468 | } |
469 | |
470 | |
471 | //-------------------------------------------------------------------------------------- |
472 | // Implementation of JavaCallArguments |
473 | |
474 | inline bool is_value_state_indirect_oop(uint state) { |
475 | assert(state != JavaCallArguments::value_state_oop, |
476 | "Checking for handles after removal" ); |
477 | assert(state < JavaCallArguments::value_state_limit, |
478 | "Invalid value state %u" , state); |
479 | return state != JavaCallArguments::value_state_primitive; |
480 | } |
481 | |
482 | inline oop resolve_indirect_oop(intptr_t value, uint state) { |
483 | switch (state) { |
484 | case JavaCallArguments::value_state_handle: |
485 | { |
486 | oop* ptr = reinterpret_cast<oop*>(value); |
487 | return Handle::raw_resolve(ptr); |
488 | } |
489 | |
490 | case JavaCallArguments::value_state_jobject: |
491 | { |
492 | jobject obj = reinterpret_cast<jobject>(value); |
493 | return JNIHandles::resolve(obj); |
494 | } |
495 | |
496 | default: |
497 | ShouldNotReachHere(); |
498 | return NULL; |
499 | } |
500 | } |
501 | |
502 | intptr_t* JavaCallArguments::parameters() { |
503 | // First convert all handles to oops |
504 | for(int i = 0; i < _size; i++) { |
505 | uint state = _value_state[i]; |
506 | assert(state != value_state_oop, "Multiple handle conversions" ); |
507 | if (is_value_state_indirect_oop(state)) { |
508 | oop obj = resolve_indirect_oop(_value[i], state); |
509 | _value[i] = cast_from_oop<intptr_t>(obj); |
510 | _value_state[i] = value_state_oop; |
511 | } |
512 | } |
513 | // Return argument vector |
514 | return _value; |
515 | } |
516 | |
517 | |
518 | class SignatureChekker : public SignatureIterator { |
519 | private: |
520 | int _pos; |
521 | BasicType _return_type; |
522 | u_char* _value_state; |
523 | intptr_t* _value; |
524 | |
525 | public: |
526 | bool _is_return; |
527 | |
528 | SignatureChekker(Symbol* signature, |
529 | BasicType return_type, |
530 | bool is_static, |
531 | u_char* value_state, |
532 | intptr_t* value) : |
533 | SignatureIterator(signature), |
534 | _pos(0), |
535 | _return_type(return_type), |
536 | _value_state(value_state), |
537 | _value(value), |
538 | _is_return(false) |
539 | { |
540 | if (!is_static) { |
541 | check_value(true); // Receiver must be an oop |
542 | } |
543 | } |
544 | |
545 | void check_value(bool type) { |
546 | uint state = _value_state[_pos++]; |
547 | if (type) { |
548 | guarantee(is_value_state_indirect_oop(state), |
549 | "signature does not match pushed arguments: %u at %d" , |
550 | state, _pos - 1); |
551 | } else { |
552 | guarantee(state == JavaCallArguments::value_state_primitive, |
553 | "signature does not match pushed arguments: %u at %d" , |
554 | state, _pos - 1); |
555 | } |
556 | } |
557 | |
558 | void check_doing_return(bool state) { _is_return = state; } |
559 | |
560 | void check_return_type(BasicType t) { |
561 | guarantee(_is_return && t == _return_type, "return type does not match" ); |
562 | } |
563 | |
564 | void check_int(BasicType t) { |
565 | if (_is_return) { |
566 | check_return_type(t); |
567 | return; |
568 | } |
569 | check_value(false); |
570 | } |
571 | |
572 | void check_double(BasicType t) { check_long(t); } |
573 | |
574 | void check_long(BasicType t) { |
575 | if (_is_return) { |
576 | check_return_type(t); |
577 | return; |
578 | } |
579 | |
580 | check_value(false); |
581 | check_value(false); |
582 | } |
583 | |
584 | void check_obj(BasicType t) { |
585 | if (_is_return) { |
586 | check_return_type(t); |
587 | return; |
588 | } |
589 | |
590 | intptr_t v = _value[_pos]; |
591 | if (v != 0) { |
592 | // v is a "handle" referring to an oop, cast to integral type. |
593 | // There shouldn't be any handles in very low memory. |
594 | guarantee((size_t)v >= (size_t)os::vm_page_size(), |
595 | "Bad JNI oop argument %d: " PTR_FORMAT, _pos, v); |
596 | // Verify the pointee. |
597 | oop vv = resolve_indirect_oop(v, _value_state[_pos]); |
598 | guarantee(oopDesc::is_oop_or_null(vv, true), |
599 | "Bad JNI oop argument %d: " PTR_FORMAT " -> " PTR_FORMAT, |
600 | _pos, v, p2i(vv)); |
601 | } |
602 | |
603 | check_value(true); // Verify value state. |
604 | } |
605 | |
606 | void do_bool() { check_int(T_BOOLEAN); } |
607 | void do_char() { check_int(T_CHAR); } |
608 | void do_float() { check_int(T_FLOAT); } |
609 | void do_double() { check_double(T_DOUBLE); } |
610 | void do_byte() { check_int(T_BYTE); } |
611 | void do_short() { check_int(T_SHORT); } |
612 | void do_int() { check_int(T_INT); } |
613 | void do_long() { check_long(T_LONG); } |
614 | void do_void() { check_return_type(T_VOID); } |
615 | void do_object(int begin, int end) { check_obj(T_OBJECT); } |
616 | void do_array(int begin, int end) { check_obj(T_OBJECT); } |
617 | }; |
618 | |
619 | |
620 | void JavaCallArguments::verify(const methodHandle& method, BasicType return_type) { |
621 | guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed" ); |
622 | |
623 | // Treat T_OBJECT and T_ARRAY as the same |
624 | if (return_type == T_ARRAY) return_type = T_OBJECT; |
625 | |
626 | // Check that oop information is correct |
627 | Symbol* signature = method->signature(); |
628 | |
629 | SignatureChekker sc(signature, |
630 | return_type, |
631 | method->is_static(), |
632 | _value_state, |
633 | _value); |
634 | sc.iterate_parameters(); |
635 | sc.check_doing_return(true); |
636 | sc.iterate_returntype(); |
637 | } |
638 | |