Mirai's Miscellaneous Misadventures

M22 / engines / wasm.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
3
4#include <mimimi/allocators.h>
5
6struct mimimi_image;
7
8void mimimi_wasm_javascript_stamp(void *data, int x, int y, struct mimimi_image *image);
9void mimimi_wasm_stamp(void *data, int x, int y, struct mimimi_image *image)
10{
11	mimimi_wasm_javascript_stamp(data, x, y, image);
12}
13
14static unsigned char *mimimi_wasm_null = 0;
15
16extern unsigned char __heap_base;
17static unsigned char *mimimi_wasm_heap = &__heap_base;
18static unsigned long int mimimi_wasm_start = (unsigned long int)&__heap_base;
19
20static unsigned char mimimi_wasm_blocks[0x10000] = {};
21
22static void mimimi_wasm_grow(int n)
23{
24	unsigned long int size = __builtin_wasm_memory_size(0) * 0x10000 - mimimi_wasm_start;
25	if (size < n)
26		if (__builtin_wasm_memory_grow(0, (n - size - 1) / 0x10000 + 1) < 0)
27			__builtin_trap();
28}
29
30void *mimimi_wasm_allocate(unsigned int size)
31{
32	int blocks = (size - 1) / 8192 + 1;
33	
34	for (int i = 0 ; i < 0x10000 ; i++)
35	{
36		for (int j = 0 ; j < blocks ; j++)
37		{
38			if (mimimi_wasm_blocks[i + j] != 0)
39				goto next;
40		}
41		
42		mimimi_wasm_blocks[i] = 1;
43		for (int j = 1 ; j < blocks ; j++)
44			mimimi_wasm_blocks[i + j] = 2;
45		
46		unsigned char *data = mimimi_wasm_heap + i * 8192;
47		mimimi_wasm_grow(data - mimimi_wasm_null);
48		return data;
49		
50		next:;
51	}
52	
53	__builtin_trap();
54}
55
56static void mimimi_wasm_deallocate(void *data0)
57{
58	unsigned char *data = data0;
59	int block = (data - mimimi_wasm_heap) / 8192;
60	
61	mimimi_wasm_blocks[block] = 0;
62	for (int i = 1 ; mimimi_wasm_blocks[block + i] == 2 ; i++)
63		mimimi_wasm_blocks[block + i] = 0;
64}
65
66static void *mimimi_wasm_reallocate(void *data0, unsigned int size)
67{
68	if (data0 == 0) return mimimi_wasm_allocate(size);
69	
70	unsigned char *data = data0;
71	int block = (data - mimimi_wasm_heap) / 8192;
72	
73	int current_count = 1;
74	while (mimimi_wasm_blocks[block + current_count] == 2) current_count++;
75	
76	int target_count = (size - 1) / 8192 + 1;
77	
78	if (target_count <= current_count)
79	{
80		for (int i = target_count ; i < current_count ; i++)
81			mimimi_wasm_blocks[block + i] = 0;
82		return data;
83	}
84	
85	for (int i = current_count ; i < target_count ; i++)
86	{
87		if (mimimi_wasm_blocks[block + i] != 0)
88		{
89			unsigned char *new = mimimi_wasm_allocate(size);
90			for (unsigned int i = 0 ; i < current_count * 8192 ; i++)
91				new[i] = data[i];
92			mimimi_wasm_deallocate(data);
93			return new;
94		}
95	}
96	
97	for (int i = current_count ; i < target_count ; i++)
98		mimimi_wasm_blocks[block + i] = 2;
99	return data;
100}
101
102static struct mimimi_allocator mimimi_wasm_allocator_value = {&mimimi_wasm_allocate, &mimimi_wasm_reallocate, &mimimi_wasm_deallocate, 0};
103struct mimimi_allocator *mimimi_wasm_allocator = &mimimi_wasm_allocator_value;