| author | |
| committer | |
| log | c805c7228978df4af34ee0d63948234fb0ab504e |
| tree | 83d7226098fc20c43d90bae9a96bde731594924a |
| parent | e1ce81eb546e10ae505b411b6882266d1834fce1 |
9 files changed, 74 insertions(+), 74 deletions(-)
build.zig+1-1| ... | ... | @@ -183,7 +183,7 @@ pub fn build(b: *std.Build) !void { |
| 183 | 183 | const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null); |
| 184 | 184 | const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null); |
| 185 | 185 | const tracy_callstack_depth: u32 = b.option(u32, "tracy-callstack-depth", "Declare callstack depth for Tracy data. Does nothing if -Dtracy_callstack is not provided") orelse 10; |
| 186 | const debug_gpa = b.option(bool, "debug-allocator", "Force the compiler to use DebugAllocator") orelse false; | |
| 186 | const debug_gpa = b.option(bool, "debug-allocator", "Force the compiler to use SafeAllocator") orelse false; | |
| 187 | 187 | const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse (enable_llvm or only_c); |
| 188 | 188 | const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false; |
| 189 | 189 | const strip = b.option(bool, "strip", "Omit debug information"); |
lib/compiler/build_runner.zig+3-3| ... | ... | @@ -26,9 +26,9 @@ pub const std_options: std.Options = .{ |
| 26 | 26 | pub fn main(init: process.Init.Minimal) !void { |
| 27 | 27 | // The build runner is often short-lived, but thanks to `--watch` and `--webui`, that's not |
| 28 | 28 | // always the case. So, we do need a true gpa for some things. |
| 29 | var debug_gpa_state: std.heap.DebugAllocator(.{}) = .init; | |
| 30 | defer _ = debug_gpa_state.deinit(); | |
| 31 | const gpa = debug_gpa_state.allocator(); | |
| 29 | var safe_gpa_state: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 30 | defer _ = safe_gpa_state.deinit(); | |
| 31 | const gpa = safe_gpa_state.allocator(); | |
| 32 | 32 | |
| 33 | 33 | var threaded: std.Io.Threaded = .init(gpa, .{ |
| 34 | 34 | .environ = init.environ, |
lib/compiler/test_runner.zig+24-14| ... | ... | @@ -91,8 +91,8 @@ fn mainServer(init: std.process.Init.Minimal) !void { |
| 91 | 91 | return std.process.exit(0); |
| 92 | 92 | }, |
| 93 | 93 | .query_test_metadata => { |
| 94 | testing.allocator_instance = .{}; | |
| 95 | defer if (testing.allocator_instance.deinit() == .leak) { | |
| 94 | testing.allocator_instance = .init(std.heap.page_allocator, .{}); | |
| 95 | defer if (testing.allocator_instance.deinit() != 0) { | |
| 96 | 96 | @panic("internal test runner memory leak"); |
| 97 | 97 | }; |
| 98 | 98 | |
| ... | ... | @@ -123,7 +123,10 @@ fn mainServer(init: std.process.Init.Minimal) !void { |
| 123 | 123 | |
| 124 | 124 | .run_test => { |
| 125 | 125 | testing.environ = init.environ; |
| 126 | testing.allocator_instance = .{}; | |
| 126 | testing.allocator_instance = .init(std.heap.page_allocator, .{ | |
| 127 | .canary = 0xc3a701ba, | |
| 128 | .check_write_after_free = true, | |
| 129 | }); | |
| 127 | 130 | testing.io_instance = .init(testing.allocator, .{ |
| 128 | 131 | .argv0 = .init(init.args), |
| 129 | 132 | .environ = init.environ, |
| ... | ... | @@ -150,8 +153,7 @@ fn mainServer(init: std.process.Init.Minimal) !void { |
| 150 | 153 | }, |
| 151 | 154 | }; |
| 152 | 155 | testing.io_instance.deinit(); |
| 153 | const leak_count = testing.allocator_instance.detectLeaks(); | |
| 154 | testing.allocator_instance.deinitWithoutLeakChecks(); | |
| 156 | const leak_count = testing.allocator_instance.deinit(); | |
| 155 | 157 | try server.serveTestResults(.{ |
| 156 | 158 | .index = index, |
| 157 | 159 | .flags = .{ |
| ... | ... | @@ -173,8 +175,8 @@ fn mainServer(init: std.process.Init.Minimal) !void { |
| 173 | 175 | // since they are not present. |
| 174 | 176 | if (!builtin.fuzz) unreachable; |
| 175 | 177 | |
| 176 | var gpa_instance: std.heap.DebugAllocator(.{}) = .init; | |
| 177 | defer if (gpa_instance.deinit() == .leak) { | |
| 178 | var gpa_instance: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 179 | defer if (gpa_instance.deinit() != 0) { | |
| 178 | 180 | @panic("internal test runner memory leak"); |
| 179 | 181 | }; |
| 180 | 182 | const gpa = gpa_instance.allocator(); |
| ... | ... | @@ -271,14 +273,17 @@ fn mainTerminal(init: std.process.Init.Minimal) void { |
| 271 | 273 | |
| 272 | 274 | var leaks: usize = 0; |
| 273 | 275 | for (test_fn_list, 0..) |test_fn, i| { |
| 274 | testing.allocator_instance = .{}; | |
| 276 | testing.allocator_instance = .init(std.heap.page_allocator, .{ | |
| 277 | .canary = 0xc3a701ba, | |
| 278 | .check_write_after_free = true, | |
| 279 | }); | |
| 275 | 280 | testing.io_instance = .init(testing.allocator, .{ |
| 276 | 281 | .argv0 = .init(init.args), |
| 277 | 282 | .environ = init.environ, |
| 278 | 283 | }); |
| 279 | 284 | defer { |
| 280 | 285 | testing.io_instance.deinit(); |
| 281 | if (testing.allocator_instance.deinit() == .leak) leaks += 1; | |
| 286 | if (testing.allocator_instance.deinit() != 0) leaks += 1; | |
| 282 | 287 | } |
| 283 | 288 | testing.log_level = .warn; |
| 284 | 289 | testing.environ = init.environ; |
| ... | ... | @@ -430,8 +435,11 @@ var fuzz_runner: if (builtin.fuzz) struct { |
| 430 | 435 | error.WriteFailed => panic("failed to write to stdout: {t}", .{stdout_writer.err.?}), |
| 431 | 436 | }; |
| 432 | 437 | |
| 433 | testing.allocator_instance = .{}; | |
| 434 | defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1); | |
| 438 | testing.allocator_instance = .init(std.heap.page_allocator, .{ | |
| 439 | .canary = 0xc3a701ba, | |
| 440 | .check_write_after_free = true, | |
| 441 | }); | |
| 442 | defer if (testing.allocator_instance.deinit() != 0) std.process.exit(1); | |
| 435 | 443 | is_fuzz_test = false; |
| 436 | 444 | |
| 437 | 445 | builtin.test_functions[fuzz_runner.indexes[i]].func() catch |err| switch (err) { |
| ... | ... | @@ -554,8 +562,11 @@ pub fn fuzz( |
| 554 | 562 | |
| 555 | 563 | fn test_one() callconv(.c) bool { |
| 556 | 564 | @disableInstrumentation(); |
| 557 | testing.allocator_instance = .{}; | |
| 558 | defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1); | |
| 565 | testing.allocator_instance = .init(std.heap.page_allocator, .{ | |
| 566 | .canary = 0xcacce5e0, | |
| 567 | .check_write_after_free = true, | |
| 568 | }); | |
| 569 | defer if (testing.allocator_instance.deinit() != 0) std.process.exit(1); | |
| 559 | 570 | log_err_count = 0; |
| 560 | 571 | testOne(ctx, @constCast(&testing.Smith{ .in = null })) catch |err| switch (err) { |
| 561 | 572 | error.SkipZigTest => return true, |
| ... | ... | @@ -582,7 +593,6 @@ pub fn fuzz( |
| 582 | 593 | if (builtin.fuzz) { |
| 583 | 594 | // Preserve the calling test's allocator state |
| 584 | 595 | const prev_allocator_state = testing.allocator_instance; |
| 585 | testing.allocator_instance = .{}; | |
| 586 | 596 | defer testing.allocator_instance = prev_allocator_state; |
| 587 | 597 | |
| 588 | 598 | global.ctx = context; |
lib/fuzzer.zig+3-3| ... | ... | @@ -39,10 +39,10 @@ fn logOverride( |
| 39 | 39 | fw.interface.flush() catch panic("failed to write to fuzzer log: {t}", .{fw.err.?}); |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | var debug_allocator: std.heap.DebugAllocator(.{}) = .init; | |
| 42 | var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 43 | 43 | const gpa = switch (builtin.mode) { |
| 44 | .Debug => debug_allocator.allocator(), | |
| 45 | .ReleaseFast, .ReleaseSmall, .ReleaseSafe => std.heap.smp_allocator, | |
| 44 | .Debug, .ReleaseSafe => safe_allocator.allocator(), | |
| 45 | .ReleaseFast, .ReleaseSmall => std.heap.smp_allocator, | |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | 48 | // Seperate from `exec` to allow initialization before `exec` is. |
lib/std/heap/ArenaAllocator.zig+3-5| ... | ... | @@ -671,12 +671,10 @@ test "reset while retaining a buffer" { |
| 671 | 671 | |
| 672 | 672 | // Create two internal buffers |
| 673 | 673 | _ = try a.alloc(u8, 1); |
| 674 | _ = try a.alloc(u8, 1000); | |
| 675 | ||
| 676 | 674 | try std.testing.expect(arena_allocator.state.used_list != null); |
| 677 | ||
| 678 | // Check that we have at least two buffers | |
| 679 | try std.testing.expect(arena_allocator.state.used_list.?.next != null); | |
| 675 | while (arena_allocator.state.used_list.?.next == null) { | |
| 676 | _ = try a.alloc(u8, 1000); | |
| 677 | } | |
| 680 | 678 | |
| 681 | 679 | // This retains the first allocated buffer |
| 682 | 680 | try std.testing.expect(arena_allocator.reset(.{ .retain_with_limit = 2 })); |
lib/std/mem.zig+12-6| ... | ... | @@ -201,9 +201,12 @@ test "Allocator.resize" { |
| 201 | 201 | defer testing.allocator.free(values); |
| 202 | 202 | |
| 203 | 203 | for (values, 0..) |*v, i| v.* = @as(T, @intCast(i)); |
| 204 | if (!testing.allocator.resize(values, values.len + 10)) return error.OutOfMemory; | |
| 205 | values = values.ptr[0 .. values.len + 10]; | |
| 206 | try testing.expect(values.len == 110); | |
| 204 | if (testing.allocator.resize(values, values.len + 10)) { | |
| 205 | values = values.ptr[0 .. values.len + 10]; | |
| 206 | try testing.expect(values.len == 110); | |
| 207 | } else { | |
| 208 | // `resize` is not guaranteed to succeed even if there is sufficient memory. | |
| 209 | } | |
| 207 | 210 | } |
| 208 | 211 | |
| 209 | 212 | const primitiveFloatTypes = .{ |
| ... | ... | @@ -217,9 +220,12 @@ test "Allocator.resize" { |
| 217 | 220 | defer testing.allocator.free(values); |
| 218 | 221 | |
| 219 | 222 | for (values, 0..) |*v, i| v.* = @as(T, @floatFromInt(i)); |
| 220 | if (!testing.allocator.resize(values, values.len + 10)) return error.OutOfMemory; | |
| 221 | values = values.ptr[0 .. values.len + 10]; | |
| 222 | try testing.expect(values.len == 110); | |
| 223 | if (testing.allocator.resize(values, values.len + 10)) { | |
| 224 | values = values.ptr[0 .. values.len + 10]; | |
| 225 | try testing.expect(values.len == 110); | |
| 226 | } else { | |
| 227 | // `resize` is not guaranteed to succeed even if there is sufficient memory. | |
| 228 | } | |
| 223 | 229 | } |
| 224 | 230 | } |
| 225 | 231 |
lib/std/start.zig+7-8| ... | ... | @@ -710,12 +710,11 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { |
| 710 | 710 | /// General error message for a malformed return type |
| 711 | 711 | const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; |
| 712 | 712 | |
| 713 | const use_debug_allocator = !is_wasm and switch (builtin.mode) { | |
| 714 | .Debug => true, | |
| 715 | .ReleaseSafe => !builtin.link_libc, // Not ideal, but the best we have for now. | |
| 713 | const use_safe_allocator = !is_wasm and switch (builtin.mode) { | |
| 714 | .Debug, .ReleaseSafe => true, | |
| 716 | 715 | .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal. |
| 717 | 716 | }; |
| 718 | var debug_allocator: std.heap.DebugAllocator(.{}) = .init; | |
| 717 | var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 719 | 718 | |
| 720 | 719 | inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.Block) u8 { |
| 721 | 720 | const fn_info = @typeInfo(@TypeOf(root.main)).@"fn"; |
| ... | ... | @@ -725,8 +724,8 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B |
| 725 | 724 | .environ = .{ .block = environ }, |
| 726 | 725 | })); |
| 727 | 726 | |
| 728 | const gpa = if (use_debug_allocator) | |
| 729 | debug_allocator.allocator() | |
| 727 | const gpa = if (use_safe_allocator) | |
| 728 | safe_allocator.allocator() | |
| 730 | 729 | else if (builtin.link_libc) |
| 731 | 730 | std.heap.c_allocator |
| 732 | 731 | else if (is_wasm) |
| ... | ... | @@ -736,8 +735,8 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B |
| 736 | 735 | else |
| 737 | 736 | comptime unreachable; |
| 738 | 737 | |
| 739 | defer if (use_debug_allocator) { | |
| 740 | _ = debug_allocator.deinit(); // Leaks do not affect return code. | |
| 738 | defer if (use_safe_allocator) { | |
| 739 | _ = safe_allocator.deinit(); // Leaks do not affect return code. | |
| 741 | 740 | }; |
| 742 | 741 | |
| 743 | 742 | const arena_backing_allocator = if (is_wasm) gpa else std.heap.page_allocator; |
lib/std/testing.zig+5-13| ... | ... | @@ -17,19 +17,11 @@ var failing_allocator_instance = FailingAllocator.init(base_allocator_instance.a |
| 17 | 17 | }); |
| 18 | 18 | var base_allocator_instance = std.heap.FixedBufferAllocator.init(""); |
| 19 | 19 | |
| 20 | /// This should only be used in temporary test programs. | |
| 21 | pub const allocator = allocator_instance.allocator(); | |
| 22 | pub var allocator_instance: std.heap.DebugAllocator(.{ | |
| 23 | .stack_trace_frames = if (std.debug.sys_can_stack_trace) 10 else 0, | |
| 24 | .resize_stack_traces = true, | |
| 25 | // A unique value so that when a default-constructed | |
| 26 | // DebugAllocator is incorrectly passed to testing allocator, or | |
| 27 | // vice versa, panic occurs. | |
| 28 | .canary = @truncate(0x2731e675c3a701ba), | |
| 29 | }) = b: { | |
| 30 | if (!builtin.is_test) @compileError("testing allocator used when not testing"); | |
| 31 | break :b .init; | |
| 32 | }; | |
| 20 | pub var allocator_instance: std.heap.SafeAllocator = undefined; | |
| 21 | pub const allocator = if (builtin.is_test) | |
| 22 | allocator_instance.allocator() | |
| 23 | else | |
| 24 | @compileError("not testing"); | |
| 33 | 25 | |
| 34 | 26 | pub var io_instance: Io.Threaded = undefined; |
| 35 | 27 | pub const io = if (builtin.is_test) io_instance.io() else @compileError("not testing"); |
src/main.zig+16-21| ... | ... | @@ -157,34 +157,29 @@ pub fn log( |
| 157 | 157 | std.log.defaultLog(level, scope, format, args); |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | const use_debug_allocator = build_options.debug_gpa or | |
| 160 | const use_safe_allocator = build_options.debug_gpa or | |
| 161 | 161 | (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) { |
| 162 | 162 | .Debug, .ReleaseSafe => true, |
| 163 | 163 | .ReleaseFast, .ReleaseSmall => false, |
| 164 | 164 | }); |
| 165 | 165 | |
| 166 | const RootAllocator = if (use_debug_allocator) std.heap.DebugAllocator(.{ | |
| 166 | // TODO: The `align(@alignOf(std.heap.SafeAllocator))` can be removed the next time zig1.wasm is updated | |
| 167 | var safe_allocator: std.heap.SafeAllocator align(@alignOf(std.heap.SafeAllocator)) = .init(std.heap.page_allocator, .{ | |
| 167 | 168 | .stack_trace_frames = build_options.mem_leak_frames, |
| 168 | .thread_safe = switch (build_options.io_mode) { | |
| 169 | .threaded => true, | |
| 170 | .evented => false, | |
| 171 | }, | |
| 172 | }) else struct { | |
| 173 | pub const init: RootAllocator = .{}; | |
| 174 | pub fn allocator(_: RootAllocator) Allocator { | |
| 175 | if (native_os == .wasi) return std.heap.wasm_allocator; | |
| 176 | if (builtin.link_libc) return std.heap.c_allocator; | |
| 177 | return std.heap.smp_allocator; | |
| 178 | } | |
| 179 | pub fn deinit(_: RootAllocator) std.heap.Check { | |
| 180 | return .ok; | |
| 181 | } | |
| 182 | }; | |
| 169 | }); | |
| 183 | 170 | |
| 184 | 171 | pub fn main(init: std.process.Init.Minimal) anyerror!void { |
| 185 | var root_allocator: RootAllocator = .init; | |
| 186 | defer _ = root_allocator.deinit(); | |
| 187 | const root_gpa = root_allocator.allocator(); | |
| 172 | const root_gpa = if (use_safe_allocator) | |
| 173 | safe_allocator.allocator() | |
| 174 | else if (native_os == .wasi) | |
| 175 | std.heap.wasm_allocator | |
| 176 | else if (builtin.link_libc) | |
| 177 | std.heap.c_allocator | |
| 178 | else | |
| 179 | std.heap.smp_allocator; | |
| 180 | defer if (use_safe_allocator) { | |
| 181 | _ = safe_allocator.deinit(); | |
| 182 | }; | |
| 188 | 183 | var io_impl: IoImpl = undefined; |
| 189 | 184 | switch (build_options.io_mode) { |
| 190 | 185 | .threaded => io_impl = .init(root_gpa, .{ |
| ... | ... | @@ -197,7 +192,7 @@ pub fn main(init: std.process.Init.Minimal) anyerror!void { |
| 197 | 192 | .argv0 = .init(init.args), |
| 198 | 193 | .environ = init.environ, |
| 199 | 194 | |
| 200 | .backing_allocator_needs_mutex = use_debug_allocator, | |
| 195 | .backing_allocator_needs_mutex = false, | |
| 201 | 196 | }), |
| 202 | 197 | } |
| 203 | 198 | defer io_impl.deinit(); |