| 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 | |