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 {...@@ -285,7 +285,7 @@ const WasmPageAllocator = struct {
285 // Revisit if this is settled: https://github.com/ziglang/zig/issues/3806285 // Revisit if this is settled: https://github.com/ziglang/zig/issues/3806
286 const not_found = std.math.maxInt(usize);286 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 {
289 @setCold(true);289 @setCold(true);
290 for (self.data) |segment, i| {290 for (self.data) |segment, i| {
291 const spills_into_next = @bitCast(i128, segment) < 0;291 const spills_into_next = @bitCast(i128, segment) < 0;
...@@ -298,7 +298,8 @@ const WasmPageAllocator = struct {...@@ -298,7 +298,8 @@ const WasmPageAllocator = struct {
298 var count: usize = 0;298 var count: usize = 0;
299 while (j + count < self.totalPages() and self.getBit(j + count) == .free) {299 while (j + count < self.totalPages() and self.getBit(j + count) == .free) {
300 count += 1;300 count += 1;
301 if (count >= num_pages) {301 const addr = j * mem.page_size;
302 if (count >= num_pages and mem.isAligned(addr, alignment)) {
302 self.setBits(j, num_pages, .used);303 self.setBits(j, num_pages, .used);
303 return j;304 return j;
304 }305 }
...@@ -329,29 +330,36 @@ const WasmPageAllocator = struct {...@@ -329,29 +330,36 @@ const WasmPageAllocator = struct {
329330
330 fn alloc(allocator: *Allocator, len: usize, alignment: u29, len_align: u29) error{OutOfMemory}![]u8 {331 fn alloc(allocator: *Allocator, len: usize, alignment: u29, len_align: u29) error{OutOfMemory}![]u8 {
331 const page_count = nPages(len);332 const page_count = nPages(len);
332 const page_idx = try allocPages(page_count);333 const page_idx = try allocPages(page_count, alignment);
333 return @intToPtr([*]u8, page_idx * mem.page_size)334 return @intToPtr([*]u8, page_idx * mem.page_size)
334 [0..alignPageAllocLen(page_count * mem.page_size, len, len_align)];335 [0..alignPageAllocLen(page_count * mem.page_size, len, len_align)];
335 }336 }
336 fn allocPages(page_count: usize) !usize {337 fn allocPages(page_count: usize, alignment: u29) !usize {
337 {338 {
338 const idx = conventional.useRecycled(page_count);339 const idx = conventional.useRecycled(page_count, alignment);
339 if (idx != FreeBlock.not_found) {340 if (idx != FreeBlock.not_found) {
340 return idx;341 return idx;
341 }342 }
342 }343 }
343344
344 const idx = extended.useRecycled(page_count);345 const idx = extended.useRecycled(page_count, alignment);
345 if (idx != FreeBlock.not_found) {346 if (idx != FreeBlock.not_found) {
346 return idx + extendedOffset();347 return idx + extendedOffset();
347 }348 }
348349
349 const prev_page_count = @wasmMemoryGrow(0, @intCast(u32, page_count));350 const next_page_idx = @wasmMemorySize(0);
350 if (prev_page_count <= 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)
351 return error.OutOfMemory;356 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);
352 }361 }
353362 return @intCast(usize, aligned_page_idx);
354 return @intCast(usize, prev_page_count);
355 }363 }
356364
357 fn freePages(start: usize, end: usize) void {365 fn freePages(start: usize, end: usize) void {