From 0c3d08e9676a7defd16b88307838f7294d28c3e5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 28 Oct 2018 08:26:47 -0700 Subject: [PATCH] std: Improve codegen size of accessing TLS Some code in the TLS implementation in libstd stores `Some(val)` into an `&mut Option` (effectively) and then pulls out `&T`, but it currently uses `.unwrap()` which can codegen into a panic even though it can never panic. With sufficient optimizations enabled (like LTO) the compiler can see through this but this commit helps it along in normal mode (`--release` with Cargo by default) to avoid codegen'ing the panic path. This ends up improving the optimized codegen on wasm by ensuring that a call to panic pulling in more file size doesn't stick around. --- src/libstd/thread/local.rs | 11 ++++++++++- src/test/run-make/wasm-panic-small/Makefile | 3 +++ src/test/run-make/wasm-panic-small/foo.rs | 8 ++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 59f100fad1bb9..ccbead7cc2f77 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -14,6 +14,7 @@ use cell::UnsafeCell; use fmt; +use hint; use mem; /// A thread local storage key which owns its contents. @@ -275,7 +276,15 @@ impl LocalKey { // operations a little differently and make this safe to call. mem::replace(&mut *ptr, Some(value)); - (*ptr).as_ref().unwrap() + // After storing `Some` we want to get a reference to the contents of + // what we just stored. While we could use `unwrap` here and it should + // always work it empirically doesn't seem to always get optimized away, + // which means that using something like `try_with` can pull in + // panicking code and cause a large size bloat. + match *ptr { + Some(ref x) => x, + None => hint::unreachable_unchecked(), + } } /// Acquires a reference to the value in this TLS key. diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile index 330ae300c445e..48b530c995725 100644 --- a/src/test/run-make/wasm-panic-small/Makefile +++ b/src/test/run-make/wasm-panic-small/Makefile @@ -11,6 +11,9 @@ all: $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c wc -c < $(TMPDIR)/foo.wasm [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ] + $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg d + wc -c < $(TMPDIR)/foo.wasm + [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ] else all: endif diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs index 1ea724ca94d47..441e92976a396 100644 --- a/src/test/run-make/wasm-panic-small/foo.rs +++ b/src/test/run-make/wasm-panic-small/foo.rs @@ -27,3 +27,11 @@ pub fn foo() { pub fn foo() { panic!("{}", "a"); } + +#[no_mangle] +#[cfg(d)] +pub fn foo() -> usize { + use std::cell::Cell; + thread_local!(static A: Cell> = Cell::new(Vec::new())); + A.try_with(|x| x.replace(Vec::new()).len()).unwrap_or(0) +}