Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lib/std/heap/general_purpose_allocator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
const prev = bucket.prev;
if (config.never_unmap) {
// free page that was intentionally leaked by never_unmap
self.backing_allocator.free(bucket.page[0..page_size]);
const array_ptr = bucket.page[0..page_size];
comptime assert(@TypeOf(array_ptr) == *align(page_size) [page_size]u8);
self.backing_allocator.free(@as([]align(page_size) u8, array_ptr));
}
// alloc_cursor was set to slot count when bucket added to empty_buckets
self.freeBucket(bucket, @divExact(page_size, bucket.alloc_cursor));
Expand Down Expand Up @@ -814,7 +816,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
self.buckets[bucket_index] = bucket.prev;
}
if (!config.never_unmap) {
self.backing_allocator.free(bucket.page[0..page_size]);
const array_ptr = bucket.page[0..page_size];
comptime assert(@TypeOf(array_ptr) == *align(page_size) [page_size]u8);
self.backing_allocator.free(@as([]align(page_size) u8, array_ptr));
}
if (!config.retain_metadata) {
self.freeBucket(bucket, size_class);
Expand Down
35 changes: 29 additions & 6 deletions lib/std/mem/Allocator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub fn create(self: Allocator, comptime T: type) Error!*T {
/// `ptr` should be the return value of `create`, or otherwise
/// have the same address and alignment property.
pub fn destroy(self: Allocator, ptr: anytype) void {
const info = @typeInfo(@TypeOf(ptr)).Pointer;
const info = ensureSlice(@TypeOf(ptr), "destroy", .One);
const T = info.child;
if (@sizeOf(T) == 0) return;
const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));
Expand Down Expand Up @@ -224,7 +224,7 @@ pub fn allocAdvancedWithRetAddr(
/// the pointer, however the allocator implementation may refuse the resize
/// request by returning `false`.
pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) bool {
const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
const Slice = ensureSlice(@TypeOf(old_mem), "resize", .Slice);
const T = Slice.child;
if (new_n == 0) {
self.free(old_mem);
Expand All @@ -245,7 +245,7 @@ pub fn resize(self: Allocator, old_mem: anytype, new_n: usize) bool {
/// can be larger, smaller, or the same size as the old memory allocation.
/// If `new_n` is 0, this is the same as `free` and it always succeeds.
pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: {
const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
const Slice = ensureSlice(@TypeOf(old_mem), "realloc", .Slice);
break :t Error![]align(Slice.alignment) Slice.child;
} {
return self.reallocAdvanced(old_mem, new_n, @returnAddress());
Expand All @@ -257,10 +257,10 @@ pub fn reallocAdvanced(
new_n: usize,
return_address: usize,
) t: {
const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
const Slice = ensureSlice(@TypeOf(old_mem), "reallocAdvanced", .Slice);
break :t Error![]align(Slice.alignment) Slice.child;
} {
const Slice = @typeInfo(@TypeOf(old_mem)).Pointer;
const Slice = ensureSlice(@TypeOf(old_mem), "reallocAdvanced", .Slice);
const T = Slice.child;
if (old_mem.len == 0) {
return self.allocAdvancedWithRetAddr(T, Slice.alignment, new_n, return_address);
Expand Down Expand Up @@ -293,7 +293,7 @@ pub fn reallocAdvanced(
/// Free an array allocated with `alloc`. To free a single item,
/// see `destroy`.
pub fn free(self: Allocator, memory: anytype) void {
const Slice = @typeInfo(@TypeOf(memory)).Pointer;
const Slice = ensureSlice(@TypeOf(memory), "free", .Slice);
const bytes = mem.sliceAsBytes(memory);
const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0;
if (bytes_len == 0) return;
Expand All @@ -318,6 +318,29 @@ pub fn dupeZ(allocator: Allocator, comptime T: type, m: []const T) ![:0]T {
return new_buf[0..m.len :0];
}

inline fn ensureSlice(
comptime Type: type,
comptime function_name: []const u8,
comptime expected_size: std.builtin.Type.Pointer.Size,
) std.builtin.Type.Pointer {
const expectation = switch (expected_size) {
.One => "a single item pointer",
.Slice => "a slice",
else => unreachable,
};
const type_info = @typeInfo(Type);

if (type_info == .Pointer) {
const pointer = type_info.Pointer;

if (pointer.size == expected_size) {
return pointer;
}
}

@compileError(std.fmt.comptimePrint("{s} expects {s} but received a value of type `{s}`", .{ function_name, expectation, @typeName(Type) }));
}

/// TODO replace callsites with `@log2` after this proposal is implemented:
/// https://github.com/ziglang/zig/issues/13642
inline fn log2a(x: anytype) switch (@typeInfo(@TypeOf(x))) {
Expand Down