| ... | ... | @@ -253,7 +253,7 @@ extern fn @"llvm.wasm.memory.size.i32"(u32) u32; |
| 253 | 253 | extern fn @"llvm.wasm.memory.grow.i32"(u32, u32) i32; |
| 254 | 254 | |
| 255 | 255 | test "" { |
| 256 | | _ = WasmPageAllocator.alloc; |
| 256 | _ = WasmPageAllocator.realloc; |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | 259 | const WasmPageAllocator = struct { |
| ... | ... | @@ -261,12 +261,24 @@ const WasmPageAllocator = struct { |
| 261 | 261 | offset: usize = 0, |
| 262 | 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 | 274 | return null; |
| 266 | 275 | } |
| 276 | |
| 277 | fn reclaim(self: *FreeBlock, start_page: usize, end_page: usize) void {} |
| 267 | 278 | }; |
| 268 | | var base = FreeBlock{}; |
| 269 | | var additional = FreeBlock{}; |
| 279 | |
| 280 | var conventional = FreeBlock{}; |
| 281 | var extended = FreeBlock{}; |
| 270 | 282 | |
| 271 | 283 | fn nPages(memsize: usize) usize { |
| 272 | 284 | return std.mem.alignForward(memsize, std.mem.page_size) / std.mem.page_size; |
| ... | ... | @@ -278,7 +290,7 @@ const WasmPageAllocator = struct { |
| 278 | 290 | } |
| 279 | 291 | |
| 280 | 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 | 294 | const prev_page_count = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, n_pages)); |
| 283 | 295 | if (prev_page_count < 0) { |
| 284 | 296 | return error.OutOfMemory; |
| ... | ... | @@ -305,13 +317,28 @@ const WasmPageAllocator = struct { |
| 305 | 317 | } |
| 306 | 318 | |
| 307 | 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); |
| 309 | | if (shrinkage > 0) { |
| 310 | | const success = base.recycle(old_mem[new_size..old_mem.len]); |
| 311 | | if (!success) { |
| 312 | | std.debug.assert(additional.recycle(old_mem[new_size..old_mem.len])); |
| 320 | const free_start = nPages(@ptrToInt(old_mem.ptr) + new_size); |
| 321 | var free_end = nPages(@ptrToInt(old_mem.ptr) + old_mem.len); |
| 322 | |
| 323 | if (free_end > free_start) { |
| 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 | 342 | return old_mem[0..new_size]; |
| 316 | 343 | } |
| 317 | 344 | }; |