Do not zero localalloc if not asked. (mono/mono#16881)
authorJay Krell <jaykrell@microsoft.com>
Mon, 7 Oct 2019 14:42:13 +0000 (07:42 -0700)
committerLarry Ewing <lewing@microsoft.com>
Mon, 7 Oct 2019 14:42:13 +0000 (09:42 -0500)
Note that we will still touch the pages (mono_emit_stack_alloc).

Commit migrated from https://github.com/mono/mono/commit/f0ff9f3860b50f3ed857b9b820d5adce5cbd7f10

src/mono/mono/mini/method-to-ir.c
src/mono/mono/tests/Makefile.am
src/mono/mono/tests/localloc-noinit.il [new file with mode: 0644]

index 184d333..8e4cc5d 100644 (file)
@@ -10941,7 +10941,7 @@ mono_ldptr:
                        MONO_ADD_INS (cfg->cbb, ins);
 
                        cfg->flags |= MONO_CFG_HAS_ALLOCA;
-                       if (init_locals)
+                       if (header->init_locals)
                                ins->flags |= MONO_INST_INIT;
 
                        MONO_START_BB (cfg, end_bb);
index 5239da1..6330eff 100755 (executable)
@@ -1030,6 +1030,7 @@ TESTS_IL_SRC=                     \
        gh-13057_mono_local_emulate_ops_av.il \
        module-cctor-entrypoint.il \
        bug-gh-9706.il \
+       localloc-noinit.il \
        calli_native.il
 
 # This test crashes the runtime, even with recent fixes.
@@ -1633,17 +1634,28 @@ REMOTING_DISABLED_TESTS = \
 
 if FULL_AOT_TESTS
 PROFILE_DISABLED_TESTS += $(REMOTING_DISABLED_TESTS)
+
+# Test is too sensitive.
+PROFILE_DISABLED_TESTS += localloc-noinit.exe
 endif
 
 if HYBRID_AOT_TESTS
 PROFILE_DISABLED_TESTS += $(REMOTING_DISABLED_TESTS)
+
+# Test is too sensitive.
+PROFILE_DISABLED_TESTS += localloc-noinit.exe
 endif
 
 if FULL_AOT_INTERP_TESTS
 PROFILE_DISABLED_TESTS += $(REMOTING_DISABLED_TESTS)
+
+# Test is too sensitive.
+PROFILE_DISABLED_TESTS += localloc-noinit.exe
+
 endif
 
 AOT_DISABLED_TESTS= \
+       localloc-noinit.exe \
        constraints-load.exe \
        calli_sig_check.exe
 
@@ -1910,6 +1922,8 @@ INTERP_DISABLED_TESTS += tailcall/interface-conservestack/9.exe
 # expected InvalidProgramException not thrown
 INTERP_DISABLED_TESTS += calli_sig_check.exe
 
+# Test is too sensitive.
+INTERP_DISABLED_TESTS += localloc-noinit.exe
 
 # bug-48015.exe: be careful when re-enabling, it happens that it returns with exit code 0, but doesn't actually execute the test.
 # bug-60862.exe: missing support to map IP->method; only works on platforms with altstack support.
@@ -1976,6 +1990,15 @@ INTERP_DISABLED_TESTS += \
        bug-80307.exe \
        dim-diamondshape.exe \
        pinvoke3.exe
+
+# Test is too sensitive.
+DISABLED_TESTS += localloc-noinit.exe
+
+endif
+
+if HOST_WIN32
+# Test is too sensitive?
+DISABLED_TESTS += localloc-noinit.exe
 endif
 
 if AMD64
diff --git a/src/mono/mono/tests/localloc-noinit.il b/src/mono/mono/tests/localloc-noinit.il
new file mode 100644 (file)
index 0000000..571fec0
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+using System;
+
+class A
+{
+       // In the il, remove "init" in the ".locals" of this function:
+       // There might be a way to write this in C# directly, but it is not
+       // straightforward.
+       static unsafe byte* NoInit (int size, byte value)
+       {
+               byte* data = stackalloc byte [0x10000 + size];
+               for (int i = 0; i < size; ++i)
+                       data [i] += value; // try to keep same form as Init function
+               return data;
+       }
+
+       static unsafe byte* Init (int size, byte value)
+       {
+               byte* data = stackalloc byte [0x10000 + size];
+               for (int i = 0; i < size; ++i)
+                       data [i] = value;
+               return data;
+       }
+
+       static void assert (int a, int b, int c, bool f)
+       {
+               if (f)
+                       return;
+               Console.WriteLine ("assert failed {0} {1} {2}", a, b, c);
+               Environment.Exit (1);
+       }
+
+       unsafe public static void Main ()
+       {
+               int count = 123;
+               byte value = 31;
+               byte * data;
+
+               data = Init (count, value);
+               for (int i = 0; i < 100; ++i)
+                       assert (1, i, data [i], data [i] == value);
+
+               data = NoInit (count, 0);
+               // Previously this would work:
+               for (int i = 0; i < 100; ++i)
+                       assert (2, i, data [i], data [i] == 0);
+
+               // Now this works:
+               for (int i = 0; i < 100; ++i)
+                       assert (3, i, data [i], data [i] == value);
+       }
+}
+*/
+
+.assembly extern mscorlib { }
+
+.assembly '1' { }
+
+.module '1.exe'
+
+.class A
+{
+  .method static uint8* NoInit(int32 size, uint8 valu) noinlining
+  {
+    .maxstack  3
+    .locals      (uint8* data, int32 i)
+//  .locals init (uint8* data, int32 i)
+       ldc.i4     0x10000
+       ldarg size
+       add
+       localloc
+//     ret             // changes stack layout do not match Init?
+       stloc data
+       ldc.i4 0
+       stloc i
+       br       IL_001d
+
+IL_0010:
+       ldloc data
+       ldloc i
+       add
+       dup
+       ldind.u1
+       ldarg valu
+       add
+       stind.i1
+       ldloc i
+       ldc.i4 1
+       add
+       stloc i
+IL_001d:
+       ldloc 1
+       ldarg size
+       clt
+       brtrue   IL_0010
+
+       ldloc data
+       ret
+  }
+
+  .method static uint8* Init (int32 size, uint8 valu) noinlining
+  {
+       .maxstack  2
+       .locals init (uint8* data, int32 i)
+       ldc.i4     0x10000
+       ldarg size
+       add
+       localloc
+       stloc data
+       ldc.i4 0
+       stloc i
+       br.s       IL_0019
+
+IL_0010:
+       ldloc data
+       ldloc i
+       add
+       ldarg valu
+       stind.i1
+       ldloc i
+       ldc.i4 1
+       add
+       stloc i
+IL_0019:
+       ldloc i
+       ldarg size
+       clt
+       brtrue   IL_0010
+
+       ldloc data
+       ret
+  }
+
+  .method static void  'assert' (int32 a, int32 b, int32 c, bool f)
+  {
+       .maxstack  4
+
+       ldarg.3
+       brfalse.s  IL_0008
+       br.s       IL_002c
+
+IL_0008:
+       ldstr      "assert failed {0} {1} {2}"
+       ldarg.0
+       box        [mscorlib]System.Int32
+       ldarg 1
+       box        [mscorlib]System.Int32
+       ldarg 2
+       box        [mscorlib]System.Int32
+       call       void [mscorlib]System.Console::WriteLine (string, object, object, object)
+       ldc.i4 1
+       call       void [mscorlib]System.Environment::Exit (int32)
+IL_002c:
+       ret
+  }
+
+  .method public static void Main ()
+  {
+    .entrypoint
+    .maxstack  5
+    .locals init (int32 count, uint8 valu, uint8* data, int32 i)
+
+// --------------------------------------------------
+
+       ldc.i4   123
+       stloc count
+       ldc.i4   31
+       stloc valu
+
+// --------------------------------------------------
+
+       ldloc count
+       ldloc valu
+       call       uint8* A::Init (int32, uint8)
+       stloc data
+
+
+       ldc.i4 0
+       stloc i
+       br.s       IL_0031
+IL_0013:
+       ldc.i4 1
+       ldloc i
+       ldloc i
+       ldloc data
+       add
+       ldind.u1
+       dup
+       ldloc valu
+       ceq
+       call       void A::'assert' (int32, int32, int32, bool)
+       ldloc i
+       ldc.i4 1
+       add
+       stloc i
+IL_0031:
+       ldloc i
+       ldc.i4   100
+       clt
+       brtrue   IL_0013
+
+ // --------------------------------------------------
+
+       ldloc count
+       ldc.i4 0
+       call       uint8* A::NoInit (int32, uint8)
+       stloc data
+
+// --------------------------------------------------
+/*
+       ldc.i4 0
+       stloc.s    i
+       br.s       IL_0065
+
+IL_0049:
+       ldc.i4 2
+       ldloc    i
+       ldloc data
+       ldloc    i
+       add
+       ldind.u1
+       dup
+       ldc.i4 0
+       ceq
+       call       void A::'assert' (int32, int32, int32, bool)
+       ldloc    i
+       ldc.i4 1
+       add
+       stloc    i
+IL_0065:
+       ldloc    i
+       ldc.i4   100
+       clt
+       brtrue   IL_0049
+*/
+// --------------------------------------------------
+       ldc.i4.0
+       stloc.s    i
+       br.s       IL_0092
+
+IL_0076:
+       ldc.i4 3
+       ldloc    i
+       ldloc data
+       ldloc    i
+       add
+       ldind.u1
+       dup
+       ldloc valu
+       ceq
+       call       void A::'assert' (int32, int32, int32, bool)
+       ldloc    i
+       ldc.i4 1
+       add
+       stloc    i
+IL_0092:
+       ldloc    i
+       ldc.i4   100
+       clt
+       brtrue   IL_0076
+       ret
+  }
+}