367 // Continuation point for runtime calls returning with a pending exception. |
367 // Continuation point for runtime calls returning with a pending exception. |
368 // The pending exception check happened in the runtime or native call stub. |
368 // The pending exception check happened in the runtime or native call stub. |
369 // The pending exception in Thread is converted into a Java-level exception. |
369 // The pending exception in Thread is converted into a Java-level exception. |
370 // |
370 // |
371 // Contract with Java-level exception handlers: |
371 // Contract with Java-level exception handlers: |
372 // rax,: exception |
372 // rax: exception |
373 // rdx: throwing pc |
373 // rdx: throwing pc |
374 // |
374 // |
375 // NOTE: At entry of this stub, exception-pc must be on stack !! |
375 // NOTE: At entry of this stub, exception-pc must be on stack !! |
376 |
376 |
377 address generate_forward_exception() { |
377 address generate_forward_exception() { |
378 StubCodeMark mark(this, "StubRoutines", "forward exception"); |
378 StubCodeMark mark(this, "StubRoutines", "forward exception"); |
379 address start = __ pc(); |
379 address start = __ pc(); |
|
380 const Register thread = rcx; |
|
381 |
|
382 // other registers used in this stub |
|
383 const Register exception_oop = rax; |
|
384 const Register handler_addr = rbx; |
|
385 const Register exception_pc = rdx; |
380 |
386 |
381 // Upon entry, the sp points to the return address returning into Java |
387 // Upon entry, the sp points to the return address returning into Java |
382 // (interpreted or compiled) code; i.e., the return address becomes the |
388 // (interpreted or compiled) code; i.e., the return address becomes the |
383 // throwing pc. |
389 // throwing pc. |
384 // |
390 // |
387 // A potential result in registers can be ignored as well. |
393 // A potential result in registers can be ignored as well. |
388 |
394 |
389 #ifdef ASSERT |
395 #ifdef ASSERT |
390 // make sure this code is only executed if there is a pending exception |
396 // make sure this code is only executed if there is a pending exception |
391 { Label L; |
397 { Label L; |
392 __ get_thread(rcx); |
398 __ get_thread(thread); |
393 __ cmpptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
399 __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
394 __ jcc(Assembler::notEqual, L); |
400 __ jcc(Assembler::notEqual, L); |
395 __ stop("StubRoutines::forward exception: no pending exception (1)"); |
401 __ stop("StubRoutines::forward exception: no pending exception (1)"); |
396 __ bind(L); |
402 __ bind(L); |
397 } |
403 } |
398 #endif |
404 #endif |
399 |
405 |
400 // compute exception handler into rbx, |
406 // compute exception handler into rbx, |
401 __ movptr(rax, Address(rsp, 0)); |
407 __ get_thread(thread); |
|
408 __ movptr(exception_pc, Address(rsp, 0)); |
402 BLOCK_COMMENT("call exception_handler_for_return_address"); |
409 BLOCK_COMMENT("call exception_handler_for_return_address"); |
403 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rax); |
410 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc); |
404 __ mov(rbx, rax); |
411 __ mov(handler_addr, rax); |
405 |
412 |
406 // setup rax, & rdx, remove return address & clear pending exception |
413 // setup rax & rdx, remove return address & clear pending exception |
407 __ get_thread(rcx); |
414 __ get_thread(thread); |
408 __ pop(rdx); |
415 __ pop(exception_pc); |
409 __ movptr(rax, Address(rcx, Thread::pending_exception_offset())); |
416 __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); |
410 __ movptr(Address(rcx, Thread::pending_exception_offset()), NULL_WORD); |
417 __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); |
411 |
418 |
412 #ifdef ASSERT |
419 #ifdef ASSERT |
413 // make sure exception is set |
420 // make sure exception is set |
414 { Label L; |
421 { Label L; |
415 __ testptr(rax, rax); |
422 __ testptr(exception_oop, exception_oop); |
416 __ jcc(Assembler::notEqual, L); |
423 __ jcc(Assembler::notEqual, L); |
417 __ stop("StubRoutines::forward exception: no pending exception (2)"); |
424 __ stop("StubRoutines::forward exception: no pending exception (2)"); |
418 __ bind(L); |
425 __ bind(L); |
419 } |
426 } |
420 #endif |
427 #endif |
421 |
428 |
|
429 // Verify that there is really a valid exception in RAX. |
|
430 __ verify_oop(exception_oop); |
|
431 |
|
432 // Restore SP from BP if the exception PC is a MethodHandle call site. |
|
433 __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0); |
|
434 __ cmovptr(Assembler::notEqual, rsp, rbp); |
|
435 |
422 // continue at exception handler (return address removed) |
436 // continue at exception handler (return address removed) |
423 // rax,: exception |
437 // rax: exception |
424 // rbx,: exception handler |
438 // rbx: exception handler |
425 // rdx: throwing pc |
439 // rdx: throwing pc |
426 __ verify_oop(rax); |
440 __ jmp(handler_addr); |
427 __ jmp(rbx); |
|
428 |
441 |
429 return start; |
442 return start; |
430 } |
443 } |
431 |
444 |
432 |
445 |