summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-03-04 08:54:44 -0500
committerWormHeamer2025-03-04 08:54:44 -0500
commitc1d26bdba9c0d62c3e34c8ca374f45d4795e1305 (patch)
treec914978b44f23bef3f0059a2a9baa3c25a21da79
parent20cbe7ee472c416b243541e661e7eb11621a881f (diff)
store pointers in zone frame, finer-grained alignment, zn_new, etc
-rw-r--r--zone.h154
1 files changed, 90 insertions, 64 deletions
diff --git a/zone.h b/zone.h
index 936f757..b5aeee5 100644
--- a/zone.h
+++ b/zone.h
@@ -2,6 +2,7 @@
#define ZONE_H
#include <stdint.h>
+#include <stddef.h>
#ifndef ZONE_MIN_CAPACITY
#define ZONE_MIN_CAPACITY 1024
@@ -13,17 +14,17 @@
typedef struct ZoneFrame ZoneFrame;
struct ZoneFrame {
ZoneFrame *prev, *next;
- size_t length, capacity;
- uintptr_t data[];
+ uint8_t *beg, *end;
+ uint8_t data[];
};
typedef struct {
- ZoneFrame *tail, *here;
+ ZoneFrame *cur, *tail;
} Zone;
typedef struct {
ZoneFrame *zf;
- size_t length;
+ uint8_t *beg;
} ZoneState;
void zn_free(Zone *z);
@@ -31,10 +32,15 @@ void zn_reset(Zone *z);
void zn_save(Zone *z, ZoneState *m);
void zn_load(Zone *z, ZoneState *m);
-void *zn_alloc(Zone *z, size_t n);
-void *zn_zf_alloc(Zone *z, ZoneFrame **zf, size_t n);
-void *zn_zf_realloc(Zone *z, ZoneFrame **zf, void *ptr, size_t oldsz, size_t newsz);
+void *zn_alloc(Zone *z, ptrdiff_t n);
+void *zn_alloc_align(Zone *z, ptrdiff_t n, size_t align);
+void *zn_realloc(Zone *z, void *ptr, ptrdiff_t oldsz, ptrdiff_t newsz);
+void *zn_realloc_align(Zone *z, void *ptr, ptrdiff_t oldsz, ptrdiff_t newsz, size_t align);
+
char *zn_strdup(Zone *z, const char *s);
+void *zn_zeroed(void *, size_t);
+
+#define zn_new(z, t) (t*)zn_zeroed(zn_alloc_align(z, sizeof(t), alignof(t)), sizeof(t))
#ifdef ZONE_IMPL
@@ -66,7 +72,7 @@ char *zn_strdup(Zone *z, const char *s);
return zf;
}
static void zn_zf_free(ZoneFrame *zf) {
- munmap(zf, sizeof *zf + zf->capacity * sizeof(uintptr_t));
+ munmap(zf, (uintptr_t)zf->end - (uintptr_t)zf);
}
static size_t zn_zf_capacity(size_t cap) {
if (cap < ZONE_MIN_CAPACITY) cap = ZONE_MIN_CAPACITY;
@@ -100,99 +106,119 @@ char *zn_strdup(Zone *z, const char *s);
#endif
static ZoneFrame *zn_zf_new(size_t capacity) {
+ capacity = zn_zf_capacity(capacity);
ZoneFrame *zf = zn_zf_allocate(capacity);
zf->prev = NULL;
zf->next = NULL;
- zf->length = 0;
- zf->capacity = capacity;
+ zf->beg = zf->data;
+ zf->end = (uint8_t*)zf + capacity;
return zf;
}
-void *zn_alloc(Zone *z, size_t n) {
- return zn_zf_alloc(z, NULL, n);
-}
+#define PTR_ALIGN(ptr, align) (typeof(ptr))((uint8_t*)ptr + ((-(uintptr_t)ptr) & ((align)-1)))
-void *zn_zf_alloc(Zone *z, ZoneFrame **zfo, size_t n) {
- ZoneFrame *zf = NULL;
- size_t wordsz = (n + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
- for (ZoneFrame *f = z->here; f; f = f->next) {
- if (f->capacity - f->length >= wordsz) {
- zf = f;
- break;
- }
+void *zn_alloc_align(Zone *z, ptrdiff_t n, size_t align) {
+ ZoneFrame *zf = z->cur;
+ while (zf && PTR_ALIGN(zf->beg, align) + n >= zf->end) {
+ zf = zf->next;
}
if (!zf) {
- zf = zn_zf_new(zn_zf_capacity(wordsz));
+ zf = zn_zf_new(n + align - 1);
zf->prev = z->tail;
if (z->tail) z->tail->next = zf;
z->tail = zf;
+ z->cur = zf;
}
- void *ptr = &zf->data[zf->length];
- zf->length += wordsz;
- z->here = zf;
- if (zfo) *zfo = zf;
- return ptr;
+ zf->beg = PTR_ALIGN(zf->beg, align);
+ void *p = zf->beg;
+ zf->beg += n;
+ return p;
}
-void *zn_zf_realloc(Zone *z, ZoneFrame **zfo, void *old, size_t oldsz, size_t newsz) {
- ZoneFrame *zf = *zfo;
- size_t old_wordsz = (oldsz + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
- size_t new_wordsz = (newsz + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
- if (&zf->data[zf->length - old_wordsz] == old && zf->length + new_wordsz - old_wordsz <= zf->capacity) {
- zf->length = zf->length + new_wordsz - old_wordsz;
- return old;
+void *zn_realloc_align(Zone *z, void *ptr, ptrdiff_t oldsz, ptrdiff_t newsz, size_t align) {
+ goto justalloc;
+ if (!ptr || !oldsz) return zn_alloc_align(z, newsz, align);
+ if (z->cur && ptr == z->cur->beg - oldsz && z->cur->beg - oldsz + newsz < z->cur->end) {
+ z->cur->beg -= oldsz;
+ z->cur->beg += newsz;
+ return ptr;
} else {
- void *new = zn_zf_alloc(z, zfo, newsz);
- zf->length -= old_wordsz;
- memcpy(new, old, oldsz);
- return new;
+justalloc:
+ void *p = zn_alloc_align(z, newsz, align);
+ memcpy(p, ptr, oldsz);
+ return p;
}
}
+static inline size_t zn_align_for(size_t n) {
+ size_t a = 1;
+ while (n > a) a <<= 1;
+ return a;
+}
+
+void *zn_alloc(Zone *z, ptrdiff_t n) {
+ return zn_alloc_align(z, n, zn_align_for(n));
+}
+
+void *zn_realloc(Zone *z, void *ptr, ptrdiff_t oldsz, ptrdiff_t newsz) {
+ return zn_realloc_align(z, ptr, oldsz, newsz, zn_align_for(newsz));
+}
+
+void *zn_calloc(Zone *z, size_t n, size_t size) {
+ void *p = zn_alloc_align(z, n * size, zn_align_for(size));
+ memset(p, 0, n * size);
+ return p;
+}
+
void zn_free(Zone *z) {
- ZoneFrame *p, *t;
- t = z->tail;
- while (t) {
- p = t->prev;
- zn_zf_free(t);
- t = p;
+ ZoneFrame *a = z->tail, *b;
+ while (a) {
+ b = a->prev;
+ zn_zf_free(a);
+ a = b;
}
}
void zn_reset(Zone *z) {
- ZoneFrame *zf = z->here;
- if (!zf) return;
- for (;;) {
- zf->length = 0;
- if (zf->prev) zf = zf->prev;
- else break;
+ ZoneFrame *zf = z->tail;
+ while (zf) {
+ zf->beg = zf->data;
+ if (!zf->prev) break;
+ zf = zf->prev;
}
- z->tail = zf;
-}
-
-char *zn_strdup(Zone *z, const char *s) {
- size_t n = strlen(s) + 1;
- char *d = zn_alloc(z, n);
- memcpy(d, s, n);
- return d;
+ if (zf) z->cur = zf;
}
void zn_save(Zone *z, ZoneState *m) {
- m->zf = z->here;
- m->length = z->here ? z->tail->length : 0;
+ m->zf = z->cur;
+ m->beg = z->cur ? z->cur->beg : 0;
}
void zn_load(Zone *z, ZoneState *m) {
if (m->zf) {
- while (z->here != m->zf) {
- z->here->length = 0;
- z->here = z->here->prev;
+ while (z->cur != m->zf) {
+ z->cur->beg = z->cur->data;
+ z->cur = z->cur->prev;
}
- m->zf->length = m->length;
+ m->zf->beg = m->beg;
} else {
zn_reset(z);
}
}
+/* utils */
+
+char *zn_strdup(Zone *z, const char *s) {
+ size_t n = strlen(s) + 1;
+ char *d = zn_alloc_align(z, n, 1);
+ memcpy(d, s, n);
+ return d;
+}
+
+void *zn_zeroed(void *ptr, size_t n) {
+ memset(ptr, 0, n);
+ return ptr;
+}
+
#endif
#endif