| ... | @@ -102,8 +102,8 @@ pub inline fn rawFree(self: Allocator, buf: []u8, log2_buf_align: u8, ret_addr: | ... | @@ -102,8 +102,8 @@ pub inline fn rawFree(self: Allocator, buf: []u8, log2_buf_align: u8, ret_addr: |
| 102 | /// Call `destroy` with the result to free the memory. | 102 | /// Call `destroy` with the result to free the memory. |
| 103 | pub fn create(self: Allocator, comptime T: type) Error!*T { | 103 | pub fn create(self: Allocator, comptime T: type) Error!*T { |
| 104 | if (@sizeOf(T) == 0) return @as(*T, @ptrFromInt(math.maxInt(usize))); | 104 | if (@sizeOf(T) == 0) return @as(*T, @ptrFromInt(math.maxInt(usize))); |
| 105 | const slice = try self.allocAdvancedWithRetAddr(T, null, 1, @returnAddress()); | 105 | const ptr: *T = @ptrCast(try self.allocBytesWithAlignment(@alignOf(T), @sizeOf(T), @returnAddress())); |
| 106 | return &slice[0]; | 106 | return ptr; |
| 107 | } | 107 | } |
| 108 | | 108 | |
| 109 | /// `ptr` should be the return value of `create`, or otherwise | 109 | /// `ptr` should be the return value of `create`, or otherwise |
| ... | @@ -113,7 +113,7 @@ pub fn destroy(self: Allocator, ptr: anytype) void { | ... | @@ -113,7 +113,7 @@ pub fn destroy(self: Allocator, ptr: anytype) void { |
| 113 | const T = info.child; | 113 | const T = info.child; |
| 114 | if (@sizeOf(T) == 0) return; | 114 | if (@sizeOf(T) == 0) return; |
| 115 | const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr))); | 115 | const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr))); |
| 116 | self.rawFree(non_const_ptr[0..@sizeOf(T)], math.log2(info.alignment), @returnAddress()); | 116 | self.rawFree(non_const_ptr[0..@sizeOf(T)], log2a(info.alignment), @returnAddress()); |
| 117 | } | 117 | } |
| 118 | | 118 | |
| 119 | /// Allocates an array of `n` items of type `T` and sets all the | 119 | /// Allocates an array of `n` items of type `T` and sets all the |
| ... | @@ -192,7 +192,7 @@ pub fn alignedAlloc( | ... | @@ -192,7 +192,7 @@ pub fn alignedAlloc( |
| 192 | return self.allocAdvancedWithRetAddr(T, alignment, n, @returnAddress()); | 192 | return self.allocAdvancedWithRetAddr(T, alignment, n, @returnAddress()); |
| 193 | } | 193 | } |
| 194 | | 194 | |
| 195 | pub fn allocAdvancedWithRetAddr( | 195 | pub inline fn allocAdvancedWithRetAddr( |
| 196 | self: Allocator, | 196 | self: Allocator, |
| 197 | comptime T: type, | 197 | comptime T: type, |
| 198 | /// null means naturally aligned | 198 | /// null means naturally aligned |
| ... | @@ -201,23 +201,30 @@ pub fn allocAdvancedWithRetAddr( | ... | @@ -201,23 +201,30 @@ pub fn allocAdvancedWithRetAddr( |
| 201 | return_address: usize, | 201 | return_address: usize, |
| 202 | ) Error![]align(alignment orelse @alignOf(T)) T { | 202 | ) Error![]align(alignment orelse @alignOf(T)) T { |
| 203 | const a = alignment orelse @alignOf(T); | 203 | const a = alignment orelse @alignOf(T); |
| | 204 | const ptr: [*]align(a) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address)); |
| | 205 | return ptr[0..n]; |
| | 206 | } |
| | 207 | |
| | 208 | fn allocWithSizeAndAlignment(self: Allocator, comptime size: usize, comptime alignment: u29, n: usize, return_address: usize) Error![*]align(alignment) u8 { |
| | 209 | const byte_count = math.mul(usize, size, n) catch return Error.OutOfMemory; |
| | 210 | return self.allocBytesWithAlignment(alignment, byte_count, return_address); |
| | 211 | } |
| 204 | | 212 | |
| | 213 | fn allocBytesWithAlignment(self: Allocator, comptime alignment: u29, byte_count: usize, return_address: usize) Error![*]align(alignment) u8 { |
| 205 | // The Zig Allocator interface is not intended to solve alignments beyond | 214 | // The Zig Allocator interface is not intended to solve alignments beyond |
| 206 | // the minimum OS page size. For these use cases, the caller must use OS | 215 | // the minimum OS page size. For these use cases, the caller must use OS |
| 207 | // APIs directly. | 216 | // APIs directly. |
| 208 | comptime assert(a <= mem.page_size); | 217 | comptime assert(alignment <= mem.page_size); |
| 209 | | 218 | |
| 210 | if (n == 0) { | 219 | if (byte_count == 0) { |
| 211 | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), a); | 220 | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment); |
| 212 | return @as([*]align(a) T, @ptrFromInt(ptr))[0..0]; | 221 | return @as([*]align(alignment) u8, @ptrFromInt(ptr)); |
| 213 | } | 222 | } |
| 214 | | 223 | |
| 215 | const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory; | 224 | const byte_ptr = self.rawAlloc(byte_count, log2a(alignment), return_address) orelse return Error.OutOfMemory; |
| 216 | const byte_ptr = self.rawAlloc(byte_count, log2a(a), return_address) orelse return Error.OutOfMemory; | | |
| 217 | // TODO: https://github.com/ziglang/zig/issues/4298 | 225 | // TODO: https://github.com/ziglang/zig/issues/4298 |
| 218 | @memset(byte_ptr[0..byte_count], undefined); | 226 | @memset(byte_ptr[0..byte_count], undefined); |
| 219 | const byte_slice: []align(a) u8 = @alignCast(byte_ptr[0..byte_count]); | 227 | return @as([*]align(alignment) u8, @alignCast(byte_ptr)); |
| 220 | return mem.bytesAsSlice(T, byte_slice); | | |
| 221 | } | 228 | } |
| 222 | | 229 | |
| 223 | /// Requests to modify the size of an allocation. It is guaranteed to not move | 230 | /// Requests to modify the size of an allocation. It is guaranteed to not move |