| ... | ... | @@ -318,6 +318,51 @@ pub const FixedBufferAllocator = struct { |
| 318 | 318 | } |
| 319 | 319 | }; |
| 320 | 320 | |
| 321 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; |
| 322 | |
| 323 | /// This allocator tries to allocate the specified number of 64 KB pages and uses FixedBufferAllocator internally |
| 324 | pub const WasmAllocator = blk: { |
| 325 | if (builtin.arch != builtin.Arch.wasm32) { |
| 326 | @compileError("only supported in wasm32"); |
| 327 | } else { |
| 328 | const mem_grow = @"llvm.wasm.memory.grow.i32"; |
| 329 | |
| 330 | const WASM_PAGE_SIZE = 64 * 1024; // 64 kilobytes |
| 331 | |
| 332 | break :blk struct { |
| 333 | allocator: Allocator, |
| 334 | fb_allocator: FixedBufferAllocator, |
| 335 | |
| 336 | pub fn init(num_pages: u32) !WasmAllocator { |
| 337 | const prev_block = mem_grow(0, num_pages); |
| 338 | if (prev_block == -1) { |
| 339 | return error.OutOfMemory; |
| 340 | } |
| 341 | |
| 342 | const buffer_slice = @intToPtr([*]u8, @intCast(usize, prev_block) * WASM_PAGE_SIZE)[0..(WASM_PAGE_SIZE * num_pages)]; |
| 343 | |
| 344 | return WasmAllocator{ |
| 345 | .allocator = Allocator{ |
| 346 | .reallocFn = realloc, |
| 347 | .shrinkFn = shrink, |
| 348 | }, |
| 349 | .fb_allocator = FixedBufferAllocator.init(buffer_slice), |
| 350 | }; |
| 351 | } |
| 352 | |
| 353 | fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { |
| 354 | const self = @fieldParentPtr(WasmAllocator, "allocator", allocator); |
| 355 | return FixedBufferAllocator.realloc(&self.fb_allocator.allocator, old_mem, old_align, new_size, new_align); |
| 356 | } |
| 357 | |
| 358 | fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| 359 | const self = @fieldParentPtr(WasmAllocator, "allocator", allocator); |
| 360 | return FixedBufferAllocator.shrink(&self.fb_allocator.allocator, old_mem, old_align, new_size, new_align); |
| 361 | } |
| 362 | }; |
| 363 | } |
| 364 | }; |
| 365 | |
| 321 | 366 | pub const ThreadSafeFixedBufferAllocator = blk: { |
| 322 | 367 | if (builtin.single_threaded) { |
| 323 | 368 | break :blk FixedBufferAllocator; |