| author | |
| committer | |
| log | f45f9649e3fc2aa2b6a76476f2467f02ffc7d461 |
| tree | 4d10ac814ef9d7d7e9f06fffac796217336bfbc5 |
| parent | 9f235a105b29c6f1c0c773f66c40e7ee655da559 |
Emscripten currently implements `emscripten_return_address()` by calling
out into JavaScript and parsing a stack trace, which introduces
significant overhead that we would prefer to avoid in release builds.
This is especially problematic for allocators because the generic parts
of `std.mem.Allocator` make frequent use of `@returnAddress`, even
though very few allocator implementations even observe the return
address, which makes allocators nigh unusable for performance-critical
applications like games if the compiler is unable to devirtualize the
allocator calls.3 files changed, 11 insertions(+), 4 deletions(-)
lib/std/debug.zig+3-1| ... | ... | @@ -183,9 +183,11 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) { |
| 183 | 183 | |
| 184 | 184 | // `@returnAddress()` in LLVM 10 gives |
| 185 | 185 | // "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address". |
| 186 | // On Emscripten, Zig only supports `@returnAddress()` in debug builds | |
| 187 | // because Emscripten's implementation is very slow. | |
| 186 | 188 | .wasm32, |
| 187 | 189 | .wasm64, |
| 188 | => native_os == .emscripten, | |
| 190 | => native_os == .emscripten and builtin.mode == .Debug, | |
| 189 | 191 | |
| 190 | 192 | // `@returnAddress()` is unsupported in LLVM 13. |
| 191 | 193 | .bpfel, |
src/codegen/llvm.zig+1-1| ... | ... | @@ -9525,7 +9525,7 @@ pub const FuncGen = struct { |
| 9525 | 9525 | _ = inst; |
| 9526 | 9526 | const o = self.ng.object; |
| 9527 | 9527 | const llvm_usize = try o.lowerType(Type.usize); |
| 9528 | if (!target_util.supportsReturnAddress(o.pt.zcu.getTarget())) { | |
| 9528 | if (!target_util.supportsReturnAddress(o.pt.zcu.getTarget(), self.ng.ownerModule().optimize_mode)) { | |
| 9529 | 9529 | // https://github.com/ziglang/zig/issues/11946 |
| 9530 | 9530 | return o.builder.intValue(llvm_usize, 0); |
| 9531 | 9531 | } |
src/target.zig+7-2| ... | ... | @@ -248,9 +248,14 @@ pub fn libcProvidesStackProtector(target: std.Target) bool { |
| 248 | 248 | return !target.isMinGW() and target.os.tag != .wasi and !target.cpu.arch.isSpirV(); |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | pub fn supportsReturnAddress(target: std.Target) bool { | |
| 251 | /// Returns true if `@returnAddress()` is supported by the target and has a | |
| 252 | /// reasonably performant implementation for the requested optimization mode. | |
| 253 | pub fn supportsReturnAddress(target: std.Target, optimize: std.builtin.OptimizeMode) bool { | |
| 252 | 254 | return switch (target.cpu.arch) { |
| 253 | .wasm32, .wasm64 => target.os.tag == .emscripten, | |
| 255 | // Emscripten currently implements `emscripten_return_address()` by calling | |
| 256 | // out into JavaScript and parsing a stack trace, which introduces significant | |
| 257 | // overhead that we would prefer to avoid in release builds. | |
| 258 | .wasm32, .wasm64 => target.os.tag == .emscripten and optimize == .Debug, | |
| 254 | 259 | .bpfel, .bpfeb => false, |
| 255 | 260 | .spirv, .spirv32, .spirv64 => false, |
| 256 | 261 | else => true, |