Mercurial > hg > CbC > CbC_gcc
comparison gcc/ggc-tests.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Unit tests for GCC's garbage collector (and gengtype etc). | |
2 Copyright (C) 2015-2017 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
23 #include "tree-core.h" | |
24 #include "tree.h" | |
25 #include "ggc-internal.h" /* (for ggc_force_collect). */ | |
26 #include "selftest.h" | |
27 | |
28 #if CHECKING_P | |
29 | |
30 /* A helper function for writing ggc tests. */ | |
31 | |
32 void | |
33 selftest::forcibly_ggc_collect () | |
34 { | |
35 ggc_force_collect = true; | |
36 ggc_collect (); | |
37 ggc_force_collect = false; | |
38 } | |
39 | |
40 /* The various GTY markers must be outside of a namespace to be seen by | |
41 gengtype, so we don't put this file within the selftest namespace. */ | |
42 | |
43 | |
44 | |
45 /* Verify that a simple struct works, and that it can | |
46 own references to non-roots, and have them be marked. */ | |
47 | |
48 struct GTY(()) test_struct | |
49 { | |
50 struct test_struct *other; | |
51 }; | |
52 | |
53 static GTY(()) test_struct *root_test_struct; | |
54 | |
55 static void | |
56 test_basic_struct () | |
57 { | |
58 root_test_struct = ggc_cleared_alloc <test_struct> (); | |
59 root_test_struct->other = ggc_cleared_alloc <test_struct> (); | |
60 | |
61 selftest::forcibly_ggc_collect (); | |
62 | |
63 ASSERT_TRUE (ggc_marked_p (root_test_struct)); | |
64 ASSERT_TRUE (ggc_marked_p (root_test_struct->other)); | |
65 } | |
66 | |
67 | |
68 | |
69 /* Selftest for GTY((length)). */ | |
70 | |
71 /* A test struct using GTY((length)). */ | |
72 | |
73 struct GTY(()) test_of_length | |
74 { | |
75 int num_elem; | |
76 struct test_of_length * GTY ((length ("%h.num_elem"))) elem[1]; | |
77 }; | |
78 | |
79 static GTY(()) test_of_length *root_test_of_length; | |
80 | |
81 static void | |
82 test_length () | |
83 { | |
84 const int count = 5; | |
85 size_t sz = sizeof (test_of_length) + (count- 1) * sizeof (test_of_length *); | |
86 root_test_of_length = (test_of_length *)ggc_internal_cleared_alloc (sz); | |
87 root_test_of_length->num_elem = count; | |
88 for (int i = 0; i < count; i++) | |
89 root_test_of_length->elem[i] = ggc_cleared_alloc <test_of_length> (); | |
90 | |
91 selftest::forcibly_ggc_collect (); | |
92 | |
93 ASSERT_TRUE (ggc_marked_p (root_test_of_length)); | |
94 for (int i = 0; i < count; i++) | |
95 ASSERT_TRUE (ggc_marked_p (root_test_of_length->elem[i])); | |
96 } | |
97 | |
98 | |
99 | |
100 /* Selftest for unions, GTY((tag)), and GTY((desc)). */ | |
101 | |
102 /* A struct with a reference that's an a different offset to test_struct, | |
103 to ensure that we're using the correct types. */ | |
104 | |
105 struct GTY(()) test_other | |
106 { | |
107 char dummy[256]; | |
108 test_struct *m_ptr; | |
109 }; | |
110 | |
111 enum which_field | |
112 { | |
113 WHICH_FIELD_USE_TEST_STRUCT, | |
114 WHICH_FIELD_USE_TEST_OTHER | |
115 }; | |
116 | |
117 /* An example function for use by a GTY((desc)) marker. */ | |
118 | |
119 static enum which_field | |
120 calc_desc (int kind) | |
121 { | |
122 switch (kind) | |
123 { | |
124 case 0: return WHICH_FIELD_USE_TEST_STRUCT; | |
125 case 1: return WHICH_FIELD_USE_TEST_OTHER; | |
126 default: | |
127 gcc_unreachable (); | |
128 } | |
129 } | |
130 | |
131 /* A struct containing an example of a union, showing the "tag" and | |
132 "desc" markers. */ | |
133 | |
134 struct GTY(()) test_of_union | |
135 { | |
136 int m_kind; | |
137 union u { | |
138 test_struct * GTY ((tag ("WHICH_FIELD_USE_TEST_STRUCT") )) u_test_struct; | |
139 test_other * GTY ((tag ("WHICH_FIELD_USE_TEST_OTHER") )) u_test_other; | |
140 } GTY ((desc ("calc_desc (%0.m_kind)"))) m_u; | |
141 }; | |
142 | |
143 /* Example roots. */ | |
144 | |
145 static GTY(()) test_of_union *root_test_of_union_1; | |
146 static GTY(()) test_of_union *root_test_of_union_2; | |
147 | |
148 /* Verify that the above work correctly. */ | |
149 | |
150 static void | |
151 test_union () | |
152 { | |
153 root_test_of_union_1 = ggc_cleared_alloc <test_of_union> (); | |
154 root_test_of_union_1->m_kind = 0; | |
155 test_struct *ts = ggc_cleared_alloc <test_struct> (); | |
156 root_test_of_union_1->m_u.u_test_struct = ts; | |
157 | |
158 root_test_of_union_2 = ggc_cleared_alloc <test_of_union> (); | |
159 root_test_of_union_2->m_kind = 1; | |
160 test_other *other = ggc_cleared_alloc <test_other> (); | |
161 root_test_of_union_2->m_u.u_test_other = other; | |
162 test_struct *referenced_by_other = ggc_cleared_alloc <test_struct> (); | |
163 other->m_ptr = referenced_by_other; | |
164 | |
165 selftest::forcibly_ggc_collect (); | |
166 | |
167 ASSERT_TRUE (ggc_marked_p (root_test_of_union_1)); | |
168 ASSERT_TRUE (ggc_marked_p (ts)); | |
169 | |
170 ASSERT_TRUE (ggc_marked_p (root_test_of_union_2)); | |
171 ASSERT_TRUE (ggc_marked_p (other)); | |
172 ASSERT_TRUE (ggc_marked_p (referenced_by_other)); | |
173 } | |
174 | |
175 | |
176 | |
177 /* Verify that destructors get run when instances are collected. */ | |
178 | |
179 struct GTY(()) test_struct_with_dtor | |
180 { | |
181 /* This struct has a destructor; it *ought* to be called | |
182 by the ggc machinery when instances are collected. */ | |
183 ~test_struct_with_dtor () { dtor_call_count++; } | |
184 | |
185 static int dtor_call_count; | |
186 }; | |
187 | |
188 int test_struct_with_dtor::dtor_call_count; | |
189 | |
190 static void | |
191 test_finalization () | |
192 { | |
193 #if GCC_VERSION >= 4003 | |
194 ASSERT_FALSE (need_finalization_p <test_struct> ()); | |
195 ASSERT_TRUE (need_finalization_p <test_struct_with_dtor> ()); | |
196 #endif | |
197 | |
198 /* Create some garbage. */ | |
199 const int count = 10; | |
200 for (int i = 0; i < count; i++) | |
201 ggc_cleared_alloc <test_struct_with_dtor> (); | |
202 | |
203 test_struct_with_dtor::dtor_call_count = 0; | |
204 | |
205 selftest::forcibly_ggc_collect (); | |
206 | |
207 /* Verify that the destructor was run for each instance. */ | |
208 ASSERT_EQ (count, test_struct_with_dtor::dtor_call_count); | |
209 } | |
210 | |
211 | |
212 | |
213 /* Verify that a global can be marked as "deletable". */ | |
214 | |
215 static GTY((deletable)) test_struct *test_of_deletable; | |
216 | |
217 static void | |
218 test_deletable_global () | |
219 { | |
220 test_of_deletable = ggc_cleared_alloc <test_struct> (); | |
221 ASSERT_TRUE (test_of_deletable != NULL); | |
222 | |
223 selftest::forcibly_ggc_collect (); | |
224 | |
225 ASSERT_EQ (NULL, test_of_deletable); | |
226 } | |
227 | |
228 | |
229 | |
230 /* Verify that gengtype etc can cope with inheritance. */ | |
231 | |
232 class GTY((desc("%h.m_kind"), tag("0"))) example_base | |
233 { | |
234 public: | |
235 example_base () | |
236 : m_kind (0), | |
237 m_a (ggc_cleared_alloc <test_struct> ()) | |
238 {} | |
239 | |
240 void * | |
241 operator new (size_t sz) | |
242 { | |
243 return ggc_internal_cleared_alloc (sz); | |
244 } | |
245 | |
246 protected: | |
247 example_base (int kind) | |
248 : m_kind (kind), | |
249 m_a (ggc_cleared_alloc <test_struct> ()) | |
250 {} | |
251 | |
252 public: | |
253 int m_kind; | |
254 test_struct *m_a; | |
255 }; | |
256 | |
257 class GTY((tag("1"))) some_subclass : public example_base | |
258 { | |
259 public: | |
260 some_subclass () | |
261 : example_base (1), | |
262 m_b (ggc_cleared_alloc <test_struct> ()) | |
263 {} | |
264 | |
265 test_struct *m_b; | |
266 }; | |
267 | |
268 class GTY((tag("2"))) some_other_subclass : public example_base | |
269 { | |
270 public: | |
271 some_other_subclass () | |
272 : example_base (2), | |
273 m_c (ggc_cleared_alloc <test_struct> ()) | |
274 {} | |
275 | |
276 test_struct *m_c; | |
277 }; | |
278 | |
279 /* Various test roots, both expressed as a ptr to the actual class, and | |
280 as a ptr to the base class. */ | |
281 static GTY(()) example_base *test_example_base; | |
282 static GTY(()) some_subclass *test_some_subclass; | |
283 static GTY(()) some_other_subclass *test_some_other_subclass; | |
284 static GTY(()) example_base *test_some_subclass_as_base_ptr; | |
285 static GTY(()) example_base *test_some_other_subclass_as_base_ptr; | |
286 | |
287 static void | |
288 test_inheritance () | |
289 { | |
290 test_example_base = new example_base (); | |
291 test_some_subclass = new some_subclass (); | |
292 test_some_other_subclass = new some_other_subclass (); | |
293 test_some_subclass_as_base_ptr = new some_subclass (); | |
294 test_some_other_subclass_as_base_ptr = new some_other_subclass (); | |
295 | |
296 selftest::forcibly_ggc_collect (); | |
297 | |
298 /* Verify that the roots and everything referenced by them got marked | |
299 (both for fields in the base class and those in subclasses). */ | |
300 ASSERT_TRUE (ggc_marked_p (test_example_base)); | |
301 ASSERT_TRUE (ggc_marked_p (test_example_base->m_a)); | |
302 | |
303 ASSERT_TRUE (ggc_marked_p (test_some_subclass)); | |
304 ASSERT_TRUE (ggc_marked_p (test_some_subclass->m_a)); | |
305 ASSERT_TRUE (ggc_marked_p (test_some_subclass->m_b)); | |
306 | |
307 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass)); | |
308 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass->m_a)); | |
309 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass->m_c)); | |
310 | |
311 ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr)); | |
312 ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr->m_a)); | |
313 ASSERT_TRUE (ggc_marked_p (((some_subclass *) | |
314 test_some_subclass_as_base_ptr)->m_b)); | |
315 | |
316 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr)); | |
317 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr->m_a)); | |
318 ASSERT_TRUE (ggc_marked_p (((some_other_subclass *) | |
319 test_some_other_subclass_as_base_ptr)->m_c)); | |
320 } | |
321 | |
322 | |
323 | |
324 /* Test of chain_next/chain_prev | |
325 | |
326 Construct a very long linked list, so that without | |
327 the chain_next/chain_prev optimization we'd have | |
328 a stack overflow when gt_ggc_mx_test_node recurses. */ | |
329 | |
330 struct GTY(( chain_next ("%h.m_next"), | |
331 chain_prev ("%h.m_prev") )) test_node | |
332 { | |
333 test_node *m_prev; | |
334 test_node *m_next; | |
335 int m_idx; | |
336 }; | |
337 | |
338 static GTY(()) test_node *root_test_node; | |
339 | |
340 static void | |
341 test_chain_next () | |
342 { | |
343 /* Ideally we would construct a long list so that the number of | |
344 stack frames would be deep enough to crash if gengtype has created | |
345 something that recurses. | |
346 | |
347 However, as the list is lengthened to increase the chance of | |
348 overflowing the stack, the test will require more time and memory | |
349 to run. On a Fedora 20 x86_64 box with 128GB of RAM, count=2000000 | |
350 without the chain_next optimization reliably overflowed the stack, | |
351 but the test took 0.5s to run. | |
352 | |
353 For now this test runs with a low value for "count", which defeats | |
354 the main purpose of the test - though it at least gives us coverage | |
355 for walking a GTY((chain_next)) list. | |
356 | |
357 We could potentially increase this value once we have a better sense | |
358 of the time and space requirements of the test on different hosts, | |
359 or perhaps find a way to reduce the stack size when running this | |
360 testcase. */ | |
361 const int count = 10; | |
362 | |
363 /* Build the linked list. */ | |
364 root_test_node = ggc_cleared_alloc <test_node> (); | |
365 test_node *tail_node = root_test_node; | |
366 for (int i = 0; i < count; i++) | |
367 { | |
368 test_node *new_node = ggc_cleared_alloc <test_node> (); | |
369 tail_node->m_next = new_node; | |
370 new_node->m_prev = tail_node; | |
371 new_node->m_idx = i; | |
372 tail_node = new_node; | |
373 } | |
374 | |
375 selftest::forcibly_ggc_collect (); | |
376 | |
377 /* If we got here, we survived. */ | |
378 | |
379 /* Verify that all nodes in the list were marked. */ | |
380 ASSERT_TRUE (ggc_marked_p (root_test_node)); | |
381 test_node *iter_node = root_test_node->m_next; | |
382 for (int i = 0; i < count; i++) | |
383 { | |
384 ASSERT_TRUE (ggc_marked_p (iter_node)); | |
385 ASSERT_EQ (i, iter_node->m_idx); | |
386 iter_node = iter_node->m_next; | |
387 } | |
388 } | |
389 | |
390 | |
391 | |
392 /* Test for GTY((user)). */ | |
393 | |
394 struct GTY((user)) user_struct | |
395 { | |
396 char dummy[16]; | |
397 test_struct *m_ptr; | |
398 }; | |
399 | |
400 static GTY(()) user_struct *root_user_struct_ptr; | |
401 | |
402 /* A global for verifying that the user-provided gt_ggc_mx gets | |
403 called. */ | |
404 static int num_calls_to_user_gt_ggc_mx; | |
405 | |
406 /* User-provided implementation of gt_ggc_mx. */ | |
407 | |
408 static void | |
409 gt_ggc_mx (user_struct *p) | |
410 { | |
411 num_calls_to_user_gt_ggc_mx++; | |
412 gt_ggc_mx_test_struct (p->m_ptr); | |
413 } | |
414 | |
415 /* User-provided implementation of gt_pch_nx. */ | |
416 | |
417 static void | |
418 gt_pch_nx (user_struct *p) | |
419 { | |
420 gt_pch_nx_test_struct (p->m_ptr); | |
421 } | |
422 | |
423 /* User-provided implementation of gt_pch_nx. */ | |
424 | |
425 static void | |
426 gt_pch_nx (user_struct *p, gt_pointer_operator op, void *cookie) | |
427 { | |
428 op (&(p->m_ptr), cookie); | |
429 } | |
430 | |
431 /* Verify that GTY((user)) works. */ | |
432 | |
433 static void | |
434 test_user_struct () | |
435 { | |
436 root_user_struct_ptr = ggc_cleared_alloc <user_struct> (); | |
437 test_struct *referenced = ggc_cleared_alloc <test_struct> (); | |
438 root_user_struct_ptr->m_ptr = referenced; | |
439 | |
440 num_calls_to_user_gt_ggc_mx = 0; | |
441 | |
442 selftest::forcibly_ggc_collect (); | |
443 | |
444 ASSERT_TRUE (ggc_marked_p (root_user_struct_ptr)); | |
445 ASSERT_TRUE (ggc_marked_p (referenced)); | |
446 ASSERT_TRUE (num_calls_to_user_gt_ggc_mx > 0); | |
447 } | |
448 | |
449 | |
450 | |
451 /* Smoketest to ensure that the tree type is marked. */ | |
452 | |
453 static GTY(()) tree dummy_unittesting_tree; | |
454 | |
455 static void | |
456 test_tree_marking () | |
457 { | |
458 dummy_unittesting_tree = build_int_cst (integer_type_node, 1066); | |
459 | |
460 selftest::forcibly_ggc_collect (); | |
461 | |
462 ASSERT_TRUE (ggc_marked_p (dummy_unittesting_tree)); | |
463 } | |
464 | |
465 | |
466 | |
467 /* Ideas for other tests: | |
468 - pch-handling */ | |
469 | |
470 namespace selftest { | |
471 | |
472 /* Run all of the selftests within this file. */ | |
473 | |
474 void | |
475 ggc_tests_c_tests () | |
476 { | |
477 test_basic_struct (); | |
478 test_length (); | |
479 test_union (); | |
480 test_finalization (); | |
481 test_deletable_global (); | |
482 test_inheritance (); | |
483 test_chain_next (); | |
484 test_user_struct (); | |
485 test_tree_marking (); | |
486 } | |
487 | |
488 } // namespace selftest | |
489 | |
490 #include "gt-ggc-tests.h" | |
491 | |
492 #else /* #if CHECKING_P */ | |
493 | |
494 /* The #if CHECKING_P code above has various GTY-marked roots. | |
495 gengtype has no knowledge of the preprocessor, and so detects | |
496 these roots and writes them out to gt-ggc-tests.h. | |
497 In a !CHECKING_P build we can ignore gt-ggc-tests.h, but the | |
498 root tables are referenced in the various generated gtype-*.c | |
499 files like this: | |
500 | |
501 ...snip... | |
502 extern const struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[]; | |
503 ...snip... | |
504 | |
505 EXPORTED_CONST struct ggc_root_tab * const gt_ggc_rtab[] = { | |
506 ...snip... | |
507 gt_ggc_r_gt_ggc_tests_h, | |
508 ...snip... | |
509 }; | |
510 | |
511 Hence to avoid a link failure, we provide dummy implementations | |
512 of these root tables in an unchecked build. | |
513 | |
514 Note that these conditional roots imply that PCH files are | |
515 incompatible between checked and unchecked builds. */ | |
516 | |
517 EXPORTED_CONST struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[] = { | |
518 LAST_GGC_ROOT_TAB | |
519 }; | |
520 | |
521 EXPORTED_CONST struct ggc_root_tab gt_ggc_rd_gt_ggc_tests_h[] = { | |
522 LAST_GGC_ROOT_TAB | |
523 }; | |
524 | |
525 #endif /* #else clause of #if CHECKING_P */ |