summary refs log tree commit diff
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