1 //////////////////////////////////////////////////////////////////////////////
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are welcomed to incorporate any part of ADLib and Prop into
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
18 // This software is still under development and we welcome(read crave for)
19 // any suggestions and help from the users.
21 // Allen Leung (leunga@cs.nyu.edu)
23 //////////////////////////////////////////////////////////////////////////////
29 #include <sys/types.h>
30 #include <AD/gc/gcconfig.h> // system configuration
31 #include <AD/gc/gc.h> // garbage collector base class
32 #include <AD/gc/gcobject.h> // garbage collectable objects
33 #include <AD/gc/gctimer.h> // timer stuff
34 #include <AD/gc/gcmacros.h> // useful macros
36 //////////////////////////////////////////////////////////////////////////////
38 //////////////////////////////////////////////////////////////////////////////
39 GC
* GC::collectors
[ GC_MAX_NUMBER_OF_COLLECTORS
];
40 int GC::number_of_collectors
= 0;
42 //////////////////////////////////////////////////////////////////////////////
43 // Method that returns a name for the collector
44 //////////////////////////////////////////////////////////////////////////////
45 const char * GC::my_name() const { return "GC"; }
47 //////////////////////////////////////////////////////////////////////////////
49 //////////////////////////////////////////////////////////////////////////////
52 verbosity_level( GC::gc_notify_minor_collection
|
53 GC::gc_notify_major_collection
|
54 GC::gc_notify_weak_pointer_collection
|
55 GC::gc_notify_heap_expansion
|
56 GC::gc_notify_heap_info
|
57 GC::gc_print_collection_time
61 should_finalize(false),
62 should_collect_weak_pointers(true)
65 // Assign a gc ID number to each collector.
66 // It must be non-zero.
68 if (number_of_collectors
>= GC_MAX_NUMBER_OF_COLLECTORS
) {
69 error ("Number of collectors exceeded the hard limit");
72 for (id
= 1; id
< GC_MAX_NUMBER_OF_COLLECTORS
; id
++) {
73 if (collectors
[id
] == 0) { collectors
[id
] = this; break; }
75 number_of_collectors
++;
78 //////////////////////////////////////////////////////////////////////////////
80 //////////////////////////////////////////////////////////////////////////////
83 number_of_collectors
--;
86 //////////////////////////////////////////////////////////////////////////////
87 // The default method for free doesn't do anything.
88 //////////////////////////////////////////////////////////////////////////////
89 void GC::free(void * /* obj */) {}
91 //////////////////////////////////////////////////////////////////////////////
92 // The default method for c_alloc just calls the m_alloc routine.
93 // We assume all subclasses already initialize memory to zeros.
94 //////////////////////////////////////////////////////////////////////////////
95 void * GC::c_alloc(size_t n
) { return m_alloc(n
); }
96 void * GC::m_alloc(size_t) { error("m_alloc() is unimplemented"); return 0; }
98 //////////////////////////////////////////////////////////////////////////////
99 // Methods that deal the verbosity and console messages.
100 //////////////////////////////////////////////////////////////////////////////
101 int GC::verbosity() const { return verbosity_level
; }
102 Bool
GC::is_verbose() const
103 { return verbosity_level
&
104 (gc_notify_minor_collection
| gc_notify_major_collection
);
106 Bool
GC::is_debugging() const
107 { return verbosity_level
& gc_print_debugging_info
; }
108 void GC::set_verbosity (int v
) { verbosity_level
= v
; }
110 void GC::set_console (ostream
& f
) { console
= &f
; }
111 void GC::set_console (ostream
* f
) { set_console (*f
); }
112 ostream
& GC::get_console () const { return *console
; }
113 Bool
GC::has_console () const { return console
!= 0; }
115 //////////////////////////////////////////////////////////////////////////////
116 // Default set gc ratio method does nothing
117 //////////////////////////////////////////////////////////////////////////////
118 void GC::set_gc_ratio(int r
) { gc_ratio
= r
; }
119 void GC::set_initial_heap_size(size_t) {}
120 void GC::set_min_heap_growth (size_t) {}
122 //////////////////////////////////////////////////////////////////////////////
123 // Method to set/reset the finalization flag
124 //////////////////////////////////////////////////////////////////////////////
125 Bool
GC::set_finalization(Bool f
)
126 { Bool old_flag
= should_finalize
;
131 //////////////////////////////////////////////////////////////////////////////
132 // Method to set/reset the weak pointer collection flag
133 //////////////////////////////////////////////////////////////////////////////
134 Bool
GC::set_weak_pointer_collection(Bool f
)
135 { Bool old_flag
= should_collect_weak_pointers
;
136 should_collect_weak_pointers
= f
;
140 //////////////////////////////////////////////////////////////////////////////
141 // Method for printing an error message
142 //////////////////////////////////////////////////////////////////////////////
143 void GC::error (const char * message
) const
145 if (has_console()) f
= &get_console(); else f
= &cerr
;
146 (*f
) << '[' << my_name() << ": " << message
<< "]\n" << flush
;
149 //////////////////////////////////////////////////////////////////////////////
150 // Method to reset statistics
151 //////////////////////////////////////////////////////////////////////////////
152 void GC::reset_statistics(GC::Statistics
& stat
)
153 { stat
.bytes_used
= 0;
154 stat
.bytes_managed
= 0;
156 stat
.number_of_collections
= 0;
157 stat
.number_of_heap_expansions
= 0;
158 stat
.gc_user_time
.clear();
159 stat
.gc_system_time
.clear();
160 stat
.total_gc_user_time
.clear();
161 stat
.total_gc_system_time
.clear();
164 //////////////////////////////////////////////////////////////////////////////
165 // Method to print the statistics
166 //////////////////////////////////////////////////////////////////////////////
167 ostream
& GC::print_statistics(ostream
& f
)
168 { Statistics s
= statistics();
169 f
<< "[ Algorithm: " << s
.algorithm
<< '\n'
170 << " Version: " << s
.version
<< '\n'
171 << " Bytes used: " << s
.bytes_used
<< '\n'
172 << " Bytes in heap: " << s
.bytes_managed
<< '\n'
173 << " Bytes available: " << s
.bytes_free
<< '\n'
174 << " Number of collections: " << s
.number_of_collections
<< '\n'
175 << " Number of heap expansions: " << s
.number_of_heap_expansions
<< '\n'
177 << " Total GC time: "
178 << (s
.total_gc_system_time
+ s
.total_gc_user_time
)
179 << " (user: " << s
.total_gc_user_time
180 << ", system: " << s
.total_gc_system_time
<< ")\n"
187 //////////////////////////////////////////////////////////////////////////////
188 // Method for scanning user roots
189 //////////////////////////////////////////////////////////////////////////////
190 void GC::scan_user_roots()
193 // scan root objects.
194 for (i
= 0; i
< number_of_objects(); i
++) {
195 root_obj(i
).trace(this);
198 // scan root pointers
199 for (i
= 0; i
< number_of_pointers(); i
++) {
200 GCObject
* ptr
= root_ptr(i
);
201 if (ptr
) ptr
->trace(this);