8 #ifndef POTION_BIRTH_SIZE
9 #define POTION_BIRTH_SIZE (PN_SIZE_T << 21)
12 #ifndef POTION_MIN_BIRTH_SIZE
13 #define POTION_MIN_BIRTH_SIZE (PN_SIZE_T << 15)
16 #ifndef POTION_MAX_BIRTH_SIZE
17 #define POTION_MAX_BIRTH_SIZE (16 * POTION_BIRTH_SIZE)
20 #if POTION_MAX_BIRTH_SIZE < 4 * POTION_BIRTH_SIZE
21 #error invalid min and max birth sizes
24 #define POTION_GC_THRESHOLD (3 * POTION_BIRTH_SIZE)
25 #define POTION_GC_PERIOD 256
26 #define POTION_NB_ROOTS 64
28 #define SET_GEN(t, p, s) \
30 M->t##_cur = p + (sizeof(PN) * 2); \
31 M->t##_hi = p + (s); \
34 #define SET_STOREPTR(n) \
35 M->birth_storeptr = (void *)(((void **)M->birth_hi) - (n))
38 *(M->birth_storeptr--) = (void *)p
40 #define DEL_BIRTH_REGION() \
41 if (M->birth_lo == M && IN_BIRTH_REGION(M->protect)) { \
42 void *protend = (void *)PN_ALIGN((_PN)M->protect, POTION_PAGESIZE); \
43 pngc_page_delete(protend, (char *)M->birth_hi - (char *)protend); \
45 void *protend = (void *)M->birth_lo; \
46 pngc_page_delete(protend, (char *)M->birth_hi - (char *)protend); \
49 #define IS_GC_PROTECTED(p) \
50 ((_PN)(p) >= (_PN)M && (_PN)(p) < (_PN)M->protect)
52 #define IN_BIRTH_REGION(p) \
53 ((_PN)(p) > (_PN)M->birth_lo && (_PN)(p) < (_PN)M->birth_hi)
55 #define IN_OLDER_REGION(p) \
56 ((_PN)(p) > (_PN)M->old_lo && (_PN)(p) < (_PN)M->old_hi)
58 #define IS_NEW_PTR(p) \
59 (PN_IS_PTR(p) && IN_BIRTH_REGION(p) && !IS_GC_PROTECTED(p))
61 #define GC_FORWARD(p, v) do { \
62 struct PNFwd *_pnobj = (struct PNFwd *)v; \
63 if (_pnobj->fwd == POTION_COPIED) \
66 *(p) = (_PN)potion_gc_copy(P, (struct PNObject *)v); \
69 #define GC_MINOR_UPDATE(p) do { \
71 PN _pnv = potion_fwd((_PN)p); \
72 if (IN_BIRTH_REGION(_pnv) && !IS_GC_PROTECTED(_pnv)) \
73 { GC_FORWARD((_PN *)&(p), _pnv); } \
77 #define GC_MAJOR_UPDATE(p) do { \
79 PN _pnv = potion_fwd((_PN)p); \
80 if (!IS_GC_PROTECTED(_pnv) && \
81 (IN_BIRTH_REGION(_pnv) || IN_OLDER_REGION(_pnv))) \
82 {GC_FORWARD((_PN *)&(p), _pnv);} \
86 #define GC_MINOR_UPDATE_TABLE(name, kh, is_map) do { \
88 for (k = kh_begin(kh); k != kh_end(kh); ++k) \
89 if (kh_exist(name, kh, k)) { \
90 PN v1 = kh_key(name, kh, k); \
91 GC_MINOR_UPDATE(v1); \
92 kh_key(name, kh, k) = v1; \
94 PN v2 = kh_val(name, kh, k); \
95 GC_MINOR_UPDATE(v2); \
96 kh_val(name, kh, k) = v2; \
101 #define GC_MAJOR_UPDATE_TABLE(name, kh, is_map) do { \
103 for (k = kh_begin(kh); k != kh_end(kh); ++k) \
104 if (kh_exist(name, kh, k)) { \
105 PN v1 = kh_key(name, kh, k); \
106 GC_MAJOR_UPDATE(v1); \
107 kh_key(name, kh, k) = v1; \
109 PN v2 = kh_val(name, kh, k); \
110 GC_MAJOR_UPDATE(v2); \
111 kh_val(name, kh, k) = v2; \
116 #define GC_MINOR_STRINGS() do { \
118 GC_MINOR_UPDATE(P->strings); \
119 for (k = kh_begin(P->strings); k != kh_end(P->strings); ++k) \
120 if (kh_exist(str, P->strings, k)) { \
121 PN v = kh_key(str, P->strings, k); \
122 if (IN_BIRTH_REGION(v) && !IS_GC_PROTECTED(v)) { \
123 if (((struct PNFwd *)v)->fwd == POTION_COPIED) \
124 kh_key(str, P->strings, k) = ((struct PNFwd *)v)->ptr; \
126 kh_del(str, P->strings, k); \
131 #define GC_MAJOR_STRINGS() do { \
133 GC_MAJOR_UPDATE(P->strings); \
134 for (k = kh_begin(P->strings); k != kh_end(P->strings); ++k) \
135 if (kh_exist(str, P->strings, k)) { \
136 PN v = kh_key(str, P->strings, k); \
137 if (!IS_GC_PROTECTED(v) && \
138 (IN_BIRTH_REGION(v) || IN_OLDER_REGION(v))) { \
139 if (((struct PNFwd *)v)->fwd == POTION_COPIED) \
140 kh_key(str, P->strings, k) = ((struct PNFwd *)v)->ptr; \
142 kh_del(str, P->strings, k); \
148 int suggest = ((
char *)oldhi - (
char *)oldlo) / 2;
149 if (need * 2 > suggest) suggest = need * 2;
void * potion_mark_major(Potion *, const struct PNObject *)
void potion_gc_release(Potion *)
static int potion_birth_suggest(int need, volatile void *oldlo, volatile void *oldhi)
#define POTION_MIN_BIRTH_SIZE
#define POTION_BIRTH_SIZE
standard objects act like C structs the fields are defined by the type and it's a fixed size...
void * pngc_page_new(int *, const char)
void * potion_gc_copy(Potion *, struct PNObject *)
the global interpreter state P. currently singleton (not threads yet)
void * potion_mark_minor(Potion *, const struct PNObject *)
PN_SIZE potion_mark_stack(Potion *, int)
PN_SIZE potion_stack_len(Potion *, _PN **)