111
|
1 /* Unit tests for GCC's garbage collector (and gengtype etc).
|
131
|
2 Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
111
|
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 */
|