| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- Author: Dietmar Maurer ([email protected])
- (C) 2001 Ximian, Inc.
- Exception implementation (jit):
- ===============================
- Stack unwinding:
- ================
- We record the code address (start_address, size) of all methods. That way it is
- possible to map an instruction pointer (IP) to the method information needed
- for unwinding the stack:
- We also save a Last Managed Frame (LMF) structure at each call from managed to
- unmanaged code. That way we can recover from exceptions inside unmanaged code.
- void handle_exception ((struct sigcontext *ctx, gpointer obj)
- {
- if (ctx->bp < mono_end_of_stack) {
- /* unhandled exception */
- abort ();
- }
- info = mono_jit_info_table_find (mono_jit_info_table, ctx->ip);
- if (info) { // we are inside managed code
- if (ch = find_catch_handler ())
- execute_catch_handler (ch, ctx, obj);
-
- execute_all_finally_handler ();
- // restore register, including IP and Frame pointer
- ctx = restore_caller_saved_registers_from_ctx (ji, ctx);
- // continue unwinding
- handle_exception (ctx, obj);
- } else {
- lmf = get_last_managed_frame ();
-
- // restore register, including IP and Frame pointer
- ctx = restore_caller_saved_registers_from_lmf (ji, lmf);
-
- // continue unwinding
- handle_exception (ctx, obj);
- }
- }
- Code generation:
- ================
- leave: is simply translated into a branch to the target. If the leave
- instruction is inside a finally block (but not inside another handler)
- we call the finally handler before we branch to the target.
- finally/endfinally: is translated into subroutine ending with a "return"
- statement. The subroutine does not save EBP/ESP, because we need access to the
- local variables of the enclosing method. We have to use a "call"
- instruction to execute such finally handlers. This makes it possible to
- execute them inside the stack unwinding code.
- throw: we first save all regs into a sigcontext struct (we pass the
- exception object in register ECX), and then call the stack unwinding
- code.
- catch handler: receives the exception object in ECX. They store that
- object into a local variable, so that rethrow can access the object.
|