Simplify the arm prolog/epilog generation by not saving the sp to the stack, its...
[mono.git] / mono / mini / gc-test.cs
1 using System;
2 using System.Reflection;
3 using System.Runtime.CompilerServices;
4
5 /*
6  * Regression tests for the GC support in the JIT
7  */
8
9 class Tests {
10
11         static int Main () {
12                 return TestDriver.RunTests (typeof (Tests));
13         }
14
15         public static int test_36_simple () {
16                 // Overflow the registers
17                 object o1 = (1);
18                 object o2 = (2);
19                 object o3 = (3);
20                 object o4 = (4);
21                 object o5 = (5);
22                 object o6 = (6);
23                 object o7 = (7);
24                 object o8 = (8);
25
26                 /* Prevent the variables from being local to a bb */
27                 bool b = o1 != null;
28                 GC.Collect (0);
29
30                 if (b)
31                         return (int)o1 + (int)o2 + (int)o3 + (int)o4 + (int)o5 + (int)o6 + (int)o7 + (int)o8;
32                 else
33                         return 0;
34         }
35
36         public static int test_36_liveness () {
37                 object o = 5;
38                 object o1, o2, o3, o4, o5, o6, o7, o8;
39
40                 bool b = o != null;
41
42                 GC.Collect (1);
43
44                 o1 = (1);
45                 o2 = (2);
46                 o3 = (3);
47                 o4 = (4);
48                 o5 = (5);
49                 o6 = (6);
50                 o7 = (7);
51                 o8 = (8);
52
53                 if (b)
54                         return (int)o1 + (int)o2 + (int)o3 + (int)o4 + (int)o5 + (int)o6 + (int)o7 + (int)o8;
55                 else
56                         return 0;
57         }
58
59         struct FooStruct {
60                 public object o1;
61                 public int i;
62                 public object o2;
63
64                 public FooStruct (int i1, int i, int i2) {
65                         this.o1 = i1;
66                         this.i = i;
67                         this.o2 = i2;
68                 }
69         }
70
71         public static int test_4_vtype () {
72                 FooStruct s = new FooStruct (1, 2, 3);
73
74                 GC.Collect (1);
75
76                 return (int)s.o1 + (int)s.o2;
77         }
78
79         class BigClass {
80                 public object o1, o2, o3, o4, o5, o6, o7, o8, o9, o10;
81                 public object o11, o12, o13, o14, o15, o16, o17, o18, o19, o20;
82                 public object o21, o22, o23, o24, o25, o26, o27, o28, o29, o30;
83                 public object o31, o32;
84         }
85
86         static void set_fields (BigClass b) {
87                 b.o31 = 31;
88                 b.o32 = 32;
89
90                 b.o1 = 1;
91                 b.o2 = 2;
92                 b.o3 = 3;
93                 b.o4 = 4;
94                 b.o5 = 5;
95                 b.o6 = 6;
96                 b.o7 = 7;
97                 b.o8 = 8;
98                 b.o9 = 9;
99                 b.o10 = 10;
100                 b.o11 = 11;
101                 b.o12 = 12;
102                 b.o13 = 13;
103                 b.o14 = 14;
104                 b.o15 = 15;
105                 b.o16 = 16;
106                 b.o17 = 17;
107                 b.o18 = 18;
108                 b.o19 = 19;
109                 b.o20 = 20;
110                 b.o21 = 21;
111                 b.o22 = 22;
112                 b.o23 = 23;
113                 b.o24 = 24;
114                 b.o25 = 25;
115                 b.o26 = 26;
116                 b.o27 = 27;
117                 b.o28 = 28;
118                 b.o29 = 29;
119                 b.o30 = 30;
120         }
121
122         // Test marking of objects with > 32 fields
123         public static int test_528_mark_runlength_large () {
124                 BigClass b = new BigClass ();
125
126                 /* 
127                  * Do the initialization in a separate method so no object refs remain in
128                  * spill slots.
129                  */
130                 set_fields (b);
131
132                 GC.Collect (1);
133
134                 return 
135                         (int)b.o1 + (int)b.o2 + (int)b.o3 + (int)b.o4 + (int)b.o5 +
136                         (int)b.o6 + (int)b.o7 + (int)b.o8 + (int)b.o9 + (int)b.o10 +
137                         (int)b.o11 + (int)b.o12 + (int)b.o13 + (int)b.o14 + (int)b.o15 +
138                         (int)b.o16 + (int)b.o17 + (int)b.o18 + (int)b.o19 + (int)b.o20 +
139                         (int)b.o21 + (int)b.o22 + (int)b.o23 + (int)b.o24 + (int)b.o25 +
140                         (int)b.o26 + (int)b.o27 + (int)b.o28 + (int)b.o29 + (int)b.o30 +
141                         (int)b.o31 + (int)b.o32;
142         }
143
144         static void cond (bool b) {
145                 if (b) {
146                         /* Exhaust all registers so 'o' is stack allocated */
147                         int sum = 0, i, j, k, l, m;
148                         for (i = 0; i < 100; ++i)
149                                 sum ++;
150                         for (j = 0; j < 100; ++j)
151                                 sum ++;
152                         for (k = 0; k < 100; ++k)
153                                 sum ++;
154                         for (l = 0; l < 100; ++l)
155                                 sum ++;
156                         for (m = 0; m < 100; ++m)
157                                 sum ++;
158
159                         object o = new object ();
160                         sum += i + j + k;
161                         if (b) {
162                                 throw new Exception (o.ToString ());
163                         }
164                 }
165                 GC.Collect (1);
166         }
167
168         /* 
169          * Tests liveness of object references which are initialized conditionally,
170          * used in an out-of-line bblock, and the initlocals assignment is optimized away.
171          */
172         public static int test_0_liveness_out_of_line_bblocks () {
173                 cond (false);
174                 return 0;
175         }
176
177         /*
178          * Test liveness and loops.
179          */
180         public static int test_0_liveness_2 () {
181                 object o = new object ();
182                 for (int n = 0; n < 10; ++n) {
183                         /* Exhaust all registers so 'o' is stack allocated */
184                         int sum = 0, i, j, k, l, m;
185                         for (i = 0; i < 100; ++i)
186                                 sum ++;
187                         for (j = 0; j < 100; ++j)
188                                 sum ++;
189                         for (k = 0; k < 100; ++k)
190                                 sum ++;
191                         for (l = 0; l < 100; ++l)
192                                 sum ++;
193                         for (m = 0; m < 100; ++m)
194                                 sum ++;
195
196                         if (o != null)
197                                 o.ToString ();
198
199                         GC.Collect (1);
200
201                         if (o != null)
202                                 o.ToString ();
203
204                         sum += i + j + k;
205
206                         GC.Collect (1);
207                 }
208
209                 return 0;
210         }
211
212         /*
213          * Test liveness and stack slot sharing
214          * This doesn't work yet, its hard to make the JIT share the stack slots of the
215          * two 'o' variables.
216          */
217         public static int test_0_liveness_3 () {
218                 bool b = false;
219                 bool b2 = true;
220
221                 /* Exhaust all registers so 'o' is stack allocated */
222                 int sum = 0, i, j, k, l, m, n, s;
223                 for (i = 0; i < 100; ++i)
224                         sum ++;
225                 for (j = 0; j < 100; ++j)
226                         sum ++;
227                 for (k = 0; k < 100; ++k)
228                         sum ++;
229                 for (l = 0; l < 100; ++l)
230                         sum ++;
231                 for (m = 0; m < 100; ++m)
232                         sum ++;
233                 for (n = 0; n < 100; ++n)
234                         sum ++;
235                 for (s = 0; s < 100; ++s)
236                         sum ++;
237
238                 if (b) {
239                         object o = new object ();
240
241                         /* Make sure o is global */
242                         if (b2)
243                                 Console.WriteLine ();
244
245                         o.ToString ();
246                 }
247
248                 GC.Collect (1);
249
250                 if (b) {
251                         object o = new object ();
252
253                         /* Make sure o is global */
254                         if (b2)
255                                 Console.WriteLine ();
256
257                         o.ToString ();
258                 }
259
260                 sum += i + j + k + l + m + n + s;
261
262                 return 0;
263         }
264
265         /*
266          * Test liveness of variables used to handle items on the IL stack.
267          */
268         [MethodImplAttribute (MethodImplOptions.NoInlining)]
269         static string call1 () {
270                 return "A";
271         }
272
273         [MethodImplAttribute (MethodImplOptions.NoInlining)]
274         static string call2 () {
275                 GC.Collect (1);
276                 return "A";
277         }
278
279         public static int test_0_liveness_4 () {
280                 bool b = false;
281                 bool b2 = true;
282
283                 /* Exhaust all registers so 'o' is stack allocated */
284                 int sum = 0, i, j, k, l, m, n, s;
285                 for (i = 0; i < 100; ++i)
286                         sum ++;
287                 for (j = 0; j < 100; ++j)
288                         sum ++;
289                 for (k = 0; k < 100; ++k)
290                         sum ++;
291                 for (l = 0; l < 100; ++l)
292                         sum ++;
293                 for (m = 0; m < 100; ++m)
294                         sum ++;
295                 for (n = 0; n < 100; ++n)
296                         sum ++;
297                 for (s = 0; s < 100; ++s)
298                         sum ++;
299
300                 string o = b ? call1 () : call2 ();
301
302                 GC.Collect (1);
303
304                 sum += i + j + k + l + m + n + s;
305
306                 return 0;
307         }
308
309
310         /*
311          * Test liveness of volatile variables
312          */
313         [MethodImplAttribute (MethodImplOptions.NoInlining)]
314         static void liveness_5_1 (out object o) {
315                 o = new object ();
316         }
317
318         public static int test_0_liveness_5 () {
319                 bool b = false;
320                 bool b2 = true;
321
322                 /* Exhaust all registers so 'o' is stack allocated */
323                 int sum = 0, i, j, k, l, m, n, s;
324                 for (i = 0; i < 100; ++i)
325                         sum ++;
326                 for (j = 0; j < 100; ++j)
327                         sum ++;
328                 for (k = 0; k < 100; ++k)
329                         sum ++;
330                 for (l = 0; l < 100; ++l)
331                         sum ++;
332                 for (m = 0; m < 100; ++m)
333                         sum ++;
334                 for (n = 0; n < 100; ++n)
335                         sum ++;
336                 for (s = 0; s < 100; ++s)
337                         sum ++;
338
339                 object o;
340
341                 liveness_5_1 (out o);
342
343                 for (int x = 0; x < 10; ++x) {
344
345                         o.ToString ();
346
347                         GC.Collect (1);
348                 }
349
350                 sum += i + j + k + l + m + n + s;
351
352                 return 0;
353         }
354
355         /*
356          * Test the case when a stack slot becomes dead, then live again due to a backward
357          * branch.
358          */
359
360         [MethodImplAttribute (MethodImplOptions.NoInlining)]
361         static object liveness_6_1 () {
362                 return new object ();
363         }
364
365         public static int test_0_liveness_6 () {
366                 bool b = false;
367                 bool b2 = true;
368
369                 /* Exhaust all registers so 'o' is stack allocated */
370                 int sum = 0, i, j, k, l, m, n, s;
371                 for (i = 0; i < 100; ++i)
372                         sum ++;
373                 for (j = 0; j < 100; ++j)
374                         sum ++;
375                 for (k = 0; k < 100; ++k)
376                         sum ++;
377                 for (l = 0; l < 100; ++l)
378                         sum ++;
379                 for (m = 0; m < 100; ++m)
380                         sum ++;
381                 for (n = 0; n < 100; ++n)
382                         sum ++;
383                 for (s = 0; s < 100; ++s)
384                         sum ++;
385
386                 for (int x = 0; x < 10; ++x) {
387
388                         GC.Collect (1);
389
390                         object o = liveness_6_1 ();
391
392                         o.ToString ();
393
394                         GC.Collect (1);
395                 }
396
397                 sum += i + j + k + l + m + n + s;
398
399                 return 0;
400         }
401 }