[jit] Remove mini_emit_stobj from method-to-ir.c and move mini_emit_wb_aware_memcpy...
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 11 May 2017 23:36:26 +0000 (16:36 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 18 May 2017 01:51:19 +0000 (18:51 -0700)
mono/mini/memory-access.c
mono/mini/method-to-ir.c
mono/mini/mini.h

index f6030b0cbd0dec35f0822fb0c741c8a27a55bc3a..57b7c92b19c4cbe97f71c69d2502f1e64353d1ab 100644 (file)
@@ -233,6 +233,107 @@ mini_emit_memset_const_size (MonoCompile *cfg, MonoInst *dest, int value, int si
        mini_emit_memset_internal (cfg, dest, NULL, value, NULL, size, align);
 }
 
+
+static void
+create_write_barrier_bitmap (MonoCompile *cfg, MonoClass *klass, unsigned *wb_bitmap, int offset)
+{
+       MonoClassField *field;
+       gpointer iter = NULL;
+
+       while ((field = mono_class_get_fields (klass, &iter))) {
+               int foffset;
+
+               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                       continue;
+               foffset = klass->valuetype ? field->offset - sizeof (MonoObject): field->offset;
+               if (mini_type_is_reference (mono_field_get_type (field))) {
+                       g_assert ((foffset % SIZEOF_VOID_P) == 0);
+                       *wb_bitmap |= 1 << ((offset + foffset) / SIZEOF_VOID_P);
+               } else {
+                       MonoClass *field_class = mono_class_from_mono_type (field->type);
+                       if (field_class->has_references)
+                               create_write_barrier_bitmap (cfg, field_class, wb_bitmap, offset + foffset);
+               }
+       }
+}
+
+static gboolean
+mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align)
+{
+       int dest_ptr_reg, tmp_reg, destreg, srcreg, offset;
+       unsigned need_wb = 0;
+
+       if (align == 0)
+               align = 4;
+
+       /*types with references can't have alignment smaller than sizeof(void*) */
+       if (align < SIZEOF_VOID_P)
+               return FALSE;
+
+       if (size > 5 * SIZEOF_VOID_P)
+               return FALSE;
+
+       create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
+
+       destreg = iargs [0]->dreg;
+       srcreg = iargs [1]->dreg;
+       offset = 0;
+
+       dest_ptr_reg = alloc_preg (cfg);
+       tmp_reg = alloc_preg (cfg);
+
+       /*tmp = dreg*/
+       EMIT_NEW_UNALU (cfg, iargs [0], OP_MOVE, dest_ptr_reg, destreg);
+
+       while (size >= SIZEOF_VOID_P) {
+               MonoInst *load_inst;
+               MONO_INST_NEW (cfg, load_inst, OP_LOAD_MEMBASE);
+               load_inst->dreg = tmp_reg;
+               load_inst->inst_basereg = srcreg;
+               load_inst->inst_offset = offset;
+               MONO_ADD_INS (cfg->cbb, load_inst);
+
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, dest_ptr_reg, 0, tmp_reg);
+
+               if (need_wb & 0x1)
+                       mini_emit_write_barrier (cfg, iargs [0], load_inst);
+
+               offset += SIZEOF_VOID_P;
+               size -= SIZEOF_VOID_P;
+               need_wb >>= 1;
+
+               /*tmp += sizeof (void*)*/
+               if (size >= SIZEOF_VOID_P) {
+                       NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dest_ptr_reg, dest_ptr_reg, SIZEOF_VOID_P);
+                       MONO_ADD_INS (cfg->cbb, iargs [0]);
+               }
+       }
+
+       /* Those cannot be references since size < sizeof (void*) */
+       while (size >= 4) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tmp_reg, srcreg, offset);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, tmp_reg);
+               offset += 4;
+               size -= 4;
+       }
+
+       while (size >= 2) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmp_reg, srcreg, offset);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, tmp_reg);
+               offset += 2;
+               size -= 2;
+       }
+
+       while (size >= 1) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmp_reg, srcreg, offset);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, tmp_reg);
+               offset += 1;
+               size -= 1;
+       }
+
+       return TRUE;
+}
+
 static void
 mini_emit_memory_copy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native)
 {
index 2883c23ea3cedd7fe144d4086ddeeb2ec41eef61..b07f117d957ad765223db3a6feb794939df13379 100644 (file)
@@ -2827,29 +2827,6 @@ mini_get_memcpy_method (void)
        return memcpy_method;
 }
 
-static void
-create_write_barrier_bitmap (MonoCompile *cfg, MonoClass *klass, unsigned *wb_bitmap, int offset)
-{
-       MonoClassField *field;
-       gpointer iter = NULL;
-
-       while ((field = mono_class_get_fields (klass, &iter))) {
-               int foffset;
-
-               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
-                       continue;
-               foffset = klass->valuetype ? field->offset - sizeof (MonoObject): field->offset;
-               if (mini_type_is_reference (mono_field_get_type (field))) {
-                       g_assert ((foffset % SIZEOF_VOID_P) == 0);
-                       *wb_bitmap |= 1 << ((offset + foffset) / SIZEOF_VOID_P);
-               } else {
-                       MonoClass *field_class = mono_class_from_mono_type (field->type);
-                       if (field_class->has_references)
-                               create_write_barrier_bitmap (cfg, field_class, wb_bitmap, offset + foffset);
-               }
-       }
-}
-
 void
 mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
 {
@@ -2908,177 +2885,6 @@ mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
        EMIT_NEW_DUMMY_USE (cfg, dummy_use, value);
 }
 
-gboolean
-mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align)
-{
-       int dest_ptr_reg, tmp_reg, destreg, srcreg, offset;
-       unsigned need_wb = 0;
-
-       if (align == 0)
-               align = 4;
-
-       /*types with references can't have alignment smaller than sizeof(void*) */
-       if (align < SIZEOF_VOID_P)
-               return FALSE;
-
-       if (size > 5 * SIZEOF_VOID_P)
-               return FALSE;
-
-       create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
-
-       destreg = iargs [0]->dreg;
-       srcreg = iargs [1]->dreg;
-       offset = 0;
-
-       dest_ptr_reg = alloc_preg (cfg);
-       tmp_reg = alloc_preg (cfg);
-
-       /*tmp = dreg*/
-       EMIT_NEW_UNALU (cfg, iargs [0], OP_MOVE, dest_ptr_reg, destreg);
-
-       while (size >= SIZEOF_VOID_P) {
-               MonoInst *load_inst;
-               MONO_INST_NEW (cfg, load_inst, OP_LOAD_MEMBASE);
-               load_inst->dreg = tmp_reg;
-               load_inst->inst_basereg = srcreg;
-               load_inst->inst_offset = offset;
-               MONO_ADD_INS (cfg->cbb, load_inst);
-
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, dest_ptr_reg, 0, tmp_reg);
-
-               if (need_wb & 0x1)
-                       mini_emit_write_barrier (cfg, iargs [0], load_inst);
-
-               offset += SIZEOF_VOID_P;
-               size -= SIZEOF_VOID_P;
-               need_wb >>= 1;
-
-               /*tmp += sizeof (void*)*/
-               if (size >= SIZEOF_VOID_P) {
-                       NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dest_ptr_reg, dest_ptr_reg, SIZEOF_VOID_P);
-                       MONO_ADD_INS (cfg->cbb, iargs [0]);
-               }
-       }
-
-       /* Those cannot be references since size < sizeof (void*) */
-       while (size >= 4) {
-               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tmp_reg, srcreg, offset);
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, tmp_reg);
-               offset += 4;
-               size -= 4;
-       }
-
-       while (size >= 2) {
-               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmp_reg, srcreg, offset);
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, tmp_reg);
-               offset += 2;
-               size -= 2;
-       }
-
-       while (size >= 1) {
-               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmp_reg, srcreg, offset);
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, tmp_reg);
-               offset += 1;
-               size -= 1;
-       }
-
-       return TRUE;
-}
-
-/*
- * Emit code to copy a valuetype of type @klass whose address is stored in
- * @src->dreg to memory whose address is stored at @dest->dreg.
- */
-void
-mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native)
-{
-       MonoInst *iargs [4];
-       int n;
-       guint32 align = 0;
-       MonoMethod *memcpy_method;
-       MonoInst *size_ins = NULL;
-       MonoInst *memcpy_ins = NULL;
-
-       g_assert (klass);
-       if (cfg->gshared)
-               klass = mono_class_from_mono_type (mini_get_underlying_type (&klass->byval_arg));
-
-       /*
-        * This check breaks with spilled vars... need to handle it during verification anyway.
-        * g_assert (klass && klass == src->klass && klass == dest->klass);
-        */
-
-       if (mini_is_gsharedvt_klass (klass)) {
-               g_assert (!native);
-               size_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_VALUE_SIZE);
-               memcpy_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_MEMCPY);
-       }
-
-       if (native)
-               n = mono_class_native_size (klass, &align);
-       else
-               n = mono_class_value_size (klass, &align);
-
-       if (!align)
-               align = SIZEOF_VOID_P;
-       /* if native is true there should be no references in the struct */
-       if (cfg->gen_write_barriers && (klass->has_references || size_ins) && !native) {
-               /* Avoid barriers when storing to the stack */
-               if (!((dest->opcode == OP_ADD_IMM && dest->sreg1 == cfg->frame_reg) ||
-                         (dest->opcode == OP_LDADDR))) {
-                       int context_used;
-
-                       iargs [0] = dest;
-                       iargs [1] = src;
-
-                       context_used = mini_class_check_context_used (cfg, klass);
-
-                       /* It's ok to intrinsify under gsharing since shared code types are layout stable. */
-                       if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && mini_emit_wb_aware_memcpy (cfg, klass, iargs, n, align)) {
-                               return;
-                       } else if (size_ins || align < SIZEOF_VOID_P) {
-                               if (context_used) {
-                                       iargs [2] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
-                               }  else {
-                                       iargs [2] = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass);
-                                       if (!cfg->compile_aot)
-                                               mono_class_compute_gc_descriptor (klass);
-                               }
-                               if (size_ins)
-                                       mono_emit_jit_icall (cfg, mono_gsharedvt_value_copy, iargs);
-                               else
-                                       mono_emit_jit_icall (cfg, mono_value_copy, iargs);
-                       } else {
-                               /* We don't unroll more than 5 stores to avoid code bloat. */
-                               /*This is harmless and simplify mono_gc_get_range_copy_func */
-                               n += (SIZEOF_VOID_P - 1);
-                               n &= ~(SIZEOF_VOID_P - 1);
-
-                               EMIT_NEW_ICONST (cfg, iargs [2], n);
-                               mono_emit_jit_icall (cfg, mono_gc_get_range_copy_func (), iargs);
-                       }
-               }
-       }
-
-       if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 8) {
-               /* FIXME: Optimize the case when src/dest is OP_LDADDR */
-               mini_emit_memcpy (cfg, dest->dreg, 0, src->dreg, 0, n, align);
-       } else {
-               iargs [0] = dest;
-               iargs [1] = src;
-               if (size_ins)
-                       iargs [2] = size_ins;
-               else
-                       EMIT_NEW_ICONST (cfg, iargs [2], n);
-               
-               memcpy_method = mini_get_memcpy_method ();
-               if (memcpy_ins)
-                       mini_emit_calli (cfg, mono_method_signature (memcpy_method), iargs, memcpy_ins, NULL, NULL);
-               else
-                       mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
-       }
-}
-
 MonoMethod*
 mini_get_memset_method (void)
 {
index 0d860307421d54c2c9b80842cacba2b5f070ac46..c9a18e873622329602f8b2d26a54817fe8a52d91 100644 (file)
@@ -2652,7 +2652,6 @@ MonoInst*         mini_emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClas
 MonoInst*         mini_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg);
 MonoInst*         mini_emit_memory_barrier (MonoCompile *cfg, int kind);
 void              mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value);
-gboolean          mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align);
 MonoInst*         mini_emit_memory_load (MonoCompile *cfg, MonoType *type, MonoInst *src, int offset, int ins_flag);
 void              mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoInst *value, int ins_flag);
 void              mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoInst *size, int ins_flag);