[coop] switch to GC unsafe state in SIGFPE handler as it may throw an exception
[mono-project.git] / docs / exceptions
blobbd22de9f25f4ad5886baa969e9465e6f914fc11e
1              Exception Implementation in the Mono Runtime
2                  Dietmar Maurer (dietmar@ximian.com)
3                         (C) 2001 Ximian, Inc.
5 Exception implementation (jit):
6 ===============================
8 Stack unwinding:
9 ================
11 We record the code address (start_address, size) of all methods. That way it is
12 possible to map an instruction pointer (IP) to the method information needed
13 for unwinding the stack:
15 We also save a Last Managed Frame (LMF) structure at each call from managed to
16 unmanaged code. That way we can recover from exceptions inside unmanaged code.
18 void handle_exception ((struct sigcontext *ctx, gpointer obj)
20         if (ctx->bp < mono_end_of_stack) {
21                 /* unhandled exception */
22                 abort ();
23         }
25         info = mono_jit_info_table_find (mono_jit_info_table, ctx->ip);
27         if (info) { // we are inside managed code
29                 if (ch =  find_catch_handler ())
30                         execute_catch_handler (ch, ctx, obj); 
31                 
32                 execute_all_finally_handler ();
34                 // restore register, including IP and Frame pointer
35                 ctx = restore_caller_saved_registers_from_ctx (ji, ctx);
37                 // continue unwinding
38                 handle_exception (ctx, obj);
40         } else {
42                 lmf = get_last_managed_frame ();
43                 
44                 // restore register, including IP and Frame pointer
45                 ctx = restore_caller_saved_registers_from_lmf (ji, lmf);
46                 
47                 // continue unwinding
48                 handle_exception (ctx, obj);
49         }
53 Code generation:
54 ================
56 leave: is simply translated into a branch to the target. If the leave
57 instruction is inside a finally block (but not inside another handler)
58 we call the finally handler before we branch to the target.
60 finally/endfinally, filter/endfilter: is translated into subroutine ending with
61 a "return" statement. The subroutine does not save EBP, because we need access
62 to the local variables of the enclosing method. Its is possible that
63 instructions inside those handlers modify the stack pointer, thus we save the
64 stack pointer at the start of the handler, and restore it at the end. We have
65 to use a "call" instruction to execute such finally handlers. This makes it
66 also possible to execute them inside the stack unwinding code. The exception
67 object for filters is passed in a local variable (cfg->exvar).
69 throw: we first save all regs into a sigcontext struct and then call the stack
70 unwinding code.
72 catch handler: catch hanlders are always called from the stack unwinding
73 code. The exception object is passed in a local variable (cfg->exvar).