From 10a5f28ff4580b5bb143e744c62340886e67682a Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 8 May 2022 20:21:25 -0400 Subject: [PATCH 01/10] Switch CI bucket to intelligent tiering We currently upload approximately 166 GB/day into this bucket (estimate based on duration of storage and total current size). My estimate is that this change should decrease our costs (which are currently in credits) and is in the worst case (if all objects are brought into hot storage due to unanticipated frequent access) only going to add an additional ~$4 to the monthly bill. If access is rare (as expected) to most objects then we expect to save approximately ~$350/month (after this change takes full effect in ~168 days). --- src/ci/scripts/upload-artifacts.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index 312ec9d805012..cea9b770f2a20 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -38,4 +38,5 @@ if [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then fi deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)" -retry aws s3 cp --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}" +retry aws s3 cp --storage-class INTELLIGENT_TIERING \ + --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}" From 1c1f16c3e3222d9e8d0b17285244e6155fc69db3 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 13 May 2022 13:04:48 +0000 Subject: [PATCH 02/10] Move cgu_reuse a bit earlier There is no reason it needs to be lazily computed at the first iteration of the cgu loop. --- compiler/rustc_codegen_ssa/src/base.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 7b7e09208a24a..4bee274901673 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -607,6 +607,11 @@ pub fn codegen_crate( second_half.iter().rev().interleave(first_half).copied().collect() }; + // Calculate the CGU reuse + let cgu_reuse = tcx.sess.time("find_cgu_reuse", || { + codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::>() + }); + // The non-parallel compiler can only translate codegen units to LLVM IR // on a single thread, leading to a staircase effect where the N LLVM // threads have to wait on the single codegen threads to generate work @@ -618,7 +623,7 @@ pub fn codegen_crate( // non-parallel compiler anymore, we can compile CGUs end-to-end in // parallel and get rid of the complicated scheduling logic. #[cfg(parallel_compiler)] - let pre_compile_cgus = |cgu_reuse: &[CguReuse]| { + let pre_compile_cgus = || { tcx.sess.time("compile_first_CGU_batch", || { // Try to find one CGU to compile per thread. let cgus: Vec<_> = cgu_reuse @@ -643,9 +648,8 @@ pub fn codegen_crate( }; #[cfg(not(parallel_compiler))] - let pre_compile_cgus = |_: &[CguReuse]| (FxHashMap::default(), Duration::new(0, 0)); + let pre_compile_cgus = || (FxHashMap::default(), Duration::new(0, 0)); - let mut cgu_reuse = Vec::new(); let mut pre_compiled_cgus: Option> = None; let mut total_codegen_time = Duration::new(0, 0); let start_rss = tcx.sess.time_passes().then(|| get_resident_set_size()); @@ -656,12 +660,8 @@ pub fn codegen_crate( // Do some setup work in the first iteration if pre_compiled_cgus.is_none() { - // Calculate the CGU reuse - cgu_reuse = tcx.sess.time("find_cgu_reuse", || { - codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect() - }); // Pre compile some CGUs - let (compiled_cgus, codegen_time) = pre_compile_cgus(&cgu_reuse); + let (compiled_cgus, codegen_time) = pre_compile_cgus(); pre_compiled_cgus = Some(compiled_cgus); total_codegen_time += codegen_time; } From a06deb519173b07932b4718cdbd90e47feca17cd Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 13 May 2022 13:17:07 +0000 Subject: [PATCH 03/10] Compute pre_compiled_cgus more eagerly This reduces the complexity of this code a lot --- compiler/rustc_codegen_ssa/src/base.rs | 47 +++++++++++--------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 4bee274901673..d11f1534153ad 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -15,8 +15,9 @@ use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; +use rustc_data_structures::sync::par_iter; #[cfg(parallel_compiler)] -use rustc_data_structures::sync::{par_iter, ParallelIterator}; +use rustc_data_structures::sync::ParallelIterator; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; @@ -612,6 +613,9 @@ pub fn codegen_crate( codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::>() }); + let mut total_codegen_time = Duration::new(0, 0); + let start_rss = tcx.sess.time_passes().then(|| get_resident_set_size()); + // The non-parallel compiler can only translate codegen units to LLVM IR // on a single thread, leading to a staircase effect where the N LLVM // threads have to wait on the single codegen threads to generate work @@ -622,8 +626,7 @@ pub fn codegen_crate( // This likely is a temporary measure. Once we don't have to support the // non-parallel compiler anymore, we can compile CGUs end-to-end in // parallel and get rid of the complicated scheduling logic. - #[cfg(parallel_compiler)] - let pre_compile_cgus = || { + let mut pre_compiled_cgus = if cfg!(parallel_compiler) { tcx.sess.time("compile_first_CGU_batch", || { // Try to find one CGU to compile per thread. let cgus: Vec<_> = cgu_reuse @@ -643,43 +646,31 @@ pub fn codegen_crate( }) .collect(); - (pre_compiled_cgus, start_time.elapsed()) + total_codegen_time += start_time.elapsed(); + + pre_compiled_cgus }) + } else { + FxHashMap::default() }; - #[cfg(not(parallel_compiler))] - let pre_compile_cgus = || (FxHashMap::default(), Duration::new(0, 0)); - - let mut pre_compiled_cgus: Option> = None; - let mut total_codegen_time = Duration::new(0, 0); - let start_rss = tcx.sess.time_passes().then(|| get_resident_set_size()); - for (i, cgu) in codegen_units.iter().enumerate() { ongoing_codegen.wait_for_signal_to_codegen_item(); ongoing_codegen.check_for_errors(tcx.sess); - // Do some setup work in the first iteration - if pre_compiled_cgus.is_none() { - // Pre compile some CGUs - let (compiled_cgus, codegen_time) = pre_compile_cgus(); - pre_compiled_cgus = Some(compiled_cgus); - total_codegen_time += codegen_time; - } - let cgu_reuse = cgu_reuse[i]; tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); match cgu_reuse { CguReuse::No => { - let (module, cost) = - if let Some(cgu) = pre_compiled_cgus.as_mut().unwrap().remove(&i) { - cgu - } else { - let start_time = Instant::now(); - let module = backend.compile_codegen_unit(tcx, cgu.name()); - total_codegen_time += start_time.elapsed(); - module - }; + let (module, cost) = if let Some(cgu) = pre_compiled_cgus.remove(&i) { + cgu + } else { + let start_time = Instant::now(); + let module = backend.compile_codegen_unit(tcx, cgu.name()); + total_codegen_time += start_time.elapsed(); + module + }; // This will unwind if there are errors, which triggers our `AbortCodegenOnDrop` // guard. Unfortunately, just skipping the `submit_codegened_module_to_llvm` makes // compilation hang on post-monomorphization errors. From 6259670d50b145461f729042be8705444f4d8f78 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 17 May 2022 18:46:11 -0400 Subject: [PATCH 04/10] Revert "Auto merge of #96441 - ChrisDenton:sync-pipes, r=m-ou-se" This reverts commit ddb7fbe8434be481607ae199fe2aee976ee2fc2e, reversing changes made to baaa3b682986879c7784b5733ecea942e9ae7de3. --- library/std/src/os/windows/io/handle.rs | 13 --- library/std/src/sys/windows/c.rs | 6 -- library/std/src/sys/windows/handle.rs | 5 -- library/std/src/sys/windows/pipe.rs | 101 ++++++------------------ library/std/src/sys/windows/process.rs | 38 ++------- 5 files changed, 31 insertions(+), 132 deletions(-) diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 0ecac6b447570..90a5b7466fec4 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -204,19 +204,6 @@ impl OwnedHandle { })?; unsafe { Ok(Self::from_raw_handle(ret)) } } - - /// Allow child processes to inherit the handle. - #[cfg(not(target_vendor = "uwp"))] - pub(crate) fn set_inheritable(&self) -> io::Result<()> { - cvt(unsafe { - c::SetHandleInformation( - self.as_raw_handle(), - c::HANDLE_FLAG_INHERIT, - c::HANDLE_FLAG_INHERIT, - ) - })?; - Ok(()) - } } impl TryFrom for OwnedHandle { diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 0692da1d79519..5f14edaf067c0 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -1022,12 +1022,6 @@ extern "system" { bWaitAll: BOOL, dwMilliseconds: DWORD, ) -> DWORD; - pub fn CreatePipe( - hReadPipe: *mut HANDLE, - hWritePipe: *mut HANDLE, - lpPipeAttributes: *const SECURITY_ATTRIBUTES, - nSize: DWORD, - ) -> BOOL; pub fn CreateNamedPipeW( lpName: LPCWSTR, dwOpenMode: DWORD, diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index c319cb28630f5..ef9a8bd690031 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -221,11 +221,6 @@ impl Handle { Ok(Self(self.0.duplicate(access, inherit, options)?)) } - #[cfg(not(target_vendor = "uwp"))] - pub(crate) fn set_inheritable(&self) -> io::Result<()> { - self.0.set_inheritable() - } - /// Performs a synchronous read. /// /// If the handle is opened for asynchronous I/O then this abort the process. diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index 2c586f1abe433..013c776c476c3 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -18,20 +18,13 @@ use crate::sys_common::IntoInner; // Anonymous pipes //////////////////////////////////////////////////////////////////////////////// -// A 64kb pipe capacity is the same as a typical Linux default. -const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024; - -pub enum AnonPipe { - Sync(Handle), - Async(Handle), +pub struct AnonPipe { + inner: Handle, } impl IntoInner for AnonPipe { fn into_inner(self) -> Handle { - match self { - Self::Sync(handle) => handle, - Self::Async(handle) => handle, - } + self.inner } } @@ -39,46 +32,6 @@ pub struct Pipes { pub ours: AnonPipe, pub theirs: AnonPipe, } -impl Pipes { - /// Create a new pair of pipes where both pipes are synchronous. - /// - /// These must not be used asynchronously. - pub fn new_synchronous( - ours_readable: bool, - their_handle_inheritable: bool, - ) -> io::Result { - unsafe { - // If `CreatePipe` succeeds, these will be our pipes. - let mut read = ptr::null_mut(); - let mut write = ptr::null_mut(); - - if c::CreatePipe(&mut read, &mut write, ptr::null(), PIPE_BUFFER_CAPACITY) == 0 { - Err(io::Error::last_os_error()) - } else { - let (ours, theirs) = if ours_readable { (read, write) } else { (write, read) }; - let ours = Handle::from_raw_handle(ours); - #[cfg(not(target_vendor = "uwp"))] - let theirs = Handle::from_raw_handle(theirs); - #[cfg(target_vendor = "uwp")] - let mut theirs = Handle::from_raw_handle(theirs); - - if their_handle_inheritable { - #[cfg(not(target_vendor = "uwp"))] - { - theirs.set_inheritable()?; - } - - #[cfg(target_vendor = "uwp")] - { - theirs = theirs.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?; - } - } - - Ok(Pipes { ours: AnonPipe::Sync(ours), theirs: AnonPipe::Sync(theirs) }) - } - } - } -} /// Although this looks similar to `anon_pipe` in the Unix module it's actually /// subtly different. Here we'll return two pipes in the `Pipes` return value, @@ -100,6 +53,9 @@ impl Pipes { /// with `OVERLAPPED` instances, but also works out ok if it's only ever used /// once at a time (which we do indeed guarantee). pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result { + // A 64kb pipe capacity is the same as a typical Linux default. + const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024; + // Note that we specifically do *not* use `CreatePipe` here because // unfortunately the anonymous pipes returned do not support overlapped // operations. Instead, we create a "hopefully unique" name and create a @@ -200,9 +156,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res }; opts.security_attributes(&mut sa); let theirs = File::open(Path::new(&name), &opts)?; - let theirs = AnonPipe::Sync(theirs.into_inner()); + let theirs = AnonPipe { inner: theirs.into_inner() }; - Ok(Pipes { ours: AnonPipe::Async(ours), theirs }) + Ok(Pipes { + ours: AnonPipe { inner: ours }, + theirs: AnonPipe { inner: theirs.into_inner() }, + }) } } @@ -212,12 +171,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res /// This is achieved by creating a new set of pipes and spawning a thread that /// relays messages between the source and the synchronous pipe. pub fn spawn_pipe_relay( - source: &Handle, + source: &AnonPipe, ours_readable: bool, their_handle_inheritable: bool, ) -> io::Result { // We need this handle to live for the lifetime of the thread spawned below. - let source = AnonPipe::Async(source.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?); + let source = source.duplicate()?; // create a new pair of anon pipes. let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?; @@ -268,24 +227,19 @@ type AlertableIoFn = unsafe extern "system" fn( impl AnonPipe { pub fn handle(&self) -> &Handle { - match self { - Self::Async(ref handle) => handle, - Self::Sync(ref handle) => handle, - } + &self.inner } pub fn into_handle(self) -> Handle { - self.into_inner() + self.inner + } + fn duplicate(&self) -> io::Result { + self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner }) } pub fn read(&self, buf: &mut [u8]) -> io::Result { let result = unsafe { let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; - match self { - Self::Sync(ref handle) => handle.read(buf), - Self::Async(_) => { - self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len) - } - } + self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len) }; match result { @@ -299,33 +253,28 @@ impl AnonPipe { } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - io::default_read_vectored(|buf| self.read(buf), bufs) + self.inner.read_vectored(bufs) } #[inline] pub fn is_read_vectored(&self) -> bool { - false + self.inner.is_read_vectored() } pub fn write(&self, buf: &[u8]) -> io::Result { unsafe { let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD; - match self { - Self::Sync(ref handle) => handle.write(buf), - Self::Async(_) => { - self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len) - } - } + self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len) } } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - io::default_write_vectored(|buf| self.write(buf), bufs) + self.inner.write_vectored(bufs) } #[inline] pub fn is_write_vectored(&self) -> bool { - false + self.inner.is_write_vectored() } /// Synchronizes asynchronous reads or writes using our anonymous pipe. @@ -397,7 +346,7 @@ impl AnonPipe { // Asynchronous read of the pipe. // If successful, `callback` will be called once it completes. - let result = io(self.handle().as_handle(), buf, len, &mut overlapped, callback); + let result = io(self.inner.as_handle(), buf, len, &mut overlapped, callback); if result == c::FALSE { // We can return here because the call failed. // After this we must not return until the I/O completes. diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 8e5325b80e4a5..9fd399f4ba1d3 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -23,7 +23,7 @@ use crate::sys::cvt; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; use crate::sys::path; -use crate::sys::pipe::{self, AnonPipe, Pipes}; +use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; use crate::sys_common::mutex::StaticMutex; use crate::sys_common::process::{CommandEnv, CommandEnvs}; @@ -172,7 +172,7 @@ pub enum Stdio { Inherit, Null, MakePipe, - AsyncPipe(Handle), + Pipe(AnonPipe), Handle(Handle), } @@ -527,33 +527,13 @@ impl Stdio { }, Stdio::MakePipe => { - // Handles that are passed to a child process must be synchronous - // because they will be read synchronously (see #95759). - // Therefore we prefer to make both ends of a pipe synchronous - // just in case our end of the pipe is passed to another process. - // - // However, we may need to read from both the child's stdout and - // stderr simultaneously when waiting for output. This requires - // async reads so as to avoid blocking either pipe. - // - // The solution used here is to make handles synchronous - // except for our side of the stdout and sterr pipes. - // If our side of those pipes do end up being given to another - // process then we use a "pipe relay" to synchronize access - // (see `Stdio::AsyncPipe` below). - let pipes = if stdio_id == c::STD_INPUT_HANDLE { - // For stdin both sides of the pipe are synchronous. - Pipes::new_synchronous(false, true)? - } else { - // For stdout/stderr our side of the pipe is async and their side is synchronous. - pipe::anon_pipe(true, true)? - }; + let ours_readable = stdio_id != c::STD_INPUT_HANDLE; + let pipes = pipe::anon_pipe(ours_readable, true)?; *pipe = Some(pipes.ours); Ok(pipes.theirs.into_handle()) } - Stdio::AsyncPipe(ref source) => { - // We need to synchronize asynchronous pipes by using a pipe relay. + Stdio::Pipe(ref source) => { let ours_readable = stdio_id != c::STD_INPUT_HANDLE; pipe::spawn_pipe_relay(source, ours_readable, true).map(AnonPipe::into_handle) } @@ -582,13 +562,7 @@ impl Stdio { impl From for Stdio { fn from(pipe: AnonPipe) -> Stdio { - // Note that it's very important we don't give async handles to child processes. - // Therefore if the pipe is asynchronous we must have a way to turn it synchronous. - // See #95759. - match pipe { - AnonPipe::Sync(handle) => Stdio::Handle(handle), - AnonPipe::Async(handle) => Stdio::AsyncPipe(handle), - } + Stdio::Pipe(pipe) } } From a47edcf72aff3fb4e8bb52cc7823fd140ce5470d Mon Sep 17 00:00:00 2001 From: Gim <93856041+gimbles@users.noreply.github.com> Date: Wed, 18 May 2022 07:31:58 +0530 Subject: [PATCH 05/10] Update macros.rs --- library/std/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index e512c0d81a0f3..c7348951511c4 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -72,7 +72,7 @@ macro_rules! print { /// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone /// (no additional CARRIAGE RETURN (`\r`/`U+000D`)). /// -/// Use the [`format!`] syntax to write data to the standard output. +/// This macro uses the same syntax as [`format!`], but writes to the standard output instead. /// See [`std::fmt`] for more information. /// /// Use `println!` only for the primary output of your program. Use From 72496d88d3b80ecc4d24e1fec84d399c8efa4466 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 18 May 2022 11:39:46 +0200 Subject: [PATCH 06/10] Move some DOM generation into the HTML settings file directly --- src/librustdoc/html/render/context.rs | 16 +++++++++++++--- src/librustdoc/html/static/js/settings.js | 18 ++---------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 528180288de6a..81f961992b6f1 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -596,9 +596,19 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { |buf: &mut Buffer| { write!( buf, - "\ - ", + "
\ +

\ + Rustdoc settings\ +

\ + \ + \ + Back\ + \ + \ +
\ + \ + ", root_path = page.static_root_path.unwrap_or(""), suffix = page.resource_suffix, ) diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 2e2305029cddd..8770cc3f3b149 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -206,22 +206,8 @@ ]; // Then we build the DOM. - let innerHTML = ""; - let elementKind = "div"; - - if (isSettingsPage) { - elementKind = "section"; - innerHTML = `
-

- Rustdoc settings -

- - Back - -
`; - } - innerHTML += `
${buildSettingsPageSections(settings)}
`; - + const elementKind = isSettingsPage ? "section" : "div"; + const innerHTML = `
${buildSettingsPageSections(settings)}
`; const el = document.createElement(elementKind); el.id = "settings"; el.innerHTML = innerHTML; From 30b536e2c5ea9dc52eae72dee4a377a15e508910 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 18 May 2022 11:40:29 +0200 Subject: [PATCH 07/10] Update browser-ui-test version --- .../docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index f76f9131742ee..b3ec1638fda74 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.9.2 \ No newline at end of file +0.9.3 \ No newline at end of file From f45f8262078bde0435560a1e17fb749d0f46dc30 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Mon, 16 May 2022 21:46:20 -0700 Subject: [PATCH 08/10] Update MIR passes that assumed inline can never unwind. --- compiler/rustc_mir_transform/src/abort_unwinding_calls.rs | 7 +++++++ compiler/rustc_mir_transform/src/generator.rs | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index ade6555f4d2c1..11980382ffdb2 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,4 +1,5 @@ use crate::MirPass; +use rustc_ast::InlineAsmOptions; use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::ty::layout; @@ -85,6 +86,12 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => { layout::fn_can_unwind(tcx, None, Abi::Rust) } + TerminatorKind::InlineAsm { options, .. } => { + options.contains(InlineAsmOptions::MAY_UNWIND) + } + _ if terminator.unwind().is_some() => { + span_bug!(span, "unexpected terminator that may unwind {:?}", terminator) + } _ => continue, }; diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index b7dec57b75768..9e7bf5c792951 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1042,8 +1042,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => {} + | TerminatorKind::FalseUnwind { .. } => {} // Resume will *continue* unwinding, but if there's no other unwinding terminator it // will never be reached. @@ -1057,6 +1056,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } + | TerminatorKind::InlineAsm { .. } | TerminatorKind::Assert { .. } => return true, } } From 39cd1da1cb8514b2cf4f1679cd458d3542539078 Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Mon, 16 May 2022 21:51:20 -0700 Subject: [PATCH 09/10] Add mir-opt test for asm_unwind + panic=abort --- ...c_abort.main.AbortUnwindingCalls.after.mir | 24 +++++++++++++++++++ src/test/mir-opt/asm_unwind_panic_abort.rs | 15 ++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir create mode 100644 src/test/mir-opt/asm_unwind_panic_abort.rs diff --git a/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir new file mode 100644 index 0000000000000..3432075780063 --- /dev/null +++ b/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir @@ -0,0 +1,24 @@ +// MIR for `main` after AbortUnwindingCalls + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/asm_unwind_panic_abort.rs:11:11: 11:11 + let _1: (); // in scope 0 at $DIR/asm_unwind_panic_abort.rs:13:9: 13:49 + scope 1 { + } + + bb0: { + StorageLive(_1); // scope 1 at $DIR/asm_unwind_panic_abort.rs:13:9: 13:49 + _1 = const (); // scope 1 at $DIR/asm_unwind_panic_abort.rs:13:9: 13:49 + asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:13:9: 13:49 + } + + bb1: { + StorageDead(_1); // scope 1 at $DIR/asm_unwind_panic_abort.rs:13:48: 13:49 + _0 = const (); // scope 1 at $DIR/asm_unwind_panic_abort.rs:12:5: 14:6 + return; // scope 0 at $DIR/asm_unwind_panic_abort.rs:15:2: 15:2 + } + + bb2 (cleanup): { + abort; // scope 0 at $DIR/asm_unwind_panic_abort.rs:11:1: 15:2 + } +} diff --git a/src/test/mir-opt/asm_unwind_panic_abort.rs b/src/test/mir-opt/asm_unwind_panic_abort.rs new file mode 100644 index 0000000000000..e0c89393d54bd --- /dev/null +++ b/src/test/mir-opt/asm_unwind_panic_abort.rs @@ -0,0 +1,15 @@ +//! Tests that unwinding from an asm block is caught and forced to abort +//! when `-C panic=abort`. + +// min-llvm-version: 13.0.0 +// compile-flags: -C panic=abort +// no-prefer-dynamic + +#![feature(asm_unwind)] + +// EMIT_MIR asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir +fn main() { + unsafe { + std::arch::asm!("", options(may_unwind)); + } +} From 6986a72547a82b6844406a82beadc90b4d622eba Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 May 2022 13:52:43 -0700 Subject: [PATCH 10/10] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 3f052d8eed98c..a4c1cd0eb6b18 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3f052d8eed98c6a24f8b332fb2e6e6249d12d8c1 +Subproject commit a4c1cd0eb6b18082a7e693f5a665548fe1534be4