summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}