Fuchsia support for std::process via liblaunchpad.
Now we can launch processes on Fuchsia via the Rust standard library! ... Mostly.
Right now, ~5% of the time, reading the stdout/stderr off the pipes will fail. Some Magenta kernel people think it's probably a bug in Magenta's pipes. I wrote a unit test that demonstrates the issue in C, which I was told will expedite a fix. https://fuchsia-review.googlesource.com/#/c/15628/
Hopefully this can get merged once the issue is fixed :)
@raphlinus
limit the length of types in monomorphization
This adds the new insta-stable `#![type_size_limit]` crate attribute to control
the limit, and is obviously a [breaking-change] fixable by that.
Fixes#37311.
r? @nikomatsakis
The `visit_fn` code mutates its surrounding context. Between *items*,
this was saved/restored, but between impl items it was not. This meant
that we wound up with `CallSiteScope` entries with two parents (or
more!). As far as I can tell, this is harmless in actual type-checking,
since the regions you interact with are always from at most one of those
branches. But it can slow things down.
Before, the effect was limited, since it only applied to impl items
within an impl. After #37660, impl items are visisted all together at
the end, and hence this could create a very messed up
hierarchy. Isolating impl item properly solves both issues.
I cannot come up with a way to unit-test this; for posterity, however,
you can observe the messed up hierarchies with a test as simple as the
following, which would create a callsite scope with two parents both
before and after
```
struct Foo {
}
impl Foo {
fn bar(&self) -> usize {
22
}
fn baz(&self) -> usize {
22
}
}
fn main() { }
```
Fixes#37864.
the .git directory is modified by `bootstrap` when it updates this git
submodule; this triggered rebuilds every time `bootstrap` was called.
likely fixes#38094
This causes us to dump a bunch of has information to stdout that can be
useful in tracking down incremental compilation invalidations,
particularly across crates.
[LLVM 4.0] Don't assume llvm::StringRef is null terminated
StringRefs have a length and their contents are not usually null-terminated. The solution is to either copy the string data (in `rustc_llvm::diagnostic`) or take the size into account (in LLVMRustPrintPasses).
I couldn't trigger a bug caused by this (apparently all the strings returned in practice are actually null-terminated) but this is more correct and more future-proof.
cc #37609
rustdoc: get back missing crate-name when --playground-url is used
follow up PR #37763
r? @alexcrichton (since you r+ed to #37763 )
----
Edit: When `#![doc(html_playground_url="")]` is used, the current crate name is saved to `PLAYGROUND`, so rustdoc may generate `extern crate NAME;` into code snips automatically. But when `--playground-url` was introduced in PR #37763, I forgot saving crate name to `PLAYGROUND`. This PR fix that.
----
Update:
- add test
- unstable `--playground-url`
Add small-copy optimization for copy_from_slice
## Summary
During benchmarking, I found that one of my programs spent between 5 and 10 percent of the time doing memmoves. Ultimately I tracked these down to single-byte slices being copied with a memcopy. Doing a manual copy if the slice contains only one element can speed things up significantly. For my program, this reduced the running time by 20%.
## Background
I am optimizing a program that relies heavily on reading a single byte at a time. To avoid IO overhead, I read all data into a vector once, and then I use a `Cursor` around that vector to read from. During profiling, I noticed that `__memmove_avx_unaligned_erms` was hot, taking up 7.3% of the running time. It turns out that these were caused by calls to `Cursor::read()`, which calls `<&[u8] as Read>::read()`, which calls `&[T]::copy_from_slice()`, which calls `ptr::copy_nonoverlapping()`. This one is implemented as a memcopy. Copying a single byte with a memcopy is very wasteful, because (at least on my platform) it involves calling `memcpy` in libc. This is an indirect call when libc is linked dynamically, and furthermore `memcpy` is optimized for copying large amounts of data at the cost of a bit of overhead for small copies.
## Benchmarks
Before I made this change, `perf` reported the following for my program. I only included the relevant functions, and how they rank. (This is on a different machine than where I ran the original benchmarks. It has an older CPU, so `__memmove_sse2_unaligned_erms` is called instead of `__memmove_avx_unaligned_erms`.)
```
#3 5.47% bench_decode libc-2.24.so [.] __memmove_sse2_unaligned_erms
#5 1.67% bench_decode libc-2.24.so [.] memcpy@GLIBC_2.2.5
#6 1.51% bench_decode bench_decode [.] memcpy@plt
```
`memcpy` is eating up 8.65% of the total running time, and the overhead of dispatching to a specialized fast copy function (`memcpy@GLIBC` showing up) is clearly visible. The price of dynamic linking (`memcpy@plt` showing up) is visible too.
After this change, this is what `perf` reports:
```
#5 0.33% bench_decode libc-2.24.so [.] __memmove_sse2_unaligned_erms
#14 0.01% bench_decode libc-2.24.so [.] memcpy@GLIBC_2.2.5
```
Now only 0.34% of the running time is spent on memcopies. The dynamic linking overhead is not significant at all any more.
To add some more data, my program generates timing results for the operation in its main loop. These are the timings before and after the change:
| Time before | Time after | After/Before |
|---------------|---------------|--------------|
| 29.8 ± 0.8 ns | 23.6 ± 0.5 ns | 0.79 ± 0.03 |
The time is basically the total running time divided by a constant; the actual numbers are not important. This change reduced the total running time by 21% (much more than the original 9% spent on memmoves, likely because the CPU is stalling a lot less because data dependencies are more transparent). Of course YMMV and for most programs this will not matter at all. But when it does, the gains can be significant!
## Alternatives
* At first I implemented this in `io::Cursor`. I moved it to `&[T]::copy_from_slice()` instead, but this might be too intrusive, especially because it applies to all `T`, not just `u8`. To restrict this to `io::Read`, `<&[u8] as Read>::read()` is probably the best place.
* I tried copying bytes in a loop up to 64 or 8 bytes before calling `Read::read`, but both resulted in about a 20% slowdown instead of speedup.
This adds a CommandExt trait for Windows along with an implementation of it
for std::process::Command with methods to set the process creation flags that
are passed to CreateProcess.
Make core::fmt::Void a non-empty type.
Adding back this change that was removed from PR #36449 because it's a fix and because I immediately hit a problem with it again when I started implementing my fix for #12609.
Some notes:
* This code attempts to present the breakdown of each variant for
every enum in the MIR. This is meant to guide decisions about how to
revise representations e.g. when to box payloads for rare variants
to shrink the size of the enum overall.
* I left out the "Total:" line that hir-stats presents, because this
implementation uses the MIR Visitor infrastructure, and the memory
usage of structures directly embedded in other structures (e.g. the
`func: Operand` in a `TerminatorKind:Call`) is not distinguished
from similar structures allocated in a `Vec` (e.g. the `args:
Vec<Operand>` in a `TerminatorKind::Call`). This means that a naive
summation of all the accumulated sizes is misleading, because it
will double-count the contribution of the `Operand` of the `func` as
well as the size of the whole `TerminatorKind`.
* I did consider abandoning the MIR Visitor and instead hand-coding
a traversal that distinguished embedded storage from indirect
storage. But such code would be fragile; better to just require
people to take care when interpreting the presented results.
* This traverses the `mir.promoted` rvalues to capture stats for MIR
stored there, even though the MIR visitor super_mir method does not
do so. (I did not observe any new mir being traversed when compiling
the rustc crate, however.)
* It might be nice to try to unify this code with hir-stats. Then
again, the reporting portion is the only common code (I think), and
it is small compared to the visitors in hir-stats and mir-stats.
Based on the discussion in https://github.com/rust-lang/rust/pull/37573,
it is likely better to keep this limited to std::io, instead of
modifying a function which users expect to be a memcpy.
Ultimately copy_from_slice is being a bottleneck, not io::Cursor::read.
It might be worthwhile to move the check here, so more places can
benefit from it.
During benchmarking, I found that one of my programs spent between 5 and
10 percent of the time doing memmoves. Ultimately I tracked these down
to single-byte slices being copied with a memcopy in io::Cursor::read().
Doing a manual copy if only one byte is requested can speed things up
significantly. For my program, this reduced the running time by 20%.
Why special-case only a single byte, and not a "small" slice in general?
I tried doing this for slices of at most 64 bytes and of at most 8
bytes. In both cases my test program was significantly slower.
rustdoc: link to cross-crate sources directly.
Fixes#37684 by implementing proper support for getting the `Span` of definitions across crates.
In rustdoc this is used to generate direct links to the original source instead of fragile redirects.
This functionality could be expanded further for making error reporting code more uniform and seamless across crates, although at the moment there is no actual source to print, only file/line/column information.
Closes#37870 which is also "fixes" #37684 by throwing away the builtin macro docs from libcore.
After this lands, #37727 could be reverted, although it doesn't matter much either way.