From 57f545eed8e940520855c127245414db9ea29310 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 25 Apr 2019 13:35:45 -0700 Subject: [PATCH 1/2] std.heap.DirectAllocator: reduce the amount of redundant memcpy calls on Windows Previously the memory would be copied to a different aligned address in some cases where the old offset could have been used. This fixes it so that it will always try to use the old offset when possible, and only uses a different offset if the old one is truly invalid (not aligned or not enough space to store the alloc at the old offset). --- std/heap.zig | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/std/heap.zig b/std/heap.zig index 1e539bf4b1..27f16d0391 100644 --- a/std/heap.zig +++ b/std/heap.zig @@ -170,16 +170,20 @@ pub const DirectAllocator = struct { ) orelse return error.OutOfMemory; const offset = old_adjusted_addr - root_addr; const new_root_addr = @ptrToInt(new_ptr); - const adjusted_addr = new_root_addr + offset; - const new_adjusted_addr = mem.alignForward(new_root_addr, new_align); - // If HeapReAlloc didn't happen to move the memory to the new alignment - // then we need to copy it - if (new_adjusted_addr != adjusted_addr) { + var new_adjusted_addr = new_root_addr + offset; + const offset_is_valid = new_adjusted_addr + new_size + @sizeOf(usize) <= new_root_addr + amt; + const offset_is_aligned = new_adjusted_addr % new_align == 0; + if (!offset_is_valid or !offset_is_aligned) { + // If HeapReAlloc didn't happen to move the memory to the new alignment, + // or the memory starting at the old offset would be outside of the new allocation, + // then we need to copy the memory to a valid aligned address and use that + const new_aligned_addr = mem.alignForward(new_root_addr, new_align); @memcpy( + @intToPtr([*]u8, new_aligned_addr), @intToPtr([*]u8, new_adjusted_addr), - @intToPtr([*]u8, adjusted_addr), std.math.min(old_mem.len, new_size), ); + new_adjusted_addr = new_aligned_addr; } const new_record_addr = new_adjusted_addr + new_size; @intToPtr(*align(1) usize, new_record_addr).* = new_root_addr; From afc33f00ee65bfefa173200e4ec8c0f329172d3f Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 25 Apr 2019 13:41:19 -0700 Subject: [PATCH 2/2] heap: fixup style of realloc memory copies --- std/heap.zig | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/std/heap.zig b/std/heap.zig index 27f16d0391..239a65961a 100644 --- a/std/heap.zig +++ b/std/heap.zig @@ -139,11 +139,7 @@ pub const DirectAllocator = struct { return shrink(allocator, old_mem, old_align, new_size, new_align); } const result = try alloc(allocator, new_size, new_align); - if (result.len >= old_mem.len) { - mem.copy(u8, result, old_mem); - } else { - @memcpy(result.ptr, old_mem.ptr, new_size); - } + @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); _ = os.posix.munmap(@ptrToInt(old_mem.ptr), old_mem.len); return result; }, @@ -274,11 +270,7 @@ pub const ArenaAllocator = struct { return error.OutOfMemory; } else { const result = try alloc(allocator, new_size, new_align); - if (result.len >= old_mem.len) { - mem.copy(u8, result, old_mem); - } else { - @memcpy(result.ptr, old_mem.ptr, new_size); - } + @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); return result; } } @@ -336,11 +328,7 @@ pub const FixedBufferAllocator = struct { return error.OutOfMemory; } else { const result = try alloc(allocator, new_size, new_align); - if (result.len >= old_mem.len) { - mem.copy(u8, result, old_mem); - } else { - @memcpy(result.ptr, old_mem.ptr, new_size); - } + @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); return result; } } @@ -483,11 +471,7 @@ pub const ThreadSafeFixedBufferAllocator = blk: { return error.OutOfMemory; } else { const result = try alloc(allocator, new_size, new_align); - if (result.len >= old_mem.len) { - mem.copy(u8, result, old_mem); - } else { - @memcpy(result.ptr, old_mem.ptr, new_size); - } + @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len)); return result; } }