Every synchronized method has unlocking code in exit and unwind blocks. When exception occures while unlocking (eg. IllegalMonitorStateException) the throw_exception_from() function must not return address at beginning of exit or unwind block. Function checks if exception source is inside unlocking code and returns address past that code if this is the case.
Signed-off-by: Tomek Grabiec <[email protected]> --- include/jit/compilation-unit.h | 9 +++++++++ jit/emit.c | 2 ++ jit/exception.c | 23 ++++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletions(-) diff --git a/include/jit/compilation-unit.h b/include/jit/compilation-unit.h index 1471680..e17c675 100644 --- a/include/jit/compilation-unit.h +++ b/include/jit/compilation-unit.h @@ -39,6 +39,15 @@ struct compilation_unit { /* It's needed to spill exception object reference at eh entry */ struct stack_slot *exception_spill_slot; + + /* + * Pointers inside exit block and unwind block after monitor + * unlocking code. The code is only present if method is + * synchronized. These pointers are used to skip unlocking + * when exception is thrown from that unlocking code. + */ + unsigned char *exit_past_unlock_ptr; + unsigned char *unwind_past_unlock_ptr; }; struct compilation_unit *alloc_compilation_unit(struct methodblock *); diff --git a/jit/emit.c b/jit/emit.c index 4fe3a73..1f32949 100644 --- a/jit/emit.c +++ b/jit/emit.c @@ -63,11 +63,13 @@ int emit_machine_code(struct compilation_unit *cu) emit_body(cu->exit_bb, cu->objcode); if (method_is_synchronized(cu->method)) emit_monitorexit(cu); + cu->exit_past_unlock_ptr = buffer_current(cu->objcode); emit_epilog(cu->objcode); emit_body(cu->unwind_bb, cu->objcode); if (method_is_synchronized(cu->method)) emit_monitorexit(cu); + cu->unwind_past_unlock_ptr = buffer_current(cu->objcode); emit_unwind(cu->objcode); return 0; diff --git a/jit/exception.c b/jit/exception.c index d78fe83..93ca53d 100644 --- a/jit/exception.c +++ b/jit/exception.c @@ -165,6 +165,20 @@ static unsigned char *find_handler(struct compilation_unit *cu, return NULL; } +static bool +is_inside_exit_unlock(struct compilation_unit *cu, unsigned char *ptr) +{ + return ptr >= bb_native_ptr(cu->exit_bb) && + ptr < cu->exit_past_unlock_ptr; +} + +static bool +is_inside_unwind_unlock(struct compilation_unit *cu, unsigned char *ptr) +{ + return ptr >= bb_native_ptr(cu->unwind_bb) && + ptr < cu->unwind_past_unlock_ptr; +} + /** * throw_exception_from - returns native pointer inside jitted method * that sould be executed to handle exception. @@ -205,12 +219,19 @@ unsigned char *throw_exception_from(struct compilation_unit *cu, signal_exception(exception); - if (!is_jit_method(frame->return_address)) + if (!is_jit_method(frame->return_address)) { /* * No handler found within jitted method call chain. * Return to previous (not jit) method. */ + if (is_inside_exit_unlock(cu, native_ptr)) + return cu->exit_past_unlock_ptr; + return bb_native_ptr(cu->exit_bb); + } + + if (is_inside_unwind_unlock(cu, native_ptr)) + return cu->unwind_past_unlock_ptr; return bb_native_ptr(cu->unwind_bb); } -- 1.6.0.6 ------------------------------------------------------------------------------ Crystal Reports - New Free Runtime and 30 Day Trial Check out the new simplified licensing option that enables unlimited royalty-free distribution of the report engine for externally facing server and web deployment. http://p.sf.net/sfu/businessobjects _______________________________________________ Jatovm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jatovm-devel
