35#define ARENA_ASSERT assert
38#define ARENA_BACKEND_LIBC_MALLOC 0
39#define ARENA_BACKEND_LINUX_MMAP 1
40#define ARENA_BACKEND_WIN32_VIRTUALALLOC 2
41#define ARENA_BACKEND_WASM_HEAPBASE 3
44#define ARENA_BACKEND ARENA_BACKEND_LIBC_MALLOC
65#ifndef ARENA_REGION_DEFAULT_CAPACITY
66#define ARENA_REGION_DEFAULT_CAPACITY (8*1024)
88#ifndef ARENA_DA_INIT_CAP
89#define ARENA_DA_INIT_CAP 256
93 #define cast_ptr(ptr) (decltype(ptr))
98#define arena_da_append(a, da, item) \
100 if ((da)->count >= (da)->capacity) { \
101 size_t new_capacity = (da)->capacity == 0 ? ARENA_DA_INIT_CAP : (da)->capacity*2; \
102 (da)->items = cast_ptr((da)->items)arena_realloc( \
104 (da)->capacity*sizeof(*(da)->items), \
105 new_capacity*sizeof(*(da)->items)); \
106 (da)->capacity = new_capacity; \
109 (da)->items[(da)->count++] = (item); \
113#define arena_da_append_many(a, da, new_items, new_items_count) \
115 if ((da)->count + (new_items_count) > (da)->capacity) { \
116 size_t new_capacity = (da)->capacity; \
117 if (new_capacity == 0) new_capacity = ARENA_DA_INIT_CAP; \
118 while ((da)->count + (new_items_count) > new_capacity) new_capacity *= 2; \
119 (da)->items = cast_ptr((da)->items)arena_realloc( \
121 (da)->capacity*sizeof(*(da)->items), \
122 new_capacity*sizeof(*(da)->items)); \
123 (da)->capacity = new_capacity; \
125 arena_memcpy((da)->items + (da)->count, (new_items), (new_items_count)*sizeof(*(da)->items)); \
126 (da)->count += (new_items_count); \
130#define arena_sb_append_buf arena_da_append_many
133#define arena_sb_append_cstr(a, sb, cstr) \
135 const char *s = (cstr); \
136 size_t n = arena_strlen(s); \
137 arena_da_append_many(a, sb, s, n); \
142#define arena_sb_append_null(a, sb) arena_da_append(a, sb, 0)
146#ifdef ARENA_IMPLEMENTATION
148#if ARENA_BACKEND == ARENA_BACKEND_LIBC_MALLOC
155 size_t size_bytes =
sizeof(
Region) +
sizeof(uintptr_t)*capacity;
169#elif ARENA_BACKEND == ARENA_BACKEND_LINUX_MMAP
175 size_t size_bytes =
sizeof(
Region) +
sizeof(uintptr_t) * capacity;
176 Region *r = mmap(NULL, size_bytes, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
186 size_t size_bytes =
sizeof(
Region) +
sizeof(uintptr_t) * r->
capacity;
187 int ret = munmap(r, size_bytes);
191#elif ARENA_BACKEND == ARENA_BACKEND_WIN32_VIRTUALALLOC
194# error "Current platform is not Windows"
197#define WIN32_LEAN_AND_MEAN
200#define INV_HANDLE(x) (((x) == NULL) || ((x) == INVALID_HANDLE_VALUE))
204 SIZE_T size_bytes =
sizeof(
Region) +
sizeof(uintptr_t) * capacity;
205 Region *r = VirtualAllocEx(
209 MEM_COMMIT | MEM_RESERVE,
226 BOOL free_result = VirtualFreeEx(
233 if (FALSE == free_result)
237#elif ARENA_BACKEND == ARENA_BACKEND_WASM_HEAPBASE
241extern unsigned char __heap_base;
244unsigned char* bump_pointer = &__heap_base;
248#define ARENA_WASM_PAGE_SIZE (64*1024)
252 size_t size_bytes =
sizeof(
Region) +
sizeof(uintptr_t)*capacity;
253 Region *r = (
void*)bump_pointer;
256 size_t current_memory_size = ARENA_WASM_PAGE_SIZE * __builtin_wasm_memory_size(0);
257 size_t desired_memory_size = (size_t) bump_pointer + size_bytes;
258 if (desired_memory_size > current_memory_size) {
259 size_t delta_bytes = desired_memory_size - current_memory_size;
260 size_t delta_pages = (delta_bytes + (ARENA_WASM_PAGE_SIZE - 1))/ARENA_WASM_PAGE_SIZE;
261 if (__builtin_wasm_memory_grow(0, delta_pages) < 0) {
267 bump_pointer += size_bytes;
285# error "Unknown Arena backend"
296 size_t size = (size_bytes +
sizeof(uintptr_t) - 1)/
sizeof(uintptr_t);
298 if (a->end == NULL) {
301 if (capacity < size) capacity = size;
306 while (a->end->count + size > a->end->capacity && a->end->next != NULL) {
307 a->end = a->end->next;
310 if (a->end->count + size > a->end->capacity) {
313 if (capacity < size) capacity = size;
315 a->end = a->end->next;
318 void *result = &a->end->
data[a->end->count];
319 a->end->count += size;
325 if (newsz <= oldsz)
return oldptr;
327 char *newptr_char = (
char*)newptr;
328 char *oldptr_char = (
char*)oldptr;
329 for (
size_t i = 0; i < oldsz; ++i) {
330 newptr_char[i] = oldptr_char[i];
335size_t arena_strlen(
const char *s)
342void *
arena_memcpy(
void *dest,
const void *src,
size_t n)
344 char *d = (
char*) dest;
345 const char *s = (
const char*) src;
346 for (; n; n--) *d++ = *s++;
352 size_t n = arena_strlen(cstr);
368 va_copy(args_copy, args);
369 int n = vsnprintf(NULL, 0, format, args_copy);
374 vsnprintf(result, n + 1, format, args);
382 va_start(args, format);
399 m.
count = a->end->count;
407 for (
Region *r = a->begin; r != NULL; r = r->
next) {
void * arena_alloc(Arena *a, size_t size_bytes)
void arena_trim(Arena *a)
void free_region(Region *r)
#define ARENA_ASSERT
Definition arena.h:35
void arena_reset(Arena *a)
char * arena_vsprintf(Arena *a, const char *format, va_list args)
void arena_free(Arena *a)
void arena_rewind(Arena *a, Arena_Mark m)
Arena_Mark arena_snapshot(Arena *a)
void * arena_realloc(Arena *a, void *oldptr, size_t oldsz, size_t newsz)
Region * new_region(size_t capacity)
void * arena_memcpy(void *dest, const void *src, size_t n)
char * arena_strdup(Arena *a, const char *cstr)
char * arena_sprintf(Arena *a, const char *format,...)
void * arena_memdup(Arena *a, void *data, size_t size)
#define ARENA_REGION_DEFAULT_CAPACITY
Definition hawaii.c:2
size_t count
Definition arena.h:62
Region * region
Definition arena.h:61
Region * end
Definition arena.h:57
Region * begin
Definition arena.h:57
size_t count
Definition arena.h:51
uintptr_t data[]
Definition arena.h:53
Region * next
Definition arena.h:50
size_t capacity
Definition arena.h:52