| ... | ... | @@ -179,7 +179,11 @@ pub fn destroy(self: Allocator, ptr: anytype) void { |
| 179 | 179 | const T = info.child; |
| 180 | 180 | if (@sizeOf(T) == 0) return; |
| 181 | 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 | 189 | /// Allocates an array of `n` items of type `T` and sets all the |
| ... | ... | @@ -266,7 +270,7 @@ pub inline fn allocAdvancedWithRetAddr( |
| 266 | 270 | n: usize, |
| 267 | 271 | return_address: usize, |
| 268 | 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 | 274 | const ptr: [*]align(a.toByteUnits()) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address)); |
| 271 | 275 | return ptr[0..n]; |
| 272 | 276 | } |
| ... | ... | @@ -278,7 +282,7 @@ fn allocWithSizeAndAlignment( |
| 278 | 282 | n: usize, |
| 279 | 283 | return_address: usize, |
| 280 | 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 | 286 | return self.allocBytesWithAlignment(alignment, byte_count, return_address); |
| 283 | 287 | } |
| 284 | 288 | |
| ... | ... | @@ -293,7 +297,7 @@ fn allocBytesWithAlignment( |
| 293 | 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 | 301 | @memset(byte_ptr[0..byte_count], undefined); |
| 298 | 302 | return @alignCast(byte_ptr); |
| 299 | 303 | } |
| ... | ... | @@ -308,9 +312,9 @@ fn allocBytesWithAlignment( |
| 308 | 312 | /// |
| 309 | 313 | /// `new_len` may be zero, in which case the allocation is freed. |
| 310 | 314 | pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 311 | | const Slice = @typeInfo(@TypeOf(allocation)).pointer; |
| 312 | | const T = Slice.child; |
| 313 | | const alignment = Slice.alignment; |
| 315 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; |
| 316 | comptime assert(slice_info.size == .slice); |
| 317 | const T = slice_info.child; |
| 314 | 318 | if (new_len == 0) { |
| 315 | 319 | self.free(allocation); |
| 316 | 320 | return true; |
| ... | ... | @@ -323,7 +327,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 323 | 327 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |
| 324 | 328 | //const new_len_bytes = new_len *| @sizeOf(T); |
| 325 | 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 | 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 | 351 | /// `new_len` may be zero, in which case the allocation is freed. |
| 343 | 352 | /// |
| 344 | 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: { |
| 346 | | const Slice = @typeInfo(@TypeOf(allocation)).pointer; |
| 347 | | break :t ?[]align(Slice.alignment) Slice.child; |
| 348 | | } { |
| 349 | | const Slice = @typeInfo(@TypeOf(allocation)).pointer; |
| 350 | | const T = Slice.child; |
| 351 | | |
| 352 | | const alignment = Slice.alignment; |
| 354 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) { |
| 355 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; |
| 356 | comptime assert(slice_info.size == .slice); |
| 357 | const T = slice_info.child; |
| 358 | |
| 353 | 359 | if (new_len == 0) { |
| 354 | 360 | self.free(allocation); |
| 355 | 361 | return allocation[0..0]; |
| ... | ... | @@ -367,9 +373,13 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { |
| 367 | 373 | // on WebAssembly: https://github.com/ziglang/zig/issues/9660 |
| 368 | 374 | //const new_len_bytes = new_len *| @sizeOf(T); |
| 369 | 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; |
| 371 | | const new_memory: []align(alignment) u8 = @alignCast(new_ptr[0..new_len_bytes]); |
| 372 | | return mem.bytesAsSlice(T, new_memory); |
| 376 | const new_ptr = self.rawRemap( |
| 377 | old_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 | 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 | 396 | /// do the realloc more efficiently than the caller |
| 387 | 397 | /// * `resize` which returns `false` when the `Allocator` implementation cannot |
| 388 | 398 | /// change the size without relocating the allocation. |
| 389 | | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: { |
| 390 | | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; |
| 391 | | break :t Error![]align(Slice.alignment) Slice.child; |
| 392 | | } { |
| 399 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) { |
| 393 | 400 | return self.reallocAdvanced(old_mem, new_n, @returnAddress()); |
| 394 | 401 | } |
| 395 | 402 | |
| ... | ... | @@ -398,51 +405,49 @@ pub fn reallocAdvanced( |
| 398 | 405 | old_mem: anytype, |
| 399 | 406 | new_n: usize, |
| 400 | 407 | return_address: usize, |
| 401 | | ) t: { |
| 402 | | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; |
| 403 | | break :t Error![]align(Slice.alignment) Slice.child; |
| 404 | | } { |
| 405 | | const Slice = @typeInfo(@TypeOf(old_mem)).pointer; |
| 406 | | const T = Slice.child; |
| 408 | ) Error!@TypeOf(old_mem) { |
| 409 | const slice_info = @typeInfo(@TypeOf(old_mem)).pointer; |
| 410 | comptime assert(slice_info.size == .slice); |
| 411 | const T = slice_info.child; |
| 407 | 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 | 415 | if (new_n == 0) { |
| 411 | 416 | self.free(old_mem); |
| 412 | | const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), Slice.alignment); |
| 413 | | return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0]; |
| 417 | const alignment = slice_info.alignment orelse @alignOf(T); |
| 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 | 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 | 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| { |
| 420 | | const new_bytes: []align(Slice.alignment) u8 = @alignCast(p[0..byte_count]); |
| 421 | | return mem.bytesAsSlice(T, new_bytes); |
| 426 | if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), byte_count, return_address)) |p| { |
| 427 | return @ptrCast(@alignCast(p[0..byte_count])); |
| 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 | 431 | return error.OutOfMemory; |
| 426 | 432 | const copy_len = @min(byte_count, old_byte_slice.len); |
| 427 | 433 | @memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]); |
| 428 | 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]); |
| 432 | | return mem.bytesAsSlice(T, new_bytes); |
| 437 | return @ptrCast(@alignCast(new_mem[0..byte_count])); |
| 433 | 438 | } |
| 434 | 439 | |
| 435 | 440 | /// Free an array allocated with `alloc`. |
| 436 | 441 | /// If memory has length 0, free is a no-op. |
| 437 | 442 | /// To free a single item, see `destroy`. |
| 438 | 443 | pub fn free(self: Allocator, memory: anytype) void { |
| 439 | | const Slice = @typeInfo(@TypeOf(memory)).pointer; |
| 440 | | const bytes = mem.sliceAsBytes(memory); |
| 441 | | const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0; |
| 442 | | if (bytes_len == 0) return; |
| 443 | | const non_const_ptr = @constCast(bytes.ptr); |
| 444 | | @memset(non_const_ptr[0..bytes_len], undefined); |
| 445 | | self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress()); |
| 444 | const slice_info = @typeInfo(@TypeOf(memory)).pointer; |
| 445 | comptime assert(slice_info.size == .slice); |
| 446 | const mem_with_sent = memory[0 .. memory.len + @intFromBool(slice_info.sentinel() != null)]; |
| 447 | const bytes: []u8 = @ptrCast(@constCast(mem_with_sent)); |
| 448 | if (bytes.len == 0) return; |
| 449 | @memset(bytes, undefined); |
| 450 | self.rawFree(bytes, .fromByteUnits(slice_info.alignment orelse @alignOf(slice_info.child)), @returnAddress()); |
| 446 | 451 | } |
| 447 | 452 | |
| 448 | 453 | /// Copies `m` to newly allocated memory. Caller owns the memory. |