| ... | @@ -318,9 +318,10 @@ pub const FixedBufferAllocator = struct { | ... | @@ -318,9 +318,10 @@ pub const FixedBufferAllocator = struct { |
| 318 | } | 318 | } |
| 319 | }; | 319 | }; |
| 320 | | 320 | |
| | 321 | // FIXME: Exposed LLVM intrinsics is a bug |
| | 322 | // See: https://github.com/ziglang/zig/issues/2291 |
| 321 | extern fn @"llvm.wasm.memory.size.i32"(u32) u32; | 323 | extern fn @"llvm.wasm.memory.size.i32"(u32) u32; |
| 322 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; | 324 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; |
| 323 | const WASM_PAGE_SIZE = 64 * 1024; // 64 kilobytes | | |
| 324 | | 325 | |
| 325 | pub const wasm_allocator = &wasm_allocator_state.allocator; | 326 | pub const wasm_allocator = &wasm_allocator_state.allocator; |
| 326 | var wasm_allocator_state = WasmAllocator{ | 327 | var wasm_allocator_state = WasmAllocator{ |
| ... | @@ -333,7 +334,7 @@ var wasm_allocator_state = WasmAllocator{ | ... | @@ -333,7 +334,7 @@ var wasm_allocator_state = WasmAllocator{ |
| 333 | .end_index = 0, | 334 | .end_index = 0, |
| 334 | }; | 335 | }; |
| 335 | | 336 | |
| 336 | pub const WasmAllocator = struct { | 337 | const WasmAllocator = struct { |
| 337 | allocator: Allocator, | 338 | allocator: Allocator, |
| 338 | start_ptr: [*]u8, | 339 | start_ptr: [*]u8, |
| 339 | num_pages: usize, | 340 | num_pages: usize, |
| ... | @@ -347,11 +348,11 @@ pub const WasmAllocator = struct { | ... | @@ -347,11 +348,11 @@ pub const WasmAllocator = struct { |
| 347 | const adjusted_index = self.end_index + (adjusted_addr - addr); | 348 | const adjusted_index = self.end_index + (adjusted_addr - addr); |
| 348 | const new_end_index = adjusted_index + size; | 349 | const new_end_index = adjusted_index + size; |
| 349 | | 350 | |
| 350 | const required_memory = new_end_index - (self.num_pages * WASM_PAGE_SIZE); | 351 | if (new_end_index > self.num_pages * os.page_size) { |
| | 352 | const required_memory = new_end_index - (self.num_pages * os.page_size); |
| 351 | | 353 | |
| 352 | if (required_memory > 0) { | 354 | var num_pages: u32 = required_memory / os.page_size; |
| 353 | var num_pages: u32 = @divTrunc(required_memory, WASM_PAGE_SIZE); | 355 | if (required_memory % os.page_size != 0) { |
| 354 | if (@rem(required_memory, WASM_PAGE_SIZE) != 0) { | | |
| 355 | num_pages += 1; | 356 | num_pages += 1; |
| 356 | } | 357 | } |
| 357 | | 358 | |
| ... | @@ -369,7 +370,7 @@ pub const WasmAllocator = struct { | ... | @@ -369,7 +370,7 @@ pub const WasmAllocator = struct { |
| 369 | return result; | 370 | return result; |
| 370 | } | 371 | } |
| 371 | | 372 | |
| 372 | // Check if memory is the last "item" and it aligns. That lets us expand or reclaim memory | 373 | // Check if memory is the last "item" and is aligned correctly |
| 373 | fn is_last_item(allocator: *Allocator, memory: []u8, alignment: u29) bool { | 374 | fn is_last_item(allocator: *Allocator, memory: []u8, alignment: u29) bool { |
| 374 | const self = @fieldParentPtr(WasmAllocator, "allocator", allocator); | 375 | const self = @fieldParentPtr(WasmAllocator, "allocator", allocator); |
| 375 | return memory.ptr == self.start_ptr + self.end_index - memory.len and mem.alignForward(@ptrToInt(memory.ptr), alignment) == @ptrToInt(memory.ptr); | 376 | return memory.ptr == self.start_ptr + self.end_index - memory.len and mem.alignForward(@ptrToInt(memory.ptr), alignment) == @ptrToInt(memory.ptr); |
| ... | @@ -380,14 +381,14 @@ pub const WasmAllocator = struct { | ... | @@ -380,14 +381,14 @@ pub const WasmAllocator = struct { |
| 380 | | 381 | |
| 381 | // Initialize start_ptr at the first realloc | 382 | // Initialize start_ptr at the first realloc |
| 382 | if (self.num_pages == 0) { | 383 | if (self.num_pages == 0) { |
| 383 | self.start_ptr = @intToPtr([*]u8, @intCast(usize, @"llvm.wasm.memory.size.i32"(0)) * WASM_PAGE_SIZE); | 384 | self.start_ptr = @intToPtr([*]u8, @intCast(usize, @"llvm.wasm.memory.size.i32"(0)) * os.page_size); |
| 384 | } | 385 | } |
| 385 | | 386 | |
| 386 | if (is_last_item(allocator, old_mem, new_align)) { | 387 | if (is_last_item(allocator, old_mem, new_align)) { |
| 387 | const start_index = self.end_index - old_mem.len; | 388 | const start_index = self.end_index - old_mem.len; |
| 388 | const new_end_index = start_index + new_size; | 389 | const new_end_index = start_index + new_size; |
| 389 | | 390 | |
| 390 | if (new_end_index > self.num_pages * WASM_PAGE_SIZE) { | 391 | if (new_end_index > self.num_pages * os.page_size) { |
| 391 | _ = try alloc(allocator, new_end_index - self.end_index, new_align); | 392 | _ = try alloc(allocator, new_end_index - self.end_index, new_align); |
| 392 | } | 393 | } |
| 393 | const result = self.start_ptr[start_index..new_end_index]; | 394 | const result = self.start_ptr[start_index..new_end_index]; |
| ... | @@ -404,7 +405,6 @@ pub const WasmAllocator = struct { | ... | @@ -404,7 +405,6 @@ pub const WasmAllocator = struct { |
| 404 | } | 405 | } |
| 405 | | 406 | |
| 406 | fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { | 407 | fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| 407 | // TODO: Use is_last_item or other heuristic here | | |
| 408 | return old_mem[0..new_size]; | 408 | return old_mem[0..new_size]; |
| 409 | } | 409 | } |
| 410 | }; | 410 | }; |