rewrite GC
This commit is contained in:
parent
275c03f518
commit
8c3a666975
46
bltin.c
46
bltin.c
@ -1,28 +1,28 @@
|
|||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fn.h"
|
#include "fn.h"
|
||||||
|
|
||||||
Object Nil = (Object){.type=OSYMBOL, .sym="nil"};
|
Object Nil = (Object){.type=OSYMBOL, .beg="nil"};
|
||||||
Object Minus= (Object){.type=OBLTIN, .sym="-"};
|
Object Minus= (Object){.type=OBLTIN, .beg="-"};
|
||||||
Object Plus = (Object){.type=OBLTIN, .sym="+"};
|
Object Plus = (Object){.type=OBLTIN, .beg="+"};
|
||||||
Object Mul = (Object){.type=OBLTIN, .sym="*"};
|
Object Mul = (Object){.type=OBLTIN, .beg="*"};
|
||||||
Object Div = (Object){.type=OBLTIN, .sym="/"};
|
Object Div = (Object){.type=OBLTIN, .beg="/"};
|
||||||
Object Mod = (Object){.type=OBLTIN, .sym="%"};
|
Object Mod = (Object){.type=OBLTIN, .beg="%"};
|
||||||
|
|
||||||
Object Ge = (Object){.type=OBLTIN, .sym= ">="};
|
Object Ge = (Object){.type=OBLTIN, .beg= ">="};
|
||||||
Object Le = (Object){.type=OBLTIN, .sym= "<="};
|
Object Le = (Object){.type=OBLTIN, .beg= "<="};
|
||||||
Object Lt = (Object){.type=OBLTIN, .sym= "<"};
|
Object Lt = (Object){.type=OBLTIN, .beg= "<"};
|
||||||
Object Gt = (Object){.type=OBLTIN, .sym= ">"};
|
Object Gt = (Object){.type=OBLTIN, .beg= ">"};
|
||||||
Object Ne = (Object){.type=OBLTIN, .sym= "!="};
|
Object Ne = (Object){.type=OBLTIN, .beg= "!="};
|
||||||
Object Eq = (Object){.type=OBLTIN, .sym= "=="};
|
Object Eq = (Object){.type=OBLTIN, .beg= "=="};
|
||||||
|
|
||||||
Object Lambda= (Object){.type=OBLTIN, .sym="lambda"};
|
Object Lambda= (Object){.type=OBLTIN, .beg="lambda"};
|
||||||
Object Car = (Object){.type=OBLTIN, .sym="car"};
|
Object Car = (Object){.type=OBLTIN, .beg="car"};
|
||||||
Object Cdr = (Object){.type=OBLTIN, .sym="cdr"};
|
Object Cdr = (Object){.type=OBLTIN, .beg="cdr"};
|
||||||
Object Quote= (Object){.type=OBLTIN, .sym="'"};
|
Object Quote= (Object){.type=OBLTIN, .beg="'"};
|
||||||
Object Cons = (Object){.type=OBLTIN, .sym="cons"};
|
Object Cons = (Object){.type=OBLTIN, .beg="cons"};
|
||||||
Object Define= (Object){.type=OBLTIN, .sym="define"};
|
Object Define= (Object){.type=OBLTIN, .beg="define"};
|
||||||
Object Setq = (Object){.type=OBLTIN, .sym="setq"};
|
Object Setq = (Object){.type=OBLTIN, .beg="setq"};
|
||||||
Object If = (Object){.type=OBLTIN, .sym="if"};
|
Object If = (Object){.type=OBLTIN, .beg="if"};
|
||||||
|
|
||||||
extern Object* fnplus(Object *, Object *);
|
extern Object* fnplus(Object *, Object *);
|
||||||
extern Object* fnmul(Object *, Object *);
|
extern Object* fnmul(Object *, Object *);
|
||||||
@ -50,7 +50,7 @@ bltinlookup(Object *obj)
|
|||||||
{
|
{
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
Object *sym;
|
Object *beg;
|
||||||
Bltinfn fn;
|
Bltinfn fn;
|
||||||
}bltins[] = {
|
}bltins[] = {
|
||||||
{&Lambda , fnlambda},
|
{&Lambda , fnlambda},
|
||||||
@ -75,8 +75,8 @@ bltinlookup(Object *obj)
|
|||||||
{0},
|
{0},
|
||||||
};
|
};
|
||||||
|
|
||||||
for(int i = 0; bltins[i].sym; ++i){
|
for(int i = 0; bltins[i].beg; ++i){
|
||||||
if(obj == bltins[i].sym)
|
if(obj == bltins[i].beg)
|
||||||
return bltins[i].fn;
|
return bltins[i].fn;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
48
dat.h
48
dat.h
@ -1,19 +1,17 @@
|
|||||||
#include <stdint.h>
|
typedef struct GC GC;
|
||||||
|
|
||||||
typedef uintptr_t u64;
|
|
||||||
typedef struct Object Object;
|
typedef struct Object Object;
|
||||||
typedef Object* (*Bltinfn)(Object *env, Object *args);
|
typedef Object* (*Bltinfn)(Object *env, Object *args);
|
||||||
|
|
||||||
enum OType
|
enum OType
|
||||||
{
|
{
|
||||||
OERROR,
|
ONONE,
|
||||||
OCELL,
|
|
||||||
OSYMBOL,
|
|
||||||
OIDENT,
|
|
||||||
OINT,
|
|
||||||
OSTRING,
|
|
||||||
OLAMBDA,
|
|
||||||
OBLTIN,
|
OBLTIN,
|
||||||
|
OSYMBOL,
|
||||||
|
OCELL,
|
||||||
|
OIDENT,
|
||||||
|
OSTRING,
|
||||||
|
OINT,
|
||||||
|
OLAMBDA,
|
||||||
OFUNC,
|
OFUNC,
|
||||||
OENV,
|
OENV,
|
||||||
};
|
};
|
||||||
@ -22,7 +20,6 @@ struct Object
|
|||||||
{
|
{
|
||||||
enum OType type; /* type */
|
enum OType type; /* type */
|
||||||
int flag; /* flag */
|
int flag; /* flag */
|
||||||
Object *next; /* for gc */
|
|
||||||
Object *forward;
|
Object *forward;
|
||||||
union{
|
union{
|
||||||
/* int */
|
/* int */
|
||||||
@ -32,8 +29,7 @@ struct Object
|
|||||||
Object *car;
|
Object *car;
|
||||||
Object *cdr;
|
Object *cdr;
|
||||||
};
|
};
|
||||||
/* string & ident */
|
/* string & ident & symbol */
|
||||||
char *sym;
|
|
||||||
struct{
|
struct{
|
||||||
char *beg;
|
char *beg;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@ -54,32 +50,6 @@ struct Object
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
*0 ~ 64 : for object
|
|
||||||
*64 ~ 100 : for string
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int running;
|
|
||||||
void *memory;
|
|
||||||
u64 cap;
|
|
||||||
u64 using;
|
|
||||||
u64 top;
|
|
||||||
/* objects */
|
|
||||||
struct{
|
|
||||||
Object *objs;
|
|
||||||
Object *freed;
|
|
||||||
u64 ob;
|
|
||||||
u64 oe;
|
|
||||||
u64 op;
|
|
||||||
};
|
|
||||||
/* string */
|
|
||||||
struct{
|
|
||||||
u64 sb;
|
|
||||||
u64 se;
|
|
||||||
};
|
|
||||||
}GC;
|
|
||||||
|
|
||||||
extern GC *gc;
|
extern GC *gc;
|
||||||
extern Object Nil;
|
extern Object Nil;
|
||||||
extern Object Minus;
|
extern Object Minus;
|
||||||
|
|||||||
2
eval.c
2
eval.c
@ -144,7 +144,7 @@ plusstr(Object *env, Object *p)
|
|||||||
for(;p!=&Nil; p=p->cdr){
|
for(;p!=&Nil; p=p->cdr){
|
||||||
if(p->car->type != OSTRING)
|
if(p->car->type != OSTRING)
|
||||||
error("+ take only number");
|
error("+ take only number");
|
||||||
strputs(str, p->car->beg);
|
str = strputs(str, p->car);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|||||||
10
fn.h
10
fn.h
@ -16,16 +16,16 @@ Object* newstr(GC *,int);
|
|||||||
Object* newfn(GC *,Object *env, Object *params, Object *body);
|
Object* newfn(GC *,Object *env, Object *params, Object *body);
|
||||||
|
|
||||||
/* gc.c */
|
/* gc.c */
|
||||||
Object* newobj(GC *,enum OType);
|
|
||||||
void* gcalloc(GC *,int);
|
|
||||||
void* gcralloc(GC *, void*, int);
|
|
||||||
GC* newgc(void *top, int cap);
|
GC* newgc(void *top, int cap);
|
||||||
void gcrun(GC *);
|
void gcrun(GC *);
|
||||||
|
void* gcalloc(GC *gc, int sz);
|
||||||
|
void printgc(char *, GC *);
|
||||||
|
|
||||||
/* str.c */
|
/* str.c */
|
||||||
void strputc(Object*, int);
|
Object* strputc(Object*, int);
|
||||||
void strputs(Object*, char*);
|
Object* strputs(Object*, Object*);
|
||||||
int strequal(Object*, Object*);
|
int strequal(Object*, Object*);
|
||||||
|
void strinit(Object *s, Object *str);
|
||||||
|
|
||||||
/* error.c */
|
/* error.c */
|
||||||
void panic(char *fmt, ...);
|
void panic(char *fmt, ...);
|
||||||
|
|||||||
340
gc.c
340
gc.c
@ -4,50 +4,75 @@
|
|||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct GC
|
||||||
|
{
|
||||||
|
int running;
|
||||||
|
int cap;
|
||||||
|
int using;
|
||||||
|
uintptr_t *top;
|
||||||
|
uintptr_t *beg;
|
||||||
|
uintptr_t *end;
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
USING = 1 << 1,
|
USING = 1 << 1,
|
||||||
FORWARD = 1 << 2,
|
FORWARD = 1 << 2,
|
||||||
|
|
||||||
OFFSET = sizeof(int),
|
PTR = sizeof(void*),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Object*
|
||||||
|
findobj(GC *gc, uintptr_t *stk)
|
||||||
|
{
|
||||||
|
if(gc->beg <= stk && stk < gc->end)
|
||||||
|
for(uintptr_t *p = gc->beg; p < stk;){
|
||||||
|
if(*p){
|
||||||
|
if(p <= stk && stk < p + *p) return (Object*)&p[1];
|
||||||
|
else p += *p;
|
||||||
|
}else{
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
cloneobj(GC *dst, GC *src, Object *obj)
|
cloneobj(GC *dst, GC *src, Object *obj)
|
||||||
{
|
{
|
||||||
if(obj == 0)
|
if(obj->type==OBLTIN||obj->type==OSYMBOL) return obj;
|
||||||
return 0;
|
if(obj->flag&FORWARD) return obj->forward;
|
||||||
if(obj->type==OBLTIN||obj->type==OSYMBOL)
|
|
||||||
return obj;
|
Object *p;
|
||||||
if(obj->flag&FORWARD)
|
|
||||||
return obj->forward;
|
|
||||||
Object *p = newobj(dst, obj->type);
|
|
||||||
obj->flag |= FORWARD;
|
obj->flag |= FORWARD;
|
||||||
obj->forward = p;
|
|
||||||
switch(obj->type){
|
switch(obj->type){
|
||||||
default: panic("unreachable");
|
default: panic("unreachable");
|
||||||
case OINT:
|
case OINT:
|
||||||
p->num = obj->num;
|
obj->forward = p = newint(dst, obj->num);
|
||||||
break;
|
break;
|
||||||
case OSTRING:
|
case OSTRING:
|
||||||
case OIDENT:{
|
obj->forward = p = newstr(dst, obj->end - obj->beg);
|
||||||
int len = obj->ptr - obj->beg;
|
strinit(p, obj);
|
||||||
p->beg = gcalloc(dst, len + 1);
|
break;
|
||||||
p->end = p->ptr = p->beg + len;
|
case OIDENT:
|
||||||
memcpy(p->beg, obj->beg, len + 1);
|
obj->forward = p = newsymbol(dst, obj->beg, obj->ptr - obj->beg);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case OCELL:
|
case OCELL:
|
||||||
|
obj->forward = p = newcons(dst, &Nil, &Nil);
|
||||||
p->car = cloneobj(dst, src, obj->car);
|
p->car = cloneobj(dst, src, obj->car);
|
||||||
p->cdr = cloneobj(dst, src, obj->cdr);
|
p->cdr = cloneobj(dst, src, obj->cdr);
|
||||||
break;
|
break;
|
||||||
case OENV:
|
case OENV:
|
||||||
|
obj->forward = p = newenv(dst, &Nil, &Nil, &Nil);
|
||||||
p->name = cloneobj(dst, src, obj->name);
|
p->name = cloneobj(dst, src, obj->name);
|
||||||
p->vars = cloneobj(dst, src, obj->vars);
|
p->vars = cloneobj(dst, src, obj->vars);
|
||||||
p->up = cloneobj(dst, src, obj->up);
|
p->up = cloneobj(dst, src, obj->up);
|
||||||
break;
|
break;
|
||||||
case OFUNC:
|
case OFUNC:
|
||||||
|
obj->forward = p = newfn(dst, &Nil, &Nil, &Nil);
|
||||||
p->params = cloneobj(dst, src, obj->params);
|
p->params = cloneobj(dst, src, obj->params);
|
||||||
p->body = cloneobj(dst, src, obj->body);
|
p->body = cloneobj(dst, src, obj->body);
|
||||||
p->env = cloneobj(dst, src, obj->env);
|
p->env = cloneobj(dst, src, obj->env);
|
||||||
@ -56,138 +81,45 @@ cloneobj(GC *dst, GC *src, Object *obj)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
|
||||||
moveobj(Object *p)
|
|
||||||
{
|
|
||||||
if(p == 0 || p->type == 0)
|
|
||||||
return 0;
|
|
||||||
switch(p->type){
|
|
||||||
default:
|
|
||||||
return p->forward;
|
|
||||||
case OBLTIN:
|
|
||||||
case OSYMBOL:
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
forwardstack(u64 bot, GC *dst, GC *src)
|
gcraise(GC *src)
|
||||||
{
|
{
|
||||||
u64 pos, diff, *stk;
|
jmp_buf reg;
|
||||||
Object *moved, *org;
|
uintptr_t _ = 0;
|
||||||
for(; bot < src->top; bot += sizeof(bot)){
|
if(src->running) return;
|
||||||
stk = (u64*)(void**)bot;
|
if(setjmp(reg) == 1) return;
|
||||||
if(src->ob <= *stk && *stk < src->oe){
|
|
||||||
diff = (*stk - src->ob) % sizeof(Object);
|
GC *dst = newgc(src->top, src->cap * 2);
|
||||||
org = (Object*)(*stk - diff);
|
src->running = dst->running = 1;
|
||||||
if((moved = moveobj(org)) == 0)
|
for(uintptr_t *p = src->beg; p < src->end;)
|
||||||
continue;
|
if(*p){
|
||||||
diff = (u64)org - *stk;
|
cloneobj(dst, src, (Object*)&p[1]);
|
||||||
pos = (u64)moved + diff;
|
p += *p;
|
||||||
memcpy(stk, &pos, sizeof(pos));
|
}else{
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
else if(src->sb <= *stk && *stk < src->se)
|
for(uintptr_t *bot = &_; bot < src->top; bot++){
|
||||||
for(org = src->objs; org; org = org->next){
|
Object *p = findobj(src, (uintptr_t*)*bot);
|
||||||
if(org->type == OSTRING || org->type == OIDENT){
|
if(p){
|
||||||
u64 beg = (u64)org->beg - OFFSET;
|
uintptr_t diff = (uintptr_t)p - *bot;
|
||||||
u64 end = beg + *(int*)beg;
|
uintptr_t pos = (uintptr_t)p->forward + diff;
|
||||||
if(beg <= *stk && *stk < end){
|
memcpy(bot, &pos, PTR);
|
||||||
moved = moveobj(org);
|
|
||||||
diff = (*stk - beg);
|
|
||||||
pos = (u64)moved->beg - OFFSET + diff;
|
|
||||||
memcpy(stk, &pos, sizeof(pos));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
free((void*)src->beg);
|
||||||
gccompact(int cap, GC *src)
|
dst->running = 0;
|
||||||
{
|
|
||||||
void *_ = 0;
|
|
||||||
u64 bot = (u64)&_;
|
|
||||||
GC *dst = newgc((void*)src->top, cap);
|
|
||||||
dst->running = 1;
|
|
||||||
for(Object *p=src->objs; p; p=p->next)
|
|
||||||
cloneobj(dst, src, p);
|
|
||||||
forwardstack(bot, dst, src);
|
|
||||||
free(src->memory);
|
|
||||||
*src = *dst;
|
*src = *dst;
|
||||||
free(dst);
|
free(dst);
|
||||||
}
|
longjmp(reg, 1);
|
||||||
|
|
||||||
void
|
|
||||||
gcfree(GC *gc, void *src)
|
|
||||||
{
|
|
||||||
int *p = (int*)src - 1;
|
|
||||||
int sz = *p;
|
|
||||||
memset(p, 0, sz);
|
|
||||||
gc->using -= sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
freeobj(GC *gc, Object *p)
|
|
||||||
{
|
|
||||||
gc->using -= sizeof(Object);
|
|
||||||
p->next = 0;
|
|
||||||
switch(p->type){
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
case OSTRING:
|
|
||||||
case OIDENT:
|
|
||||||
gcfree(gc, 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(GC *gc, 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");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
gcralloc(GC *gc, void *src, int sz)
|
|
||||||
{
|
|
||||||
void *dst = gcalloc(gc, sz);
|
|
||||||
int osz = ((int*)src)[-1];
|
|
||||||
memcpy(dst, src, osz);
|
|
||||||
gcfree(gc, src);
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mark(GC *gc, Object *obj)
|
mark(GC *gc, Object *obj)
|
||||||
{
|
{
|
||||||
if(obj == 0 || obj->flag&USING ||
|
if(obj->flag&USING||obj->type==ONONE||obj->type==OSYMBOL||obj->type==OBLTIN)
|
||||||
obj->type == 0|| obj->type==OBLTIN ||obj->type==OSYMBOL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
obj->flag = USING;
|
obj->flag = USING;
|
||||||
switch(obj->type){
|
switch(obj->type){
|
||||||
default:break;
|
default:break;
|
||||||
@ -211,91 +143,93 @@ mark(GC *gc, Object *obj)
|
|||||||
void
|
void
|
||||||
gcsweep(GC *gc)
|
gcsweep(GC *gc)
|
||||||
{
|
{
|
||||||
Object *last = 0;
|
for(uintptr_t *p = gc->beg; p < gc->end;)
|
||||||
for(Object *p = gc->objs; p;){
|
if(*p){
|
||||||
if(p->type == 0|| p->type==OBLTIN ||p->type==OSYMBOL)
|
Object *obj = (Object*)&p[1];
|
||||||
return;
|
if(obj->flag & USING){
|
||||||
if(p->flag&USING){
|
obj->flag = 0;
|
||||||
p->flag &= ~(USING);
|
p += p[0];
|
||||||
last = p;
|
|
||||||
p = p->next;
|
|
||||||
}else{
|
|
||||||
Object *tmp = p;
|
|
||||||
if(last == 0){
|
|
||||||
gc->objs = p->next;
|
|
||||||
}else{
|
}else{
|
||||||
last->next = p->next;
|
uintptr_t sz = *p;
|
||||||
|
memset(p, 0, sz*PTR);
|
||||||
|
gc->using -= sz*PTR;
|
||||||
|
p += sz;
|
||||||
}
|
}
|
||||||
p = p->next;
|
}else{
|
||||||
freeobj(gc, tmp);
|
p++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gcmark(GC *gc)
|
gcmark(GC *gc)
|
||||||
{
|
{
|
||||||
u64 _ = 0, stk, diff;
|
uintptr_t _ = 0;
|
||||||
u64 bot = (u64)&_;
|
for(uintptr_t *bot = &_; bot < gc->top; bot++){
|
||||||
Object *obj;
|
Object *obj = findobj(gc, (uintptr_t*)*bot);
|
||||||
for(; bot < gc->top; bot += sizeof(bot)){
|
if(obj)
|
||||||
stk = (u64)*(void**)bot;
|
|
||||||
if(gc->ob <= stk && stk <= gc->oe){
|
|
||||||
diff = (stk - gc->ob) % sizeof(Object);
|
|
||||||
obj = (Object*)(stk - diff);
|
|
||||||
mark(gc, obj);
|
mark(gc, obj);
|
||||||
}
|
|
||||||
else if(gc->sb <= stk && stk <= gc->se)
|
|
||||||
for(Object *obj = gc->objs; obj; obj = obj->next)
|
|
||||||
if(obj->type == OSTRING || obj->type == OIDENT){
|
|
||||||
u64 beg = (u64)obj->beg - OFFSET;
|
|
||||||
u64 end = beg + *(int*)beg;
|
|
||||||
if(beg <= stk && stk < end){
|
|
||||||
mark(gc, obj);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gcrun(GC *src)
|
gcrun(GC *gc)
|
||||||
{
|
{
|
||||||
if(src->running)
|
if(gc->running)
|
||||||
return;
|
return;
|
||||||
printf("BEFORE=> cap:%10ld using:%10ld remain:%10ld\n", src->cap, src->using, src->cap - src->using);
|
printgc("gc-beg", gc);
|
||||||
src->running = 1;
|
gc->running = 1;
|
||||||
jmp_buf reg;
|
jmp_buf reg;
|
||||||
if(setjmp(reg)==1){
|
if(setjmp(reg)==1){
|
||||||
printf("AFTER => cap:%10ld using:%10ld remain:%10ld\n", src->cap, src->using, src->cap - src->using);
|
gc->running = 0;
|
||||||
src->running = 0;
|
printgc("gc-end", gc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gcmark(src);
|
gcmark(gc);
|
||||||
gcsweep(src);
|
gcsweep(gc);
|
||||||
if(src->using >= src->cap * 0.5){
|
|
||||||
gccompact(src->cap * 2, src);
|
|
||||||
}
|
|
||||||
longjmp(reg, 1);
|
longjmp(reg, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
static void*
|
||||||
newobj(GC *gc, enum OType type)
|
alloc(GC *gc, int sz)
|
||||||
{
|
{
|
||||||
gcrun(gc);
|
sz /= PTR;
|
||||||
gc->using += sizeof(Object);
|
for(uintptr_t *p = gc->beg; p < gc->end - sz;){
|
||||||
Object *r = 0;
|
int i = 0;
|
||||||
if(gc->freed){
|
for(; p[i] == 0 && i < sz; ++i)
|
||||||
r = gc->freed;
|
;
|
||||||
gc->freed = gc->freed->next;
|
if(i == sz){
|
||||||
}else{
|
*p = sz;
|
||||||
r = (Object*)gc->op;
|
gc->using += sz*PTR;
|
||||||
gc->op += sizeof(Object);
|
return p+1;
|
||||||
|
}
|
||||||
|
if(p[i]) p = &p[i] + p[i];
|
||||||
|
else p = &p[i] + 1;
|
||||||
}
|
}
|
||||||
r->type = type;
|
return 0;
|
||||||
if(gc->objs)
|
}
|
||||||
r->next = gc->objs;
|
|
||||||
return gc->objs = r;
|
void*
|
||||||
|
gcalloc(GC *gc, int sz)
|
||||||
|
{
|
||||||
|
sz += PTR;
|
||||||
|
if(sz%PTR) sz = sz + PTR - sz % PTR;
|
||||||
|
if(gc->using + sz > gc->cap * 0.64) gcrun(gc);
|
||||||
|
|
||||||
|
void *p = alloc(gc, sz);
|
||||||
|
if(p)
|
||||||
|
return p;
|
||||||
|
gcraise(gc);
|
||||||
|
p = alloc(gc, sz);
|
||||||
|
if(p)
|
||||||
|
return p;
|
||||||
|
panic("newobj:can't alloc %d byte", sz);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
printgc(char *prefix, GC *gc)
|
||||||
|
{
|
||||||
|
printf("%*s=> cap:%10d using:%10d remain:%10d\n", 10, prefix, gc->cap, gc->using, gc->cap - gc->using);
|
||||||
}
|
}
|
||||||
|
|
||||||
GC*
|
GC*
|
||||||
@ -304,16 +238,10 @@ newgc(void *top, int cap)
|
|||||||
GC *gc = calloc(1, sizeof(GC));
|
GC *gc = calloc(1, sizeof(GC));
|
||||||
if(gc == 0)
|
if(gc == 0)
|
||||||
panic("can't alloc %d byte\n", sizeof(GC));
|
panic("can't alloc %d byte\n", sizeof(GC));
|
||||||
gc->top = (u64)top;
|
|
||||||
if((gc->memory = calloc(1, cap)) == 0)
|
|
||||||
panic("can't alloc %d byte\n", cap);
|
|
||||||
gc->cap = cap;
|
gc->cap = cap;
|
||||||
gc->using = 0;
|
gc->top = top;
|
||||||
|
if((gc->beg = calloc(1, cap)) == 0)
|
||||||
gc->op = gc->ob = (u64)gc->memory;
|
panic("can't alloc %d byte\n", cap);
|
||||||
gc->oe = gc->op + (float)cap * 0.75;
|
gc->end = gc->beg + cap/PTR;
|
||||||
|
|
||||||
gc->sb = (u64)gc->memory + (float)cap * 0.75;
|
|
||||||
gc->se = (u64)gc->memory + cap;
|
|
||||||
return gc;
|
return gc;
|
||||||
}
|
}
|
||||||
|
|||||||
5
main.c
5
main.c
@ -32,7 +32,7 @@ SExprint(Object *obj)
|
|||||||
break;
|
break;
|
||||||
case OBLTIN:
|
case OBLTIN:
|
||||||
case OSYMBOL:
|
case OSYMBOL:
|
||||||
printf("%s", obj->sym);
|
printf("%s", obj->beg);
|
||||||
break;
|
break;
|
||||||
case OENV:
|
case OENV:
|
||||||
printf("<env>");
|
printf("<env>");
|
||||||
@ -71,6 +71,7 @@ loop(void)
|
|||||||
while(1){
|
while(1){
|
||||||
Object *res = nextexpr();
|
Object *res = nextexpr();
|
||||||
res = eval(env, res);
|
res = eval(env, res);
|
||||||
|
printgc("status", gc);
|
||||||
printf("=============res===========\n");
|
printf("=============res===========\n");
|
||||||
printexpr(res);
|
printexpr(res);
|
||||||
printf("=============env===========\n");
|
printf("=============env===========\n");
|
||||||
@ -82,6 +83,6 @@ loop(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
gc = newgc(&argc, 4000);
|
gc = newgc(&argc, 500);
|
||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
|||||||
35
obj.c
35
obj.c
@ -3,10 +3,18 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static Object*
|
||||||
|
newobj(GC *gc, enum OType type, int sz)
|
||||||
|
{
|
||||||
|
Object *obj = gcalloc(gc, sizeof(Object) + sz);
|
||||||
|
obj->type = type;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
newint(GC *gc, long val)
|
newint(GC *gc, long val)
|
||||||
{
|
{
|
||||||
Object *obj = newobj(gc, OINT);
|
Object *obj = newobj(gc, OINT, 0);
|
||||||
obj->num = val;
|
obj->num = val;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -14,7 +22,7 @@ newint(GC *gc, long val)
|
|||||||
Object*
|
Object*
|
||||||
newcons(GC *gc, Object *car, Object *cdr)
|
newcons(GC *gc, Object *car, Object *cdr)
|
||||||
{
|
{
|
||||||
Object *obj = newobj(gc, OCELL);
|
Object *obj = newobj(gc, OCELL, 0);
|
||||||
obj->car = car;
|
obj->car = car;
|
||||||
obj->cdr = cdr;
|
obj->cdr = cdr;
|
||||||
return obj;
|
return obj;
|
||||||
@ -23,7 +31,7 @@ newcons(GC *gc, Object *car, Object *cdr)
|
|||||||
Object*
|
Object*
|
||||||
newenv(GC *gc, Object* name, Object *vars, Object *up)
|
newenv(GC *gc, Object* name, Object *vars, Object *up)
|
||||||
{
|
{
|
||||||
Object *obj = newobj(gc, OENV);
|
Object *obj = newobj(gc, OENV, 0);
|
||||||
obj->name = name;
|
obj->name = name;
|
||||||
obj->up = up;
|
obj->up = up;
|
||||||
obj->vars = vars;
|
obj->vars = vars;
|
||||||
@ -40,7 +48,7 @@ newacons(GC *gc, Object *x, Object *y, Object *z)
|
|||||||
Object*
|
Object*
|
||||||
newfn(GC *gc, Object *env, Object *params, Object *body)
|
newfn(GC *gc, Object *env, Object *params, Object *body)
|
||||||
{
|
{
|
||||||
Object *fn = newobj(gc, OFUNC);
|
Object *fn = newobj(gc, OFUNC, 0);
|
||||||
fn->params = params;
|
fn->params = params;
|
||||||
fn->body = body;
|
fn->body = body;
|
||||||
fn->env = env;
|
fn->env = env;
|
||||||
@ -57,21 +65,22 @@ newsymbol(GC *gc, char *str, int len)
|
|||||||
};
|
};
|
||||||
for(int i = 0; i < sizeof(syms)/sizeof(syms[0]); ++i){
|
for(int i = 0; i < sizeof(syms)/sizeof(syms[0]); ++i){
|
||||||
Object *c = syms[i];
|
Object *c = syms[i];
|
||||||
if(strlen(c->sym)==len && memcmp(c->sym, str, len) == 0)
|
if(strlen(c->beg)==len && memcmp(c->beg, str, len) == 0)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
Object *obj = newobj(gc, OIDENT);
|
Object *obj = newobj(gc, OIDENT, len + 1);
|
||||||
obj->beg = gcalloc(gc, len + 1);
|
obj->ptr = obj->beg = (char*)&obj[1];
|
||||||
obj->end = obj->ptr = obj->beg + len;
|
obj->end = obj->beg + len;
|
||||||
memcpy(obj->beg, str, len+1);
|
memcpy(obj->beg, str, len + 1);
|
||||||
|
obj->ptr += len;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object*
|
Object*
|
||||||
newstr(GC *gc, int len)
|
newstr(GC *gc, int len)
|
||||||
{
|
{
|
||||||
Object *obj = newobj(gc, OSTRING);
|
Object *obj = newobj(gc, OSTRING, len + 1);
|
||||||
obj->ptr = obj->beg = gcalloc(gc, len + 1);
|
obj->ptr = obj->beg = (char*)&obj[1];
|
||||||
obj->end = obj->beg + len;
|
obj->end = obj->beg + len;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
2
parser.c
2
parser.c
@ -88,7 +88,7 @@ string(void)
|
|||||||
{
|
{
|
||||||
Object *str = newstr(gc, 16);
|
Object *str = newstr(gc, 16);
|
||||||
while(lookup() != '\"'){
|
while(lookup() != '\"'){
|
||||||
strputc(str, get());
|
str = strputc(str, get());
|
||||||
}
|
}
|
||||||
expect('\"');
|
expect('\"');
|
||||||
return str;
|
return str;
|
||||||
|
|||||||
52
str.c
52
str.c
@ -3,33 +3,41 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
strraise(Object *s, int ns)
|
strinit(Object *s, Object *p)
|
||||||
{
|
{
|
||||||
int pos = s->ptr - s->beg;
|
for(char *c = p->beg ; c < p->ptr;)
|
||||||
char *ptr = gcralloc(gc, s->beg, ns + 1);
|
*s->ptr++ = *c++;
|
||||||
s->beg = ptr;
|
|
||||||
s->ptr = s->beg + pos;
|
|
||||||
s->end = s->beg + ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
strputc(Object *s, int c)
|
|
||||||
{
|
|
||||||
if(s->ptr >= s->end)
|
|
||||||
strraise(s, (s->end - s->beg) * 2);
|
|
||||||
*s->ptr++ = c;
|
|
||||||
*s->ptr = 0;
|
*s->ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Object*
|
||||||
strputs(Object *s, char *ptr)
|
strraise(Object *s, int ns)
|
||||||
{
|
{
|
||||||
int l = strlen(ptr);
|
Object *dst = newstr(gc, ns + 1);
|
||||||
if(s->ptr + l >= s->end)
|
strinit(dst, s);
|
||||||
strraise(s, s->end - s->beg + l);
|
return dst;
|
||||||
memcpy(s->ptr, ptr, l);
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
strputc(Object *s, int c)
|
||||||
|
{
|
||||||
|
if(s->ptr + 1 >= s->end)
|
||||||
|
s = strraise(s, (s->end - s->beg) * 2);
|
||||||
|
*s->ptr++ = c;
|
||||||
|
*s->ptr = 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object*
|
||||||
|
strputs(Object *s, Object *ptr)
|
||||||
|
{
|
||||||
|
int l = ptr->ptr - ptr->beg;
|
||||||
|
if(s->ptr + l>= s->end)
|
||||||
|
s = strraise(s, s->end - s->beg + l);
|
||||||
|
memcpy(s->ptr, ptr->beg, l);
|
||||||
s->ptr += l;
|
s->ptr += l;
|
||||||
s->ptr[0] = 0;
|
*s->ptr = 0;
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -38,4 +46,4 @@ strequal(Object *a, Object *b)
|
|||||||
int la = a->ptr - a->beg;
|
int la = a->ptr - a->beg;
|
||||||
int lb = b->ptr - b->beg;
|
int lb = b->ptr - b->beg;
|
||||||
return la == lb && memcmp(a->beg, b->beg, la) == 0;
|
return la == lb && memcmp(a->beg, b->beg, la) == 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user