1 //////////////////////////////////////////////////////////////////////////////
2 // This program tests the garbage collector classes.
3 // We'll allocate a long linked list in the collectable heap, then invoke
4 // garbage collection a few times.
6 // List cells of of random length.
8 // Note: In your application you'll only have to include <AD/gc/gcobject.h>.
9 // In this case we'll have to import some other implementation dependent
10 // information since we'll have do some poking around with the heap.
11 //////////////////////////////////////////////////////////////////////////////
17 #include <AD/gc/bgc.h>
18 #include <AD/gc/gcobject.h>
19 #include <AD/gc/gcheaps.h>
20 #include <AD/gc/markswp.h>
22 MarkSweepGC marksweep_gc
;
24 #define LENGTH (256 * 32)
25 #define UNIT (16 * 64)
28 //////////////////////////////////////////////////////////////////////////////
29 // The list class defined below is made a garbage collectable class by
30 // deriving from GCObject and adding a tracing method ``trace.''
31 //////////////////////////////////////////////////////////////////////////////
32 class LIST
: public GCObject
{
34 char c
; // some position dependent storage
35 LIST
* next
; // the link
36 int len
; // len of junk
37 int x
[1]; // some other junk
40 LIST(LIST
* n
, char c1
, int l
) : next(n
), c(c1
), len(l
)
41 { for (int i
= 0; i
< l
; i
++) x
[i
] = l
- i
; }
43 // The tracing method.
44 void trace(GC
* gc
) { next
= (LIST
*)gc
->trace(next
); }
47 //////////////////////////////////////////////////////////////////////////////
48 // Method to print a list, currently unused.
49 //////////////////////////////////////////////////////////////////////////////
51 { if (x
) { cout
<< x
->c
; print(x
->next
); }
54 //////////////////////////////////////////////////////////////////////////////
55 // This method checks that a list is well and okay.
56 //////////////////////////////////////////////////////////////////////////////
57 void verify (LIST
* x
)
59 cout
<< "Verifying list\n" << flush
;
60 for ( ; x
; x
= x
->next
, count
++) {
62 // Make sure that it lies within the collectable heap.
64 assert (HM::is_mapped(x
) && HM::page_gc(x
) == marksweep_gc
.gc_id());
65 assert (HM::get_object_map().is_marked(x
));
68 for (int i
= 0; i
< x
->len
; i
++)
69 assert (x
->x
[i
] == x
->len
- i
);
70 assert (x
->c
== (LENGTH
- count
- 1) / UNIT
+ 'a');
73 // Make sure that it has the right length.
74 assert (count
== LENGTH
);
75 cout
<< "List is okay\n" << flush
;
86 for (int i
= 0; i
< LENGTH
; i
++) {
87 int l
= rand() % JUNK
;
88 x
= new (sizeof(LIST
) + (l
-1) * sizeof(int)) LIST (x
,i
/ UNIT
+ 'a', l
);
89 // The following line generates some garbage.
90 new (sizeof(LIST
) + (l
-1) * sizeof(int)) LIST (x
, i
/ UNIT
+ 'a', l
);
93 // cout << "&x = " << (void*)&x << '\n';
94 // cout << "&x = " << (void*)&x << " x = " << (void*)x << '\n';
95 cout
<< "List allocated\n";
97 GC::get_default_gc().collect();
100 GC::get_default_gc().collect();
104 GC::get_default_gc().collect();
109 GC::set_default_gc(marksweep_gc
);
110 GC::Statistics stats
= GC::get_default_gc().statistics();
111 cout
<< "Algorithm: " << stats
.algorithm
<< '\n'
112 << "Version: " << stats
.version
<< '\n';
115 GC::get_default_gc().collect();
118 "If you don't see a crash by now then it's probably ok :-)\n"
119 "Ideally, the heap should be completely reclaimed at this\n"
120 "point, but since the collector is conservative, retention\n"
123 "Actually this test is bit unfair, since we are allocating\n"
124 "a long linked list, a strongly connected data structure, and if\n"
125 "any one part of the list is incorrectly promoted then a large\n"
126 "portion of the storage will be retained.\n"