Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add std.heap.AutoAllocator #23432

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ int main(int argc, char **argv) {
"pub const value_tracing = false;\n"
"pub const skip_non_native = false;\n"
"pub const debug_gpa = false;\n"
"pub const mem_leak_frames = 0;\n"
"pub const dev = .core;\n"
"pub const value_interpret_mode = .direct;\n"
, zig_version);
Expand Down
61 changes: 60 additions & 1 deletion lib/std/heap.zig
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,51 @@ pub fn StackFallbackAllocator(comptime size: usize) type {
};
}

pub const AutoAllocatorOptions = struct {
debug_allocator_config: DebugAllocatorConfig = .{},
};

pub fn AutoAllocator(options: AutoAllocatorOptions) type {
const impl: enum { debug, smp, wasm, c } = if (builtin.os.tag == .wasi)
.wasm
else switch (builtin.mode) {
.Debug => .debug,
.ReleaseSafe, .ReleaseFast, .ReleaseSmall => if (builtin.link_libc)
.c
else if (builtin.single_threaded)
.debug
else
.smp,
};

return struct {
inner: switch (impl) {
.debug => DebugAllocator(options.debug_allocator_config),
else => void,
} = switch (impl) {
.debug => .init,
else => {},
},

pub fn allocator(self: *@This()) std.mem.Allocator {
return switch (impl) {
.debug => self.inner.allocator(),
.wasm => wasm_allocator,
.c => c_allocator,
.smp => smp_allocator,
};
}

pub fn deinit(self: *@This()) Check {
defer self.* = undefined;
return switch (impl) {
.debug => self.inner.deinit(),
else => .ok,
};
}
};
}

test c_allocator {
if (builtin.link_libc) {
try testAllocator(c_allocator);
Expand Down Expand Up @@ -524,6 +569,20 @@ test PageAllocator {
}
}

test AutoAllocator {
var ctx: AutoAllocator(.{}) = .{};
const allocator = ctx.allocator();

try testAllocator(allocator);
try testAllocatorAligned(allocator);
if (!builtin.target.cpu.arch.isWasm()) {
try testAllocatorLargeAlignment(allocator);
try testAllocatorAlignedShrink(allocator);
}

try testing.expectEqual(.ok, ctx.deinit());
}

test ArenaAllocator {
var arena_allocator = ArenaAllocator.init(page_allocator);
defer arena_allocator.deinit();
Expand All @@ -535,7 +594,7 @@ test ArenaAllocator {
try testAllocatorAlignedShrink(allocator);
}

test "StackFallbackAllocator" {
test StackFallbackAllocator {
{
var stack_allocator = stackFallback(4096, std.testing.allocator);
try testAllocator(stack_allocator.get());
Expand Down
31 changes: 10 additions & 21 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -168,32 +168,21 @@ pub fn log(
std.debug.print(prefix1 ++ prefix2 ++ format ++ "\n", args);
}

var debug_allocator: std.heap.DebugAllocator(.{
const debug_allocator_config: std.heap.DebugAllocatorConfig = .{
.stack_trace_frames = build_options.mem_leak_frames,
}) = .init;
};
var auto_allocator: std.heap.AutoAllocator(.{ .debug_allocator_config = debug_allocator_config }) = .{};
var debug_allocator: std.heap.DebugAllocator(debug_allocator_config) = .init;

pub fn main() anyerror!void {
crash_report.initialize();

const gpa, const is_debug = gpa: {
if (build_options.debug_gpa) break :gpa .{ debug_allocator.allocator(), true };
if (native_os == .wasi) break :gpa .{ std.heap.wasm_allocator, false };
if (builtin.link_libc) {
// We would prefer to use raw libc allocator here, but cannot use
// it if it won't support the alignment we need.
if (@alignOf(std.c.max_align_t) < @max(@alignOf(i128), std.atomic.cache_line)) {
break :gpa .{ std.heap.c_allocator, false };
}
break :gpa .{ std.heap.raw_c_allocator, false };
}
break :gpa switch (builtin.mode) {
.Debug, .ReleaseSafe => .{ debug_allocator.allocator(), true },
.ReleaseFast, .ReleaseSmall => .{ std.heap.smp_allocator, false },
};
};
defer if (is_debug) {
_ = debug_allocator.deinit();
};
const gpa_instance = if (build_options.debug_gpa) &debug_allocator else &auto_allocator;
const gpa = gpa_instance.allocator();
// See #22984 - Currently it is irrelevant if we leak allocator state on exit since we are
// already leaking allocations. Disabling this temporarily avoids those error message.
// defer _ = gpa_instance.deinit();

var arena_instance = std.heap.ArenaAllocator.init(gpa);
defer arena_instance.deinit();
const arena = arena_instance.allocator();
Expand Down
1 change: 1 addition & 0 deletions stage1/config.zig.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ pub const enable_tracy = false;
pub const value_tracing = false;
pub const skip_non_native = false;
pub const debug_gpa = false;
pub const mem_leak_frames = 0;
pub const dev = .core;
pub const value_interpret_mode = .direct;
Loading