2 using System.Reflection;
3 using System.Runtime.CompilerServices;
4 using System.Collections;
5 using System.Threading;
8 * Regression tests for the GC support in the JIT
17 public static int Main (string[] args) {
18 return TestDriver.RunTests (typeof (Tests), args);
22 public static int test_36_simple () {
23 // Overflow the registers
33 /* Prevent the variables from being local to a bb */
38 return (int)o1 + (int)o2 + (int)o3 + (int)o4 + (int)o5 + (int)o6 + (int)o7 + (int)o8;
43 public static int test_36_liveness () {
45 object o1, o2, o3, o4, o5, o6, o7, o8;
61 return (int)o1 + (int)o2 + (int)o3 + (int)o4 + (int)o5 + (int)o6 + (int)o7 + (int)o8;
71 public FooStruct (int i1, int i, int i2) {
78 public static int test_4_vtype () {
79 FooStruct s = new FooStruct (1, 2, 3);
83 return (int)s.o1 + (int)s.o2;
87 public object o1, o2, o3, o4, o5, o6, o7, o8, o9, o10;
88 public object o11, o12, o13, o14, o15, o16, o17, o18, o19, o20;
89 public object o21, o22, o23, o24, o25, o26, o27, o28, o29, o30;
90 public object o31, o32;
93 static void set_fields (BigClass b) {
129 // Test marking of objects with > 32 fields
130 public static int test_528_mark_runlength_large () {
131 BigClass b = new BigClass ();
134 * Do the initialization in a separate method so no object refs remain in
142 (int)b.o1 + (int)b.o2 + (int)b.o3 + (int)b.o4 + (int)b.o5 +
143 (int)b.o6 + (int)b.o7 + (int)b.o8 + (int)b.o9 + (int)b.o10 +
144 (int)b.o11 + (int)b.o12 + (int)b.o13 + (int)b.o14 + (int)b.o15 +
145 (int)b.o16 + (int)b.o17 + (int)b.o18 + (int)b.o19 + (int)b.o20 +
146 (int)b.o21 + (int)b.o22 + (int)b.o23 + (int)b.o24 + (int)b.o25 +
147 (int)b.o26 + (int)b.o27 + (int)b.o28 + (int)b.o29 + (int)b.o30 +
148 (int)b.o31 + (int)b.o32;
152 * Test liveness and loops.
154 public static int test_0_liveness_2 () {
155 object o = new object ();
156 for (int n = 0; n < 10; ++n) {
157 /* Exhaust all registers so 'o' is stack allocated */
158 int sum = 0, i, j, k, l, m;
159 for (i = 0; i < 100; ++i)
161 for (j = 0; j < 100; ++j)
163 for (k = 0; k < 100; ++k)
165 for (l = 0; l < 100; ++l)
167 for (m = 0; m < 100; ++m)
187 * Test liveness and stack slot sharing
188 * This doesn't work yet, its hard to make the JIT share the stack slots of the
191 public static int test_0_liveness_3 () {
195 /* Exhaust all registers so 'o' is stack allocated */
196 int sum = 0, i, j, k, l, m, n, s;
197 for (i = 0; i < 100; ++i)
199 for (j = 0; j < 100; ++j)
201 for (k = 0; k < 100; ++k)
203 for (l = 0; l < 100; ++l)
205 for (m = 0; m < 100; ++m)
207 for (n = 0; n < 100; ++n)
209 for (s = 0; s < 100; ++s)
213 object o = new object ();
215 /* Make sure o is global */
217 Console.WriteLine ();
225 object o = new object ();
227 /* Make sure o is global */
229 Console.WriteLine ();
234 sum += i + j + k + l + m + n + s;
240 * Test liveness of variables used to handle items on the IL stack.
242 [MethodImplAttribute (MethodImplOptions.NoInlining)]
243 static string call1 () {
247 [MethodImplAttribute (MethodImplOptions.NoInlining)]
248 static string call2 () {
253 public static int test_0_liveness_4 () {
257 /* Exhaust all registers so 'o' is stack allocated */
258 int sum = 0, i, j, k, l, m, n, s;
259 for (i = 0; i < 100; ++i)
261 for (j = 0; j < 100; ++j)
263 for (k = 0; k < 100; ++k)
265 for (l = 0; l < 100; ++l)
267 for (m = 0; m < 100; ++m)
269 for (n = 0; n < 100; ++n)
271 for (s = 0; s < 100; ++s)
274 string o = b ? call1 () : call2 ();
278 sum += i + j + k + l + m + n + s;
285 * Test liveness of volatile variables
287 [MethodImplAttribute (MethodImplOptions.NoInlining)]
288 static void liveness_5_1 (out object o) {
292 public static int test_0_liveness_5 () {
296 /* Exhaust all registers so 'o' is stack allocated */
297 int sum = 0, i, j, k, l, m, n, s;
298 for (i = 0; i < 100; ++i)
300 for (j = 0; j < 100; ++j)
302 for (k = 0; k < 100; ++k)
304 for (l = 0; l < 100; ++l)
306 for (m = 0; m < 100; ++m)
308 for (n = 0; n < 100; ++n)
310 for (s = 0; s < 100; ++s)
315 liveness_5_1 (out o);
317 for (int x = 0; x < 10; ++x) {
324 sum += i + j + k + l + m + n + s;
330 * Test the case when a stack slot becomes dead, then live again due to a backward
334 [MethodImplAttribute (MethodImplOptions.NoInlining)]
335 static object alloc_obj () {
336 return new object ();
339 [MethodImplAttribute (MethodImplOptions.NoInlining)]
340 static bool return_true () {
344 [MethodImplAttribute (MethodImplOptions.NoInlining)]
345 static bool return_false () {
349 public static int test_0_liveness_6 () {
353 /* Exhaust all registers so 'o' is stack allocated */
354 int sum = 0, i, j, k, l, m, n, s;
355 for (i = 0; i < 100; ++i)
357 for (j = 0; j < 100; ++j)
359 for (k = 0; k < 100; ++k)
361 for (l = 0; l < 100; ++l)
363 for (m = 0; m < 100; ++m)
365 for (n = 0; n < 100; ++n)
367 for (s = 0; s < 100; ++s)
370 for (int x = 0; x < 10; ++x) {
374 object o = alloc_obj ();
381 sum += i + j + k + l + m + n + s;
386 public static int test_0_multi_dim_ref_array_wbarrier () {
387 string [,] arr = new string [256, 256];
388 for (int i = 0; i < 256; ++i) {
389 for (int j = 0; j < 100; ++j)
390 arr [i, j] = "" + i + " " + j;
398 * Liveness + out of line bblocks
400 public static int test_0_liveness_7 () {
401 /* Exhaust all registers so 'o' is stack allocated */
402 int sum = 0, i, j, k, l, m, n, s;
403 for (i = 0; i < 100; ++i)
405 for (j = 0; j < 100; ++j)
407 for (k = 0; k < 100; ++k)
409 for (l = 0; l < 100; ++l)
411 for (m = 0; m < 100; ++m)
413 for (n = 0; n < 100; ++n)
415 for (s = 0; s < 100; ++s)
421 if (return_false ()) {
422 // This bblock is in-line
423 object o = alloc_obj ();
425 if (return_false ()) {
426 // This bblock is out-of-line, and o is live here
427 throw new Exception (o.ToString ());
431 // o is dead here too
437 // Liveness + finally clauses
438 public static int test_0_liveness_8 () {
439 /* Exhaust all registers so 'o' is stack allocated */
440 int sum = 0, i, j, k, l, m, n, s;
441 for (i = 0; i < 100; ++i)
443 for (j = 0; j < 100; ++j)
445 for (k = 0; k < 100; ++k)
447 for (l = 0; l < 100; ++l)
449 for (m = 0; m < 100; ++m)
451 for (n = 0; n < 100; ++n)
453 for (s = 0; s < 100; ++s)
467 [MethodImplAttribute (MethodImplOptions.NoInlining)]
468 static object alloc_string () {
472 [MethodImplAttribute (MethodImplOptions.NoInlining)]
473 static object alloc_obj_and_gc () {
475 return new object ();
478 [MethodImplAttribute (MethodImplOptions.NoInlining)]
479 static void clobber_regs_and_gc () {
480 int sum = 0, i, j, k, l, m, n, s;
481 for (i = 0; i < 100; ++i)
483 for (j = 0; j < 100; ++j)
485 for (k = 0; k < 100; ++k)
487 for (l = 0; l < 100; ++l)
489 for (m = 0; m < 100; ++m)
491 for (n = 0; n < 100; ++n)
493 for (s = 0; s < 100; ++s)
498 [MethodImplAttribute (MethodImplOptions.NoInlining)]
499 static void liveness_9_call1 (object o1, object o2, object o3) {
505 // Liveness + JIT temporaries
506 public static int test_0_liveness_9 () {
507 // the result of alloc_obj () goes into a vreg, which gets converted to a
508 // JIT temporary because of the branching introduced by the cast
509 // FIXME: This doesn't crash if MONO_TYPE_I is not treated as a GC ref
510 liveness_9_call1 (alloc_obj (), (string)alloc_string (), alloc_obj_and_gc ());
514 // Liveness for registers
515 public static int test_0_liveness_10 () {
516 // Make sure this goes into a register
517 object o = alloc_obj ();
524 // Break the bblock so o doesn't become a local vreg
526 // Clobber it with a call and run a GC
527 clobber_regs_and_gc ();
533 class ObjWithShiftOp {
534 public static ObjWithShiftOp operator >> (ObjWithShiftOp bi1, int shiftVal) {
535 clobber_regs_and_gc ();
540 // Liveness for spill slots holding managed pointers
541 public static int test_0_liveness_11 () {
542 ObjWithShiftOp[] arr = new ObjWithShiftOp [10];
543 // This uses an ldelema internally
544 // FIXME: This doesn't crash if mp-s are not correctly tracked, just writes to
552 [MethodImplAttribute (MethodImplOptions.NoInlining)]
553 public static void liveness_12_inner (int a, int b, int c, int d, int e, int f, object o, ref string s) {
563 // Liveness for param area
564 public static int test_0_liveness_12 () {
565 var f = new FooClass () { s = "A" };
566 // The ref argument should be passed on the stack
567 liveness_12_inner (1, 2, 3, 4, 5, 6, new object (), ref f.s);
575 struct BarStruct : IFace {
584 public static int test_0_liveness_unbox_trampoline () {
585 var s = new BarStruct ();
592 public static void liveness_13_inner (ref ArrayList arr) {
593 // The value of arr will be stored in a spill slot
594 arr.Add (alloc_obj_and_gc ());
597 // Liveness for byref arguments in spill slots
598 public static int test_0_liveness_13 () {
599 var arr = new ArrayList ();
600 liveness_13_inner (ref arr);
604 static ThreadLocal<object> tls;
606 [MethodImplAttribute (MethodImplOptions.NoInlining)]
607 static void alloc_tls_obj () {
608 tls = new ThreadLocal<object> ();
609 tls.Value = new object ();
612 public static int test_0_thread_local () {
615 Type t = tls.Value.GetType ();
616 if (t == typeof (object))
623 public object o1, o2, o3;
625 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;
628 public static int test_12_large_bitmap () {
629 LargeBitmap lb = new LargeBitmap ();
637 return (int)lb.o1 + (int)lb.o2 + (int)lb.o3 + (int)lb.o32;