2 * branch-opts.c: Branch optimizations support
5 * Patrik Torstensson (Patrik.Torstesson at gmail.com)
7 * (C) 2005 Ximian, Inc. http://www.ximian.com
12 * Used by the arch code to replace the exception handling
13 * with a direct branch. This is safe to do if the
14 * exception object isn't used, no rethrow statement and
15 * no filter statement (verify).
19 mono_branch_optimize_exception_target (MonoCompile *cfg, MonoBasicBlock *bb, const char * exname)
21 MonoMethod *method = cfg->method;
22 MonoMethodHeader *header = mono_method_get_header (method);
23 MonoExceptionClause *clause;
27 if (!(cfg->opt & MONO_OPT_EXCEPTION))
30 if (bb->region == -1 || !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
33 exclass = mono_class_from_name (mono_get_corlib (), "System", exname);
34 /* search for the handler */
35 for (i = 0; i < header->num_clauses; ++i) {
36 clause = &header->clauses [i];
37 if (MONO_OFFSET_IN_CLAUSE (clause, bb->real_offset)) {
38 if (clause->data.catch_class && mono_class_is_assignable_from (clause->data.catch_class, exclass)) {
41 /* get the basic block for the handler and
42 * check if the exception object is used.
43 * Flag is set during method_to_ir due to
44 * pop-op is optmized away in codegen (burg).
46 tbb = g_hash_table_lookup (cfg->bb_hash, header->code + clause->handler_offset);
47 if (tbb && tbb->flags & BB_EXCEPTION_DEAD_OBJ && !(tbb->flags & BB_EXCEPTION_UNSAFE)) {
48 MonoBasicBlock *targetbb = tbb;
49 gboolean unsafe = FALSE;
51 /* Check if this catch clause is ok to optimize by
52 * looking for the BB_EXCEPTION_UNSAFE in every BB that
53 * belongs to the same region.
55 * UNSAFE flag is set during method_to_ir (OP_RETHROW)
57 while (!unsafe && tbb->next_bb && tbb->region == tbb->next_bb->region) {
58 if (tbb->next_bb->flags & BB_EXCEPTION_UNSAFE) {
68 /* Create dummy inst to allow easier integration in
69 * arch dependent code (opcode ignored)
71 MONO_INST_NEW (cfg, jump, CEE_BR);
73 /* Allocate memory for our branch target */
74 jump->inst_i1 = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
75 jump->inst_true_bb = targetbb;
77 if (cfg->verbose_level > 2)
78 g_print ("found exception to optimize - returning branch to BB%d (%s) (instead of throw) for method %s:%s\n", targetbb->block_num, clause->data.catch_class->name, cfg->method->klass->name, cfg->method->name);
86 /* Branching to an outer clause could skip inner clauses */