From eec0a6600963a12a8e8c3ae6caaa744e38a8e7f4 Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Thu, 11 May 2017 16:36:26 -0700 Subject: [PATCH] [jit] Remove mini_emit_stobj from method-to-ir.c and move mini_emit_wb_aware_memcpy to memory-access.c --- mono/mini/memory-access.c | 101 ++++++++++++++++++++ mono/mini/method-to-ir.c | 194 -------------------------------------- mono/mini/mini.h | 1 - 3 files changed, 101 insertions(+), 195 deletions(-) diff --git a/mono/mini/memory-access.c b/mono/mini/memory-access.c index f6030b0cbd0..57b7c92b19c 100644 --- a/mono/mini/memory-access.c +++ b/mono/mini/memory-access.c @@ -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) { diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 2883c23ea3c..b07f117d957 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -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) { diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 0d860307421..c9a18e87362 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -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); -- 2.25.1