authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-03 14:52:04-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-04 00:27:09-08:00
logff67f70cf983ce772b0b4ef4a891bca1a51781c4
tree389a0408dcd4a8793959cf29c4cf5b15a69031aa
parent5b9e6a2b2daf6b3c17adee4cea32d9319337dd2e

start: tweak default allocator choices

On wasm targets, when libc is linked, we have to go through libc.

2 files changed, 19 insertions(+), 13 deletions(-)

lib/std/process.zig+3-2
......@@ -40,10 +40,11 @@ pub const Init = struct {
4040 /// exit. Not threadsafe.
4141 arena: *std.heap.ArenaAllocator,
4242 /// A default-selected general purpose allocator for temporary heap
43 /// allocations. Debug mode will set up leak checking. Threadsafe.
43 /// allocations. Debug mode will set up leak checking if possible.
44 /// Threadsafe.
4445 gpa: Allocator,
4546 /// An appropriate default Io implementation based on the target
46 /// configuration. Debug mode will set up leak checking.
47 /// configuration. Debug mode will set up leak checking if possible.
4748 io: Io,
4849 /// Environment variables, initialized with `gpa`. Not threadsafe.
4950 environ_map: *Environ.Map,
lib/std/start.zig+16-11
......@@ -1,13 +1,16 @@
11// This file is included in the compilation unit when exporting an executable.
22
3const root = @import("root");
4const std = @import("std.zig");
53const builtin = @import("builtin");
4const native_arch = builtin.cpu.arch;
5const native_os = builtin.os.tag;
6const is_wasm = native_arch.isWasm();
7
8const std = @import("std.zig");
69const assert = std.debug.assert;
710const uefi = std.os.uefi;
811const elf = std.elf;
9const native_arch = builtin.cpu.arch;
10const native_os = builtin.os.tag;
12
13const root = @import("root");
1114
1215const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";
1316
......@@ -22,7 +25,7 @@ comptime {
2225 }
2326 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
2427 if (builtin.link_libc and @hasDecl(root, "main")) {
25 if (native_arch.isWasm()) {
28 if (is_wasm) {
2629 @export(&mainWithoutEnv, .{ .name = "__main_argc_argv" });
2730 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {
2831 @export(&main, .{ .name = "main" });
......@@ -57,7 +60,7 @@ comptime {
5760 // case it's not required to provide an entrypoint such as main.
5861 @export(&startWasi, .{ .name = wasm_start_sym });
5962 }
60 } else if (native_arch.isWasm() and native_os == .freestanding) {
63 } else if (is_wasm and native_os == .freestanding) {
6164 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which
6265 // case it's not required to provide an entrypoint such as main.
6366 if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(&wasm_freestanding_start, .{ .name = start_sym_name });
......@@ -660,7 +663,7 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
660663/// General error message for a malformed return type
661664const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
662665
663const use_debug_allocator = !native_arch.isWasm() and switch (builtin.mode) {
666const use_debug_allocator = !is_wasm and switch (builtin.mode) {
664667 .Debug => true,
665668 .ReleaseSafe => !builtin.link_libc, // Not ideal, but the best we have for now.
666669 .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal.
......@@ -675,12 +678,12 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
675678 .environ = .{ .block = environ },
676679 }));
677680
678 const gpa = if (native_arch.isWasm())
679 std.heap.wasm_allocator
680 else if (use_debug_allocator)
681 const gpa = if (use_debug_allocator)
681682 debug_allocator.allocator()
682683 else if (builtin.link_libc)
683684 std.heap.c_allocator
685 else if (is_wasm)
686 std.heap.wasm_allocator
684687 else if (!builtin.single_threaded)
685688 std.heap.smp_allocator
686689 else
......@@ -690,7 +693,9 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
690693 _ = debug_allocator.deinit(); // Leaks do not affect return code.
691694 };
692695
693 var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator);
696 const arena_backing_allocator = if (is_wasm) gpa else std.heap.page_allocator;
697
698 var arena_allocator = std.heap.ArenaAllocator.init(arena_backing_allocator);
694699 defer arena_allocator.deinit();
695700
696701 var threaded: std.Io.Threaded = .init(gpa, .{