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