66#include <sys/mman.h>
77#include "gc.h"
88
9- extern __attribute(( noreturn )) void error (char * fmt , ...);
9+ extern void error (char * fmt , ...);
1010
1111// The pointer pointing to the beginning of the current heap
1212void * memory ;
@@ -18,32 +18,30 @@ static void *from_space;
1818static size_t mem_nused = 0 ;
1919
2020// Flags to debug GC
21- static bool gc_running = false;
22- static bool debug_gc = false;
23- static bool always_gc = false;
21+ bool gc_running = false;
22+ bool debug_gc = false;
23+ bool always_gc = false;
2424
2525
2626// The list containing all symbols. Such data structure is traditionally called the "obarray", but I
2727// avoid using it as a variable name as this is not an array but a list.
28- extern Obj * Symbols ;
29-
30- static void gc (void * root ); // forward decl
28+ Obj * Symbols ;
3129
3230// Round up the given value to a multiple of size. Size must be a power of 2. It adds size - 1
3331// first, then zero-ing the least significant bits to make the result a multiple of size. I know
3432// these bit operations may look a little bit tricky, but it's efficient and thus frequently used.
3533static inline size_t roundup (size_t var , size_t size ) {
36- return (var + size - 1 ) & ~(size - 1 ); // 傳回的大小必須是 2 的次方
34+ return (var + size - 1 ) & ~(size - 1 );
3735}
3836
3937// Allocates memory block. This may start GC if we don't have enough memory.
40- Obj * alloc (void * root , int type , size_t size ) { // 分配比 size 大的記憶體給 type 的物件
38+ Obj * alloc (void * root , int type , size_t size ) {
4139 // The object must be large enough to contain a pointer for the forwarding pointer. Make it
4240 // larger if it's smaller than that.
4341 size = roundup (size , sizeof (void * ));
4442
4543 // Add the size of the type tag and size fields.
46- size += offsetof(Obj , value ); // offsetof 的功能 -- 參考 https://en.cppreference.com/w/cpp/types/offsetof
44+ size += offsetof(Obj , value );
4745
4846 // Round up the object size to the nearest alignment boundary, so that the next object will be
4947 // allocated at the proper alignment boundary. Currently we align the object at the same
@@ -55,20 +53,20 @@ Obj *alloc(void *root, int type, size_t size) { // 分配比 size 大的記憶
5553 // more predictable and repeatable. If there's a memory bug that the C variable has a direct
5654 // reference to a Lisp object, the pointer will become invalid by this GC call. Dereferencing
5755 // that will immediately cause SEGV.
58- if (always_gc && !gc_running ) // 每次分配前都做垃圾收集
56+ if (always_gc && !gc_running )
5957 gc (root );
6058
6159 // Otherwise, run GC only when the available memory is not large enough.
62- if (!always_gc && MEMORY_SIZE < mem_nused + size ) // 只有記憶體不足時才做垃圾收集
60+ if (!always_gc && MEMORY_SIZE < mem_nused + size )
6361 gc (root );
6462
6563 // Terminate the program if we couldn't satisfy the memory request. This can happen if the
6664 // requested size was too large or the from-space was filled with too many live objects.
67- if (MEMORY_SIZE < mem_nused + size ) // heap 記憶體用完了
65+ if (MEMORY_SIZE < mem_nused + size )
6866 error ("Memory exhausted" );
6967
7068 // Allocate the object.
71- Obj * obj = memory + mem_nused ; // memory: heap 起點 men_nused: 目前用掉的大小。
69+ Obj * obj = memory + mem_nused ;
7270 obj -> type = type ;
7371 obj -> size = size ;
7472 mem_nused += size ;
@@ -84,12 +82,12 @@ Obj *alloc(void *root, int type, size_t size) { // 分配比 size 大的記憶
8482// to-space. The objects before "scan1" are the objects that are fully copied. The objects between
8583// "scan1" and "scan2" have already been copied, but may contain pointers to the from-space. "scan2"
8684// points to the beginning of the free space.
87- static Obj * scan1 ; // Cheney 算法請參考 -- https://blog.csdn.net/MrLiii/article/details/113521913
88- static Obj * scan2 ; // scan1, scan2 就是上文中的 SCAN 與 Free
85+ static Obj * scan1 ;
86+ static Obj * scan2 ;
8987
9088// Moves one object from the from-space to the to-space. Returns the object's new address. If the
9189// object has already been moved, does nothing but just returns the new address.
92- static inline Obj * forward (Obj * obj ) { // 將 obj 從 from 區移到 to 區
90+ static inline Obj * forward (Obj * obj ) {
9391 // If the object's address is not in the from-space, the object is not managed by GC nor it
9492 // has already been moved to the to-space.
9593 ptrdiff_t offset = (uint8_t * )obj - (uint8_t * )from_space ;
@@ -98,29 +96,29 @@ static inline Obj *forward(Obj *obj) { // 將 obj 從 from 區移到 to 區
9896
9997 // The pointer is pointing to the from-space, but the object there was a tombstone. Follow the
10098 // forwarding pointer to find the new location of the object.
101- if (obj -> type == TMOVED ) // 已經移過去了,不用再移
99+ if (obj -> type == TMOVED )
102100 return obj -> moved ;
103101
104- // Otherwise, the object has not been moved yet. Move it. // 還沒移過去,開始移
105- Obj * newloc = scan2 ; // 目標位址
106- memcpy (newloc , obj , obj -> size ); // 移過去
107- scan2 = (Obj * )((uint8_t * )scan2 + obj -> size ); // 將 scan2 往後移動
102+ // Otherwise, the object has not been moved yet. Move it.
103+ Obj * newloc = scan2 ;
104+ memcpy (newloc , obj , obj -> size );
105+ scan2 = (Obj * )((uint8_t * )scan2 + obj -> size );
108106
109107 // Put a tombstone at the location where the object used to occupy, so that the following call
110108 // of forward() can find the object's new location.
111- obj -> type = TMOVED ; // 標示該物件已完成移動
112- obj -> moved = newloc ; // 標示該物件的新位址
113- return newloc ; // 傳回該物件的新位址
109+ obj -> type = TMOVED ;
110+ obj -> moved = newloc ;
111+ return newloc ;
114112}
115113
116114void * alloc_semispace () {
117115 return mmap (NULL , MEMORY_SIZE , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANON , -1 , 0 );
118116}
119117
120- // Copies the root objects. // 移動 root 環境的物件
118+ // Copies the root objects.
121119static void forward_root_objects (void * root ) {
122- Symbols = forward (Symbols ); // 移動符號表到新記憶體區
123- for (void * * frame = root ; frame ; frame = * (void * * * )frame ) // 移動 frame 到新記憶體區
120+ Symbols = forward (Symbols );
121+ for (void * * frame = root ; frame ; frame = * (void * * * )frame )
124122 for (int i = 1 ; frame [i ] != ROOT_END ; i ++ )
125123 if (frame [i ])
126124 frame [i ] = forward (frame [i ]);
@@ -135,14 +133,14 @@ static bool getEnvFlag(char *name) {
135133
136134// Implements Cheney's copying garbage collection algorithm.
137135// http://en.wikipedia.org/wiki/Cheney%27s_algorithm
138- static void gc (void * root ) {
136+ void gc (void * root ) {
139137 assert (!gc_running );
140138 gc_running = true; // 開始垃圾蒐集
141139
142140 // Debug flags
143141 debug_gc = getEnvFlag ("MINILISP_DEBUG_GC" );
144142 always_gc = getEnvFlag ("MINILISP_ALWAYS_GC" );
145-
143+
146144 // Allocate a new semi-space.
147145 from_space = memory ;
148146 memory = alloc_semispace ();
@@ -151,40 +149,40 @@ static void gc(void *root) {
151149 scan1 = scan2 = memory ;
152150
153151 // Copy the GC root objects first. This moves the pointer scan2.
154- forward_root_objects (root ); // 移動 root 環境的物件
152+ forward_root_objects (root );
155153
156154 // Copy the objects referenced by the GC root objects located between scan1 and scan2. Once it's
157155 // finished, all live objects (i.e. objects reachable from the root) will have been copied to
158156 // the to-space.
159- while (scan1 < scan2 ) { // 將 root 指向的物件從 scan1 (FROM) 搬到 scan2 (to) 去
157+ while (scan1 < scan2 ) {
160158 switch (scan1 -> type ) {
161159 case TINT :
162- case TSTRING :
163160 case TSYMBOL :
164161 case TPRIMITIVE :
162+ case TSTRING :
165163 // Any of the above types does not contain a pointer to a GC-managed object.
166164 break ;
167165 case TCELL :
168- scan1 -> car = forward (scan1 -> car ); // 每個 list 的 car, cdr 都搬到新位址
166+ scan1 -> car = forward (scan1 -> car );
169167 scan1 -> cdr = forward (scan1 -> cdr );
170168 break ;
171169 case TFUNCTION :
172170 case TMACRO :
173- scan1 -> params = forward (scan1 -> params ); // 每個 macro 的 params, body, env 都搬到新位址
171+ scan1 -> params = forward (scan1 -> params );
174172 scan1 -> body = forward (scan1 -> body );
175173 scan1 -> env = forward (scan1 -> env );
176174 break ;
177175 case TENV :
178- scan1 -> vars = forward (scan1 -> vars ); // 每個 env 的 vars, up 都搬到新位址
176+ scan1 -> vars = forward (scan1 -> vars );
179177 scan1 -> up = forward (scan1 -> up );
180178 break ;
181179 default :
182180 error ("Bug: copy: unknown type %d" , scan1 -> type );
183181 }
184- scan1 = (Obj * )((uint8_t * )scan1 + scan1 -> size ); // 前進到下一個物件
182+ scan1 = (Obj * )((uint8_t * )scan1 + scan1 -> size );
185183 }
186184
187- // Finish up GC. // 結束垃圾蒐集
185+ // Finish up GC.
188186 munmap (from_space , MEMORY_SIZE );
189187 size_t old_nused = mem_nused ;
190188 mem_nused = (size_t )((uint8_t * )scan1 - (uint8_t * )memory );
0 commit comments