How to migrate hs17's LIR_Assembler::emit_exception_handler to hs25?

Leslie Zhai lesliezhai at llvm.org.cn
Tue Mar 27 15:57:35 UTC 2018


Hi HotSpot compiler developers,

I am new to HotSpot, and trying to migrate hs17 to hs25, but JDK-6919934 
changed:


int LIR_Assembler::emit_exception_handler() {
   // if the last instruction is a call (typically to do a throw which
   // is coming at the end after block reordering) the return address
   // must still point into the code area in order to avoid assertion
   // failures when searching for the corresponding bci => add a nop
   // (was bug 5/14/1999 - gri)
   __ nop();

   // generate code for exception handler
   address handler_base = __ start_a_stub(exception_handler_size);
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("exception handler overflow");
     return -1;
   }

   int offset = code_offset();

   // if the method does not have an exception handler, then there is
   // no reason to search for one
   if (compilation()->has_exception_handlers() || 
compilation()->env()->jvmti_can_post_on_exceptions()) {
     // the exception oop and pc are in rax, and rdx
     // no other registers need to be preserved, so invalidate them
     __ invalidate_registers(false, true, true, false, true, true);

     // check that there is really an exception
     __ verify_not_null_oop(rax);

     // search an exception handler (rax: exception oop, rdx: throwing pc)
     __ 
call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id)));

     // if the call returns here, then the exception handler for particular
     // exception doesn't exist -> unwind activation and forward 
exception to caller
   }

   // the exception oop is in rax,
   // no other registers need to be preserved, so invalidate them
   __ invalidate_registers(false, true, true, true, true, true);

   // check that there is really an exception
   __ verify_not_null_oop(rax);

   // unlock the receiver/klass if necessary
   // rax,: exception
   ciMethod* method = compilation()->method();
   if (method->is_synchronized() && GenerateSynchronizationCode) {
     monitorexit(FrameMap::rbx_oop_opr, FrameMap::rcx_opr, SYNC_header, 
0, rax);
   }

   // unwind activation and forward exception to caller
   // rax,: exception
   __ 
jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id)));
   assert(code_offset() - offset <= exception_handler_size, "overflow");
   __ end_a_stub();

   return offset;
}


To:


int LIR_Assembler::emit_exception_handler() {
   // if the last instruction is a call (typically to do a throw which
   // is coming at the end after block reordering) the return address
   // must still point into the code area in order to avoid assertion
   // failures when searching for the corresponding bci => add a nop
   // (was bug 5/14/1999 - gri)
   __ nop();

   // generate code for exception handler
   address handler_base = __ start_a_stub(exception_handler_size);
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("exception handler overflow");
     return -1;
   }

   int offset = code_offset();

   // the exception oop and pc are in rax, and rdx
   // no other registers need to be preserved, so invalidate them
   __ invalidate_registers(false, true, true, false, true, true);

   // check that there is really an exception
   __ verify_not_null_oop(rax);

   // search an exception handler (rax: exception oop, rdx: throwing pc)
   __ 
call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id)));

   __ stop("should not reach here");

   assert(code_offset() - offset <= exception_handler_size, "overflow");
   __ end_a_stub();

   return offset;
}


I have no idea how to check whether or not the Java method have an 
exception handler *without* the 
`compilation()->has_exception_handlers()` condition.

And after JDK-6939930 and JDK-7012914, it separated `unwind` handler 
from `exception` handler, added `LIR_Assembler::emit_unwind_handler` and 
`handle_exception_from_callee` StubID:


int LIR_Assembler::emit_exception_handler() {
   // if the last instruction is a call (typically to do a throw which
   // is coming at the end after block reordering) the return address
   // must still point into the code area in order to avoid assertion
   // failures when searching for the corresponding bci => add a nop
   // (was bug 5/14/1999 - gri)
   __ nop();

   // generate code for exception handler
   address handler_base = __ start_a_stub(exception_handler_size());
   if (handler_base == NULL) {
     // not enough space left for the handler
     bailout("exception handler overflow");
     return -1;
   }

   int offset = code_offset();

   // the exception oop and pc are in rax, and rdx
   // no other registers need to be preserved, so invalidate them
   __ invalidate_registers(false, true, true, false, true, true);

   // check that there is really an exception
   __ verify_not_null_oop(rax);

   // search an exception handler (rax: exception oop, rdx: throwing pc)
   __ 
call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id)));
   __ should_not_reach_here();
   guarantee(code_offset() - offset <= exception_handler_size(), 
"overflow");
   __ end_a_stub();

   return offset;
}


How to migrate `if (compilation()->has_exception_handlers()) { } else { 
}` in `Runtime1::generate_handle_exception` or 
`Runtime1::generate_unwind_exception` be equivalent for hs25 or even 
jdk11? My workaround is override `generate_handle_exception`:


diff -r 33a61051088d src/share/vm/c1/c1_Runtime1.hpp
--- a/src/share/vm/c1/c1_Runtime1.hpp   Sat Mar 24 12:18:54 2018 +0800
+++ b/src/share/vm/c1/c1_Runtime1.hpp   Tue Mar 27 23:32:54 2018 +0800
@@ -127,6 +127,7 @@
    static OopMapSet* generate_code_for(StubID id, StubAssembler* sasm);
    static OopMapSet* generate_exception_throw(StubAssembler* sasm, 
address target, bool has_argument);
    static OopMapSet* generate_handle_exception(StubID id, 
StubAssembler* sasm);
+  static OopMapSet* generate_handle_exception(StubAssembler *sasm, 
OopMapSet* oop_maps, OopMap* oop_map, bool save_fpu_registers);
    static void       generate_unwind_exception(StubAssembler *sasm);
    static OopMapSet* generate_patching(StubAssembler* sasm, address 
target);


Then reuse hs17's `LIR_Assembler::emit_exception_handler`, 
`Runtime1::generate_handle_exception`, `Runtime1::generate_code_for`... 
in hs25, but it is monkey patch... not easy to merge upstream.

Please share your porting experience, and give me some advice, thanks a lot!

-- 
Regards,
Leslie Zhai





More information about the hotspot-compiler-dev mailing list