X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fgc-test.cs;h=023a56d716507bda15dc1dc604531d94b82090eb;hb=f82f4e84b1332d94e52be8258f37f6d623c0a2c3;hp=498abf5271785dbdae789ce8bef17025f1e3314a;hpb=9e1f34dd2d7be45b2a3a6b1c133a4a1de8c3d864;p=mono.git diff --git a/mono/mini/gc-test.cs b/mono/mini/gc-test.cs index 498abf52717..023a56d7165 100644 --- a/mono/mini/gc-test.cs +++ b/mono/mini/gc-test.cs @@ -1,6 +1,8 @@ using System; using System.Reflection; using System.Runtime.CompilerServices; +using System.Collections; +using System.Threading; /* * Regression tests for the GC support in the JIT @@ -141,39 +143,6 @@ class Tests { (int)b.o31 + (int)b.o32; } - static void cond (bool b) { - if (b) { - /* Exhaust all registers so 'o' is stack allocated */ - int sum = 0, i, j, k, l, m; - for (i = 0; i < 100; ++i) - sum ++; - for (j = 0; j < 100; ++j) - sum ++; - for (k = 0; k < 100; ++k) - sum ++; - for (l = 0; l < 100; ++l) - sum ++; - for (m = 0; m < 100; ++m) - sum ++; - - object o = new object (); - sum += i + j + k; - if (b) { - throw new Exception (o.ToString ()); - } - } - GC.Collect (1); - } - - /* - * Tests liveness of object references which are initialized conditionally, - * used in an out-of-line bblock, and the initlocals assignment is optimized away. - */ - public static int test_0_liveness_out_of_line_bblocks () { - cond (false); - return 0; - } - /* * Test liveness and loops. */ @@ -358,10 +327,20 @@ class Tests { */ [MethodImplAttribute (MethodImplOptions.NoInlining)] - static object liveness_6_1 () { + static object alloc_obj () { return new object (); } + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static bool return_true () { + return true; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static bool return_false () { + return false; + } + public static int test_0_liveness_6 () { bool b = false; bool b2 = true; @@ -387,7 +366,7 @@ class Tests { GC.Collect (1); - object o = liveness_6_1 (); + object o = alloc_obj (); o.ToString (); @@ -398,4 +377,255 @@ class Tests { return 0; } -} \ No newline at end of file + + public static int test_0_multi_dim_ref_array_wbarrier () { + string [,] arr = new string [256, 256]; + for (int i = 0; i < 256; ++i) { + for (int j = 0; j < 100; ++j) + arr [i, j] = "" + i + " " + j; + } + GC.Collect (); + + return 0; + } + + /* + * Liveness + out of line bblocks + */ + public static int test_0_liveness_7 () { + /* Exhaust all registers so 'o' is stack allocated */ + int sum = 0, i, j, k, l, m, n, s; + for (i = 0; i < 100; ++i) + sum ++; + for (j = 0; j < 100; ++j) + sum ++; + for (k = 0; k < 100; ++k) + sum ++; + for (l = 0; l < 100; ++l) + sum ++; + for (m = 0; m < 100; ++m) + sum ++; + for (n = 0; n < 100; ++n) + sum ++; + for (s = 0; s < 100; ++s) + sum ++; + + // o is dead here + GC.Collect (1); + + if (return_false ()) { + // This bblock is in-line + object o = alloc_obj (); + // o is live here + if (return_false ()) { + // This bblock is out-of-line, and o is live here + throw new Exception (o.ToString ()); + } + } + + // o is dead here too + GC.Collect (1); + + return 0; + } + + // Liveness + finally clauses + public static int test_0_liveness_8 () { + /* Exhaust all registers so 'o' is stack allocated */ + int sum = 0, i, j, k, l, m, n, s; + for (i = 0; i < 100; ++i) + sum ++; + for (j = 0; j < 100; ++j) + sum ++; + for (k = 0; k < 100; ++k) + sum ++; + for (l = 0; l < 100; ++l) + sum ++; + for (m = 0; m < 100; ++m) + sum ++; + for (n = 0; n < 100; ++n) + sum ++; + for (s = 0; s < 100; ++s) + sum ++; + + object o = null; + try { + o = alloc_obj (); + } finally { + GC.Collect (1); + } + + o.GetHashCode (); + return 0; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static object alloc_string () { + return "A"; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static object alloc_obj_and_gc () { + GC.Collect (1); + return new object (); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void clobber_regs_and_gc () { + int sum = 0, i, j, k, l, m, n, s; + for (i = 0; i < 100; ++i) + sum ++; + for (j = 0; j < 100; ++j) + sum ++; + for (k = 0; k < 100; ++k) + sum ++; + for (l = 0; l < 100; ++l) + sum ++; + for (m = 0; m < 100; ++m) + sum ++; + for (n = 0; n < 100; ++n) + sum ++; + for (s = 0; s < 100; ++s) + sum ++; + GC.Collect (1); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void liveness_9_call1 (object o1, object o2, object o3) { + o1.GetHashCode (); + o2.GetHashCode (); + o3.GetHashCode (); + } + + // Liveness + JIT temporaries + public static int test_0_liveness_9 () { + // the result of alloc_obj () goes into a vreg, which gets converted to a + // JIT temporary because of the branching introduced by the cast + // FIXME: This doesn't crash if MONO_TYPE_I is not treated as a GC ref + liveness_9_call1 (alloc_obj (), (string)alloc_string (), alloc_obj_and_gc ()); + return 0; + } + + // Liveness for registers + public static int test_0_liveness_10 () { + // Make sure this goes into a register + object o = alloc_obj (); + o.GetHashCode (); + o.GetHashCode (); + o.GetHashCode (); + o.GetHashCode (); + o.GetHashCode (); + o.GetHashCode (); + // Break the bblock so o doesn't become a local vreg + if (return_true ()) + // Clobber it with a call and run a GC + clobber_regs_and_gc (); + // Access it again + o.GetHashCode (); + return 0; + } + + // Liveness for spill slots holding managed pointers + public static int test_0_liveness_11 () { + Tests[] arr = new Tests [10]; + // This uses an ldelema internally + // FIXME: This doesn't crash if mp-s are not correctly tracked, just writes to + // an old object. + arr [0] >>= 1; + + return 0; + } + + public static Tests operator >> (Tests bi1, int shiftVal) { + clobber_regs_and_gc (); + return bi1; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void liveness_12_inner (int a, int b, int c, int d, int e, int f, object o, ref string s) { + GC.Collect (1); + o.GetHashCode (); + s.GetHashCode (); + } + + class FooClass { + public string s; + } + + // Liveness for param area + public static int test_0_liveness_12 () { + var f = new FooClass () { s = "A" }; + // The ref argument should be passed on the stack + liveness_12_inner (1, 2, 3, 4, 5, 6, new object (), ref f.s); + return 0; + } + + interface IFace { + int foo (); + } + + struct BarStruct : IFace { + int i; + + public int foo () { + GC.Collect (); + return i; + } + } + + public static int test_0_liveness_unbox_trampoline () { + var s = new BarStruct (); + + IFace iface = s; + iface.foo (); + return 0; + } + + public static void liveness_13_inner (ref ArrayList arr) { + // The value of arr will be stored in a spill slot + arr.Add (alloc_obj_and_gc ()); + } + + // Liveness for byref arguments in spill slots + public static int test_0_liveness_13 () { + var arr = new ArrayList (); + liveness_13_inner (ref arr); + return 0; + } + + static ThreadLocal tls; + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + static void alloc_tls_obj () { + tls = new ThreadLocal (); + tls.Value = new object (); + } + + public static int test_0_thread_local () { + alloc_tls_obj (); + GC.Collect (); + Type t = tls.Value.GetType (); + if (t == typeof (object)) + return 0; + else + return 1; + } + + struct LargeBitmap { + public object o1, o2, o3; + public int i; + public object o4, o5, o6, o7, o9, o10, o11, o12, o13, o14, o15, o16, o17, o18, o19, o20, o21, o22, o23, o24, o25, o26, o27, o28, o29, o30, o31, o32; + } + + public static int test_12_large_bitmap () { + LargeBitmap lb = new LargeBitmap (); + lb.o1 = 1; + lb.o2 = 2; + lb.o3 = 3; + lb.o32 = 6; + + GC.Collect (0); + + return (int)lb.o1 + (int)lb.o2 + (int)lb.o3 + (int)lb.o32; + } +}