summary refs log tree commit diff
diff options
context:
space:
mode:
authorWormHeamer2025-03-06 01:06:03 -0500
committerWormHeamer2025-03-06 01:06:03 -0500
commit6e16ed9dc2ca7c6f828e89b0e62058ccd749c493 (patch)
treee8ae4a2d165ee513d755862f5e105d2915dda457
parentac0c3567053901b65c8413929aa53aa78efb51e9 (diff)
add (compiled but untested) support for wasm bulk memory
-rw-r--r--zone.h88
1 files changed, 69 insertions, 19 deletions
diff --git a/zone.h b/zone.h
index 00d788d..c42b6b1 100644
--- a/zone.h
+++ b/zone.h
@@ -4,6 +4,10 @@
 #include <stdint.h>
 #include <stddef.h>
 
+#define ZONE_USE_MALLOC         0
+#define ZONE_USE_MMAP           1
+#define ZONE_USE_WASM_BULKMEM   2
+
 #ifndef ZONE_BACKEND
 	#ifdef __unix__
 		#define ZONE_BACKEND ZONE_USE_MMAP
@@ -11,8 +15,10 @@
 		#define ZONE_BACKEND ZONE_USE_MALLOC
 	#endif
 #endif
-#define ZONE_USE_MALLOC         0
-#define ZONE_USE_MMAP           1
+
+#if !defined(ZONE_NOSTDLIB) && (ZONE_BACKEND != ZONE_USE_MMAP && ZONE_BACKEND != ZONE_USE_MALLOC)
+	#define ZONE_NOSTDLIB
+#endif
 
 typedef struct ZoneFrame ZoneFrame;
 struct ZoneFrame {
@@ -55,14 +61,38 @@ void *zn_zeroed(void *, size_t);
 
 #ifdef ZONE_IMPL
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
 #ifndef ZONE_PAGE_MULT
 #define ZONE_PAGE_MULT 2
 #endif
 
+#define UPTR_ALIGN(x, align) ((x)+((-x)&((align)-1)))
+#define PTR_ALIGN(ptr, align) (typeof(ptr)) (((uintptr_t)ptr + (align - 1)) & -align)
+
+#if ZONE_BACKEND == ZONE_USE_MMAP || ZONE_BACKEND == ZONE_USE_MALLOC
+	#include <stdio.h>
+	#include <stdlib.h>
+	[[noreturn]] void zn_abort(const char *msg) {
+		fprintf(stderr, "%s\n", msg);
+		abort();
+	}
+#elif ZONE_BACKEND == ZONE_USE_WASM_BULKMEM
+	__attribute((import_name("alert"))) void js_alert(const char *msg);
+	__attribute((import_name("abort"))) [[noreturn]] void js_abort(void);
+	[[noreturn]] void zn_abort(const char *msg) {
+		js_alert(msg);
+		js_abort();
+	}
+#else
+	#error "zn_abort not implemented for the current platform -- using __builtin_trap() instead"
+	[[noreturn]] void zn_abort(cont char *msg) {
+		(void)msg;
+		__builtin_trap();
+	}
+#endif
+
+#define ZONE_MEMSET __builtin_memset
+#define ZONE_MEMCPY __builtin_memcpy
+
 #if ZONE_BACKEND == ZONE_USE_MMAP
 
 	#include <sys/mman.h>
@@ -90,6 +120,32 @@ void *zn_zeroed(void *, size_t);
 		free(p);
 	}
 
+#elif ZONE_BACKEND == ZONE_USE_WASM_BULKMEM
+
+	#define ZONE_PAGE_SIZE 65536
+	#define ZONE_PAGE_FAIL (void*)(uintptr_t)-1
+	extern uint8_t __heap_base;
+	static void *zn_pg_free_adr = 0;
+	static void *zn_pg_alloc(size_t n) {
+		if (zn_pg_free_adr) {
+			void *p = zn_pg_free_adr;
+			zn_pg_free_adr = *(void **)zn_pg_free_adr;
+			return p;
+		}
+		void *p = &__heap_base + __builtin_wasm_memory_size(0);
+		__builtin_wasm_memory_grow(0, 1);
+		return p;
+	}
+	static void zn_pg_free(void *p, size_t n) {
+		uintptr_t adr = ((uintptr_t)p & ~0xFFFF);
+		n = (n + 0xFFFF) >> 16;
+		while (n--) {
+			void *pg = (void *)(adr + (n << 16));
+			*(void **)pg = zn_pg_free_adr;
+			zn_pg_free_adr = pg;
+		}
+	}
+
 #else
 
 	#error "unknown or unsupported zone backend"
@@ -102,10 +158,7 @@ static inline size_t zn_pg_fit(size_t cap) {
 
 static ZoneFrame *zn_zf_new(size_t capacity) {
 	ZoneFrame *zf = zn_pg_alloc(capacity / ZONE_PAGE_SIZE);
-	if (zf == ZONE_PAGE_FAIL) {
-		fprintf(stderr, "failed to allocate zone frame\n");
-		abort();
-	}
+	if (zf == ZONE_PAGE_FAIL) zn_abort("failed to allocate zone frame\n");
 	zf->prev = NULL;
 	zf->next = NULL;
 	zf->beg = zf->data;
@@ -117,9 +170,6 @@ static void zn_zf_free(ZoneFrame *z) {
 	zn_pg_free(z, (uintptr_t)z->end - (uintptr_t)z->beg);
 }
 
-#define UPTR_ALIGN(x, align) ((x)+((-x)&((align)-1)))
-#define PTR_ALIGN(ptr, align) (typeof(ptr)) (((uintptr_t)ptr + (align - 1)) & -align)
-
 void *zn_alloc_align(Zone *z, ptrdiff_t n, size_t align) {
 	ZoneFrame *zf = z->cur;
 	uint8_t *aligned;
@@ -140,16 +190,14 @@ void *zn_alloc_align(Zone *z, ptrdiff_t n, size_t align) {
 }
 
 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 {
-justalloc:
 		void *p = zn_alloc_align(z, newsz, align);
-		memcpy(p, ptr, oldsz);
+		ZONE_MEMCPY(p, ptr, oldsz);
 		return p;
 	}
 }
@@ -170,7 +218,7 @@ void *zn_realloc(Zone *z, void *ptr, ptrdiff_t oldsz, ptrdiff_t 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);
+	ZONE_MEMSET(p, 0, n * size);
 	return p;
 }
 
@@ -214,15 +262,17 @@ void zn_load(Zone *z, ZoneState *m) {
 
 /* utils */
 
+#ifndef ZONE_NOSTDLIB
 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);
+	ZONE_MEMCPY(d, s, n);
 	return d;
 }
+#endif
 
 void *zn_zeroed(void *ptr, size_t n) {
-	memset(ptr, 0, n);
+	ZONE_MEMSET(ptr, 0, n);
 	return ptr;
 }