| 187 | # Non-recursive, tri-colour, incremental mark and sweep. |
| 188 | class IncrementalTriColourGC is GC { |
| 189 | has @live_objects; # Black |
| 190 | has @grey_objects; # Guess? |
| 191 | has @dead_objects; # White |
| 192 | |
| 193 | has $do_marking; # We are in mark phase. |
| 194 | has $do_sweeping; # We are in sweep phase. |
| 195 | |
| 196 | method need_gc() { |
| 197 | return Bool::False if self.do_marking || self.do_sweeping; |
| 198 | return self.SUPER.need_gc(); |
| 199 | } |
| 200 | |
| 201 | method get_object() { |
| 202 | self.mark_a_little_bit() if self.do_marking; |
| 203 | self.sweep_a_little_bit() if self.do_sweeping; |
| 204 | self.SUPER.get_object(); |
| 205 | } |
| 206 | |
| 207 | method do_gc() { |
| 208 | # Prepare mark phase |
| 209 | self.do_marking = Bool::True; |
| 210 | self.do_sweeping = Bool::False; |
| 211 | self.dead_objects = self.objects; |
| 212 | self.objects = (); |
| 213 | |
| 214 | self.grey_objects = self.trace_roots(); |
| 215 | } |
| 216 | |
| 217 | method mark_a_little_bit() { |
| 218 | my $count = 0; |
| 219 | while(my $obj = self.grey_objects.pop) { |
| 220 | self.mark_real($obj); |
| 221 | return if $count++ > 10; |
| 222 | } |
| 223 | |
| 224 | # Switch to incremental sweep. |
| 225 | self.do_marking = Bool::False; |
| 226 | self.do_sweeping = Bool::True; |
| 227 | } |
| 228 | |
| 229 | method sweep_a_little_bit() { |
| 230 | my $count = 0; |
| 231 | while(my $dead = self.dead_objects.pop) { |
| 232 | $dead.destroy(); |
| 233 | self.allocator.free($dead); |
| 234 | return if $count++ > 10; |
| 235 | } |
| 236 | |
| 237 | # self.objects can be updated at this point of time. |
| 238 | # Add live_objects to objects to use on next GC round. |
| 239 | self.objects.push(self.live_objects); |
| 240 | |
| 241 | # .grey_objects .dead_objects are empty now. |
| 242 | # Back to normal life |
| 243 | self.do_sweeping = Bool::False; |
| 244 | } |
| 245 | |
| 246 | method mark_alive($obj) { |
| 247 | self.dead_objects.remove($obj); |
| 248 | self.grey_objects.push($obj); |
| 249 | } |
| 250 | |
| 251 | method mark_real($obj) { |
| 252 | self.live_objects.push($obj); |
| 253 | self.SUPER.mark_alive($obj); |
| 254 | } |
| 255 | }; |
| 256 | |
| 257 | |
| 258 | |