summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@pmikkelsen.com>2026-09-11 18:58:10 +0000
committerpeter <peter@pmikkelsen.com>2026-09-11 18:58:10 +0000
commit84aa10ffd3cbe81bb5e1442eeecd30a2e2903d3a (patch)
tree1461007e71e901f54da4388b73ddd456ba570277
parent3263983050990b400acb3c9b8ab3ced2497faac2 (diff)
Get rid of the big macro to visit all chunk pointers. Instead, just use functions which takes a callback.
FossilOrigin-Name: 34ea27817033db9bc3e06ba0a90495f712fc37c3672f75d4651c73d62f2945d7
-rw-r--r--src/lib/memory.c271
1 files changed, 168 insertions, 103 deletions
diff --git a/src/lib/memory.c b/src/lib/memory.c
index fb143ec..0ff4784 100644
--- a/src/lib/memory.c
+++ b/src/lib/memory.c
@@ -73,7 +73,6 @@ data(struct chunk *c)
struct chunk *
next(struct chunk *c)
{
- static struct chunk *prev;
uint8_t *p;
if(c->last)
@@ -84,94 +83,135 @@ next(struct chunk *c)
p += c->size;
assert((((uintptr_t)p) % ALIGNMENT) == 0);
- prev = c;
- UNUSED_PARAMETER(prev);
-
return (struct chunk *)p;
}
-#define VISIT_FIELD(X, tag, ptr) X(((struct tag *)data(c))->ptr)
-#define VISIT_CHUNK_PTRS(X, c) switch(c->tag){ \
- case CHUNK_TAG_APLWC_LINE: \
- VISIT_FIELD(X, aplwc_line, text); \
- VISIT_FIELD(X, aplwc_line, tokens); \
- break; \
- case CHUNK_TAG_STRING: \
- break; \
- case CHUNK_TAG_TOKEN_LIST: \
- VISIT_FIELD(X, token_list, text); \
- break; \
- case CHUNK_TAG_APLWC_VALUE: \
- break; \
- case CHUNK_TAG_APLWC_MODULE: \
- VISIT_FIELD(X, aplwc_module, name); \
- VISIT_FIELD(X, aplwc_module, tokens); \
- VISIT_FIELD(X, aplwc_module, imports); \
- VISIT_FIELD(X, aplwc_module, members); \
- VISIT_FIELD(X, aplwc_module, link); \
- break; \
- case CHUNK_TAG_MODULE_MEMBER: \
- VISIT_FIELD(X, module_member, module); \
- VISIT_FIELD(X, module_member, real_member); \
- VISIT_FIELD(X, module_member, link); \
- break; \
- case CHUNK_TAG_SYMBOL: \
- VISIT_FIELD(X, symbol, text); \
- VISIT_FIELD(X, symbol, link); \
- break; \
- case CHUNK_TAG_FREE: \
- break; \
- }
-#define VISIT_ROOT_PTRS(X) do{ \
- X(aplwc->modules); \
- X(aplwc->symtab); \
- for(frame = aplwc->memptrs; frame; frame = frame->link) \
- for(i = 0; i < frame->count; i++) \
- if(frame->ptrs[i]) \
- X(*frame->ptrs[i]); \
- for(ref = aplwc->refs; ref; ref = ref->link) \
- if(ref->ptr) \
- X(ref->ptr); \
-}while(0)
-
-#define VISIT_ALL_PTRS(X, data) do{ \
- VISIT_ROOT_PTRS(X); \
- for(c = (struct chunk *)(data); c; c = next(c)) \
- VISIT_CHUNK_PTRS(X, c); \
-}while(0)
+#define VISIT(ptr) (ptr) = fn(ptr, aux)
static void
-fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old)
+visit_chunk_ptrs(struct chunk *c, void *(*fn)(void *, void *), void *aux)
{
+ union {
+ void *vp;
+ struct aplwc_line *line;
+ struct token_list *tokens;
+ struct aplwc_module *module;
+ struct module_member *module_member;
+ struct symbol *symbol;
+ } d;
+
+ assert(c != NULL);
+
+ d.vp = data(c);
+ switch(c->tag){
+ case CHUNK_TAG_FREE:
+ break;
+ case CHUNK_TAG_APLWC_LINE:
+ VISIT(d.line->text);
+ VISIT(d.line->text);
+ VISIT(d.line->tokens);
+ break;
+ case CHUNK_TAG_STRING:
+ break;
+ case CHUNK_TAG_TOKEN_LIST:
+ VISIT(d.tokens->text);
+ break;
+ case CHUNK_TAG_APLWC_VALUE:
+ break;
+ case CHUNK_TAG_APLWC_MODULE:
+ VISIT(d.module->name);
+ VISIT(d.module->tokens);
+ VISIT(d.module->imports);
+ VISIT(d.module->members);
+ VISIT(d.module->link);
+ break;
+ case CHUNK_TAG_MODULE_MEMBER:
+ VISIT(d.module_member->module);
+ VISIT(d.module_member->real_member);
+ VISIT(d.module_member->link);
+ break;
+ case CHUNK_TAG_SYMBOL:
+ VISIT(d.symbol->text);
+ VISIT(d.symbol->link);
+ break;
+ }
+}
- struct chunk *c;
+static void
+visit_root_ptrs(struct aplwc *aplwc, void *(*fn)(void *, void *), void *aux)
+{
struct memory_ptr_frame *frame;
struct aplwc_ref *ref;
- size_t add, sub, i;
+ size_t i;
+
+ VISIT(aplwc->modules);
+ VISIT(aplwc->symtab);
+
+ for(frame = aplwc->memptrs; frame; frame = frame->link)
+ for(i = 0; i < frame->count; i++)
+ if(frame->ptrs[i])
+ VISIT(*frame->ptrs[i]);
+
+ for(ref = aplwc->refs; ref; ref = ref->link)
+ if(ref->ptr)
+ VISIT(ref->ptr);
+}
+
+static void
+visit_all_ptrs(struct aplwc *aplwc, void *(*fn)(void *, void *), void *aux)
+{
+ struct chunk *c;
+
+ visit_root_ptrs(aplwc, fn, aux);
+ for(c = (struct chunk *)aplwc->data; c; c = next(c))
+ visit_chunk_ptrs(c, fn, aux);
+}
+
+#undef VISIT
+
+struct fixref_args {
+ size_t add;
+ size_t sub;
+};
+
+static void *
+fixref(void *p, void *aux)
+{
+ struct fixref_args *args = aux;
+ uint8_t *r;
+
+ if(p == NULL)
+ return p;
+
+ r = p;
+
+ r += args->add;
+ r -= args->sub;
+ return r;
+}
+
+static void
+fixrefs(struct aplwc *aplwc, uint8_t *old)
+{
+ uint8_t *new = aplwc->data;
+ struct fixref_args args;
if(new > old){
- add = new-old;
- sub = 0;
+ args.add = new-old;
+ args.sub = 0;
}else{
- add = 0;
- sub = old-new;
+ args.add = 0;
+ args.sub = old-new;
}
-#define FIX(ptr) do{ \
- if(ptr){ \
- (ptr) = (void*)(((uint8_t*)(ptr))+add); \
- (ptr) = (void*)(((uint8_t*)(ptr))-sub); \
- } \
-}while(0)
- VISIT_ALL_PTRS(FIX, new);
-#undef FIX
+ visit_all_ptrs(aplwc, fixref, &args);
}
static enum aplwc_rc
grow(struct aplwc *aplwc, size_t extra)
{
- uint8_t *unaligned_data, *aligned_data;
- size_t unaligned_newsize, aligned_newsize, adjust;
+ uint8_t *unaligned_data, *aligned_data, *old_data;
+ size_t unaligned_newsize, aligned_newsize, adjust, old_size;
struct chunk *free, *head, *last;
if(aplwc->fns.alloc == NULL)
@@ -193,9 +233,15 @@ grow(struct aplwc *aplwc, size_t extra)
head = (struct chunk *)aligned_data;
last = NULL;
- if(aplwc->data){
- memmove(aligned_data, aplwc->data, aplwc->size);
- fixrefs(aplwc, aligned_data, aplwc->data);
+ old_data = aplwc->data;
+ old_size = aplwc->size;
+
+ aplwc->data = aligned_data;
+ aplwc->size = aligned_newsize;
+
+ if(old_data){
+ memmove(aplwc->data, old_data, old_size);
+ fixrefs(aplwc, old_data);
memory_destroy(aplwc);
for(free = head; free; free = next(free))
if(next(free))
@@ -203,10 +249,11 @@ grow(struct aplwc *aplwc, size_t extra)
else
last = free;
}
+ aplwc->unaligned_data = unaligned_data; /* must be after memory_destroy */
- free = (struct chunk *)(aligned_data + aplwc->size);
+ free = (struct chunk *)(aligned_data + old_size);
free->tag = CHUNK_TAG_FREE;
- free->size = aligned_newsize - aplwc->size;
+ free->size = aligned_newsize - old_size;
free->stack = NULL;
free->last = 1;
@@ -217,9 +264,6 @@ grow(struct aplwc *aplwc, size_t extra)
last->last = 0;
}
- aplwc->unaligned_data = unaligned_data;
- aplwc->data = aligned_data;
- aplwc->size = aligned_newsize;
return 1;
error:
@@ -245,23 +289,34 @@ find_free(struct aplwc *aplwc, size_t min)
return c;
}
-static void
-push(struct aplwc *aplwc, struct chunk **stack, void *p)
+struct push_args {
+ struct aplwc *aplwc;
+ struct chunk **stack;
+};
+
+static void *
+push(void *p, void *aux)
{
struct chunk *c;
+ struct push_args *args;
if(p == NULL)
- return;
+ return p;
+
+ args = aux;
+
c = (struct chunk *)(((uint8_t*)p)-HEADER_SIZE);
assert(c->tag != CHUNK_TAG_FREE);
- if(c->reachable == aplwc->reachable_bit)
- return;
+ if(c->reachable == args->aplwc->reachable_bit)
+ return p;
assert(c->stack == NULL);
- c->reachable = aplwc->reachable_bit;
- c->stack = *stack;
- *stack = c;
+ c->reachable = args->aplwc->reachable_bit;
+ c->stack = *args->stack;
+ *args->stack = c;
+
+ return p;
}
static struct chunk *
@@ -284,22 +339,20 @@ collect(struct aplwc *aplwc)
{
struct chunk *c, *prev;
struct chunk *stack;
- struct memory_ptr_frame *frame;
- struct aplwc_ref *ref;
- size_t i;
+ struct push_args args;
aplwc->reachable_bit = ~aplwc->reachable_bit;
/* Mark reachable chunks */
stack = NULL;
+ args.aplwc = aplwc;
+ args.stack = &stack;
-#define PUSH(ptr) push(aplwc, &stack, ptr)
- VISIT_ROOT_PTRS(PUSH);
+ visit_root_ptrs(aplwc, push, &args);
while(stack){
c = pop(&stack);
- VISIT_CHUNK_PTRS(PUSH, c);
-#undef PUSH
+ visit_chunk_ptrs(c, push, &args);
}
/* Free chunks not marked */
@@ -317,20 +370,32 @@ collect(struct aplwc *aplwc)
}
}
+struct swap_args {
+ void *old;
+ void *new;
+};
+
+static void *
+swap(void *p, void *aux)
+{
+ struct swap_args *args;
+
+ args = aux;
+ if(p == args->old)
+ return args->new;
+ else
+ return p;
+}
+
static void
swapptr(struct aplwc *aplwc, void *old, void *new)
{
- struct chunk *c;
- struct memory_ptr_frame *frame;
- struct aplwc_ref *ref;
- size_t i;
+ struct swap_args args;
+
+ args.old = old;
+ args.new = new;
-#define SWAP(ptr) do{ \
- if((ptr) == old) \
- (ptr) = new; \
-}while(0)
- VISIT_ALL_PTRS(SWAP, aplwc->data);
-#undef SWAP
+ visit_all_ptrs(aplwc, swap, &args);
}
static void