]> git.llucax.com Git - software/dgc/naive.git/blob - gc/gc.d
Remove invalid TODO comment
[software/dgc/naive.git] / gc / gc.d
1 /**
2  * Naive Garbage Collector implementation.
3  *
4  * This module implements a Naive Garbage Collector. The idea behind this
5  * implementation is to document all the bookkeeping and considerations that
6  * has to be taken in order to implement a garbage collector for D.
7  *
8  * The garbage collector algorithm itself is extremely simple so focus can be
9  * held in the specifics of D, and not the algorithm. A completely naive mark
10  * and sweep algorithm is used, with a recursive mark phase. The code is
11  * extremely inefficient in order to keep the code clean and easy to read and
12  * understand.
13  *
14  * The implementation is split in several modules to ease even more the
15  * lecture. All architecture/compiler specific code is done in the arch module,
16  * in order to avoid confusing version statements all over the places. The cell
17  * module has all the code related to the memory cells header. dynarray is
18  * another support module which holds the implementation of a simple dynamic
19  * array used to store root pointers and ranges. The list module holds a simple
20  * singly linked list (of cells) implementation to store the live and free
21  * lists. Finally, the iface module is the one with the C interface to comply
22  * with the Tango/Druntime GC specification.
23  *
24  * Copyright: Public Domain
25  * License:   Public Domain
26  * Authors:   Leandro Lucarella <llucax@gmail.com>
27  */
28
29 module gc.gc;
30
31 private:
32
33 // Internal imports
34 import gc.cell: Cell, BlkAttr, op_apply_ptr_range;
35 import gc.list: List;
36 import gc.dynarray: DynArray;
37 import gc.arch: push_registers, pop_registers;
38
39 // Standard imports
40 import cstdlib = tango.stdc.stdlib;
41 import cstring = tango.stdc.string;
42
43 // Debug imports
44
45 /*
46  * These are external functions coming from the D/Tango runtime. It's pretty
47  * intuitive what they do based on their names, for more details please
48  * refer to the functions documentation.
49  */
50 alias void delegate(void*, void*) mark_function;
51 extern (C) void onOutOfMemoryError();
52 extern (C) void rt_finalize(void* p, bool det=true);
53 extern (C) void rt_scanStaticData(mark_function mark);
54 extern (C) void thread_init();
55 extern (C) bool thread_needLock();
56 extern (C) void thread_suspendAll();
57 extern (C) void thread_resumeAll();
58 extern (C) void thread_scanAll(mark_function mark, void* stack_top=null);
59
60 /**
61  * A range of memory that should be scanned for pointers.
62  *
63  * This object is iterable, yielding a pointer (void*) for each iteration.
64  */
65 struct RootRange
66 {
67
68     /// Start of the memory range
69     void* from;
70
71     /// End of the memory range
72     void* to;
73
74     /// Iterate over a memory range applying dg to its elements
75     int opApply(int delegate(ref void*) dg)
76     {
77         return op_apply_ptr_range(this.from, this.to, dg);
78     }
79
80 }
81
82
83 package:
84
85
86 /**
87  * Information on a block of memory.
88  *
89  * This is part of the GC specification, it's used for the query() method.
90  *
91  * Standards: Tango/Druntime specs
92  */
93 struct BlkInfo
94 {
95
96     /// Base address of the block
97     void* base;
98
99     /// Size of the block (this is the total capacity, not the requested size)
100     size_t size;
101
102     /**
103      * Memory block attributes
104      *
105      * See_Also: cell.BlkAttr for possible values
106      */
107     uint attr;
108
109 }
110
111
112 /**
113  * GC implementation.
114  *
115  * This object contains the whole GC implementation. This is instantiated in
116  * the iface module as a global variable to provide the GC services.
117  *
118  * This implementation is designed to be extremely simple. The algorithm
119  * implemented is the most basic stop-the-world mark-sweep known.
120  *
121  * Memory is organized in cells. Each cell has a header where all the
122  * bookkeeping information is stored (like the mark bit, cell attributes,
123  * capacity, etc.), and the memory allocated for the requested memory itself.
124  *
125  * Two lists of cells are kept: free list and live list.
126  *
127  * The free list store cells known not to be referenced by the program. The
128  * live list stores cells that were referenced by the program at the end of
129  * the last collection (and just allocated cells).
130  *
131  * The root set is composed by several elements:
132  *
133  * $(UL
134  *      $(LI Static data)
135  *      $(LI Threads stack)
136  *      $(LI Registers)
137  *      $(LI Root pointers)
138  *      $(LI Root ranges)
139  * )
140  *
141  * Root pointers and ranges are user-defined.
142  *
143  * See_Also:
144  *
145  *  $(UL
146  *      $(LI cell.Cell for the cell header layout)
147  *      $(LI collect() for the main collection algorithm)
148  *      $(LI )
149  * )
150  *
151  */
152 struct GC
153 {
154
155 private:
156
157     /// List of free cells.
158     List free_list;
159
160     /// List of live cells.
161     List live_list;
162
163     /// Single root pointers.
164     DynArray!(void*) root_pointers;
165
166     /// Single root pointers.
167     DynArray!(RootRange) root_ranges;
168
169     /**
170      * "Flag" to indicate when the GC is disabled.
171      *
172      * This is a number because calls to enable() and disable() can be
173      * recursive. The number of calls to enable() should match the number of
174      * calls to disable(), though, if you want the GC to be effectively
175      * enabled again.
176      */
177     uint disabled = 0;
178
179     /**
180      * Remove the mark bit to all the live cells.
181      *
182      * This is done before starting the mark phase.
183      *
184      * See_Also:
185      *
186      *  $(UL
187      *      $(LI collect() for the main collect algorithm)
188      *      $(LI mark_all() for details on the marking phase)
189      *  )
190      */
191     void unmark()
192     {
193         foreach (cell; this.live_list)
194             cell.marked = false;
195     }
196
197     /**
198      * Marks all live data (pausing all threads)
199      *
200      * This methods start marking following all the known roots:
201      *
202      *  $(UL
203      *      $(LI Static data)
204      *      $(LI Threads stack)
205      *      $(LI Registers)
206      *      $(LI Root pointers)
207      *      $(LI Root ranges)
208      *  )
209      *
210      * Note that the registers are pushed into the stack to get scanned.
211      *
212      * This is the complete mark phase. The algorithm roughly does:
213      *
214      *  $(OL
215      *      $(LI Push registers into the stack)
216      *      $(LI Pause all threads (but the current one, of course))
217      *      $(LI Scan the static data)
218      *      $(LI Scan all threads stack)
219      *      $(LI Scan the root pointers and ranges)
220      *      $(LI Resume all threads)
221      *      $(LI Pop the registers from the stack)
222      *  )
223      *
224      *
225      * See_Also:
226      *
227      *  $(UL
228      *      $(LI collect() for the main collect algorithm)
229      *      $(LI mark() for details on the marking algorithm)
230      *      $(LI sweep() for details on the sweep phase)
231      *  )
232      */
233     void mark_all()
234     {
235         void* stack_top;
236         mixin (push_registers("stack_top"));
237         thread_suspendAll();
238         rt_scanStaticData(&mark_range);
239         thread_scanAll(&mark_range, stack_top);
240         foreach (ptr; this.root_pointers) {
241             this.mark(ptr);
242         }
243         foreach (range; this.root_ranges) {
244             this.mark_range(range.from, range.to);
245         }
246         thread_resumeAll();
247         mixin (pop_registers("stack_top"));
248     }
249
250     /**
251      * Wrapper for mark() over a range, needed by some runtime functions.
252      *
253      * This function is used as a delegate to be passed to rt_scanStaticData()
254      * and thread_scanAll(), because they expects a function taking
255      * 2 pointers.
256      *
257      * This extremely inefficient on purpose. The goal of this implementation
258      * is simplicity, nor performance.
259      *
260      * See_Also:
261      *  $(UL
262      *      $(LI mark() for details on the marking algorithm)
263      *  )
264      */
265     void mark_range(void* from, void* to)
266     {
267         foreach (ptr; RootRange(from, to))
268             mark(ptr);
269     }
270
271     /**
272      * Marks all cells accessible from a pointer.
273      *
274      * This is the mark algorithm itself. It's recursive and dumb as a log. No
275      * care is taken in regards to stack overflows. This is the first example
276      * in text books.
277      *
278      * Marking is done with all threads stopped.
279      *
280      * See_Also:
281      *  $(UL
282      *      $(LI collect() for the main collect algorithm)
283      *      $(LI mark_all() for details on the marking phase)
284      *      $(LI sweep() for details on the sweep phase)
285      *  )
286      */
287     void mark(void* ptr)
288     {
289         Cell* cell = Cell.from_ptr(this.addrOf(ptr));
290         if (cell is null)
291             return;
292         if (!cell.marked) {
293             cell.marked = true;
294             if (cell.has_pointers) {
295                 foreach (ptr; *cell)
296                     mark(ptr);
297             }
298         }
299     }
300
301     /**
302      * Move unreferenced live objects to the free list (calling finalizers).
303      *
304      * This is the sweep phase. It's very simple, it just searches the live
305      * list and move unmarked cells to the free list. This function is in
306      * charge of calling finalizers too, through the rt_finalize() runtime
307      * function.
308      *
309      * Sweeping is done concurrently with the mutator threads.
310      *
311      * See_Also:
312      *  $(UL
313      *      $(LI collect() for the main collect algorithm)
314      *      $(LI mark_all() for details on the marking phase)
315      *  )
316      */
317     void sweep()
318     {
319         foreach (cell; this.live_list) {
320             if (!cell.marked) {
321                 this.live_list.unlink(cell);
322                 if (cell.has_finalizer)
323                     rt_finalize(cell.ptr, false);
324                 this.free_list.link(cell);
325             }
326         }
327     }
328
329
330 public:
331
332     /**
333      * Initialize the GC.
334      *
335      * This initializes the thread library too, as requested by the
336      * Tango/Druntime specs.
337      */
338     void init()
339     {
340         this.disabled = 0;
341         thread_init();
342     }
343
344     /**
345      * Terminate the GC.
346      *
347      * Finalization of unreferenced cells is not mandatory by the specs.
348      * This implementation guarantees that all finalizers are called, at least
349      * at program exit (i.e. at GC termination).
350      *
351      * The specs says that "objects referenced from the data segment never get
352      * collected by the GC". While this is true for this implementation,
353      * finalizers are called for objects referenced from the data segment at
354      * program exit.
355      *
356      * There could be some problems with this, in very strange situations. For
357      * a more complete discussion about the topic please take a look at the
358      * bug 2858: http://d.puremagic.com/issues/show_bug.cgi?id=2858
359      */
360     void term()
361     {
362         foreach (cell; this.live_list)
363             if (cell.has_finalizer)
364                 rt_finalize(cell.ptr, false);
365         // Let the OS free the memory on exit.
366     }
367
368     /**
369      * Enable the GC.
370      *
371      * When the GC is enabled, a collection is triggered when malloc() can't
372      * find room in the free list to fulfill the requested size.
373      *
374      * enable() and disable() can be called recursively. The number of calls
375      * to enable() should match the number of calls to disable(), though, if
376      * you want the GC to be effectively enabled again.
377      *
378      * See_Also: disable()
379      */
380     void enable()
381     {
382         assert (this.disabled > 0);
383         this.disabled--;
384     }
385
386     /**
387      * Disable the GC.
388      *
389      * See_Also: enable()
390      */
391     void disable()
392     {
393         this.disabled++;
394         assert (this.disabled > 0);
395     }
396
397     /**
398      * Run a GC collection in order to find unreferenced objects.
399      *
400      * This is the simplest stop-the-world mark-sweep algorithm ever. It first
401      * removes the mark bit from all the live cells, then it mark the cells
402      * that are reachable through the root set (static data, stack, registers
403      * and custom root), and finally sweeps the live list looking for unmarked
404      * cells to free.
405      *
406      * The world is stopped only for the mark phase.
407      *
408      * See_Also:
409      *  $(UL
410      *      $(LI mark_all() for details on the marking phase)
411      *      $(LI sweep() for details on the sweep phase)
412      *  )
413      */
414     void collect()
415     {
416         this.unmark();
417         this.mark_all();
418         this.sweep();
419     }
420
421     /**
422      * Minimize free space usage.
423      *
424      * This method returns to the OS memory that is not longer used by
425      * the program. Usually calling this method manually is not
426      * necessary, because unused cells are recycled for future
427      * allocations. But if there is some small part of the program that
428      * requires a lot of memory and it's known that it won't be used
429      * further, calling this can reduce the memory footprint of the program
430      * considerably (at the expense of some performance lost in future
431      * allocations).
432      *
433      * This implementation just return to the OS all the cells in the free
434      * list.
435      */
436     void minimize()
437     {
438         foreach (cell; this.free_list) {
439             this.free_list.unlink(cell);
440             cstdlib.free(cell);
441         }
442     }
443
444     /**
445      * Get attributes associated to the cell pointed by ptr.
446      *
447      * Attributes is a bitmap that can have theses values:
448      *
449      *  $(UL
450      *      $(LI 1: The object stored in the cell have to be finalized)
451      *      $(LI 2: The cell should not be scanned for pointers)
452      *      $(LI 4: The cell should not be moved during a collection
453      *           (unimplemented))
454      *  )
455      *
456      * See_Also: cell.BlkAttr, setAttr(), clrAttr()
457      */
458     uint getAttr(void* ptr)
459     {
460         auto cell = this.live_list.find(ptr);
461         if (cell)
462             return cell.attr;
463         return 0;
464     }
465
466     /**
467      * Set the attributes of the cell pointed by ptr.
468      *
469      * All bits present in attr are set, other bits are untouched. The old
470      * attributes are returned.
471      *
472      * See_Also: cell.BlkAttr, getAttr(), clrAttr()
473      */
474     uint setAttr(void* ptr, uint attr)
475     {
476         auto cell = this.live_list.find(ptr);
477         if (cell) {
478             auto old = cell.attr;
479             cell.attr |= attr;
480             return cell.attr;
481         }
482         return 0;
483     }
484
485     /**
486      * Clear the attributes of the cell pointed by ptr.
487      *
488      * All bits present in attr are cleared, other bits are untouched. The old
489      * attributes are returned.
490      *
491      * See_Also: cell.BlkAttr, getAttr(), setAttr()
492      */
493     uint clrAttr(void* ptr, uint attr)
494     {
495         auto cell = this.live_list.find(ptr);
496         if (cell) {
497             auto old = cell.attr;
498             cell.attr &= ~attr;
499             return cell.attr;
500         }
501         return 0;
502     }
503
504     /**
505      * Allocate memory.
506      *
507      * This is the main allocator of the GC. The algorithm is really
508      * simple. It does a first-fit search in the free list, if no free cell is
509      * found with enough room, it runs a collection and retry (unless the GC
510      * is disabled). If there is no room still, it uses C malloc to allocate
511      * a new cell. If all that fails, then onOutOfMemoryError() runtime
512      * function is called to handle the error.
513      *
514      * attr are the attributes to associate to the new cell (see getAttr() for
515      * details).
516      */
517     void* malloc(size_t size, uint attr=0)
518     {
519         if (size == 0)
520             return null;
521
522         // Find a free cell in the free list with enough space
523         auto cell = this.free_list.pop(size);
524         if (cell)
525             goto success;
526
527         // No room in the free list found, if the GC is enabled, trigger
528         // a collection and try again
529         if (!this.disabled) {
530             this.collect();
531             cell = this.free_list.pop(size);
532             if (cell)
533                 goto success;
534         }
535
536         // No luck still, allocate new memory
537         cell = cast(Cell*) cstdlib.malloc(size + Cell.sizeof);
538         if (cell)
539             goto success;
540
541         // No memory
542         onOutOfMemoryError();
543
544         return null;
545
546     success:
547         cell.size = size;
548         if (cell.capacity == 0) // fresh cell
549             cell.capacity = size;
550         cell.attr = cast(BlkAttr) attr;
551         this.live_list.link(cell);
552
553         return cell.ptr;
554     }
555
556     /**
557      * Allocate memory (set memory to zero).
558      *
559      * Same as malloc() but set the allocated memory cell to zero.
560      */
561     void* calloc(size_t size, uint attr=0)
562     {
563         void* ptr = this.malloc(size, attr);
564
565         if (ptr is null)
566             onOutOfMemoryError();
567         else
568             cstring.memset(ptr, 0, size);
569
570         return ptr;
571     }
572
573     /**
574      * Reallocate memory.
575      *
576      * This implementation is very simple, if size less or equals than the
577      * cells capacity, the cell's size is changed and the same address is
578      * returned. Otherwise a new cell is allocated using malloc() (this can
579      * trigger a collection), the contents are moved and the old cell is freed.
580      *
581      * attr are the same as malloc().
582      */
583     void* realloc(void* ptr, size_t size, uint attr=0)
584     {
585
586         // Undercover malloc()
587         if (ptr is null)
588             return this.malloc(size, attr);
589
590         // Undercover free()
591         if (size == 0) {
592             this.free(ptr);
593             return null;
594         }
595
596         auto cell = this.live_list.find(ptr);
597         assert (cell);
598
599         // We have enough capacity already, just change the size
600         if (cell.capacity >= size) {
601             cell.size = size;
602             return cell.ptr;
603         }
604
605         // We need to move the cell because of the lack of capacity, find
606         // a free cell with the requested capacity (at least)
607         Cell* new_cell = Cell.from_ptr(this.malloc(size));
608         assert (!(new_cell is null)); // out of memory is handled by malloc()
609
610         // Move cell attributes and contents
611         new_cell.attr = cell.attr;
612         cstring.memcpy(new_cell.ptr, cell.ptr, cell.size);
613
614         // Free the old cell
615         this.free(cell);
616
617         return new_cell.ptr;
618     }
619
620     /**
621      * Attempt to in-place enlarge a memory block pointed to by ptr.
622      *
623      * The memory should be enlarged to at least min_size beyond its current
624      * capacity, up to a maximum of max_size. This does not attempt to move
625      * the memory block (like realloc() does).
626      *
627      * Returns:
628      *  0 if could not extend ptr, total size of entire memory block if
629      *  successful.
630      */
631     size_t extend(void* ptr, size_t min_size, size_t max_size)
632     {
633         assert (min_size <= max_size);
634         // There is no possible extension of the capacity for this
635         // implementation.
636         return 0;
637     }
638
639     /**
640      * Reserve memory to anticipate memory allocations.
641      *
642      * This implementation is really dumb, a single cell is allocated with
643      * size bytes. If 2 mallocs() follows a call to reserve(size), requesting
644      * size/2 bytes each, one allocation will be done still (and  half the
645      * memory of the first malloc will be wasted =) Since this is a trivial
646      * implementation, we don't care about this.
647      *
648      * The actual number of bytes reserver are returned, or 0 on error.
649      */
650     size_t reserve(size_t size)
651     {
652         assert (size > 0);
653         auto cell = cast(Cell*) cstdlib.malloc(size + Cell.sizeof);
654         if (!cell)
655             return 0;
656         cell.size = size;
657         cell.capacity = size;
658         this.free_list.link(cell);
659         return size;
660     }
661
662     /**
663      * Free unused memory.
664      *
665      * This method tells the GC that a cell is not longer used. The GC don't
666      * perform any connectivity check, if the cell was referenced by others,
667      * nasty things will happen (much like C/C++).
668      *
669      * Note that finalizers are not called by this method. Finalizers are
670      * called by the runtime when the delete operator is used, and the delete
671      * operator calls this method through the runtime.
672      */
673     void free(void* ptr)
674     {
675         if (ptr is null)
676             return;
677
678         auto cell = this.live_list.pop(ptr);
679         assert (cell);
680
681         this.free_list.link(cell);
682     }
683
684     /**
685      * Get the base address of an interior pointer into the GC heap.
686      *
687      * If ptr is not pointing into the GC heap null is returned.
688      */
689     void* addrOf(void* ptr)
690     {
691         if (ptr is null)
692             return null;
693
694         bool in_range(Cell* cell)
695         {
696             return ptr >= cell.ptr && ptr < (cell.ptr + cell.size);
697         }
698
699         auto cell = this.live_list.find(&in_range);
700         if (cell)
701             return cell.ptr;
702
703         return null;
704     }
705
706     /**
707      * Return the real size (capacity) for the cell pointed by ptr.
708      *
709      * ptr should be the base address of a heap allocated object, interior
710      * pointers are not supported (use addrOf() if you have an interior
711      * pointer). If this is not true, this method returns 0.
712      *
713      * realloc(ptr, sizeOf(ptr), attr) is guaranteed not to allocate/move
714      * memory.
715      */
716     size_t sizeOf(void* ptr)
717     {
718         auto cell = this.live_list.find(ptr);
719         if (cell)
720             return cell.capacity;
721         return 0;
722     }
723
724     /**
725      * Get information about the cell pointed by ptr.
726      *
727      * ptr should be the base address of a heap allocated object, interior
728      * pointers are not supported (use addrOf() if you have an interior
729      * pointer). If this is not true, this method returns BlkInfo.init.
730      *
731      * See BlkInfo for the information provided by this method.
732      */
733     BlkInfo query(void* ptr)
734     {
735         BlkInfo blk_info;
736
737         auto cell = this.live_list.find(ptr);
738         if (cell) {
739             blk_info.base = cell.ptr;
740             blk_info.size = cell.capacity;
741             blk_info.attr = cell.attr;
742         }
743
744         return blk_info;
745     }
746
747     /**
748      * Add a root pointer to the root set.
749      *
750      * This method can be used to register new root to the GC heap. This is
751      * only needed when the user has custom memory that has pointers into the
752      * GC heap (for example for interfacing with C programs, which allocates
753      * memory using malloc() directly).
754      *
755      * See_Also: removeRoot(), addRange(), removeRange()
756      */
757     void addRoot(void* ptr)
758     {
759         this.root_pointers.append(ptr);
760     }
761
762     /**
763      * Add a root range to the root set.
764      *
765      * This method can be used to register new root range (a memory chunk
766      * that should be scanned for pointers into the GC heap). This is
767      * only needed when the user has custom memory that has pointers into the
768      * GC heap (for example for interfacing with C programs, which allocates
769      * memory using malloc() directly).
770      *
771      * Pointers will be scanned assuming they are aligned.
772      *
773      * See_Also: removeRange(), addRoot(), removeRoot()
774      */
775     void addRange(void* ptr, size_t size)
776     {
777         this.root_ranges.append(RootRange(ptr, ptr + size));
778     }
779
780     /**
781      * Remove a root pointer from the root set.
782      *
783      * ptr has to be previously registered using addRoot(), in other case the
784      * results of this method is undefined.
785      *
786      * See_Also: addRoot(), addRange(), removeRange()
787      */
788     void removeRoot(void* ptr)
789     {
790         this.root_pointers.remove(ptr);
791     }
792
793     /**
794      * Remove a root range from the root set.
795      *
796      * ptr has to be previously registered using addRange(), in other case the
797      * results of this method is undefined.
798      *
799      * See_Also: addRange(), addRoot(), removeRoot()
800      */
801     void removeRange(void* ptr)
802     {
803         this.root_ranges.remove_if((ref RootRange range) {
804                     return range.from is ptr;
805                 });
806     }
807
808 } // struct GC
809
810 // vim: set et sw=4 sts=4 :