2008-10-23 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mono / mini / inssel.brg
index 60a4b6b3d1ff054cbe18473c48d326fb6f21a6c0..ab48c8923c2856df44e889aef94d3db287c2ef62 100644 (file)
                MonoInst *target_label; \
                target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
                target_label->opcode = OP_LABEL;        \
-               MONO_INST_LIST_ADD (&target_label->node, \
-                                  &(targetbb)->ins_list); \
+               target_label->next = (targetbb)->code; \
+        (targetbb)->code = target_label; \
                target_label->inst_c0 = (targetbb)->native_offset; \
                MONO_INST_NEW ((cfg), inst, op);        \
                inst->inst_i0 = target_label;   \
@@ -781,6 +781,10 @@ stmt: OP_LABEL {
 stmt: OP_NOP "0" {
 }
 
+stmp: OP_HARD_NOP "0" {
+       mono_bblock_add_inst (s->cbb, tree);
+}
+
 stmt: OP_BREAK "0" {
        mono_bblock_add_inst (s->cbb, tree);
 }
@@ -1456,6 +1460,7 @@ reg: OP_CCASTCLASS (reg) {
        MonoInst *end_label, *fail_label, *no_proxy_label, *ok_result_label;
        int obj_reg = state->left->reg1;
        int tmp_reg = mono_regstate_next_int (s->rs);
+       int tmp2_reg = mono_regstate_next_int (s->rs);
        int klass_reg = mono_regstate_next_int (s->rs);
 
        MONO_NEW_LABEL (s, end_label);
@@ -1482,12 +1487,8 @@ reg: OP_CCASTCLASS (reg) {
                        MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, klass_reg, mono_defaults.transparent_proxy_class, "InvalidCastException");
                }
                
-               
-               MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
-               MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
-               
-               MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
-               MONO_EMIT_NEW_COMPARE_IMM_EXC (s, EQ, tmp_reg, 0, "InvalidCastException");
+               MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp2_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
+               MONO_EMIT_NEW_COMPARE_IMM_EXC (s, EQ, tmp2_reg, 0, "InvalidCastException");
                
                MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
                MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label);
@@ -1512,8 +1513,8 @@ reg: OP_CCASTCLASS (reg) {
                MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
                MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
                
-               MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
-               MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL (s, CEE_BEQ, tmp_reg, 0, no_proxy_label);
+               MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp2_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
+               MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL (s, CEE_BEQ, tmp2_reg, 0, no_proxy_label);
                
                mini_emit_isinst (s, klass_reg, klass, fail_label, ok_result_label);
                mono_bblock_add_inst (s->cbb, fail_label);
@@ -1798,7 +1799,6 @@ mini_emit_max_iid_check_class (MonoCompile *s, int klass_reg, MonoClass *klass,
 /* Emit code which loads interface_offsets [klass->interface_id]
  * The array is stored in memory before vtable.
  */
-#ifndef MONO_ARCH_HAVE_IMT
 static void
 mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, MonoClass *klass)
 {
@@ -1812,7 +1812,6 @@ mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, Mo
                MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, vtable_reg, -((klass->interface_id + 1) * SIZEOF_VOID_P));
        }
 }
-#endif
 
 /* 
  * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoClass
@@ -1902,7 +1901,7 @@ emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, gboolean have_imt_arg,
 
        mono_call_inst_add_outarg_reg (cfg, call, method_reg, MONO_ARCH_IMT_REG, FALSE);
 #else
-       mono_arch_emit_imt_argument (cfg, call);
+       mono_arch_emit_imt_argument (cfg, call, NULL);
 #endif
 }
 #endif
@@ -1971,28 +1970,32 @@ mini_emit_virtual_call_internal (MonoCompile *cfg, void *st, MonoInst *tree, int
           MonoMethod *gmethod = mono_method_get_declaring_generic_method (method);
           mono_class_setup_vtable (gmethod->klass);
 
-          slot = gmethod->slot;
+          slot = mono_method_get_vtable_index (gmethod);
           g_assert (slot != -1);
        } else {
                /* Initialize method->slot */
                mono_class_setup_vtable (method->klass);
-               slot = method->slot;
+               slot = mono_method_get_vtable_index (method);
        }
 
        vtable_reg = mono_regstate_next_int (cfg->rs);
        MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this_reg, G_STRUCT_OFFSET (MonoObject, vtable));
        if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               slot_reg = -1;
 #ifdef MONO_ARCH_HAVE_IMT
-               guint32 imt_slot = mono_method_get_imt_slot (method);
-               emit_imt_argument (cfg, (MonoCallInst*)tree, have_imt_arg, imt_reg);
-               slot_reg = vtable_reg;
-               tree->inst_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
-#else
-               g_assert (!have_imt_arg);
-               slot_reg = mono_regstate_next_int (cfg->rs);
-               mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass);
-               tree->inst_offset = slot * SIZEOF_VOID_P;
+               if (mono_use_imt) {
+                       guint32 imt_slot = mono_method_get_imt_slot (method);
+                       emit_imt_argument (cfg, (MonoCallInst*)tree, have_imt_arg, imt_reg);
+                       slot_reg = vtable_reg;
+                       tree->inst_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
+               }
 #endif
+               if (slot_reg == -1) {
+                       g_assert (!have_imt_arg);
+                       slot_reg = mono_regstate_next_int (cfg->rs);
+                       mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass);
+                       tree->inst_offset = slot * SIZEOF_VOID_P;
+               }
        } else {
                slot_reg = vtable_reg;
                tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (slot * SIZEOF_VOID_P);
@@ -2161,10 +2164,11 @@ mini_emit_castclass (MonoCompile *s, int obj_reg, int klass_reg, MonoClass *klas
                } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
                        mini_emit_castclass_iface_class (s, eclass_reg, klass->cast_class);
                } else {
-                       mini_emit_castclass (s, obj_reg, eclass_reg, klass->cast_class, object_is_null);
+                       // Pass -1 as obj_reg to skip the check below for arrays of arrays
+                       mini_emit_castclass (s, -1, eclass_reg, klass->cast_class, object_is_null);
                }
 
-               if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
+               if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY) && (obj_reg != -1)) {
                        /* Check that the object is a vector too */
                        int bounds_reg = mono_regstate_next_int (s->rs);
                        MONO_EMIT_NEW_LOAD_MEMBASE (s, bounds_reg, obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));