| ... | @@ -253,7 +253,7 @@ extern fn @"llvm.wasm.memory.size.i32"(u32) u32; | ... | @@ -253,7 +253,7 @@ extern fn @"llvm.wasm.memory.size.i32"(u32) u32; |
| 253 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; | 253 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; |
| 254 | | 254 | |
| 255 | test "" { | 255 | test "" { |
| 256 | _ = WasmPageAllocator.alloc; | 256 | _ = WasmPageAllocator.realloc; |
| 257 | } | 257 | } |
| 258 | | 258 | |
| 259 | const WasmPageAllocator = struct { | 259 | const WasmPageAllocator = struct { |
| ... | @@ -261,12 +261,24 @@ const WasmPageAllocator = struct { | ... | @@ -261,12 +261,24 @@ const WasmPageAllocator = struct { |
| 261 | offset: usize = 0, | 261 | offset: usize = 0, |
| 262 | data: []u8 = &[_]u8{}, | 262 | data: []u8 = &[_]u8{}, |
| 263 | | 263 | |
| 264 | fn alloc(self: FreeBlock, num_pages: usize) ?[]u8 { | 264 | fn initData(self: *FreeBlock, data: []u8) void { |
| | 265 | std.mem.set(u8, data, 0); |
| | 266 | self.data = data; |
| | 267 | } |
| | 268 | |
| | 269 | fn totalPages(self: FreeBlock) usize { |
| | 270 | return self.data.len * @typeInfo(usize).Int.bits; |
| | 271 | } |
| | 272 | |
| | 273 | fn alloc(self: *FreeBlock, num_pages: usize) ?[]u8 { |
| 265 | return null; | 274 | return null; |
| 266 | } | 275 | } |
| | 276 | |
| | 277 | fn reclaim(self: *FreeBlock, start_page: usize, end_page: usize) void {} |
| 267 | }; | 278 | }; |
| 268 | var base = FreeBlock{}; | 279 | |
| 269 | var additional = FreeBlock{}; | 280 | var conventional = FreeBlock{}; |
| | 281 | var extended = FreeBlock{}; |
| 270 | | 282 | |
| 271 | fn nPages(memsize: usize) usize { | 283 | fn nPages(memsize: usize) usize { |
| 272 | return std.mem.alignForward(memsize, std.mem.page_size) / std.mem.page_size; | 284 | return std.mem.alignForward(memsize, std.mem.page_size) / std.mem.page_size; |
| ... | @@ -278,7 +290,7 @@ const WasmPageAllocator = struct { | ... | @@ -278,7 +290,7 @@ const WasmPageAllocator = struct { |
| 278 | } | 290 | } |
| 279 | | 291 | |
| 280 | const n_pages = nPages(n); | 292 | const n_pages = nPages(n); |
| 281 | return base.alloc(n_pages) orelse additional.alloc(n_pages) orelse { | 293 | return conventional.alloc(n_pages) orelse extended.alloc(n_pages) orelse { |
| 282 | const prev_page_count = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, n_pages)); | 294 | const prev_page_count = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, n_pages)); |
| 283 | if (prev_page_count < 0) { | 295 | if (prev_page_count < 0) { |
| 284 | return error.OutOfMemory; | 296 | return error.OutOfMemory; |
| ... | @@ -305,13 +317,28 @@ const WasmPageAllocator = struct { | ... | @@ -305,13 +317,28 @@ const WasmPageAllocator = struct { |
| 305 | } | 317 | } |
| 306 | | 318 | |
| 307 | pub fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { | 319 | pub fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { |
| 308 | var shrinkage = nPages(old_mem.len) - nPages(new_size); | 320 | const free_start = nPages(@ptrToInt(old_mem.ptr) + new_size); |
| 309 | if (shrinkage > 0) { | 321 | var free_end = nPages(@ptrToInt(old_mem.ptr) + old_mem.len); |
| 310 | const success = base.recycle(old_mem[new_size..old_mem.len]); | 322 | |
| 311 | if (!success) { | 323 | if (free_end > free_start) { |
| 312 | std.debug.assert(additional.recycle(old_mem[new_size..old_mem.len])); | 324 | if (conventional.data.len == 0) { |
| | 325 | conventional.initData(__heap_base[0..@intCast(usize, @"llvm.wasm.memory.size.i32"(0) * std.mem.page_size)]); |
| | 326 | } |
| | 327 | |
| | 328 | if (free_start < conventional.totalPages()) { |
| | 329 | conventional.reclaim(free_start, free_end); |
| | 330 | } else { |
| | 331 | if (extended.data.len == 0) { |
| | 332 | extended.offset = conventional.totalPages(); |
| | 333 | |
| | 334 | // Steal the last page from the memory currently being reclaimed |
| | 335 | free_end -= 1; |
| | 336 | extended.initData(@intToPtr([*]u8, free_end)[0..std.mem.page_size]); |
| | 337 | } |
| | 338 | conventional.reclaim(free_start, free_end); |
| 313 | } | 339 | } |
| 314 | } | 340 | } |
| | 341 | |
| 315 | return old_mem[0..new_size]; | 342 | return old_mem[0..new_size]; |
| 316 | } | 343 | } |
| 317 | }; | 344 | }; |