Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / memory-access.c
index 57b07ed074a91431dce98bf1e9118e42dd263887..6a6e11006cc0d395d8cd093cb51f6f667547cc98 100644 (file)
@@ -16,6 +16,7 @@
 #include "jit-icalls.h"
 
 #define MAX_INLINE_COPIES 10
+#define MAX_INLINE_COPY_SIZE 10000
 
 void 
 mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, int align)
@@ -23,7 +24,7 @@ mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val,
        int val_reg;
 
        /*FIXME arbitrary hack to avoid unbound code expansion.*/
-       g_assert (size < 10000);
+       g_assert (size < MAX_INLINE_COPY_SIZE);
        g_assert (val == 0);
        g_assert (align > 0);
 
@@ -111,7 +112,7 @@ mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int so
        int cur_reg;
 
        /*FIXME arbitrary hack to avoid unbound code expansion.*/
-       g_assert (size < 10000);
+       g_assert (size < MAX_INLINE_COPY_SIZE);
        g_assert (align > 0);
 
        if (align < SIZEOF_VOID_P) {
@@ -335,7 +336,7 @@ mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4
 }
 
 static void
-mini_emit_memory_copy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native)
+mini_emit_memory_copy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, int explicit_align, gboolean native)
 {
        MonoInst *iargs [4];
        int size;
@@ -372,8 +373,10 @@ mini_emit_memory_copy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src,
 
        if (!align)
                align = SIZEOF_VOID_P;
+       if (explicit_align)
+               align = explicit_align;
 
-       if (mini_type_is_reference (&klass->byval_arg)) {
+       if (mini_type_is_reference (&klass->byval_arg)) { // Refs *MUST* be naturally aligned
                MonoInst *store, *load;
                int dreg = alloc_ireg_ref (cfg);
 
@@ -437,7 +440,26 @@ mini_emit_memory_load (MonoCompile *cfg, MonoType *type, MonoInst *src, int offs
 {
        MonoInst *ins;
 
-       EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, type, src->dreg, offset);
+       if (ins_flag & MONO_INST_UNALIGNED) {
+               MonoInst *addr, *tmp_var;
+               int align;
+               int size = mono_type_size (type, &align);
+
+               if (offset) {
+                       MonoInst *add_offset;
+                       NEW_BIALU_IMM (cfg, add_offset, OP_PADD_IMM, alloc_preg (cfg), src->dreg, offset);
+                       MONO_ADD_INS (cfg->cbb, add_offset);
+                       src = add_offset;
+               }
+
+               tmp_var = mono_compile_create_var (cfg, type, OP_LOCAL);
+               EMIT_NEW_VARLOADA (cfg, addr, tmp_var, tmp_var->inst_vtype);
+
+               mini_emit_memcpy_const_size (cfg, addr, src, size, 1);
+               EMIT_NEW_TEMPLOAD (cfg, ins, tmp_var->inst_c0);
+       } else {
+               EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, type, src->dreg, offset);
+       }
        ins->flags |= ins_flag;
 
        if (ins_flag & MONO_INST_VOLATILE) {
@@ -458,6 +480,16 @@ mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoIn
                /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
                mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
        }
+
+       if (ins_flag & MONO_INST_UNALIGNED) {
+               MonoInst *addr, *mov, *tmp_var;
+
+               tmp_var = mono_compile_create_var (cfg, type, OP_LOCAL);
+               EMIT_NEW_TEMPSTORE (cfg, mov, tmp_var->inst_c0, value);
+               EMIT_NEW_VARLOADA (cfg, addr, tmp_var, tmp_var->inst_vtype);
+               mini_emit_memory_copy_internal (cfg, dest, addr, mono_class_from_mono_type (type), 1, FALSE);
+       }
+
        /* FIXME: should check item at sp [1] is compatible with the type of the store. */
 
        EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, type, dest->dreg, 0, value->dreg);
@@ -472,7 +504,7 @@ mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoIn
 void
 mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoInst *size, int ins_flag)
 {
-       int align = SIZEOF_VOID_P;
+       int align = (ins_flag & MONO_INST_UNALIGNED) ? 1 : SIZEOF_VOID_P;
 
        /*
         * FIXME: It's unclear whether we should be emitting both the acquire
@@ -487,11 +519,9 @@ mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, Mo
                mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
        }
 
-       if ((cfg->opt & MONO_OPT_INTRINS) && (size->opcode == OP_ICONST) && size->inst_c0 < 10000) {
+       if ((cfg->opt & MONO_OPT_INTRINS) && (size->opcode == OP_ICONST)) {
                mini_emit_memcpy_const_size (cfg, dest, src, size->inst_c0, align);
        } else {
-               if (cfg->verbose_level > 3)
-                       printf ("EMITING REGULAR COPY\n");
                mini_emit_memcpy_internal (cfg, dest, src, size, 0, align);
        }
 
@@ -504,7 +534,7 @@ mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, Mo
 void
 mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value, MonoInst *size, int ins_flag)
 {
-       int align = SIZEOF_VOID_P;
+       int align = (ins_flag & MONO_INST_UNALIGNED) ? 1 : SIZEOF_VOID_P;
 
        if (ins_flag & MONO_INST_VOLATILE) {
                /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
@@ -528,6 +558,10 @@ mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value,
 void
 mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native, int ins_flag)
 {
+       int explicit_align = 0;
+       if (ins_flag & MONO_INST_UNALIGNED)
+               explicit_align = 1;
+
        /*
         * FIXME: It's unclear whether we should be emitting both the acquire
         * and release barriers for cpblk. It is technically both a load and
@@ -541,7 +575,7 @@ mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClas
                mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
        }
 
-       mini_emit_memory_copy_internal (cfg, dest, src, klass, native);
+       mini_emit_memory_copy_internal (cfg, dest, src, klass, explicit_align, native);
 
        if (ins_flag & MONO_INST_VOLATILE) {
                /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */