[mini] Expand clr-memory-model effect (mono/mono#17093)
authorVlad Brezae <brezaevlad@gmail.com>
Fri, 27 Sep 2019 09:36:04 +0000 (12:36 +0300)
committerGitHub <noreply@github.com>
Fri, 27 Sep 2019 09:36:04 +0000 (12:36 +0300)
* [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.

Commit migrated from https://github.com/mono/mono/commit/194506d495a2e2b7b2fad5dbb655f404cecb2c04

src/mono/mono/mini/intrinsics.c
src/mono/mono/mini/memory-access.c
src/mono/mono/mini/method-to-ir.c

index fff6ff5..9aa0101 100644 (file)
@@ -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;
index 93133a2..780010e 100644 (file)
@@ -13,6 +13,7 @@
 #include <mono/utils/mono-memory-model.h>
 
 #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;
index ac4bdf8..0fc7ca1 100644 (file)
@@ -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) {