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 {...@@ -40,10 +40,11 @@ pub const Init = struct {
40 /// exit. Not threadsafe.40 /// exit. Not threadsafe.
41 arena: *std.heap.ArenaAllocator,41 arena: *std.heap.ArenaAllocator,
42 /// A default-selected general purpose allocator for temporary heap42 /// 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.
44 gpa: Allocator,45 gpa: Allocator,
45 /// An appropriate default Io implementation based on the target46 /// 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.
47 io: Io,48 io: Io,
48 /// Environment variables, initialized with `gpa`. Not threadsafe.49 /// Environment variables, initialized with `gpa`. Not threadsafe.
49 environ_map: *Environ.Map,50 environ_map: *Environ.Map,
lib/std/start.zig+16-11
...@@ -1,13 +1,16 @@...@@ -1,13 +1,16 @@
1// This file is included in the compilation unit when exporting an executable.1// This file is included in the compilation unit when exporting an executable.
22
3const root = @import("root");
4const std = @import("std.zig");
5const builtin = @import("builtin");3const 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");
6const assert = std.debug.assert;9const assert = std.debug.assert;
7const uefi = std.os.uefi;10const uefi = std.os.uefi;
8const elf = std.elf;11const elf = std.elf;
9const native_arch = builtin.cpu.arch;12
10const native_os = builtin.os.tag;13const root = @import("root");
1114
12const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";15const start_sym_name = if (native_arch.isMIPS()) "__start" else "_start";
1316
...@@ -22,7 +25,7 @@ comptime {...@@ -22,7 +25,7 @@ comptime {
22 }25 }
23 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {26 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
24 if (builtin.link_libc and @hasDecl(root, "main")) {27 if (builtin.link_libc and @hasDecl(root, "main")) {
25 if (native_arch.isWasm()) {28 if (is_wasm) {
26 @export(&mainWithoutEnv, .{ .name = "__main_argc_argv" });29 @export(&mainWithoutEnv, .{ .name = "__main_argc_argv" });
27 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {30 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {
28 @export(&main, .{ .name = "main" });31 @export(&main, .{ .name = "main" });
...@@ -57,7 +60,7 @@ comptime {...@@ -57,7 +60,7 @@ comptime {
57 // case it's not required to provide an entrypoint such as main.60 // case it's not required to provide an entrypoint such as main.
58 @export(&startWasi, .{ .name = wasm_start_sym });61 @export(&startWasi, .{ .name = wasm_start_sym });
59 }62 }
60 } else if (native_arch.isWasm() and native_os == .freestanding) {63 } else if (is_wasm and native_os == .freestanding) {
61 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which64 // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which
62 // case it's not required to provide an entrypoint such as main.65 // case it's not required to provide an entrypoint such as main.
63 if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(&wasm_freestanding_start, .{ .name = start_sym_name });66 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 {...@@ -660,7 +663,7 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
660/// General error message for a malformed return type663/// General error message for a malformed return type
661const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";664const 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) {
664 .Debug => true,667 .Debug => true,
665 .ReleaseSafe => !builtin.link_libc, // Not ideal, but the best we have for now.668 .ReleaseSafe => !builtin.link_libc, // Not ideal, but the best we have for now.
666 .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal.669 .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...@@ -675,12 +678,12 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
675 .environ = .{ .block = environ },678 .environ = .{ .block = environ },
676 }));679 }));
677680
678 const gpa = if (native_arch.isWasm())681 const gpa = if (use_debug_allocator)
679 std.heap.wasm_allocator
680 else if (use_debug_allocator)
681 debug_allocator.allocator()682 debug_allocator.allocator()
682 else if (builtin.link_libc)683 else if (builtin.link_libc)
683 std.heap.c_allocator684 std.heap.c_allocator
685 else if (is_wasm)
686 std.heap.wasm_allocator
684 else if (!builtin.single_threaded)687 else if (!builtin.single_threaded)
685 std.heap.smp_allocator688 std.heap.smp_allocator
686 else689 else
...@@ -690,7 +693,9 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B...@@ -690,7 +693,9 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
690 _ = debug_allocator.deinit(); // Leaks do not affect return code.693 _ = debug_allocator.deinit(); // Leaks do not affect return code.
691 };694 };
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);
694 defer arena_allocator.deinit();699 defer arena_allocator.deinit();
695700
696 var threaded: std.Io.Threaded = .init(gpa, .{701 var threaded: std.Io.Threaded = .init(gpa, .{