diff --git a/dat.h b/dat.h index 43e9a6f..d2920bf 100644 --- a/dat.h +++ b/dat.h @@ -1,3 +1,6 @@ +#include + +typedef uintptr_t u64; typedef struct Object Object; typedef Object* (*Bltinfn)(Object *env, Object *args); typedef struct Object Object; @@ -51,6 +54,31 @@ struct Object }; }; +/* + *0 ~ 64 : for object + *64 ~ 100 : for string + */ +typedef struct +{ + void *memory; + u64 cap; + u64 using; + u64 top; + /* objects */ + struct{ + Object *objs; + u64 ob; + u64 oe; + u64 op; + Object *freed; + }; + /* string */ + struct{ + u64 sb; + u64 se; + }; +}GC; + extern Object Nil; extern Object True; extern Object False; diff --git a/fn.h b/fn.h index e634bd2..b5c9263 100644 --- a/fn.h +++ b/fn.h @@ -18,8 +18,8 @@ Object* newfn(Object *env, Object *params, Object *body); /* gc.c */ void gcstatus(void); Object* newobj(enum OType); -void* xalloc(int); -void* xralloc(void*, int); +void* gcalloc(int); +void* gcralloc(void*, int); void gcinit(void *top, int cap); void gcrun(void); diff --git a/gc.c b/gc.c index cdb796d..cb12e9c 100644 --- a/gc.c +++ b/gc.c @@ -1,45 +1,86 @@ #include "dat.h" #include "fn.h" #include -#include #include -#include #include +#include enum { USING = 1 << 1, -}; -typedef struct -{ - int total; - int using; - uintptr_t top; - uintptr_t beg; - uintptr_t end; - Object objs; - Object freed; -}GC; + OFFSET = sizeof(int), +}; GC gc = {0}; -static void -pushobj(Object *list, Object *obj) +void +gcfree(void *src) { - Object *l = list; - Object *c = l->next; - while(c){ - l = c; - c=c->next; - } - l->next = obj; + int *p = (int*)src - 1; + int sz = *p; + memset(p, 0, sz); + gc.using -= sz; } -static void +void +freeobj(Object *p) +{ + gc.using -= sizeof(Object); + p->next = 0; + switch(p->type){ + default: + break; + case OSTRING: + case OIDENT: + gcfree(p->beg); + break; + } + memset(p, 0, sizeof(Object)); + if(gc.freed == 0) + gc.freed = p; + else{ + p->next = gc.freed; + gc.freed = p; + } +} + +void* +gcalloc(int sz) +{ + sz += OFFSET; + if(sz % OFFSET) sz = sz + OFFSET - (sz % OFFSET); + for(u64 i = gc.sb; i < gc.se;){ + u64 j = i; + for(;j - i < sz; j += OFFSET){ + if(*(int*)(j) != 0) + break; + } + if(j - i == sz){ + gc.using += sz; + *(int*)i = sz; + i += OFFSET; + return (void*)i; + } + i = j + *(int*)(j); + } + panic("gccalloc : Not impl yet raise"); +} + +void* +gcralloc(void *src, int sz) +{ + void *dst = gcalloc(sz); + int osz = ((int*)src)[-1]; + memcpy(dst, src, osz); + gcfree(src); + return dst; +} + +void mark(Object *obj) { - if(obj == 0 || obj->flag & USING) + if(obj == 0 || obj->flag&USING) return; obj->flag = USING; switch(obj->type){ @@ -60,57 +101,45 @@ mark(Object *obj) } } -static int -isobj(uintptr_t val) -{ - if(val < gc.beg || val >= gc.end) - return 0; - val -= gc.beg; - uintptr_t mod = val % sizeof(Object); - return mod == 0; -} - -static void -freeobj(Object *obj) -{ - switch(obj->type){ - case OSTRING: - case OIDENT: - printf("freed => '%s'\n", obj->beg); - free(obj->beg); - break; - } - memset(obj, 0, sizeof(*obj)); - pushobj(&gc.freed, obj); - gc.using -= sizeof(Object); -} - -static void +void gcsweep(void) { - Object *l = &gc.objs; - Object *c = l->next; - while(c){ - if(c->flag&USING){ - c->flag = 0; - l = c; - c = c->next; - continue; + Object *last = 0; + for(Object *p = gc.objs; p;){ + if(p->flag&USING){ + p->flag = 0; + last = p; + p = p->next; + }else{ + Object *tmp = p; + if(last == 0){ + gc.objs = p->next; + }else{ + last->next = p->next; + } + p = p->next; + freeobj(tmp); } - Object *t = c; - l->next = c->next; - c = c->next; - freeobj(t); } } -static void +int +isobj(u64 p) +{ + if(gc.ob <= p && p < gc.oe){ + p -= gc.ob; + return (p % sizeof(Object)) == 0; + } + return 0; +} + +void gcmark(void) { void *_ = 0; - uintptr_t bot = (uintptr_t)&_; + u64 bot = (u64)&_; for(; bot < gc.top; bot += sizeof(bot)){ - uintptr_t val = (uintptr_t)*(void**)bot; + u64 val = (u64)*(void**)bot; if(isobj(val)) mark((Object*)val); } @@ -119,64 +148,52 @@ gcmark(void) void gcrun(void) { + printf("before=> cap:%d using:%d remain:%d\n", gc.cap, gc.using, gc.cap-gc.using); jmp_buf reg; setjmp(reg); gcmark(); gcsweep(); - gcstatus(); + printf("after=> cap:%d using:%d remain:%d\n", gc.cap, gc.using, gc.cap-gc.using); } -void -gcstatus(void) -{ - printf("curren=> total:%d using:%d remain:%d\n", gc.total, gc.using, gc.total-gc.using); -} - -void* -xalloc(int sz) -{ - int *res = calloc(1, sz); - if(res == 0) - panic("Can't allocated %d byte", sz); - return res; -} - -void* -xralloc(void *src, int sz) -{ - int *p = realloc(src, sz); - if(p == 0) - panic("Can't allocated %d byte", sz); - return p; -} - -Object* +Object* newobj(enum OType type) -{ +{ + if(gc.op + sizeof(Object) >= gc.oe){ + panic("Not impl yet newobj raise"); + } gcrun(); - Object *obj = 0; - if(gc.freed.next){ - obj = gc.freed.next; - gc.freed.next = obj->next; - obj->next = 0; - }else - panic("not impl yet"); - obj->type = type; - pushobj(&gc.objs, obj); gc.using += sizeof(Object); - return obj; + Object *r = 0; + if(gc.freed){ + r = gc.freed; + gc.freed = gc.freed->next; + }else{ + r = (Object*)gc.op; + gc.op += sizeof(Object); + } + r->type = type; + if(gc.objs == 0) + gc.objs = r; + else{ + r->next = gc.objs; + gc.objs = r; + } + return r; } void gcinit(void *top, int cap) { - gc.total = cap; + gc.top = (u64)top; + if((gc.memory = malloc(cap)) == 0) + panic("can't alloc %d byte\n", cap); + gc.cap = cap; gc.using = 0; - gc.top = (uintptr_t)top; - gc.beg = (uintptr_t)xalloc(cap); - gc.end = gc.beg + cap; - Object *p = &gc.freed; - for(uintptr_t i = gc.beg; i < gc.end; i+=sizeof(Object)){ - p = p->next = (Object*)i; - } + + gc.op = gc.ob = (u64)gc.memory; + gc.oe = gc.op + (float)cap * 0.64; + + gc.sb = (u64)gc.memory + (float)cap * 0.64; + gc.se = (u64)gc.memory + cap; } diff --git a/main.c b/main.c index 9ddca10..05f7f28 100644 --- a/main.c +++ b/main.c @@ -64,7 +64,6 @@ loop(void) gcrun(); } while(1){ - gcstatus(); Object *res = nextexpr(); res = eval(root, res); printexpr(res); @@ -74,6 +73,6 @@ loop(void) int main(int argc, char *argv[]) { - gcinit(&argc, 3000); + gcinit(&argc, 4000); loop(); } diff --git a/makefile b/makefile index 72c9989..174b7a7 100644 --- a/makefile +++ b/makefile @@ -10,7 +10,7 @@ OFILES=\ parser.o AS=$(CC) -c -CFLAGS=-c -g -O2 +CFLAGS=-c -g -O0 all: $(NAME) diff --git a/obj.c b/obj.c index f889f84..ee24769 100644 --- a/obj.c +++ b/obj.c @@ -60,7 +60,7 @@ newsymbol(char *str, int len) return c; } Object *obj = newobj(OIDENT); - obj->beg = xalloc(len + 1); + obj->beg = gcalloc(len + 1); obj->end = obj->ptr = obj->beg + len; memcpy(obj->beg, str, len+1); return obj; @@ -70,7 +70,7 @@ Object* newstr(int len) { Object *obj = newobj(OSTRING); - obj->ptr = obj->beg = xalloc(len + 1); + obj->ptr = obj->beg = gcalloc(len + 1); obj->end = obj->beg + len; return obj; } diff --git a/str.c b/str.c index d138bbe..adcb595 100644 --- a/str.c +++ b/str.c @@ -2,11 +2,11 @@ #include "fn.h" #include -static void -raise(Object *s, int ns) +void +strraise(Object *s, int ns) { int pos = s->ptr - s->beg; - char *ptr = xralloc(s->beg, ns + 1); + char *ptr = gcralloc(s->beg, ns + 1); s->beg = ptr; s->ptr = s->beg + pos; s->end = s->beg + ns; @@ -16,7 +16,7 @@ void strputc(Object *s, int c) { if(s->ptr >= s->end) - raise(s, (s->end - s->beg) * 2); + strraise(s, (s->end - s->beg) * 2); *s->ptr++ = c; *s->ptr = 0; } @@ -26,7 +26,7 @@ strputs(Object *s, char *ptr) { int l = strlen(ptr); if(s->ptr + l >= s->end) - raise(s, s->end - s->beg + l); + strraise(s, s->end - s->beg + l); memcpy(s->ptr, ptr, l); s->ptr += l; s->ptr[0] = 0;