2005-11-20 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Sun, 20 Nov 2005 15:14:39 +0000 (15:14 -0000)
committerZoltan Varga <vargaz@gmail.com>
Sun, 20 Nov 2005 15:14:39 +0000 (15:14 -0000)
* mini-ia64.c (mono_arch_emit_exceptions): Optimize size of exception
throwing code.

 * mini-ia64.c: Add support for the throw->branch exception
optimization.

svn path=/trunk/mono/; revision=53287

mono/mini/ChangeLog
mono/mini/exceptions-ia64.c
mono/mini/mini-ia64.c

index 831c00ae80e41cd206828c9b4db2e33a5f33f293..26c3cd4160ca085cbb06c4fde74cf54a72d13d57 100644 (file)
@@ -1,5 +1,11 @@
 2005-11-20  Zoltan Varga  <vargaz@gmail.com>
 
+       * mini-ia64.c (mono_arch_emit_exceptions): Optimize size of exception
+       throwing code.
+
+        * mini-ia64.c: Add support for the throw->branch exception 
+       optimization.   
+
        * driver.c (DEFAULT_OPTIMIZATIONS): Add MONO_OPT_EXCEPTION.
 
 2005-11-18  Massimiliano Mantione  <massi@ximian.com>
index 0b8bb2f3620de70c01545ee716fbf99c48b9d2f3..64d45a2f04619c215ede6eebeaffb33e6c0000b4 100644 (file)
@@ -423,7 +423,7 @@ mono_arch_get_throw_exception_by_name (void)
  *
  * Returns a function pointer which can be used to raise 
  * corlib exceptions. The returned function has the following 
- * signature: void (*func) (guint32 ex_token, guint32 offset); 
+ * signature: void (*func) (guint32 ex_token_index, guint32 offset); 
  * Here, offset is the offset which needs to be substracted from the caller IP 
  * to get the IP of the throw. Passing the offset has the advantage that it 
  * needs no relocations in the caller.
@@ -466,6 +466,8 @@ mono_arch_get_throw_corlib_exception (void)
        /* Call exception_from_token */
        ia64_movl (code, out0 + 0, mono_defaults.exception_class->image);
        ia64_mov (code, out0 + 1, in0 + 0);
+       ia64_movl (code, GP_SCRATCH_REG, MONO_TOKEN_TYPE_DEF);
+       ia64_add (code, out0 + 1, in0 + 0, GP_SCRATCH_REG);
        ptr = mono_exception_from_token;
        ia64_movl (code, GP_SCRATCH_REG, ptr);
        ia64_ld8_inc_imm (code, GP_SCRATCH_REG2, GP_SCRATCH_REG, 8);
index 6e558ae9baf4316caa7093be5e6deee664b9e2a5..f888b8df306177e696630b498d13a029c5255ecb 100644 (file)
@@ -2193,6 +2193,15 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, Ia64CodegenState code)
        mono_add_patch_info (cfg, code.buf + code.nins - cfg->native_code, patch_type, data); \
 } while (0)
 
+#define emit_cond_system_exception(cfg,code,exc_name,predicate) do { \
+       MonoInst *tins = mono_branch_optimize_exception_target (cfg, bb, exc_name); \
+    if (tins == NULL) \
+        add_patch_info (cfg, code, MONO_PATCH_INFO_EXC, exc_name); \
+    else \
+               add_patch_info (cfg, code, MONO_PATCH_INFO_BB, tins->inst_true_bb); \
+       ia64_br_cond_pred (code, (predicate), 0); \
+} while (0)
+
 static Ia64CodegenState
 emit_call (MonoCompile *cfg, Ia64CodegenState code, guint32 patch_type, gconstpointer data)
 {
@@ -2712,20 +2721,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
                case OP_COND_EXC_IOV:
                case OP_COND_EXC_OV:
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, "OverflowException");
-                       ia64_br_cond_pred (code, 6, 0);
+                       emit_cond_system_exception (cfg, code, "OverflowException", 6);
                        break;
                case OP_COND_EXC_IC:
                case OP_COND_EXC_C:
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, "OverflowException");
-                       ia64_br_cond_pred (code, 7, 0);
+                       emit_cond_system_exception (cfg, code, "OverflowException", 7);
                        break;
                case OP_IA64_COND_EXC:
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, ins->inst_p1);
-                       ia64_br_cond_pred (code, 6, 0);
+                       emit_cond_system_exception (cfg, code, ins->inst_p1, 6);
                        break;
                case OP_IA64_CSET:
                        ia64_mov_pred (code, 7, ins->dreg, IA64_R0);
@@ -2858,24 +2861,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case CEE_CKFINITE:
                        /* Quiet NaN */
                        ia64_fclass_m (code, 6, 7, ins->sreg1, 0x080);
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, "ArithmeticException");
-                       ia64_br_cond_pred (code, 6, 0);
+                       emit_cond_system_exception (cfg, code, "ArithmeticException", 6);
                        /* Signaling NaN */
                        ia64_fclass_m (code, 6, 7, ins->sreg1, 0x040);
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, "ArithmeticException");
-                       ia64_br_cond_pred (code, 6, 0);
+                       emit_cond_system_exception (cfg, code, "ArithmeticException", 6);
                        /* Positive infinity */
                        ia64_fclass_m (code, 6, 7, ins->sreg1, 0x021);
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, "ArithmeticException");
-                       ia64_br_cond_pred (code, 6, 0);
+                       emit_cond_system_exception (cfg, code, "ArithmeticException", 6);
                        /* Negative infinity */
                        ia64_fclass_m (code, 6, 7, ins->sreg1, 0x022);
-                       add_patch_info (cfg, code,
-                                                                MONO_PATCH_INFO_EXC, "ArithmeticException");
-                       ia64_br_cond_pred (code, 6, 0);
+                       emit_cond_system_exception (cfg, code, "ArithmeticException", 6);
                        break;
 
                /* Calls */
@@ -3835,6 +3830,8 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
 
                target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors);
 
+               if (patch_info->type == MONO_PATCH_INFO_NONE)
+                       continue;
                if (mono_compile_aot) {
                        NOT_IMPLEMENTED;
                }
@@ -4162,15 +4159,12 @@ void
 mono_arch_emit_exceptions (MonoCompile *cfg)
 {
        MonoJumpInfo *patch_info;
-       int nthrows;
+       int i, nthrows;
        Ia64CodegenState code;
        gboolean empty = TRUE;
        //unw_dyn_region_info_t *r_exceptions;
-
-       /*
        MonoClass *exc_classes [16];
        guint8 *exc_throw_start [16], *exc_throw_end [16];
-       */
        guint32 code_size = 0;
 
        /* Compute needed space */
@@ -4206,34 +4200,77 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                        MonoClass *exc_class;
                        guint8* throw_ip;
                        guint8* buf;
+                       guint64 exc_token_index;
 
                        exc_class = mono_class_from_name (mono_defaults.corlib, "System", patch_info->data.name);
                        g_assert (exc_class);
+                       exc_token_index = mono_metadata_token_index (exc_class->type_token);
                        throw_ip = cfg->native_code + patch_info->ip.i;
 
                        ia64_begin_bundle (code);
 
                        ia64_patch (cfg->native_code + patch_info->ip.i, code.buf);
 
-                       ia64_movl (code, cfg->arch.reg_out0 + 0, exc_class->type_token);
+                       /* Find a throw sequence for the same exception class */
+                       for (i = 0; i < nthrows; ++i)
+                               if (exc_classes [i] == exc_class)
+                                       break;
+
+                       if (i < nthrows) {
+                               gint64 offset = exc_throw_end [i] - 16 - throw_ip;
 
-                       ia64_begin_bundle (code);
+                               if (ia64_is_adds_imm (offset))
+                                       ia64_adds_imm (code, cfg->arch.reg_out0 + 1, offset, IA64_R0);
+                               else
+                                       ia64_movl (code, cfg->arch.reg_out0 + 1, offset);
 
-                       patch_info->data.name = "mono_arch_throw_corlib_exception";
-                       patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
-                       patch_info->ip.i = code.buf - cfg->native_code;
+                               buf = code.buf + code.nins;
+                               ia64_br_cond_pred (code, 0, 0);
+                               ia64_begin_bundle (code);
+                               ia64_patch (buf, exc_throw_start [i]);
 
-                       /* Indirect call */
-                       ia64_movl (code, GP_SCRATCH_REG, 0);
-                       ia64_ld8_inc_imm (code, GP_SCRATCH_REG2, GP_SCRATCH_REG, 8);
-                       ia64_mov_to_br (code, IA64_B6, GP_SCRATCH_REG2);
-                       ia64_ld8 (code, IA64_GP, GP_SCRATCH_REG);
+                               patch_info->type = MONO_PATCH_INFO_NONE;
+                       }
+                       else {
+                               /* Arg1 */
+                               buf = code.buf;
+                               ia64_movl (code, cfg->arch.reg_out0 + 1, 0);
 
-                       /* Compute the offset */
-                       buf = code.buf + 32;
-                       ia64_movl (code, cfg->arch.reg_out0 + 1, buf - throw_ip);
+                               ia64_begin_bundle (code);
 
-                       ia64_br_call_reg (code, IA64_B0, IA64_B6);
+                               if (nthrows < 16) {
+                                       exc_classes [nthrows] = exc_class;
+                                       exc_throw_start [nthrows] = code.buf;
+                               }
+
+                               /* Arg2 */
+                               if (ia64_is_adds_imm (exc_token_index))
+                                       ia64_adds_imm (code, cfg->arch.reg_out0 + 0, exc_token_index, IA64_R0);
+                               else
+                                       ia64_movl (code, cfg->arch.reg_out0 + 0, exc_token_index);
+
+                               patch_info->data.name = "mono_arch_throw_corlib_exception";
+                               patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
+                               patch_info->ip.i = code.buf + code.nins - cfg->native_code;
+
+                               /* Indirect call */
+                               ia64_movl (code, GP_SCRATCH_REG, 0);
+                               ia64_ld8_inc_imm (code, GP_SCRATCH_REG2, GP_SCRATCH_REG, 8);
+                               ia64_mov_to_br (code, IA64_B6, GP_SCRATCH_REG2);
+                               ia64_ld8 (code, IA64_GP, GP_SCRATCH_REG);
+
+                               ia64_br_call_reg (code, IA64_B0, IA64_B6);
+
+                               /* Patch up the throw offset */
+                               ia64_begin_bundle (code);
+
+                               ia64_patch (buf, (gpointer)(code.buf - 16 - throw_ip));
+
+                               if (nthrows < 16) {
+                                       exc_throw_end [nthrows] = code.buf;
+                                       nthrows ++;
+                               }
+                       }
 
                        empty = FALSE;
                        break;