| ... | @@ -246,16 +246,12 @@ const PageAllocator = struct { | ... | @@ -246,16 +246,12 @@ const PageAllocator = struct { |
| 246 | } | 246 | } |
| 247 | }; | 247 | }; |
| 248 | | 248 | |
| 249 | extern const __heap_base: [*]u8; | | |
| 250 | // TODO Exposed LLVM intrinsics is a bug | 249 | // TODO Exposed LLVM intrinsics is a bug |
| 251 | // See: https://github.com/ziglang/zig/issues/2291 | 250 | // See: https://github.com/ziglang/zig/issues/2291 |
| 252 | extern fn @"llvm.wasm.memory.size.i32"(u32) u32; | 251 | extern fn @"llvm.wasm.memory.size.i32"(u32) u32; |
| 253 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; | 252 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; |
| 254 | | 253 | |
| 255 | const WasmPageAllocator = struct { | 254 | const WasmPageAllocator = struct { |
| 256 | // TODO: figure out why __heap_base cannot be found | | |
| 257 | var heap_base_wannabe align(16) = [_]u8{0} ** 256; | | |
| 258 | | | |
| 259 | const PageStatus = enum(u1) { | 255 | const PageStatus = enum(u1) { |
| 260 | used = 0, | 256 | used = 0, |
| 261 | free = 1, | 257 | free = 1, |
| ... | @@ -264,24 +260,24 @@ const WasmPageAllocator = struct { | ... | @@ -264,24 +260,24 @@ const WasmPageAllocator = struct { |
| 264 | }; | 260 | }; |
| 265 | | 261 | |
| 266 | const FreeBlock = struct { | 262 | const FreeBlock = struct { |
| 267 | bytes: []align(16) u8, | 263 | data: []u128, |
| 268 | | 264 | |
| 269 | const Io = std.packed_int_array.PackedIntIo(u1, .Little); | 265 | const Io = std.packed_int_array.PackedIntIo(u1, .Little); |
| 270 | | 266 | |
| 271 | fn totalPages(self: FreeBlock) usize { | 267 | fn totalPages(self: FreeBlock) usize { |
| 272 | return self.bytes.len * 8; | 268 | return self.data.len * 8; |
| 273 | } | 269 | } |
| 274 | | 270 | |
| 275 | fn getBit(self: *FreeBlock, idx: usize) PageStatus { | 271 | fn getBit(self: FreeBlock, idx: usize) PageStatus { |
| 276 | const bit_offset = 0; | 272 | const bit_offset = 0; |
| 277 | return @intToEnum(PageStatus, Io.get(self.bytes, idx, bit_offset)); | 273 | return @intToEnum(PageStatus, Io.get(@sliceToBytes(self.data), idx, bit_offset)); |
| 278 | } | 274 | } |
| 279 | | 275 | |
| 280 | fn setBits(self: *FreeBlock, start_idx: usize, len: usize, val: PageStatus) void { | 276 | fn setBits(self: FreeBlock, start_idx: usize, len: usize, val: PageStatus) void { |
| 281 | const bit_offset = 0; | 277 | const bit_offset = 0; |
| 282 | var i: usize = 0; | 278 | var i: usize = 0; |
| 283 | while (i < len) : (i += 1) { | 279 | while (i < len) : (i += 1) { |
| 284 | Io.set(self.bytes, start_idx + i, bit_offset, @enumToInt(val)); | 280 | Io.set(@sliceToBytes(self.data), start_idx + i, bit_offset, @enumToInt(val)); |
| 285 | } | 281 | } |
| 286 | } | 282 | } |
| 287 | | 283 | |
| ... | @@ -294,10 +290,9 @@ const WasmPageAllocator = struct { | ... | @@ -294,10 +290,9 @@ const WasmPageAllocator = struct { |
| 294 | // Revisit if this is settled: https://github.com/ziglang/zig/issues/3806 | 290 | // Revisit if this is settled: https://github.com/ziglang/zig/issues/3806 |
| 295 | const not_found = std.math.maxInt(usize); | 291 | const not_found = std.math.maxInt(usize); |
| 296 | | 292 | |
| 297 | fn useRecycled(self: *FreeBlock, num_pages: usize) usize { | 293 | fn useRecycled(self: FreeBlock, num_pages: usize) usize { |
| 298 | @setCold(true); | 294 | @setCold(true); |
| 299 | const segments = @bytesToSlice(u128, self.bytes); | 295 | for (self.data) |segment, i| { |
| 300 | for (segments) |segment, i| { | | |
| 301 | const spills_into_next = @bitCast(i128, segment) < 0; | 296 | const spills_into_next = @bitCast(i128, segment) < 0; |
| 302 | const has_enough_bits = @popCount(u128, segment) >= num_pages; | 297 | const has_enough_bits = @popCount(u128, segment) >= num_pages; |
| 303 | | 298 | |
| ... | @@ -319,13 +314,13 @@ const WasmPageAllocator = struct { | ... | @@ -319,13 +314,13 @@ const WasmPageAllocator = struct { |
| 319 | return not_found; | 314 | return not_found; |
| 320 | } | 315 | } |
| 321 | | 316 | |
| 322 | fn recycle(self: *FreeBlock, start_idx: usize, len: usize) void { | 317 | fn recycle(self: FreeBlock, start_idx: usize, len: usize) void { |
| 323 | self.setBits(start_idx, len, .free); | 318 | self.setBits(start_idx, len, .free); |
| 324 | } | 319 | } |
| 325 | }; | 320 | }; |
| 326 | | 321 | |
| 327 | var conventional = FreeBlock{ .bytes = &[_]u8{} }; | 322 | const conventional = FreeBlock{ .data = &[_]u128{ 0, 0 } }; |
| 328 | var extended = FreeBlock{ .bytes = &[_]u8{} }; | 323 | var extended = FreeBlock{ .data = &[_]u128{} }; |
| 329 | | 324 | |
| 330 | fn extendedOffset() usize { | 325 | fn extendedOffset() usize { |
| 331 | return conventional.totalPages(); | 326 | return conventional.totalPages(); |
| ... | @@ -373,15 +368,11 @@ const WasmPageAllocator = struct { | ... | @@ -373,15 +368,11 @@ const WasmPageAllocator = struct { |
| 373 | } | 368 | } |
| 374 | | 369 | |
| 375 | pub fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { | 370 | pub fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| | 371 | @setCold(true); |
| 376 | const free_start = nPages(@ptrToInt(old_mem.ptr) + new_size); | 372 | const free_start = nPages(@ptrToInt(old_mem.ptr) + new_size); |
| 377 | var free_end = nPages(@ptrToInt(old_mem.ptr) + old_mem.len); | 373 | var free_end = nPages(@ptrToInt(old_mem.ptr) + old_mem.len); |
| 378 | | 374 | |
| 379 | if (free_end > free_start) { | 375 | if (free_end > free_start) { |
| 380 | if (conventional.totalPages() == 0) { | | |
| 381 | //conventional.bytes = __heap_base[0..@intCast(usize, @"llvm.wasm.memory.size.i32"(0) * std.mem.page_size)]; | | |
| 382 | conventional.bytes = heap_base_wannabe[0..]; | | |
| 383 | } | | |
| 384 | | | |
| 385 | if (free_start < extendedOffset()) { | 376 | if (free_start < extendedOffset()) { |
| 386 | const clamped_end = std.math.min(extendedOffset(), free_end); | 377 | const clamped_end = std.math.min(extendedOffset(), free_end); |
| 387 | conventional.recycle(free_start, clamped_end - free_start); | 378 | conventional.recycle(free_start, clamped_end - free_start); |
| ... | @@ -393,9 +384,9 @@ const WasmPageAllocator = struct { | ... | @@ -393,9 +384,9 @@ const WasmPageAllocator = struct { |
| 393 | // TODO: would it be better if we use the first page instead? | 384 | // TODO: would it be better if we use the first page instead? |
| 394 | free_end -= 1; | 385 | free_end -= 1; |
| 395 | | 386 | |
| 396 | extended.bytes = @intToPtr([*]align(16) u8, free_end * std.mem.page_size)[0..std.mem.page_size]; | 387 | extended.data = @intToPtr([*]u128, free_end * std.mem.page_size)[0 .. std.mem.page_size / @sizeOf(u128)]; |
| 397 | // Since this is the first page being freed and we consume it, assume *nothing* is free. | 388 | // Since this is the first page being freed and we consume it, assume *nothing* is free. |
| 398 | std.mem.set(u8, extended.bytes, PageStatus.all_used); | 389 | std.mem.set(u128, extended.data, PageStatus.all_used); |
| 399 | } | 390 | } |
| 400 | const clamped_start = std.math.max(extendedOffset(), free_start); | 391 | const clamped_start = std.math.max(extendedOffset(), free_start); |
| 401 | extended.recycle(clamped_start - extendedOffset(), free_end - clamped_start); | 392 | extended.recycle(clamped_start - extendedOffset(), free_end - clamped_start); |