std: Improve codegen size of accessing TLS
Some code in the TLS implementation in libstd stores `Some(val)` into an `&mut Option<T>` (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.
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
use cell::UnsafeCell;
|
use cell::UnsafeCell;
|
||||||
use fmt;
|
use fmt;
|
||||||
|
use hint;
|
||||||
use mem;
|
use mem;
|
||||||
|
|
||||||
/// A thread local storage key which owns its contents.
|
/// A thread local storage key which owns its contents.
|
||||||
@@ -275,7 +276,15 @@ impl<T: 'static> LocalKey<T> {
|
|||||||
// operations a little differently and make this safe to call.
|
// operations a little differently and make this safe to call.
|
||||||
mem::replace(&mut *ptr, Some(value));
|
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.
|
/// Acquires a reference to the value in this TLS key.
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ all:
|
|||||||
$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c
|
$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c
|
||||||
wc -c < $(TMPDIR)/foo.wasm
|
wc -c < $(TMPDIR)/foo.wasm
|
||||||
[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
|
[ "`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
|
else
|
||||||
all:
|
all:
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -27,3 +27,11 @@ pub fn foo() {
|
|||||||
pub fn foo() {
|
pub fn foo() {
|
||||||
panic!("{}", "a");
|
panic!("{}", "a");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
#[cfg(d)]
|
||||||
|
pub fn foo() -> usize {
|
||||||
|
use std::cell::Cell;
|
||||||
|
thread_local!(static A: Cell<Vec<u32>> = Cell::new(Vec::new()));
|
||||||
|
A.try_with(|x| x.replace(Vec::new()).len()).unwrap_or(0)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user