[jit] Replace usage of mini_emit_stobj with mini_emit_memory_copy and simplify usage...
[mono.git] / mono / mini / method-to-ir.c
index 8d64aabc8a8ca471c9f43b0e1a021418f1c9109b..2883c23ea3cedd7fe144d4086ddeeb2ec41eef61 100644 (file)
@@ -2863,6 +2863,8 @@ mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
        if (!cfg->gen_write_barriers)
                return;
 
+       //method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER && !MONO_INS_IS_PCONST_NULL (sp [1])
+
        card_table = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
 
        mono_gc_get_nursery (&nursery_shift_bits, &nursery_size);
@@ -6646,7 +6648,7 @@ mini_get_method (MonoCompile *cfg, MonoMethod *m, guint32 token, MonoClass *klas
        return method;
 }
 
-static inline MonoClass*
+MonoClass*
 mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
 {
        MonoError error;
@@ -8600,6 +8602,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        sp -= n;
 
+                       if (cmethod && cmethod->klass->image == mono_defaults.corlib && !strcmp (cmethod->klass->name, "ThrowHelper"))
+                               cfg->cbb->out_of_line = TRUE;
+
                        /*
                         * We have the `constrained.' prefix opcode.
                         */
@@ -9234,7 +9239,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 
                        /* Common call */
-                       if (!(cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))
+                       if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING) && !(cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))
                                INLINE_FAILURE ("call");
                        ins = mono_emit_method_call_full (cfg, cmethod, fsig, tail_call, sp, virtual_ ? sp [0] : NULL,
                                                                                          imt_arg, vtable_arg);
@@ -9850,23 +9855,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
                        sp -= 2;
-                       if (generic_class_is_reference_type (cfg, klass)) {
-                               MonoInst *store, *load;
-                               int dreg = alloc_ireg_ref (cfg);
-
-                               NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, dreg, sp [1]->dreg, 0);
-                               load->flags |= ins_flag;
-                               MONO_ADD_INS (cfg->cbb, load);
-
-                               NEW_STORE_MEMBASE (cfg, store, OP_STORE_MEMBASE_REG, sp [0]->dreg, 0, dreg);
-                               store->flags |= ins_flag;
-                               MONO_ADD_INS (cfg->cbb, store);
-
-                               if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER)
-                                       mini_emit_write_barrier (cfg, sp [0], sp [1]);
-                       } else {
-                               mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
-                       }
+                       mini_emit_memory_copy (cfg, sp [0], sp [1], klass, FALSE, ins_flag);
                        ins_flag = 0;
                        ip += 5;
                        break;
@@ -9915,14 +9904,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 
                        /* Optimize the ldobj+stobj combination */
-                       /* The reference case ends up being a load+store anyway */
-                       /* Skip this if the operation is volatile. */
-                       if (((ip [5] == CEE_STOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 5) && read32 (ip + 6) == token) && !generic_class_is_reference_type (cfg, klass) && !(ins_flag & MONO_INST_VOLATILE)) {
+                       if (((ip [5] == CEE_STOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 5) && read32 (ip + 6) == token)) {
                                CHECK_STACK (1);
 
                                sp --;
 
-                               mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
+                               mini_emit_memory_copy (cfg, sp [0], sp [1], klass, FALSE, ins_flag);
 
                                ip += 5 + 5;
                                ins_flag = 0;
@@ -10579,7 +10566,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                dreg = alloc_ireg_mp (cfg);
                                                EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
                                                wbarrier_ptr_ins = ins;
-                                               /* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
+                                               /* The decomposition will call mini_emit_memory_copy () which will emit a wbarrier if needed */
                                                EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, dreg, 0, sp [1]->dreg);
                                        } else {
                                                EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, sp [0]->dreg, foffset, sp [1]->dreg);
@@ -11012,18 +10999,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        token = read32 (ip + 1);
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
-                       if (ins_flag & MONO_INST_VOLATILE) {
-                               /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
-                               mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
-                       }
+
                        /* FIXME: should check item at sp [1] is compatible with the type of the store. */
-                       EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0, sp [1]->dreg);
-                       ins->flags |= ins_flag;
-                       if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER &&
-                               generic_class_is_reference_type (cfg, klass) && !MONO_INS_IS_PCONST_NULL (sp [1])) {
-                               /* insert call to write barrier */
-                               mini_emit_write_barrier (cfg, sp [0], sp [1]);
-                       }
+                       mini_emit_memory_store (cfg, &klass->byval_arg, sp [0], sp [1], ins_flag);
                        ins_flag = 0;
                        ip += 5;
                        inline_costs += 1;
@@ -11849,7 +11827,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        temp = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
                                        temp->backend.is_pinvoke = 1;
                                        EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
-                                       mini_emit_stobj (cfg, dest, src, klass, TRUE);
+                                       mini_emit_memory_copy (cfg, dest, src, klass, TRUE, 0);
 
                                        EMIT_NEW_TEMPLOAD (cfg, dest, temp->inst_c0);
                                        dest->type = STACK_VTYPE;
@@ -11880,7 +11858,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else {
                                        EMIT_NEW_RETLOADA (cfg, ins);
                                }
-                               mini_emit_stobj (cfg, ins, sp [0], klass, TRUE);
+                               mini_emit_memory_copy (cfg, ins, sp [0], klass, TRUE, 0);
                                
                                if (sp != stack_start)
                                        UNVERIFIED;
@@ -12633,56 +12611,21 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ip += 6;
                                break;
                        case CEE_CPBLK:
-                       case CEE_INITBLK: {
-                               MonoInst *iargs [3];
                                CHECK_STACK (3);
                                sp -= 3;
-
-                               /* Skip optimized paths for volatile operations. */
-                               if ((ip [1] == CEE_CPBLK) && !(ins_flag & MONO_INST_VOLATILE) && (cfg->opt & MONO_OPT_INTRINS) && (sp [2]->opcode == OP_ICONST) && ((n = sp [2]->inst_c0) <= sizeof (gpointer) * 5)) {
-                                       mini_emit_memcpy (cfg, sp [0]->dreg, 0, sp [1]->dreg, 0, sp [2]->inst_c0, 0);
-                               } else if ((ip [1] == CEE_INITBLK) && !(ins_flag & MONO_INST_VOLATILE) && (cfg->opt & MONO_OPT_INTRINS) && (sp [2]->opcode == OP_ICONST) && ((n = sp [2]->inst_c0) <= sizeof (gpointer) * 5) && (sp [1]->opcode == OP_ICONST) && (sp [1]->inst_c0 == 0)) {
-                                       /* emit_memset only works when val == 0 */
-                                       mini_emit_memset (cfg, sp [0]->dreg, 0, sp [2]->inst_c0, sp [1]->inst_c0, 0);
-                               } else {
-                                       MonoInst *call;
-                                       iargs [0] = sp [0];
-                                       iargs [1] = sp [1];
-                                       iargs [2] = sp [2];
-                                       if (ip [1] == CEE_CPBLK) {
-                                               /*
-                                                * FIXME: It's unclear whether we should be emitting both the acquire
-                                                * and release barriers for cpblk. It is technically both a load and
-                                                * store operation, so it seems like that's the sensible thing to do.
-                                                *
-                                                * FIXME: We emit full barriers on both sides of the operation for
-                                                * simplicity. We should have a separate atomic memcpy method instead.
-                                                */
-                                               MonoMethod *memcpy_method = mini_get_memcpy_method ();
-
-                                               if (ins_flag & MONO_INST_VOLATILE)
-                                                       mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
-
-                                               call = mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
-                                               call->flags |= ins_flag;
-
-                                               if (ins_flag & MONO_INST_VOLATILE)
-                                                       mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
-                                       } else {
-                                               MonoMethod *memset_method = mini_get_memset_method ();
-                                               if (ins_flag & MONO_INST_VOLATILE) {
-                                                       /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
-                                                       mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
-                                               }
-                                               call = mono_emit_method_call (cfg, memset_method, iargs, NULL);
-                                               call->flags |= ins_flag;
-                                       }
-                               }
+                               mini_emit_memory_copy_bytes (cfg, sp [0], sp [1], sp [2], ins_flag);
+                               ip += 2;
+                               ins_flag = 0;
+                               inline_costs += 1;
+                               break;
+                       case CEE_INITBLK:
+                               CHECK_STACK (3);
+                               sp -= 3;
+                               mini_emit_memory_init_bytes (cfg, sp [0], sp [1], sp [2], ins_flag);
                                ip += 2;
                                ins_flag = 0;
                                inline_costs += 1;
                                break;
-                       }
                        case CEE_NO_:
                                CHECK_OPSIZE (3);
                                if (ip [2] & 0x1)
@@ -14386,7 +14329,6 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
  * - create a helper function for allocating a stack slot, taking into account 
  *   MONO_CFG_HAS_SPILLUP.
  * - merge r68207.
- * - merge the ia64 switch changes.
  * - optimize mono_regstate2_alloc_int/float.
  * - fix the pessimistic handling of variables accessed in exception handler blocks.
  * - need to write a tree optimization pass, but the creation of trees is difficult, i.e.