From 194506d495a2e2b7b2fad5dbb655f404cecb2c04 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Fri, 27 Sep 2019 12:36:04 +0300 Subject: [PATCH] [mini] Expand clr-memory-model effect (#17093) * [mini] Add memory barriers to more stores inside objects We should now have membars for all stores of an object ref inside another object (for the stores done by the jit). Used by clr-memory-model debug option. * [mini] Add memory barrier for storing objref in static fields For clr-memory-model debug option. --- mono/mini/intrinsics.c | 8 ++++++++ mono/mini/memory-access.c | 10 +++++++++- mono/mini/method-to-ir.c | 18 +++++++++++++++--- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/mono/mini/intrinsics.c b/mono/mini/intrinsics.c index fff6ff5bd9d..9aa0101314c 100644 --- a/mono/mini/intrinsics.c +++ b/mono/mini/intrinsics.c @@ -34,6 +34,8 @@ emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst MonoType *etype = m_class_get_byval_arg (eklass); if (is_set) { EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, etype, args [2]->dreg, 0); + if (mini_debug_options.clr_memory_model && mini_type_is_reference (etype)) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, etype, addr->dreg, 0, load->dreg); if (mini_type_is_reference (etype)) mini_emit_write_barrier (cfg, addr, load); @@ -1199,6 +1201,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign MONO_ADD_INS (cfg->cbb, f2i); } + if (is_ref && mini_debug_options.clr_memory_model) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); + MONO_INST_NEW (cfg, ins, opcode); ins->dreg = is_ref ? mono_alloc_ireg_ref (cfg) : mono_alloc_ireg (cfg); ins->inst_basereg = args [0]->dreg; @@ -1299,6 +1304,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign MONO_ADD_INS (cfg->cbb, f2i_cmp); } + if (is_ref && mini_debug_options.clr_memory_model) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); + MONO_INST_NEW (cfg, ins, opcode); ins->dreg = is_ref ? alloc_ireg_ref (cfg) : alloc_ireg (cfg); ins->sreg1 = args [0]->dreg; diff --git a/mono/mini/memory-access.c b/mono/mini/memory-access.c index 93133a23581..780010e7014 100644 --- a/mono/mini/memory-access.c +++ b/mono/mini/memory-access.c @@ -13,6 +13,7 @@ #include #include "mini.h" +#include "mini-runtime.h" #include "ir-emit.h" #include "jit-icalls.h" @@ -293,6 +294,9 @@ mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4 /*tmp = dreg*/ EMIT_NEW_UNALU (cfg, iargs [0], OP_MOVE, dest_ptr_reg, destreg); + if ((need_wb & 0x1) && mini_debug_options.clr_memory_model) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); + while (size >= TARGET_SIZEOF_VOID_P) { MonoInst *load_inst; MONO_INST_NEW (cfg, load_inst, OP_LOAD_MEMBASE); @@ -390,6 +394,9 @@ mini_emit_memory_copy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src, NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, dreg, src->dreg, 0); MONO_ADD_INS (cfg->cbb, load); + if (mini_debug_options.clr_memory_model) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); + NEW_STORE_MEMBASE (cfg, store, OP_STORE_MEMBASE_REG, dest->dreg, 0, dreg); MONO_ADD_INS (cfg->cbb, store); @@ -486,7 +493,8 @@ mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoIn 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); - } + } else if (mini_debug_options.clr_memory_model && mini_type_is_reference (type)) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); if (ins_flag & MONO_INST_UNALIGNED) { MonoInst *addr, *mov, *tmp_var; diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index ac4bdf8a30e..0fc7ca179be 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -3530,6 +3530,8 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, target->dreg, 0); MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException"); } + if (mini_debug_options.clr_memory_model) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, target), target->dreg); if (cfg->gen_write_barriers) { dreg = alloc_preg (cfg); @@ -4228,6 +4230,8 @@ mini_emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboole EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), array_reg, offset, sp [2]->dreg); } else { MonoInst *addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], safety_checks); + if (mini_debug_options.clr_memory_model && mini_class_is_reference (klass)) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, m_class_get_byval_arg (klass), addr->dreg, 0, sp [2]->dreg); if (mini_class_is_reference (klass)) mini_emit_write_barrier (cfg, addr, sp [2]); @@ -7746,6 +7750,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } addr = mini_emit_ldelema_ins (cfg, cmethod, sp, ip, TRUE); + if (mini_debug_options.clr_memory_model && val->type == STACK_OBJ) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, fsig->params [fsig->param_count - 1], addr->dreg, 0, val->dreg); if (cfg->gen_write_barriers && val->type == STACK_OBJ && !MONO_INS_IS_PCONST_NULL (val)) mini_emit_write_barrier (cfg, addr, val); @@ -8242,6 +8248,8 @@ calli_end: if (il_op == MONO_CEE_STIND_R4 && sp [1]->type == STACK_R8) sp [1] = convert_value (cfg, m_class_get_byval_arg (mono_defaults.single_class), sp [1]); + if (mini_debug_options.clr_memory_model && il_op == MONO_CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER) + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); NEW_STORE_MEMBASE (cfg, ins, stind_to_store_membase (il_op), sp [0]->dreg, 0, sp [1]->dreg); ins->flags |= ins_flag; ins_flag = 0; @@ -9484,9 +9492,13 @@ calli_end: /* Generate IR to do the actual load/store operation */ - if ((il_op == MONO_CEE_STFLD || il_op == MONO_CEE_STSFLD) && (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); + if ((il_op == MONO_CEE_STFLD || il_op == MONO_CEE_STSFLD)) { + 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); + } else if (mini_debug_options.clr_memory_model && mini_type_is_reference (ftype)) { + mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL); + } } if (il_op == MONO_CEE_LDSFLDA) { -- 2.11.4.GIT