authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-15 20:15:19-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-16 03:17:15-04:00
logcaefaf781e22a7b053426621719a6f1d0f69d7cb
treed77cc3e0e7841a83d6dbfa438a6f256396ff7c39
parent88724217dd1e1fe4b20fed27c8a662b66df55088

std.debug: dumpStackTrace & friends use DirectAllocator

this has the downside of failing to print a stack trace when the system is out of memory (maybe we could add a FallbackAllocator which tries DirectAllocator and falls back on the 200KB preallocated buffer). but for the more common use case when the system is not out of memory, but the debug info cannot fit in std.debug.global_allocator, now stack traces will work. this is the case for the self hosted compiler.

1 files changed, 20 insertions(+), 5 deletions(-)

std/debug/index.zig+20-5
...@@ -38,7 +38,7 @@ pub fn getSelfDebugInfo() !&ElfStackTrace {...@@ -38,7 +38,7 @@ pub fn getSelfDebugInfo() !&ElfStackTrace {
38 if (self_debug_info) |info| {38 if (self_debug_info) |info| {
39 return info;39 return info;
40 } else {40 } else {
41 const info = try openSelfDebugInfo(global_allocator);41 const info = try openSelfDebugInfo(getDebugInfoAllocator());
42 self_debug_info = info;42 self_debug_info = info;
43 return info;43 return info;
44 }44 }
...@@ -51,7 +51,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {...@@ -51,7 +51,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
51 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;51 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;
52 return;52 return;
53 };53 };
54 writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty(), start_addr) catch |err| {54 writeCurrentStackTrace(stderr, getDebugInfoAllocator(), debug_info, stderr_file.isTty(), start_addr) catch |err| {
55 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;55 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;
56 return;56 return;
57 };57 };
...@@ -64,7 +64,7 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void {...@@ -64,7 +64,7 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void {
64 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;64 stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return;
65 return;65 return;
66 };66 };
67 writeStackTrace(stack_trace, stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| {67 writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, stderr_file.isTty()) catch |err| {
68 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;68 stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return;
69 return;69 return;
70 };70 };
...@@ -592,8 +592,8 @@ fn getString(st: &ElfStackTrace, offset: u64) ![]u8 {...@@ -592,8 +592,8 @@ fn getString(st: &ElfStackTrace, offset: u64) ![]u8 {
592}592}
593593
594fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8 {594fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8 {
595 const buf = try global_allocator.alloc(u8, size);595 const buf = try allocator.alloc(u8, size);
596 errdefer global_allocator.free(buf);596 errdefer allocator.free(buf);
597 if ((try in_stream.read(buf)) < size) return error.EndOfFile;597 if ((try in_stream.read(buf)) < size) return error.EndOfFile;
598 return buf;598 return buf;
599}599}
...@@ -1126,6 +1126,21 @@ fn readILeb128(in_stream: var) !i64 {...@@ -1126,6 +1126,21 @@ fn readILeb128(in_stream: var) !i64 {
1126 }1126 }
1127}1127}
11281128
1129/// This should only be used in temporary test programs.
1129pub const global_allocator = &global_fixed_allocator.allocator;1130pub const global_allocator = &global_fixed_allocator.allocator;
1130var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]);1131var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]);
1131var global_allocator_mem: [100 * 1024]u8 = undefined;1132var global_allocator_mem: [100 * 1024]u8 = undefined;
1133
1134
1135// TODO make thread safe
1136var debug_info_allocator: ?&mem.Allocator = null;
1137var debug_info_direct_allocator: std.heap.DirectAllocator = undefined;
1138var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;
1139fn getDebugInfoAllocator() &mem.Allocator {
1140 if (debug_info_allocator) |a| return a;
1141
1142 debug_info_direct_allocator = std.heap.DirectAllocator.init();
1143 debug_info_arena_allocator = std.heap.ArenaAllocator.init(&debug_info_direct_allocator.allocator);
1144 debug_info_allocator = &debug_info_arena_allocator.allocator;
1145 return &debug_info_arena_allocator.allocator;
1146}