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
14 return TestDriver
.RunTests (typeof (Tests
));
17 public static int test_36_simple () {
18 // Overflow the registers
28 /* Prevent the variables from being local to a bb */
33 return (int)o1
+ (int)o2
+ (int)o3
+ (int)o4
+ (int)o5
+ (int)o6
+ (int)o7
+ (int)o8
;
38 public static int test_36_liveness () {
40 object o1
, o2
, o3
, o4
, o5
, o6
, o7
, o8
;
56 return (int)o1
+ (int)o2
+ (int)o3
+ (int)o4
+ (int)o5
+ (int)o6
+ (int)o7
+ (int)o8
;
66 public FooStruct (int i1
, int i
, int i2
) {
73 public static int test_4_vtype () {
74 FooStruct s
= new FooStruct (1, 2, 3);
78 return (int)s
.o1
+ (int)s
.o2
;
82 public object o1
, o2
, o3
, o4
, o5
, o6
, o7
, o8
, o9
, o10
;
83 public object o11
, o12
, o13
, o14
, o15
, o16
, o17
, o18
, o19
, o20
;
84 public object o21
, o22
, o23
, o24
, o25
, o26
, o27
, o28
, o29
, o30
;
85 public object o31
, o32
;
88 static void set_fields (BigClass b
) {
124 // Test marking of objects with > 32 fields
125 public static int test_528_mark_runlength_large () {
126 BigClass b
= new BigClass ();
129 * Do the initialization in a separate method so no object refs remain in
137 (int)b
.o1
+ (int)b
.o2
+ (int)b
.o3
+ (int)b
.o4
+ (int)b
.o5
+
138 (int)b
.o6
+ (int)b
.o7
+ (int)b
.o8
+ (int)b
.o9
+ (int)b
.o10
+
139 (int)b
.o11
+ (int)b
.o12
+ (int)b
.o13
+ (int)b
.o14
+ (int)b
.o15
+
140 (int)b
.o16
+ (int)b
.o17
+ (int)b
.o18
+ (int)b
.o19
+ (int)b
.o20
+
141 (int)b
.o21
+ (int)b
.o22
+ (int)b
.o23
+ (int)b
.o24
+ (int)b
.o25
+
142 (int)b
.o26
+ (int)b
.o27
+ (int)b
.o28
+ (int)b
.o29
+ (int)b
.o30
+
143 (int)b
.o31
+ (int)b
.o32
;
147 * Test liveness and loops.
149 public static int test_0_liveness_2 () {
150 object o
= new object ();
151 for (int n
= 0; n
< 10; ++n
) {
152 /* Exhaust all registers so 'o' is stack allocated */
153 int sum
= 0, i
, j
, k
, l
, m
;
154 for (i
= 0; i
< 100; ++i
)
156 for (j
= 0; j
< 100; ++j
)
158 for (k
= 0; k
< 100; ++k
)
160 for (l
= 0; l
< 100; ++l
)
162 for (m
= 0; m
< 100; ++m
)
182 * Test liveness and stack slot sharing
183 * This doesn't work yet, its hard to make the JIT share the stack slots of the
186 public static int test_0_liveness_3 () {
190 /* Exhaust all registers so 'o' is stack allocated */
191 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
192 for (i
= 0; i
< 100; ++i
)
194 for (j
= 0; j
< 100; ++j
)
196 for (k
= 0; k
< 100; ++k
)
198 for (l
= 0; l
< 100; ++l
)
200 for (m
= 0; m
< 100; ++m
)
202 for (n
= 0; n
< 100; ++n
)
204 for (s
= 0; s
< 100; ++s
)
208 object o
= new object ();
210 /* Make sure o is global */
212 Console
.WriteLine ();
220 object o
= new object ();
222 /* Make sure o is global */
224 Console
.WriteLine ();
229 sum
+= i
+ j
+ k
+ l
+ m
+ n
+ s
;
235 * Test liveness of variables used to handle items on the IL stack.
237 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
238 static string call1 () {
242 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
243 static string call2 () {
248 public static int test_0_liveness_4 () {
252 /* Exhaust all registers so 'o' is stack allocated */
253 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
254 for (i
= 0; i
< 100; ++i
)
256 for (j
= 0; j
< 100; ++j
)
258 for (k
= 0; k
< 100; ++k
)
260 for (l
= 0; l
< 100; ++l
)
262 for (m
= 0; m
< 100; ++m
)
264 for (n
= 0; n
< 100; ++n
)
266 for (s
= 0; s
< 100; ++s
)
269 string o
= b
? call1 () : call2 ();
273 sum
+= i
+ j
+ k
+ l
+ m
+ n
+ s
;
280 * Test liveness of volatile variables
282 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
283 static void liveness_5_1 (out object o
) {
287 public static int test_0_liveness_5 () {
291 /* Exhaust all registers so 'o' is stack allocated */
292 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
293 for (i
= 0; i
< 100; ++i
)
295 for (j
= 0; j
< 100; ++j
)
297 for (k
= 0; k
< 100; ++k
)
299 for (l
= 0; l
< 100; ++l
)
301 for (m
= 0; m
< 100; ++m
)
303 for (n
= 0; n
< 100; ++n
)
305 for (s
= 0; s
< 100; ++s
)
310 liveness_5_1 (out o
);
312 for (int x
= 0; x
< 10; ++x
) {
319 sum
+= i
+ j
+ k
+ l
+ m
+ n
+ s
;
325 * Test the case when a stack slot becomes dead, then live again due to a backward
329 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
330 static object alloc_obj () {
331 return new object ();
334 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
335 static bool return_true () {
339 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
340 static bool return_false () {
344 public static int test_0_liveness_6 () {
348 /* Exhaust all registers so 'o' is stack allocated */
349 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
350 for (i
= 0; i
< 100; ++i
)
352 for (j
= 0; j
< 100; ++j
)
354 for (k
= 0; k
< 100; ++k
)
356 for (l
= 0; l
< 100; ++l
)
358 for (m
= 0; m
< 100; ++m
)
360 for (n
= 0; n
< 100; ++n
)
362 for (s
= 0; s
< 100; ++s
)
365 for (int x
= 0; x
< 10; ++x
) {
369 object o
= alloc_obj ();
376 sum
+= i
+ j
+ k
+ l
+ m
+ n
+ s
;
381 public static int test_0_multi_dim_ref_array_wbarrier () {
382 string [,] arr
= new string [256, 256];
383 for (int i
= 0; i
< 256; ++i
) {
384 for (int j
= 0; j
< 100; ++j
)
385 arr
[i
, j
] = "" + i
+ " " + j
;
393 * Liveness + out of line bblocks
395 public static int test_0_liveness_7 () {
396 /* Exhaust all registers so 'o' is stack allocated */
397 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
398 for (i
= 0; i
< 100; ++i
)
400 for (j
= 0; j
< 100; ++j
)
402 for (k
= 0; k
< 100; ++k
)
404 for (l
= 0; l
< 100; ++l
)
406 for (m
= 0; m
< 100; ++m
)
408 for (n
= 0; n
< 100; ++n
)
410 for (s
= 0; s
< 100; ++s
)
416 if (return_false ()) {
417 // This bblock is in-line
418 object o
= alloc_obj ();
420 if (return_false ()) {
421 // This bblock is out-of-line, and o is live here
422 throw new Exception (o
.ToString ());
426 // o is dead here too
432 // Liveness + finally clauses
433 public static int test_0_liveness_8 () {
434 /* Exhaust all registers so 'o' is stack allocated */
435 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
436 for (i
= 0; i
< 100; ++i
)
438 for (j
= 0; j
< 100; ++j
)
440 for (k
= 0; k
< 100; ++k
)
442 for (l
= 0; l
< 100; ++l
)
444 for (m
= 0; m
< 100; ++m
)
446 for (n
= 0; n
< 100; ++n
)
448 for (s
= 0; s
< 100; ++s
)
462 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
463 static object alloc_string () {
467 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
468 static object alloc_obj_and_gc () {
470 return new object ();
473 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
474 static void clobber_regs_and_gc () {
475 int sum
= 0, i
, j
, k
, l
, m
, n
, s
;
476 for (i
= 0; i
< 100; ++i
)
478 for (j
= 0; j
< 100; ++j
)
480 for (k
= 0; k
< 100; ++k
)
482 for (l
= 0; l
< 100; ++l
)
484 for (m
= 0; m
< 100; ++m
)
486 for (n
= 0; n
< 100; ++n
)
488 for (s
= 0; s
< 100; ++s
)
493 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
494 static void liveness_9_call1 (object o1
, object o2
, object o3
) {
500 // Liveness + JIT temporaries
501 public static int test_0_liveness_9 () {
502 // the result of alloc_obj () goes into a vreg, which gets converted to a
503 // JIT temporary because of the branching introduced by the cast
504 // FIXME: This doesn't crash if MONO_TYPE_I is not treated as a GC ref
505 liveness_9_call1 (alloc_obj (), (string)alloc_string (), alloc_obj_and_gc ());
509 // Liveness for registers
510 public static int test_0_liveness_10 () {
511 // Make sure this goes into a register
512 object o
= alloc_obj ();
519 // Break the bblock so o doesn't become a local vreg
521 // Clobber it with a call and run a GC
522 clobber_regs_and_gc ();
528 // Liveness for spill slots holding managed pointers
529 public static int test_0_liveness_11 () {
530 Tests
[] arr
= new Tests
[10];
531 // This uses an ldelema internally
532 // FIXME: This doesn't crash if mp-s are not correctly tracked, just writes to
539 public static Tests
operator >> (Tests bi1
, int shiftVal
) {
540 clobber_regs_and_gc ();
544 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
545 public static void liveness_12_inner (int a
, int b
, int c
, int d
, int e
, int f
, object o
, ref string s
) {
555 // Liveness for param area
556 public static int test_0_liveness_12 () {
557 var f
= new FooClass () { s = "A" }
;
558 // The ref argument should be passed on the stack
559 liveness_12_inner (1, 2, 3, 4, 5, 6, new object (), ref f
.s
);
567 struct BarStruct
: IFace
{
576 public static int test_0_liveness_unbox_trampoline () {
577 var s
= new BarStruct ();
584 public static void liveness_13_inner (ref ArrayList arr
) {
585 // The value of arr will be stored in a spill slot
586 arr
.Add (alloc_obj_and_gc ());
589 // Liveness for byref arguments in spill slots
590 public static int test_0_liveness_13 () {
591 var arr
= new ArrayList ();
592 liveness_13_inner (ref arr
);
596 static ThreadLocal
<object> tls
;
598 [MethodImplAttribute (MethodImplOptions
.NoInlining
)]
599 static void alloc_tls_obj () {
600 tls
= new ThreadLocal
<object> ();
601 tls
.Value
= new object ();
604 public static int test_0_thread_local () {
607 Type t
= tls
.Value
.GetType ();
608 if (t
== typeof (object))
615 public object o1
, o2
, o3
;
617 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
;
620 public static int test_12_large_bitmap () {
621 LargeBitmap lb
= new LargeBitmap ();
629 return (int)lb
.o1
+ (int)lb
.o2
+ (int)lb
.o3
+ (int)lb
.o32
;