Skip to content

Commit e7db817

Browse files
committed
unix: Implement garbage collection support.
1 parent b62c30b commit e7db817

3 files changed

Lines changed: 101 additions & 0 deletions

File tree

unix/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ endif
3535
# source files
3636
SRC_C = \
3737
main.c \
38+
gccollect.c \
3839
file.c \
3940
socket.c \
4041
$(SRC_MOD)

unix/gccollect.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
4+
#include "misc.h"
5+
#include "mpconfig.h"
6+
#include "gc.h"
7+
8+
#if MICROPY_ENABLE_GC
9+
10+
extern void *stack_top;
11+
12+
// We capture here callee-save registers, i.e. ones which may contain
13+
// interesting values held there by our callers. It doesn't make sense
14+
// to capture caller-saved registers, because they, well, put on the
15+
// stack already by the caller.
16+
#ifdef __x86_64__
17+
typedef machine_uint_t regs_t[6];
18+
19+
void gc_helper_get_regs(regs_t arr) {
20+
register long rbx asm ("rbx");
21+
register long rbp asm ("rbp");
22+
register long r12 asm ("r12");
23+
register long r13 asm ("r13");
24+
register long r14 asm ("r14");
25+
register long r15 asm ("r15");
26+
arr[0] = rbx;
27+
arr[1] = rbp;
28+
arr[2] = r12;
29+
arr[3] = r13;
30+
arr[4] = r14;
31+
arr[5] = r15;
32+
}
33+
#endif
34+
35+
#ifdef __i386__
36+
typedef machine_uint_t regs_t[4];
37+
38+
void gc_helper_get_regs(regs_t arr) {
39+
register long ebx asm ("ebx");
40+
register long esi asm ("esi");
41+
register long edi asm ("edi");
42+
register long ebp asm ("ebp");
43+
arr[0] = ebx;
44+
arr[1] = esi;
45+
arr[2] = edi;
46+
arr[3] = ebp;
47+
}
48+
#endif
49+
50+
void gc_collect(void) {
51+
gc_collect_start();
52+
// this traces .data and .bss sections
53+
extern char __bss_start, _end;
54+
//printf(".bss: %p-%p\n", &__bss_start, &_end);
55+
gc_collect_root((void**)&__bss_start, ((uint32_t)&_end - (uint32_t)&__bss_start) / sizeof(uint32_t));
56+
regs_t regs;
57+
gc_helper_get_regs(regs);
58+
// GC stack (and regs because we captured them)
59+
gc_collect_root((void**)&regs, ((uint32_t)stack_top - (uint32_t)&regs) / sizeof(uint32_t));
60+
gc_collect_end();
61+
62+
if (0) {
63+
// print GC info
64+
gc_info_t info;
65+
gc_info(&info);
66+
printf("GC: total: " UINT_FMT ", used: " UINT_FMT ", free: " UINT_FMT "\n", info.total, info.used, info.free);
67+
printf(" No. of 1-blocks: " UINT_FMT ", 2-blocks: " UINT_FMT ", max blk sz: " UINT_FMT "\n",
68+
info.num_1block, info.num_2block, info.max_block);
69+
}
70+
}
71+
72+
#endif //MICROPY_ENABLE_GC

unix/main.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@
1515
#include "runtime0.h"
1616
#include "runtime.h"
1717
#include "repl.h"
18+
#include "gc.h"
1819

1920
#if MICROPY_USE_READLINE
2021
#include <readline/readline.h>
2122
#include <readline/history.h>
2223
#endif
2324

25+
// Heap size of GC heap (if enabled)
26+
// TODO: allow to specify on command line
27+
#define HEAP_SIZE 128*1024
28+
29+
// Stack top at the start of program
30+
void *stack_top;
31+
2432
extern const mp_obj_fun_native_t mp_builtin_open_obj;
2533
void file_init();
2634
void microsocket_init();
@@ -217,7 +225,24 @@ mp_obj_t qstr_info(void) {
217225
return mp_const_none;
218226
}
219227

228+
#if MICROPY_ENABLE_GC
229+
// TODO: this doesn't belong here
230+
static mp_obj_t pyb_gc(void) {
231+
gc_collect();
232+
return mp_const_none;
233+
}
234+
MP_DEFINE_CONST_FUN_OBJ_0(pyb_gc_obj, pyb_gc);
235+
#endif
236+
220237
int main(int argc, char **argv) {
238+
volatile int stack_dummy;
239+
stack_top = (void*)&stack_dummy;
240+
241+
#if MICROPY_ENABLE_GC
242+
char *heap = malloc(HEAP_SIZE);
243+
gc_init(heap, heap + HEAP_SIZE);
244+
#endif
245+
221246
qstr_init();
222247
rt_init();
223248

@@ -263,6 +288,9 @@ int main(int argc, char **argv) {
263288
rt_store_name(qstr_from_str("test"), test_obj_new(42));
264289
rt_store_name(qstr_from_str("mem_info"), rt_make_function_n(0, mem_info));
265290
rt_store_name(qstr_from_str("qstr_info"), rt_make_function_n(0, qstr_info));
291+
#if MICROPY_ENABLE_GC
292+
rt_store_name(qstr_from_str("gc"), (mp_obj_t)&pyb_gc_obj);
293+
#endif
266294

267295
file_init();
268296
microsocket_init();

0 commit comments

Comments
 (0)