471 __ stop("StubRoutines::forward exception: no pending exception (1)");
472 __ bind(L);
473 }
474 #endif
475
476 // compute exception handler into r19
477
478 // call the VM to find the handler address associated with the
479 // caller address. pass thread in r0 and caller pc (ret address)
480 // in r1. n.b. the caller pc is in lr, unlike x86 where it is on
481 // the stack.
482 __ mov(c_rarg1, lr);
483 // lr will be trashed by the VM call so we move it to R19
484 // (callee-saved) because we also need to pass it to the handler
485 // returned by this call.
486 __ mov(r19, lr);
487 BLOCK_COMMENT("call exception_handler_for_return_address");
488 __ call_VM_leaf(CAST_FROM_FN_PTR(address,
489 SharedRuntime::exception_handler_for_return_address),
490 rthread, c_rarg1);
491 // we should not really care that lr is no longer the callee
492 // address. we saved the value the handler needs in r19 so we can
493 // just copy it to r3. however, the C2 handler will push its own
494 // frame and then calls into the VM and the VM code asserts that
495 // the PC for the frame above the handler belongs to a compiled
496 // Java method. So, we restore lr here to satisfy that assert.
497 __ mov(lr, r19);
498 // setup r0 & r3 & clear pending exception
499 __ mov(r3, r19);
500 __ mov(r19, r0);
501 __ ldr(r0, Address(rthread, Thread::pending_exception_offset()));
502 __ str(zr, Address(rthread, Thread::pending_exception_offset()));
503
504 #ifdef ASSERT
505 // make sure exception is set
506 {
507 Label L;
508 __ cbnz(r0, L);
509 __ stop("StubRoutines::forward exception: no pending exception (2)");
510 __ bind(L);
5000 // Call runtime
5001 if (arg1 != noreg) {
5002 assert(arg2 != c_rarg1, "clobbered");
5003 __ mov(c_rarg1, arg1);
5004 }
5005 if (arg2 != noreg) {
5006 __ mov(c_rarg2, arg2);
5007 }
5008 __ mov(c_rarg0, rthread);
5009 BLOCK_COMMENT("call runtime_entry");
5010 __ mov(rscratch1, runtime_entry);
5011 __ blr(rscratch1);
5012
5013 // Generate oop map
5014 OopMap* map = new OopMap(framesize, 0);
5015
5016 oop_maps->add_gc_map(the_pc - start, map);
5017
5018 __ reset_last_Java_frame(true);
5019 __ maybe_isb();
5020
5021 __ leave();
5022
5023 // check for pending exceptions
5024 #ifdef ASSERT
5025 Label L;
5026 __ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset()));
5027 __ cbnz(rscratch1, L);
5028 __ should_not_reach_here();
5029 __ bind(L);
5030 #endif // ASSERT
5031 __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
5032
5033
5034 // codeBlob framesize is in words (not VMRegImpl::slot_size)
5035 RuntimeStub* stub =
5036 RuntimeStub::new_runtime_stub(name,
5037 &code,
5038 frame_complete,
5039 (framesize >> (LogBytesPerWord - LogBytesPerInt)),
|
471 __ stop("StubRoutines::forward exception: no pending exception (1)");
472 __ bind(L);
473 }
474 #endif
475
476 // compute exception handler into r19
477
478 // call the VM to find the handler address associated with the
479 // caller address. pass thread in r0 and caller pc (ret address)
480 // in r1. n.b. the caller pc is in lr, unlike x86 where it is on
481 // the stack.
482 __ mov(c_rarg1, lr);
483 // lr will be trashed by the VM call so we move it to R19
484 // (callee-saved) because we also need to pass it to the handler
485 // returned by this call.
486 __ mov(r19, lr);
487 BLOCK_COMMENT("call exception_handler_for_return_address");
488 __ call_VM_leaf(CAST_FROM_FN_PTR(address,
489 SharedRuntime::exception_handler_for_return_address),
490 rthread, c_rarg1);
491 if (UseSVE > 0 ) {
492 // Reinitialize the ptrue predicate register, in case the external runtime
493 // call clobbers ptrue reg, as we may return to SVE compiled code.
494 __ reinitialize_ptrue();
495 }
496 // we should not really care that lr is no longer the callee
497 // address. we saved the value the handler needs in r19 so we can
498 // just copy it to r3. however, the C2 handler will push its own
499 // frame and then calls into the VM and the VM code asserts that
500 // the PC for the frame above the handler belongs to a compiled
501 // Java method. So, we restore lr here to satisfy that assert.
502 __ mov(lr, r19);
503 // setup r0 & r3 & clear pending exception
504 __ mov(r3, r19);
505 __ mov(r19, r0);
506 __ ldr(r0, Address(rthread, Thread::pending_exception_offset()));
507 __ str(zr, Address(rthread, Thread::pending_exception_offset()));
508
509 #ifdef ASSERT
510 // make sure exception is set
511 {
512 Label L;
513 __ cbnz(r0, L);
514 __ stop("StubRoutines::forward exception: no pending exception (2)");
515 __ bind(L);
5005 // Call runtime
5006 if (arg1 != noreg) {
5007 assert(arg2 != c_rarg1, "clobbered");
5008 __ mov(c_rarg1, arg1);
5009 }
5010 if (arg2 != noreg) {
5011 __ mov(c_rarg2, arg2);
5012 }
5013 __ mov(c_rarg0, rthread);
5014 BLOCK_COMMENT("call runtime_entry");
5015 __ mov(rscratch1, runtime_entry);
5016 __ blr(rscratch1);
5017
5018 // Generate oop map
5019 OopMap* map = new OopMap(framesize, 0);
5020
5021 oop_maps->add_gc_map(the_pc - start, map);
5022
5023 __ reset_last_Java_frame(true);
5024 __ maybe_isb();
5025
5026 if (UseSVE > 0) {
5027 // Reinitialize the ptrue predicate register, in case the external runtime
5028 // call clobbers ptrue reg, as we may return to SVE compiled code.
5029 __ reinitialize_ptrue();
5030 }
5031
5032 __ leave();
5033
5034 // check for pending exceptions
5035 #ifdef ASSERT
5036 Label L;
5037 __ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset()));
5038 __ cbnz(rscratch1, L);
5039 __ should_not_reach_here();
5040 __ bind(L);
5041 #endif // ASSERT
5042 __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
5043
5044
5045 // codeBlob framesize is in words (not VMRegImpl::slot_size)
5046 RuntimeStub* stub =
5047 RuntimeStub::new_runtime_stub(name,
5048 &code,
5049 frame_complete,
5050 (framesize >> (LogBytesPerWord - LogBytesPerInt)),
|