authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2020-06-26 19:29:06-06:00
committergravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2020-06-27 08:57:35-06:00
loga728436992415d1bce44b0c63938f6443a4e9a11
treea650f594eaed11ee0ea45f84824136318c21d678
parentdc9648f868ed8ad08f040753767c03976bbcf3b7

new allocator interface after Andrew Kelley review


6 files changed, 51 insertions(+), 61 deletions(-)

lib/std/array_list.zig-2
...@@ -220,7 +220,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -220,7 +220,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
220 }220 }
221221
222 const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);222 const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
223 assert(new_memory.len >= better_capacity);
224 self.items.ptr = new_memory.ptr;223 self.items.ptr = new_memory.ptr;
225 self.capacity = new_memory.len;224 self.capacity = new_memory.len;
226 }225 }
...@@ -443,7 +442,6 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -443,7 +442,6 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
443 }442 }
444443
445 const new_memory = try allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);444 const new_memory = try allocator.reallocAtLeast(self.allocatedSlice(), better_capacity);
446 assert(new_memory.len >= better_capacity);
447 self.items.ptr = new_memory.ptr;445 self.items.ptr = new_memory.ptr;
448 self.capacity = new_memory.len;446 self.capacity = new_memory.len;
449 }447 }
lib/std/heap.zig+20-22
...@@ -25,7 +25,7 @@ usingnamespace if (comptime @hasDecl(c, "malloc_size")) struct {...@@ -25,7 +25,7 @@ usingnamespace if (comptime @hasDecl(c, "malloc_size")) struct {
25 pub const supports_malloc_size = false;25 pub const supports_malloc_size = false;
26};26};
2727
28pub const c_allocator = mem.getAllocatorPtr(&c_allocator_state);28pub const c_allocator = &c_allocator_state;
29var c_allocator_state = Allocator{29var c_allocator_state = Allocator{
30 .allocFn = cAlloc,30 .allocFn = cAlloc,
31 .resizeFn = cResize,31 .resizeFn = cResize,
...@@ -38,7 +38,7 @@ fn cAlloc(self: *Allocator, len: usize, ptr_align: u29, len_align: u29) Allocato...@@ -38,7 +38,7 @@ fn cAlloc(self: *Allocator, len: usize, ptr_align: u29, len_align: u29) Allocato
38 return ptr[0..len];38 return ptr[0..len];
39 }39 }
40 const full_len = init: {40 const full_len = init: {
41 if (comptime supports_malloc_size) {41 if (supports_malloc_size) {
42 const s = malloc_size(ptr);42 const s = malloc_size(ptr);
43 assert(s >= len);43 assert(s >= len);
44 break :init s;44 break :init s;
...@@ -56,24 +56,23 @@ fn cResize(self: *Allocator, buf: []u8, new_len: usize, len_align: u29) Allocato...@@ -56,24 +56,23 @@ fn cResize(self: *Allocator, buf: []u8, new_len: usize, len_align: u29) Allocato
56 if (new_len <= buf.len) {56 if (new_len <= buf.len) {
57 return mem.alignAllocLen(buf.len, new_len, len_align);57 return mem.alignAllocLen(buf.len, new_len, len_align);
58 }58 }
59 if (comptime supports_malloc_size) {59 if (supports_malloc_size) {
60 const full_len = malloc_size(buf.ptr);60 const full_len = malloc_size(buf.ptr);
61 if (new_len <= full_len) {61 if (new_len <= full_len) {
62 return mem.alignAllocLen(full_len, new_len, len_align);62 return mem.alignAllocLen(full_len, new_len, len_align);
63 }63 }
64 }64 }
65 // TODO: could we still use realloc? are there any cases where we can guarantee that realloc won't move memory?
66 return error.OutOfMemory;65 return error.OutOfMemory;
67}66}
6867
69/// This allocator makes a syscall directly for every allocation and free.68/// This allocator makes a syscall directly for every allocation and free.
70/// Thread-safe and lock-free.69/// Thread-safe and lock-free.
71pub const page_allocator = if (std.Target.current.isWasm())70pub const page_allocator = if (std.Target.current.isWasm())
72 mem.getAllocatorPtr(&wasm_page_allocator_state)71 &wasm_page_allocator_state
73else if (std.Target.current.os.tag == .freestanding)72else if (std.Target.current.os.tag == .freestanding)
74 root.os.heap.page_allocator73 root.os.heap.page_allocator
75else74else
76 mem.getAllocatorPtr(&page_allocator_state);75 &page_allocator_state;
7776
78var page_allocator_state = Allocator{77var page_allocator_state = Allocator{
79 .allocFn = PageAllocator.alloc,78 .allocFn = PageAllocator.alloc,
...@@ -507,9 +506,9 @@ pub const FixedBufferAllocator = struct {...@@ -507,9 +506,9 @@ pub const FixedBufferAllocator = struct {
507 return sliceContainsSlice(self.buffer, slice);506 return sliceContainsSlice(self.buffer, slice);
508 }507 }
509508
510 // NOTE: this will not work in all cases, if the last allocation had an adjusted_index509 /// NOTE: this will not work in all cases, if the last allocation had an adjusted_index
511 // then we won't be able to determine what the last allocation was. This is because510 /// then we won't be able to determine what the last allocation was. This is because
512 // the alignForward operation done in alloc is not reverisible.511 /// the alignForward operation done in alloc is not reverisible.
513 pub fn isLastAllocation(self: *FixedBufferAllocator, buf: []u8) bool {512 pub fn isLastAllocation(self: *FixedBufferAllocator, buf: []u8) bool {
514 return buf.ptr + buf.len == self.buffer.ptr + self.end_index;513 return buf.ptr + buf.len == self.buffer.ptr + self.end_index;
515 }514 }
...@@ -525,7 +524,7 @@ pub const FixedBufferAllocator = struct {...@@ -525,7 +524,7 @@ pub const FixedBufferAllocator = struct {
525 const result = self.buffer[adjusted_index..new_end_index];524 const result = self.buffer[adjusted_index..new_end_index];
526 self.end_index = new_end_index;525 self.end_index = new_end_index;
527526
528 return result[0..mem.alignAllocLen(result.len, n, len_align)];527 return result;
529 }528 }
530529
531 fn resize(allocator: *Allocator, buf: []u8, new_size: usize, len_align: u29) Allocator.Error!usize {530 fn resize(allocator: *Allocator, buf: []u8, new_size: usize, len_align: u29) Allocator.Error!usize {
...@@ -544,13 +543,12 @@ pub const FixedBufferAllocator = struct {...@@ -544,13 +543,12 @@ pub const FixedBufferAllocator = struct {
544 return if (new_size == 0) 0 else mem.alignAllocLen(buf.len - sub, new_size, len_align);543 return if (new_size == 0) 0 else mem.alignAllocLen(buf.len - sub, new_size, len_align);
545 }544 }
546545
547 var add = new_size - buf.len;546 const add = new_size - buf.len;
548 if (add + self.end_index > self.buffer.len) {547 if (add + self.end_index > self.buffer.len) {
549 //add = self.buffer.len - self.end_index;
550 return error.OutOfMemory;548 return error.OutOfMemory;
551 }549 }
552 self.end_index += add;550 self.end_index += add;
553 return mem.alignAllocLen(buf.len + add, new_size, len_align);551 return new_size;
554 }552 }
555553
556 pub fn reset(self: *FixedBufferAllocator) void {554 pub fn reset(self: *FixedBufferAllocator) void {
...@@ -735,7 +733,7 @@ test "ArenaAllocator" {...@@ -735,7 +733,7 @@ test "ArenaAllocator" {
735733
736var test_fixed_buffer_allocator_memory: [800000 * @sizeOf(u64)]u8 = undefined;734var test_fixed_buffer_allocator_memory: [800000 * @sizeOf(u64)]u8 = undefined;
737test "FixedBufferAllocator" {735test "FixedBufferAllocator" {
738 var fixed_buffer_allocator = mem.sanityWrap(FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]));736 var fixed_buffer_allocator = mem.validationWrap(FixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]));
739737
740 try testAllocator(&fixed_buffer_allocator.allocator);738 try testAllocator(&fixed_buffer_allocator.allocator);
741 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);739 try testAllocatorAligned(&fixed_buffer_allocator.allocator, 16);
...@@ -802,8 +800,8 @@ test "ThreadSafeFixedBufferAllocator" {...@@ -802,8 +800,8 @@ test "ThreadSafeFixedBufferAllocator" {
802}800}
803801
804fn testAllocator(base_allocator: *mem.Allocator) !void {802fn testAllocator(base_allocator: *mem.Allocator) !void {
805 var sanityAllocator = mem.sanityWrap(base_allocator);803 var validationAllocator = mem.validationWrap(base_allocator);
806 const allocator = &sanityAllocator.allocator;804 const allocator = &validationAllocator.allocator;
807805
808 var slice = try allocator.alloc(*i32, 100);806 var slice = try allocator.alloc(*i32, 100);
809 testing.expect(slice.len == 100);807 testing.expect(slice.len == 100);
...@@ -833,8 +831,8 @@ fn testAllocator(base_allocator: *mem.Allocator) !void {...@@ -833,8 +831,8 @@ fn testAllocator(base_allocator: *mem.Allocator) !void {
833}831}
834832
835fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29) !void {833fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29) !void {
836 var sanityAllocator = mem.sanityWrap(base_allocator);834 var validationAllocator = mem.validationWrap(base_allocator);
837 const allocator = &sanityAllocator.allocator;835 const allocator = &validationAllocator.allocator;
838836
839 // initial837 // initial
840 var slice = try allocator.alignedAlloc(u8, alignment, 10);838 var slice = try allocator.alignedAlloc(u8, alignment, 10);
...@@ -860,8 +858,8 @@ fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29)...@@ -860,8 +858,8 @@ fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29)
860}858}
861859
862fn testAllocatorLargeAlignment(base_allocator: *mem.Allocator) mem.Allocator.Error!void {860fn testAllocatorLargeAlignment(base_allocator: *mem.Allocator) mem.Allocator.Error!void {
863 var sanityAllocator = mem.sanityWrap(base_allocator);861 var validationAllocator = mem.validationWrap(base_allocator);
864 const allocator = &sanityAllocator.allocator;862 const allocator = &validationAllocator.allocator;
865863
866 //Maybe a platform's page_size is actually the same as or864 //Maybe a platform's page_size is actually the same as or
867 // very near usize?865 // very near usize?
...@@ -892,8 +890,8 @@ fn testAllocatorLargeAlignment(base_allocator: *mem.Allocator) mem.Allocator.Err...@@ -892,8 +890,8 @@ fn testAllocatorLargeAlignment(base_allocator: *mem.Allocator) mem.Allocator.Err
892}890}
893891
894fn testAllocatorAlignedShrink(base_allocator: *mem.Allocator) mem.Allocator.Error!void {892fn testAllocatorAlignedShrink(base_allocator: *mem.Allocator) mem.Allocator.Error!void {
895 var sanityAllocator = mem.sanityWrap(base_allocator);893 var validationAllocator = mem.validationWrap(base_allocator);
896 const allocator = &sanityAllocator.allocator;894 const allocator = &validationAllocator.allocator;
897895
898 var debug_buffer: [1000]u8 = undefined;896 var debug_buffer: [1000]u8 = undefined;
899 const debug_allocator = &FixedBufferAllocator.init(&debug_buffer).allocator;897 const debug_allocator = &FixedBufferAllocator.init(&debug_buffer).allocator;
lib/std/heap/arena_allocator.zig+1-1
...@@ -77,7 +77,7 @@ pub const ArenaAllocator = struct {...@@ -77,7 +77,7 @@ pub const ArenaAllocator = struct {
77 }77 }
78 const result = cur_buf[adjusted_index..new_end_index];78 const result = cur_buf[adjusted_index..new_end_index];
79 self.state.end_index = new_end_index;79 self.state.end_index = new_end_index;
80 return result[0..mem.alignAllocLen(result.len, n, len_align)];80 return result;
81 }81 }
82 }82 }
83};83};
lib/std/heap/logging_allocator.zig+1-1
...@@ -70,7 +70,7 @@ test "LoggingAllocator" {...@@ -70,7 +70,7 @@ test "LoggingAllocator" {
70 var fbs = std.io.fixedBufferStream(&log_buf);70 var fbs = std.io.fixedBufferStream(&log_buf);
7171
72 var allocator_buf: [10]u8 = undefined;72 var allocator_buf: [10]u8 = undefined;
73 var fixedBufferAllocator = std.mem.sanityWrap(std.heap.FixedBufferAllocator.init(&allocator_buf));73 var fixedBufferAllocator = std.mem.validationWrap(std.heap.FixedBufferAllocator.init(&allocator_buf));
74 const allocator = &loggingAllocator(&fixedBufferAllocator.allocator, fbs.outStream()).allocator;74 const allocator = &loggingAllocator(&fixedBufferAllocator.allocator, fbs.outStream()).allocator;
7575
76 var a = try allocator.alloc(u8, 10);76 var a = try allocator.alloc(u8, 10);
lib/std/mem.zig+28-34
...@@ -141,6 +141,9 @@ pub const Allocator = struct {...@@ -141,6 +141,9 @@ pub const Allocator = struct {
141 const new_mem = try self.callAllocFn(new_len, new_alignment, len_align);141 const new_mem = try self.callAllocFn(new_len, new_alignment, len_align);
142 @memcpy(new_mem.ptr, old_mem.ptr, std.math.min(new_len, old_mem.len));142 @memcpy(new_mem.ptr, old_mem.ptr, std.math.min(new_len, old_mem.len));
143 // DISABLED TO AVOID BUGS IN TRANSLATE C143 // DISABLED TO AVOID BUGS IN TRANSLATE C
144 // use './zig build test-translate-c' to reproduce, some of the symbols in the
145 // generated C code will be a sequence of 0xaa (the undefined value), meaning
146 // it is printing data that has been freed
144 //@memset(old_mem.ptr, undefined, old_mem.len);147 //@memset(old_mem.ptr, undefined, old_mem.len);
145 _ = self.shrinkBytes(old_mem, 0, 0);148 _ = self.shrinkBytes(old_mem, 0, 0);
146 return new_mem;149 return new_mem;
...@@ -214,6 +217,7 @@ pub const Allocator = struct {...@@ -214,6 +217,7 @@ pub const Allocator = struct {
214 return self.allocWithOptions(Elem, n, null, sentinel);217 return self.allocWithOptions(Elem, n, null, sentinel);
215 }218 }
216219
220 /// Deprecated: use `allocAdvanced`
217 pub fn alignedAlloc(221 pub fn alignedAlloc(
218 self: *Allocator,222 self: *Allocator,
219 comptime T: type,223 comptime T: type,
...@@ -221,11 +225,11 @@ pub const Allocator = struct {...@@ -221,11 +225,11 @@ pub const Allocator = struct {
221 comptime alignment: ?u29,225 comptime alignment: ?u29,
222 n: usize,226 n: usize,
223 ) Error![]align(alignment orelse @alignOf(T)) T {227 ) Error![]align(alignment orelse @alignOf(T)) T {
224 return self.alignedAlloc2(T, alignment, n, .exact);228 return self.allocAdvanced(T, alignment, n, .exact);
225 }229 }
226230
227 const Exact = enum {exact,atLeast};231 const Exact = enum {exact,at_least};
228 pub fn alignedAlloc2(232 pub fn allocAdvanced(
229 self: *Allocator,233 self: *Allocator,
230 comptime T: type,234 comptime T: type,
231 /// null means naturally aligned235 /// null means naturally aligned
...@@ -234,7 +238,7 @@ pub const Allocator = struct {...@@ -234,7 +238,7 @@ pub const Allocator = struct {
234 exact: Exact,238 exact: Exact,
235 ) Error![]align(alignment orelse @alignOf(T)) T {239 ) Error![]align(alignment orelse @alignOf(T)) T {
236 const a = if (alignment) |a| blk: {240 const a = if (alignment) |a| blk: {
237 if (a == @alignOf(T)) return alignedAlloc2(self, T, null, n, exact);241 if (a == @alignOf(T)) return allocAdvanced(self, T, null, n, exact);
238 break :blk a;242 break :blk a;
239 } else @alignOf(T);243 } else @alignOf(T);
240244
...@@ -248,7 +252,10 @@ pub const Allocator = struct {...@@ -248,7 +252,10 @@ pub const Allocator = struct {
248 // functions that heap-allocate their own frame with @Frame(func).252 // functions that heap-allocate their own frame with @Frame(func).
249 const sizeOfT = if (alignment == null) @intCast(u29, @divExact(byte_count, n)) else @sizeOf(T);253 const sizeOfT = if (alignment == null) @intCast(u29, @divExact(byte_count, n)) else @sizeOf(T);
250 const byte_slice = try self.callAllocFn(byte_count, a, if (exact == .exact) @as(u29, 0) else sizeOfT);254 const byte_slice = try self.callAllocFn(byte_count, a, if (exact == .exact) @as(u29, 0) else sizeOfT);
251 assert(if (exact == .exact) byte_slice.len == byte_count else byte_slice.len >= byte_count);255 switch (exact) {
256 .exact => assert(byte_slice.len == byte_count),
257 .at_least => assert(byte_slice.len >= byte_count),
258 }
252 @memset(byte_slice.ptr, undefined, byte_slice.len);259 @memset(byte_slice.ptr, undefined, byte_slice.len);
253 if (alignment == null) {260 if (alignment == null) {
254 // This if block is a workaround (see comment above)261 // This if block is a workaround (see comment above)
...@@ -273,7 +280,7 @@ pub const Allocator = struct {...@@ -273,7 +280,7 @@ pub const Allocator = struct {
273 break :t Error![]align(Slice.alignment) Slice.child;280 break :t Error![]align(Slice.alignment) Slice.child;
274 } {281 } {
275 const old_alignment = @typeInfo(@TypeOf(old_mem)).Pointer.alignment;282 const old_alignment = @typeInfo(@TypeOf(old_mem)).Pointer.alignment;
276 return self.alignedRealloc2(old_mem, old_alignment, new_n, .exact);283 return self.reallocAdvanced(old_mem, old_alignment, new_n, .exact);
277 }284 }
278285
279 pub fn reallocAtLeast(self: *Allocator, old_mem: var, new_n: usize) t: {286 pub fn reallocAtLeast(self: *Allocator, old_mem: var, new_n: usize) t: {
...@@ -281,25 +288,23 @@ pub const Allocator = struct {...@@ -281,25 +288,23 @@ pub const Allocator = struct {
281 break :t Error![]align(Slice.alignment) Slice.child;288 break :t Error![]align(Slice.alignment) Slice.child;
282 } {289 } {
283 const old_alignment = @typeInfo(@TypeOf(old_mem)).Pointer.alignment;290 const old_alignment = @typeInfo(@TypeOf(old_mem)).Pointer.alignment;
284 return self.alignedRealloc2(old_mem, old_alignment, new_n, .atLeast);291 return self.reallocAdvanced(old_mem, old_alignment, new_n, .at_least);
285 }292 }
286293
287 /// This is the same as `realloc`, except caller may additionally request294 // Deprecated: use `reallocAdvanced`
288 /// a new alignment, which can be larger, smaller, or the same as the old
289 /// allocation.
290 pub fn alignedRealloc(295 pub fn alignedRealloc(
291 self: *Allocator,296 self: *Allocator,
292 old_mem: var,297 old_mem: var,
293 comptime new_alignment: u29,298 comptime new_alignment: u29,
294 new_n: usize,299 new_n: usize,
295 ) Error![]align(new_alignment) @typeInfo(@TypeOf(old_mem)).Pointer.child {300 ) Error![]align(new_alignment) @typeInfo(@TypeOf(old_mem)).Pointer.child {
296 return self.alignedRealloc2(old_mem, new_alignment, new_n, .exact);301 return self.reallocAdvanced(old_mem, new_alignment, new_n, .exact);
297 }302 }
298303
299 /// This is the same as `realloc`, except caller may additionally request304 /// This is the same as `realloc`, except caller may additionally request
300 /// a new alignment, which can be larger, smaller, or the same as the old305 /// a new alignment, which can be larger, smaller, or the same as the old
301 /// allocation.306 /// allocation.
302 pub fn alignedRealloc2(307 pub fn reallocAdvanced(
303 self: *Allocator,308 self: *Allocator,
304 old_mem: var,309 old_mem: var,
305 comptime new_alignment: u29,310 comptime new_alignment: u29,
...@@ -309,7 +314,7 @@ pub const Allocator = struct {...@@ -309,7 +314,7 @@ pub const Allocator = struct {
309 const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;314 const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
310 const T = Slice.child;315 const T = Slice.child;
311 if (old_mem.len == 0) {316 if (old_mem.len == 0) {
312 return self.alignedAlloc2(T, new_alignment, new_n, exact);317 return self.allocAdvanced(T, new_alignment, new_n, exact);
313 }318 }
314 if (new_n == 0) {319 if (new_n == 0) {
315 self.free(old_mem);320 self.free(old_mem);
...@@ -392,24 +397,9 @@ pub const Allocator = struct {...@@ -392,24 +397,9 @@ pub const Allocator = struct {
392 }397 }
393};398};
394399
395/// Given a pointer to an allocator, return the *Allocator for it. `allocatorStatePtr` can400/// Detects and asserts if the std.mem.Allocator interface is violated by the caller
396/// either be a `*Allocator`, in which case it is returned as-is, otherwise, the address of401/// or the allocator.
397/// the `allocator` field is returned.402pub fn ValidationAllocator(comptime T: type) type { return struct {
398pub fn getAllocatorPtr(allocatorStatePtr: var) *Allocator {
399 // allocator must be a pointer or else this function will return a copy of the allocator which
400 // is not what this is for
401 const T = @TypeOf(allocatorStatePtr);
402 switch (@typeInfo(T)) {
403 .Pointer => {},
404 else => @compileError("getAllocatorPtr expects a pointer to an allocator but got: " ++ @typeName(T)),
405 }
406 if (T == *Allocator)
407 return allocatorStatePtr;
408 return &allocatorStatePtr.allocator;
409}
410
411/// Detects and asserts if the std.mem.Allocator interface is violated
412pub fn SanityAllocator(comptime T: type) type { return struct {
413 const Self = @This();403 const Self = @This();
414 allocator: Allocator,404 allocator: Allocator,
415 underlying_allocator: T,405 underlying_allocator: T,
...@@ -424,7 +414,8 @@ pub fn SanityAllocator(comptime T: type) type { return struct {...@@ -424,7 +414,8 @@ pub fn SanityAllocator(comptime T: type) type { return struct {
424 }414 }
425 fn getUnderlyingAllocatorPtr(self: *@This()) *Allocator {415 fn getUnderlyingAllocatorPtr(self: *@This()) *Allocator {
426 if (T == *Allocator) return self.underlying_allocator;416 if (T == *Allocator) return self.underlying_allocator;
427 return getAllocatorPtr(&self.underlying_allocator);417 if (*T == *Allocator) return &self.underlying_allocator;
418 return &self.underlying_allocator.allocator;
428 }419 }
429 pub fn alloc(allocator: *Allocator, n: usize, ptr_align: u29, len_align: u29) Allocator.Error![]u8 {420 pub fn alloc(allocator: *Allocator, n: usize, ptr_align: u29, len_align: u29) Allocator.Error![]u8 {
430 assert(n > 0);421 assert(n > 0);
...@@ -436,6 +427,7 @@ pub fn SanityAllocator(comptime T: type) type { return struct {...@@ -436,6 +427,7 @@ pub fn SanityAllocator(comptime T: type) type { return struct {
436427
437 const self = @fieldParentPtr(@This(), "allocator", allocator);428 const self = @fieldParentPtr(@This(), "allocator", allocator);
438 const result = try self.getUnderlyingAllocatorPtr().callAllocFn(n, ptr_align, len_align);429 const result = try self.getUnderlyingAllocatorPtr().callAllocFn(n, ptr_align, len_align);
430 assert(mem.isAligned(@ptrToInt(result.ptr), ptr_align));
439 if (len_align == 0) {431 if (len_align == 0) {
440 assert(result.len == n);432 assert(result.len == n);
441 } else {433 } else {
...@@ -467,8 +459,8 @@ pub fn SanityAllocator(comptime T: type) type { return struct {...@@ -467,8 +459,8 @@ pub fn SanityAllocator(comptime T: type) type { return struct {
467 };459 };
468};}460};}
469461
470pub fn sanityWrap(allocator: var) SanityAllocator(@TypeOf(allocator)) {462pub fn validationWrap(allocator: var) ValidationAllocator(@TypeOf(allocator)) {
471 return SanityAllocator(@TypeOf(allocator)).init(allocator);463 return ValidationAllocator(@TypeOf(allocator)).init(allocator);
472}464}
473465
474/// An allocator helper function. Adjusts an allocation length satisfy `len_align`.466/// An allocator helper function. Adjusts an allocation length satisfy `len_align`.
...@@ -2377,6 +2369,8 @@ test "alignForward" {...@@ -2377,6 +2369,8 @@ test "alignForward" {
2377 testing.expect(alignForward(17, 8) == 24);2369 testing.expect(alignForward(17, 8) == 24);
2378}2370}
23792371
2372/// Round an address up to the previous aligned address
2373/// Unlike `alignBackward`, `alignment` can be any positive number, not just a power of 2.
2380pub fn alignBackwardAnyAlign(i: usize, alignment: usize) usize {2374pub fn alignBackwardAnyAlign(i: usize, alignment: usize) usize {
2381 if (@popCount(usize, alignment) == 1)2375 if (@popCount(usize, alignment) == 1)
2382 return alignBackward(i, alignment);2376 return alignBackward(i, alignment);
lib/std/testing.zig+1-1
...@@ -11,7 +11,7 @@ pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.al...@@ -11,7 +11,7 @@ pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.al
11pub const failing_allocator = &failing_allocator_instance.allocator;11pub const failing_allocator = &failing_allocator_instance.allocator;
12pub var failing_allocator_instance = FailingAllocator.init(&base_allocator_instance.allocator, 0);12pub var failing_allocator_instance = FailingAllocator.init(&base_allocator_instance.allocator, 0);
1313
14pub var base_allocator_instance = std.mem.sanityWrap(std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]));14pub var base_allocator_instance = std.mem.validationWrap(std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]));
15var allocator_mem: [2 * 1024 * 1024]u8 = undefined;15var allocator_mem: [2 * 1024 * 1024]u8 = undefined;
1616
17/// This function is intended to be used only in tests. It prints diagnostics to stderr17/// This function is intended to be used only in tests. It prints diagnostics to stderr