authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2020-06-27 22:19:15-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-28 14:25:39-04:00
log374e3e42e0de10d21406c077599cfc4a6a813497
treef40c0330a7d525aaf92352fe99846e9b00af73af
parent581d16154baa3b33ad7c07da07306dd1be346411

WasmPageAllocator: fix bug not aligning allocations


1 files changed, 18 insertions(+), 10 deletions(-)

lib/std/heap.zig+18-10
......@@ -285,7 +285,7 @@ const WasmPageAllocator = struct {
285285 // Revisit if this is settled: https://github.com/ziglang/zig/issues/3806
286286 const not_found = std.math.maxInt(usize);
287287
288 fn useRecycled(self: FreeBlock, num_pages: usize) usize {
288 fn useRecycled(self: FreeBlock, num_pages: usize, alignment: u29) usize {
289289 @setCold(true);
290290 for (self.data) |segment, i| {
291291 const spills_into_next = @bitCast(i128, segment) < 0;
......@@ -298,7 +298,8 @@ const WasmPageAllocator = struct {
298298 var count: usize = 0;
299299 while (j + count < self.totalPages() and self.getBit(j + count) == .free) {
300300 count += 1;
301 if (count >= num_pages) {
301 const addr = j * mem.page_size;
302 if (count >= num_pages and mem.isAligned(addr, alignment)) {
302303 self.setBits(j, num_pages, .used);
303304 return j;
304305 }
......@@ -329,29 +330,36 @@ const WasmPageAllocator = struct {
329330
330331 fn alloc(allocator: *Allocator, len: usize, alignment: u29, len_align: u29) error{OutOfMemory}![]u8 {
331332 const page_count = nPages(len);
332 const page_idx = try allocPages(page_count);
333 const page_idx = try allocPages(page_count, alignment);
333334 return @intToPtr([*]u8, page_idx * mem.page_size)
334335 [0..alignPageAllocLen(page_count * mem.page_size, len, len_align)];
335336 }
336 fn allocPages(page_count: usize) !usize {
337 fn allocPages(page_count: usize, alignment: u29) !usize {
337338 {
338 const idx = conventional.useRecycled(page_count);
339 const idx = conventional.useRecycled(page_count, alignment);
339340 if (idx != FreeBlock.not_found) {
340341 return idx;
341342 }
342343 }
343344
344 const idx = extended.useRecycled(page_count);
345 const idx = extended.useRecycled(page_count, alignment);
345346 if (idx != FreeBlock.not_found) {
346347 return idx + extendedOffset();
347348 }
348349
349 const prev_page_count = @wasmMemoryGrow(0, @intCast(u32, page_count));
350 if (prev_page_count <= 0) {
350 const next_page_idx = @wasmMemorySize(0);
351 const next_page_addr = next_page_idx * mem.page_size;
352 const aligned_addr = mem.alignForward(next_page_addr, alignment);
353 const drop_page_count = @divExact(aligned_addr - next_page_addr, mem.page_size);
354 const result = @wasmMemoryGrow(0, @intCast(u32, drop_page_count + page_count));
355 if (result <= 0)
351356 return error.OutOfMemory;
357 assert(result == next_page_idx);
358 const aligned_page_idx = next_page_idx + drop_page_count;
359 if (drop_page_count > 0) {
360 freePages(next_page_idx, aligned_page_idx);
352361 }
353
354 return @intCast(usize, prev_page_count);
362 return @intCast(usize, aligned_page_idx);
355363 }
356364
357365 fn freePages(start: usize, end: usize) void {