Created
June 6, 2019 16:11
-
-
Save saolsen/43912593ab01612d0d9a9e9e0b8b6fb8 to your computer and use it in GitHub Desktop.
grow_memory in wasm from c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
include <stdlib.h> | |
#include <stddef.h> | |
#include <assert.h> | |
#include <webassembly.h> | |
typedef uint8_t u8; | |
typedef uint32_t u32; | |
typedef uint64_t u64; | |
typedef int32_t i32; | |
typedef int64_t i64; | |
typedef float f32; | |
typedef double f64; | |
// First pass at memory allocation. We work with arenas that pull memory | |
// a page at a time. Right now just waste the ends of pages and don't allow | |
// allocations greater than a page. | |
//@OPTIMIZE: There's wasted memory between _heap_base to the end of the first page. | |
#define page_size 65536 | |
extern void _grow(); | |
void *allocate_page() { | |
int page = __builtin_wasm_grow_memory(1); | |
_grow(); // Updates the wrapper arrays so console_log works. | |
return (uint8_t*)0 + (page * page_size); | |
} | |
typedef struct PageFooter { | |
struct PageFooter *prev; | |
} PageFooter; | |
typedef struct { | |
void *page; | |
size_t used; | |
} Arena; | |
static void* free_pages = NULL; | |
void *arena_push_size(Arena* arena, u32 size) { | |
if (size > page_size - sizeof(PageFooter)) { | |
console_error("size > maximum allocatable"); | |
} | |
if (!arena->page || arena->used + size > page_size) { | |
// Allocate a new page | |
void *new_page = NULL; | |
if (free_pages != NULL) { | |
new_page = free_pages; | |
free_pages = *(void**)new_page; | |
} else { | |
new_page = allocate_page(); | |
} | |
PageFooter *footer = (PageFooter*)((u8*)new_page + (page_size - sizeof(PageFooter))); | |
footer->prev = arena->page; | |
arena->page = new_page; | |
arena->used = 0; | |
} | |
if (size > (page_size - sizeof(PageFooter)) - arena->used) { | |
console_error("No room for some reason!"); | |
} | |
void *result = arena->page + arena->used; | |
arena->used += size; | |
return result; | |
} | |
void arena_free(Arena* arena) { | |
void *page = arena->page; | |
while(page) { | |
PageFooter *footer = (PageFooter*)((u8*)page + (page_size - sizeof(PageFooter))); | |
*(void**)page = free_pages; | |
free_pages = page; | |
page = footer->prev; | |
} | |
arena->page = NULL; | |
arena->used = 0; | |
} | |
export void test() { | |
console_log("Running Tests\n"); | |
Arena arena; | |
Arena arena_two; | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
void *mem = arena_push_size(&arena, 1024); | |
console_log("push 1024: %i", (int)mem); | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
mem = arena_push_size(&arena, 1024); | |
console_log("push 1024: %i", (int)mem); | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
console_log("free arena"); | |
arena_free(&arena); | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
mem = arena_push_size(&arena, 1024); | |
console_log("push 1024: %i", (int)mem); | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
for (int i=0; i<12; i++) { | |
mem = arena_push_size(&arena, page_size-100); | |
console_log("push %i: %i", page_size-100, (int)mem); | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
} | |
console_log("Arena2{base: %i, used: %i}", (int)arena_two.page, arena_two.used); | |
mem = arena_push_size(&arena_two, 1024); | |
console_log("push 1024 to arena 2: %i", (int)mem); | |
console_log("Arena2{base: %i, used: %i}", (int)arena_two.page, arena_two.used); | |
console_log("free arena 1"); | |
arena_free(&arena); | |
console_log("Arena{base: %i, used: %i}", (int)arena.page, arena.used); | |
mem = arena_push_size(&arena_two, 65436); | |
console_log("push 65436 to arena 2: %i", (int)mem); | |
console_log("Arena2{base: %i, used: %i}", (int)arena_two.page, arena_two.used); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment