| ... | @@ -179,7 +179,11 @@ pub fn destroy(self: Allocator, ptr: anytype) void { | ... | @@ -179,7 +179,11 @@ pub fn destroy(self: Allocator, ptr: anytype) void { |
| 179 | const T = info.child; | 179 | const T = info.child; |
| 180 | if (@sizeOf(T) == 0) return; | 180 | if (@sizeOf(T) == 0) return; |
| 181 | const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr))); | 181 | const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr))); |
| 182 | self.rawFree(non_const_ptr[0..@sizeOf(T)], .fromByteUnits(info.alignment), @returnAddress()); | 182 | self.rawFree( |
| | 183 | non_const_ptr[0..@sizeOf(T)], |
| | 184 | .fromByteUnits(info.alignment orelse @alignOf(T)), |
| | 185 | @returnAddress(), |
| | 186 | ); |
| 183 | } | 187 | } |
| 184 | | 188 | |
| 185 | /// Allocates an array of `n` items of type `T` and sets all the | 189 | /// Allocates an array of `n` items of type `T` and sets all the |
| ... | @@ -266,7 +270,7 @@ pub inline fn allocAdvancedWithRetAddr( | ... | @@ -266,7 +270,7 @@ pub inline fn allocAdvancedWithRetAddr( |
| 266 | n: usize, | 270 | n: usize, |
| 267 | return_address: usize, | 271 | return_address: usize, |
| 268 | ) Error![]align(if (alignment) |a| a.toByteUnits() else @alignOf(T)) T { | 272 | ) Error![]align(if (alignment) |a| a.toByteUnits() else @alignOf(T)) T { |
| 269 | const a = comptime (alignment orelse Alignment.of(T)); | 273 | const a: Alignment = alignment orelse comptime .of(T); |
| 270 | const ptr: [*]align(a.toByteUnits()) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address)); | 274 | const ptr: [*]align(a.toByteUnits()) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address)); |
| 271 | return ptr[0..n]; | 275 | return ptr[0..n]; |
| 272 | } | 276 | } |
| ... | @@ -278,7 +282,7 @@ fn allocWithSizeAndAlignment( | ... | @@ -278,7 +282,7 @@ fn allocWithSizeAndAlignment( |
| 278 | n: usize, | 282 | n: usize, |
| 279 | return_address: usize, | 283 | return_address: usize, |
| 280 | ) Error![*]align(alignment.toByteUnits()) u8 { | 284 | ) Error![*]align(alignment.toByteUnits()) u8 { |
| 281 | const byte_count = math.mul(usize, size, n) catch return Error.OutOfMemory; | 285 | const byte_count = math.mul(usize, size, n) catch return error.OutOfMemory; |
| 282 | return self.allocBytesWithAlignment(alignment, byte_count, return_address); | 286 | return self.allocBytesWithAlignment(alignment, byte_count, return_address); |
| 283 | } | 287 | } |
| 284 | | 288 | |
| ... | @@ -293,7 +297,7 @@ fn allocBytesWithAlignment( | ... | @@ -293,7 +297,7 @@ fn allocBytesWithAlignment( |
| 293 | return @as([*]align(alignment.toByteUnits()) u8, @ptrFromInt(ptr)); | 297 | return @as([*]align(alignment.toByteUnits()) u8, @ptrFromInt(ptr)); |
| 294 | } | 298 | } |
| 295 | | 299 | |
| 296 | const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return Error.OutOfMemory; | 300 | const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return error.OutOfMemory; |
| 297 | @memset(byte_ptr[0..byte_count], undefined); | 301 | @memset(byte_ptr[0..byte_count], undefined); |
| 298 | return @alignCast(byte_ptr); | 302 | return @alignCast(byte_ptr); |
| 299 | } | 303 | } |
| ... | @@ -308,9 +312,9 @@ fn allocBytesWithAlignment( | ... | @@ -308,9 +312,9 @@ fn allocBytesWithAlignment( |
| 308 | /// | 312 | /// |
| 309 | /// `new_len` may be zero, in which case the allocation is freed. | 313 | /// `new_len` may be zero, in which case the allocation is freed. |
| 310 | pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { | 314 | pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 311 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | 315 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; |
| 312 | const T = Slice.child; | 316 | comptime assert(slice_info.size == .slice); |
| 313 | const alignment = Slice.alignment; | 317 | const T = slice_info.child; |
| 314 | if (new_len == 0) { | 318 | if (new_len == 0) { |
| 315 | self.free(allocation); | 319 | self.free(allocation); |
| 316 | return true; | 320 | return true; |
| ... | @@ -323,7 +327,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { | ... | @@ -323,7 +327,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 323 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 | 327 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |
| 324 | //const new_len_bytes = new_len *| @sizeOf(T); | 328 | //const new_len_bytes = new_len *| @sizeOf(T); |
| 325 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false; | 329 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false; |
| 326 | return self.rawResize(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()); | 330 | return self.rawResize( |
| | 331 | old_memory, |
| | 332 | .fromByteUnits(slice_info.alignment orelse @alignOf(T)), |
| | 333 | new_len_bytes, |
| | 334 | @returnAddress(), |
| | 335 | ); |
| 327 | } | 336 | } |
| 328 | | 337 | |
| 329 | /// Request to modify the size of an allocation, allowing relocation. | 338 | /// Request to modify the size of an allocation, allowing relocation. |
| ... | @@ -342,14 +351,11 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { | ... | @@ -342,14 +351,11 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 342 | /// `new_len` may be zero, in which case the allocation is freed. | 351 | /// `new_len` may be zero, in which case the allocation is freed. |
| 343 | /// | 352 | /// |
| 344 | /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. | 353 | /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. |
| 345 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { | 354 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) { |
| 346 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | 355 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; |
| 347 | break :t ?[]align(Slice.alignment) Slice.child; | 356 | comptime assert(slice_info.size == .slice); |
| 348 | } { | 357 | const T = slice_info.child; |
| 349 | const Slice = @typeInfo(@TypeOf(allocation)).pointer; | 358 | |
| 350 | const T = Slice.child; | | |
| 351 | | | |
| 352 | const alignment = Slice.alignment; | | |
| 353 | if (new_len == 0) { | 359 | if (new_len == 0) { |
| 354 | self.free(allocation); | 360 | self.free(allocation); |
| 355 | return allocation[0..0]; | 361 | return allocation[0..0]; |
| ... | @@ -367,9 +373,13 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { | ... | @@ -367,9 +373,13 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 367 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 | 373 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |
| 368 | //const new_len_bytes = new_len *| @sizeOf(T); | 374 | //const new_len_bytes = new_len *| @sizeOf(T); |
| 369 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null; | 375 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null; |
| 370 | const new_ptr = self.rawRemap(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()) orelse return null; | 376 | const new_ptr = self.rawRemap( |
| 371 | const new_memory: []align(alignment) u8 = @alignCast(new_ptr[0..new_len_bytes]); | 377 | old_memory, |
| 372 | return mem.bytesAsSlice(T, new_memory); | 378 | .fromByteUnits(slice_info.alignment orelse @alignOf(T)), |
| | 379 | new_len_bytes, |
| | 380 | @returnAddress(), |
| | 381 | ) orelse return null; |
| | 382 | return @ptrCast(@alignCast(new_ptr[0..new_len_bytes])); |
| 373 | } | 383 | } |
| 374 | | 384 | |
| 375 | /// This function requests a new size for an existing allocation, which | 385 | /// This function requests a new size for an existing allocation, which |
| ... | @@ -386,10 +396,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { | ... | @@ -386,10 +396,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 386 | /// do the realloc more efficiently than the caller | 396 | /// do the realloc more efficiently than the caller |
| 387 | /// * `resize` which returns `false` when the `Allocator` implementation cannot | 397 | /// * `resize` which returns `false` when the `Allocator` implementation cannot |
| 388 | /// change the size without relocating the allocation. | 398 | /// change the size without relocating the allocation. |
| 389 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: { | 399 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) { |
| 390 | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; | | |
| 391 | break :t Error![]align(Slice.alignment) Slice.child; | | |
| 392 | } { | | |
| 393 | return self.reallocAdvanced(old_mem, new_n, @returnAddress()); | 400 | return self.reallocAdvanced(old_mem, new_n, @returnAddress()); |
| 394 | } | 401 | } |
| 395 | | 402 | |
| ... | @@ -398,51 +405,49 @@ pub fn reallocAdvanced( | ... | @@ -398,51 +405,49 @@ pub fn reallocAdvanced( |
| 398 | old_mem: anytype, | 405 | old_mem: anytype, |
| 399 | new_n: usize, | 406 | new_n: usize, |
| 400 | return_address: usize, | 407 | return_address: usize, |
| 401 | ) t: { | 408 | ) Error!@TypeOf(old_mem) { |
| 402 | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; | 409 | const slice_info = @typeInfo(@TypeOf(old_mem)).pointer; |
| 403 | break :t Error![]align(Slice.alignment) Slice.child; | 410 | comptime assert(slice_info.size == .slice); |
| 404 | } { | 411 | const T = slice_info.child; |
| 405 | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; | | |
| 406 | const T = Slice.child; | | |
| 407 | if (old_mem.len == 0) { | 412 | if (old_mem.len == 0) { |
| 408 | return self.allocAdvancedWithRetAddr(T, .fromByteUnits(Slice.alignment), new_n, return_address); | 413 | return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.alignment), new_n, return_address); |
| 409 | } | 414 | } |
| 410 | if (new_n == 0) { | 415 | if (new_n == 0) { |
| 411 | self.free(old_mem); | 416 | self.free(old_mem); |
| 412 | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), Slice.alignment); | 417 | const alignment = slice_info.alignment orelse @alignOf(T); |
| 413 | return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0]; | 418 | const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment); |
| | 419 | const ptr: *align(alignment) [0]T = @ptrFromInt(addr); |
| | 420 | return ptr; |
| 414 | } | 421 | } |
| 415 | | 422 | |
| 416 | const old_byte_slice = mem.sliceAsBytes(old_mem); | 423 | const old_byte_slice = mem.sliceAsBytes(old_mem); |
| 417 | const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; | 424 | const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory; |
| 418 | // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure | 425 | // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure |
| 419 | if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| { | 426 | if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), byte_count, return_address)) |p| { |
| 420 | const new_bytes: []align(Slice.alignment) u8 = @alignCast(p[0..byte_count]); | 427 | return @ptrCast(@alignCast(p[0..byte_count])); |
| 421 | return mem.bytesAsSlice(T, new_bytes); | | |
| 422 | } | 428 | } |
| 423 | | 429 | |
| 424 | const new_mem = self.rawAlloc(byte_count, .fromByteUnits(Slice.alignment), return_address) orelse | 430 | const new_mem = self.rawAlloc(byte_count, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address) orelse |
| 425 | return error.OutOfMemory; | 431 | return error.OutOfMemory; |
| 426 | const copy_len = @min(byte_count, old_byte_slice.len); | 432 | const copy_len = @min(byte_count, old_byte_slice.len); |
| 427 | @memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]); | 433 | @memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]); |
| 428 | @memset(old_byte_slice, undefined); | 434 | @memset(old_byte_slice, undefined); |
| 429 | self.rawFree(old_byte_slice, .fromByteUnits(Slice.alignment), return_address); | 435 | self.rawFree(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address); |
| 430 | | 436 | |
| 431 | const new_bytes: []align(Slice.alignment) u8 = @alignCast(new_mem[0..byte_count]); | 437 | return @ptrCast(@alignCast(new_mem[0..byte_count])); |
| 432 | return mem.bytesAsSlice(T, new_bytes); | | |
| 433 | } | 438 | } |
| 434 | | 439 | |
| 435 | /// Free an array allocated with `alloc`. | 440 | /// Free an array allocated with `alloc`. |
| 436 | /// If memory has length 0, free is a no-op. | 441 | /// If memory has length 0, free is a no-op. |
| 437 | /// To free a single item, see `destroy`. | 442 | /// To free a single item, see `destroy`. |
| 438 | pub fn free(self: Allocator, memory: anytype) void { | 443 | pub fn free(self: Allocator, memory: anytype) void { |
| 439 | const Slice = @typeInfo(@TypeOf(memory)).pointer; | 444 | const slice_info = @typeInfo(@TypeOf(memory)).pointer; |
| 440 | const bytes = mem.sliceAsBytes(memory); | 445 | comptime assert(slice_info.size == .slice); |
| 441 | const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0; | 446 | const mem_with_sent = memory[0 .. memory.len + @intFromBool(slice_info.sentinel() != null)]; |
| 442 | if (bytes_len == 0) return; | 447 | const bytes: []u8 = @ptrCast(@constCast(mem_with_sent)); |
| 443 | const non_const_ptr = @constCast(bytes.ptr); | 448 | if (bytes.len == 0) return; |
| 444 | @memset(non_const_ptr[0..bytes_len], undefined); | 449 | @memset(bytes, undefined); |
| 445 | self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress()); | 450 | self.rawFree(bytes, .fromByteUnits(slice_info.alignment orelse @alignOf(slice_info.child)), @returnAddress()); |
| 446 | } | 451 | } |
| 447 | | 452 | |
| 448 | /// Copies `m` to newly allocated memory. Caller owns the memory. | 453 | /// Copies `m` to newly allocated memory. Caller owns the memory. |