From a33d6d941bc868466328e6397497fe2aedbf544b Mon Sep 17 00:00:00 2001 From: Jake Hughes Date: Fri, 10 Jan 2025 08:58:15 +0000 Subject: [PATCH 1/3] Make finaliser elision flag a rustc flag Instead of requiring two distinct builds, finalizer elision can now be turned on or off for an existing build using the -C flag. --- compiler/rustc_middle/src/ty/util.rs | 3 +++ compiler/rustc_session/src/options.rs | 2 ++ library/std/Cargo.toml | 1 - library/std/src/gc.rs | 13 ++----------- library/sysroot/Cargo.toml | 1 - src/bootstrap/src/core/builder.rs | 5 +++++ src/bootstrap/src/core/config/config.rs | 7 ++++++- src/bootstrap/src/lib.rs | 3 --- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 492086ca1790c..a9b6784c54bbf 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1430,6 +1430,9 @@ impl<'tcx> Ty<'tcx> { /// Note that this method is used to check eligible types in unions. #[inline] pub fn needs_finalizer(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + if tcx.sess.opts.cg.no_finalizer_elision { + return self.needs_drop(tcx, param_env); + } // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d51080589481b..9ac7c82ee5b8e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1517,6 +1517,8 @@ options! { "perform LLVM link-time optimizations"), metadata: Vec = (Vec::new(), parse_list, [TRACKED], "metadata to mangle symbol names with"), + no_finalizer_elision: bool = (false, parse_bool, [TRACKED], + "disable optimization to remove unnecessary finalizers"), no_prepopulate_passes: bool = (false, parse_no_flag, [TRACKED], "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 510805e6e74ab..58564531709d1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -84,7 +84,6 @@ system-llvm-libunwind = ["unwind/system-llvm-libunwind"] # Alloy debug flags log-stats = ["alloc/log-stats"] -finalizer-elision = [] premature-finalizer-prevention = [] # Make panics and failed asserts immediately abort without formatting any message diff --git a/library/std/src/gc.rs b/library/std/src/gc.rs index 9103843991bbd..319282a69df6c 100644 --- a/library/std/src/gc.rs +++ b/library/std/src/gc.rs @@ -489,17 +489,8 @@ impl Gc { #[cfg(not(no_global_oom_handling))] unsafe fn new_internal(value: T) -> Self { #[cfg(not(bootstrap))] - { - #[cfg(feature = "finalizer-elision")] - let needs_finalizer = crate::mem::needs_finalizer::(); - #[cfg(not(feature = "finalizer-elision"))] - let needs_finalizer = crate::mem::needs_drop::(); - - if !needs_finalizer { - return Self::from_inner( - Box::leak(Box::new_in(GcBox { value }, GcAllocator)).into(), - ); - } + if !crate::mem::needs_finalizer::() { + return Self::from_inner(Box::leak(Box::new_in(GcBox { value }, GcAllocator)).into()); } unsafe extern "C" fn finalizer_shim(obj: *mut u8, _: *mut u8) { diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index e26efaebf6020..338d84d092973 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -29,5 +29,4 @@ std_detect_env_override = ["std/std_detect_env_override"] # Alloy debug flags log-stats = ["std/log-stats"] -finalizer-elision = ["std/finalizer-elision"] premature-finalizer-prevention = ["std/premature-finalizer-prevention"] diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index adef9ebd0e306..1a8fa4cfae40b 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1517,6 +1517,11 @@ impl<'a> Builder<'a> { rustflags.arg("-Zunstable-options"); } + // Alloy features + if stage != 0 && !self.config.finalizer_elision { + rustflags.arg("-Cno-finalizer-elision"); + } + // Enable compile-time checking of `cfg` names, values and Cargo `features`. // // Note: `std`, `alloc` and `core` imports some dependencies by #[path] (like diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index cb50f0966a04d..110cedaf0f545 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1771,10 +1771,15 @@ impl Config { config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); if let Some(alloy) = toml.alloy { - let Alloy { log_stats, finalizer_elision, premature_finalizer_prevention } = alloy; + let Alloy { + log_stats, + finalizer_elision, + premature_finalizer_prevention, + } = alloy; set(&mut config.log_stats, log_stats); set(&mut config.finalizer_elision, finalizer_elision); + set(&mut config.finalizer_safety_analysis, finalizer_safety_analysis); set(&mut config.premature_finalizer_prevention, premature_finalizer_prevention); } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 75f10c23e9a28..e84b262e4f248 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -753,9 +753,6 @@ impl Build { if self.config.log_stats { features.push_str(" log-stats"); } - if self.config.finalizer_elision { - features.push_str(" finalizer-elision"); - } if self.config.premature_finalizer_prevention { features.push_str(" premature-finalizer-prevention"); } From fe4f0240848358a624cc9a7471a54291bc60e0bb Mon Sep 17 00:00:00 2001 From: Jake Hughes Date: Fri, 10 Jan 2025 08:58:15 +0000 Subject: [PATCH 2/3] Add a rustc flag for disabling FSA --- compiler/rustc_mir_transform/src/check_finalizers.rs | 4 ++++ compiler/rustc_session/src/options.rs | 2 ++ src/bootstrap/src/core/builder.rs | 3 +++ src/bootstrap/src/core/config/config.rs | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/compiler/rustc_mir_transform/src/check_finalizers.rs b/compiler/rustc_mir_transform/src/check_finalizers.rs index 25db3886bf31d..0cb1fda62d700 100644 --- a/compiler/rustc_mir_transform/src/check_finalizers.rs +++ b/compiler/rustc_mir_transform/src/check_finalizers.rs @@ -73,6 +73,10 @@ impl<'tcx> FnInfo<'tcx> { impl<'tcx> MirPass<'tcx> for CheckFinalizers { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if tcx.sess.opts.cg.no_finalizer_safety_analysis { + return; + } + trace!("Running FSA on {:?}", body.source); let param_env = tcx.param_env(body.source.def_id()); if in_std_lib(tcx, body.source.def_id()) { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9ac7c82ee5b8e..647811e348c6a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1519,6 +1519,8 @@ options! { "metadata to mangle symbol names with"), no_finalizer_elision: bool = (false, parse_bool, [TRACKED], "disable optimization to remove unnecessary finalizers"), + no_finalizer_safety_analysis: bool = (false, parse_bool, [TRACKED], + "disable checking of drop methods for GC soundness"), no_prepopulate_passes: bool = (false, parse_no_flag, [TRACKED], "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 1a8fa4cfae40b..281751d24b430 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1521,6 +1521,9 @@ impl<'a> Builder<'a> { if stage != 0 && !self.config.finalizer_elision { rustflags.arg("-Cno-finalizer-elision"); } + if stage != 0 && !self.config.finalizer_safety_analysis { + rustflags.arg("-Cno-finalizer-safety-analysis"); + } // Enable compile-time checking of `cfg` names, values and Cargo `features`. // diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 110cedaf0f545..ba82aeed128c3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -309,6 +309,7 @@ pub struct Config { // alloy debug features pub log_stats: bool, // support for LOG_ALLOY_STATS pub finalizer_elision: bool, + pub finalizer_safety_analysis: bool, pub premature_finalizer_prevention: bool, // misc @@ -1143,6 +1144,7 @@ define_config! { struct Alloy { log_stats: Option = "log-stats", finalizer_elision: Option = "finalizer-elision", + finalizer_safety_analysis: Option = "finalizer-safety-analysis", premature_finalizer_prevention: Option = "premature-finalizer-prevention", } } @@ -1216,6 +1218,7 @@ impl Config { // alloy opts log_stats: false, finalizer_elision: true, + finalizer_safety_analysis: true, premature_finalizer_prevention: true, ..Default::default() @@ -1774,6 +1777,7 @@ impl Config { let Alloy { log_stats, finalizer_elision, + finalizer_safety_analysis, premature_finalizer_prevention, } = alloy; From 53f9d145362632e50d5b7e4abaae30f7cb45759e Mon Sep 17 00:00:00 2001 From: Jake Hughes Date: Fri, 10 Jan 2025 08:58:16 +0000 Subject: [PATCH 3/3] Add a rustc flag for disabling the barrier removal optimization --- compiler/rustc_mir_transform/src/remove_elidable_drops.rs | 3 +++ compiler/rustc_session/src/options.rs | 2 ++ src/bootstrap/src/core/builder.rs | 3 +++ src/bootstrap/src/core/config/config.rs | 8 ++++++++ 4 files changed, 16 insertions(+) diff --git a/compiler/rustc_mir_transform/src/remove_elidable_drops.rs b/compiler/rustc_mir_transform/src/remove_elidable_drops.rs index 92c34d9c2c663..fb984c4d88d5f 100644 --- a/compiler/rustc_mir_transform/src/remove_elidable_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_elidable_drops.rs @@ -8,6 +8,9 @@ pub struct RemoveElidableDrops; impl<'tcx> MirPass<'tcx> for RemoveElidableDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if tcx.sess.opts.cg.no_premature_finalizer_prevention_opt { + return; + } trace!("Running RemoveElidableDrops on {:?}", body.source); let is_gc_crate = tcx diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 647811e348c6a..4bd40db31ee4c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1521,6 +1521,8 @@ options! { "disable optimization to remove unnecessary finalizers"), no_finalizer_safety_analysis: bool = (false, parse_bool, [TRACKED], "disable checking of drop methods for GC soundness"), + no_premature_finalizer_prevention_opt: bool = (false, parse_bool, [TRACKED], + "disable optimization to remove unnecessary finalization barriers"), no_prepopulate_passes: bool = (false, parse_no_flag, [TRACKED], "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 281751d24b430..48bf7cf9f821e 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1524,6 +1524,9 @@ impl<'a> Builder<'a> { if stage != 0 && !self.config.finalizer_safety_analysis { rustflags.arg("-Cno-finalizer-safety-analysis"); } + if stage != 0 && !self.config.premature_finalizer_prevention_optimize { + rustflags.arg("-Cno-premature-finalizer-prevention-opt"); + } // Enable compile-time checking of `cfg` names, values and Cargo `features`. // diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ba82aeed128c3..8ed4fcf1496d1 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -311,6 +311,7 @@ pub struct Config { pub finalizer_elision: bool, pub finalizer_safety_analysis: bool, pub premature_finalizer_prevention: bool, + pub premature_finalizer_prevention_optimize: bool, // misc pub low_priority: bool, @@ -1146,6 +1147,7 @@ define_config! { finalizer_elision: Option = "finalizer-elision", finalizer_safety_analysis: Option = "finalizer-safety-analysis", premature_finalizer_prevention: Option = "premature-finalizer-prevention", + premature_finalizer_prevention_optimize: Option = "premature-finalizer-prevention-optimize", } } @@ -1220,6 +1222,7 @@ impl Config { finalizer_elision: true, finalizer_safety_analysis: true, premature_finalizer_prevention: true, + premature_finalizer_prevention_optimize: true, ..Default::default() } @@ -1779,12 +1782,17 @@ impl Config { finalizer_elision, finalizer_safety_analysis, premature_finalizer_prevention, + premature_finalizer_prevention_optimize, } = alloy; set(&mut config.log_stats, log_stats); set(&mut config.finalizer_elision, finalizer_elision); set(&mut config.finalizer_safety_analysis, finalizer_safety_analysis); set(&mut config.premature_finalizer_prevention, premature_finalizer_prevention); + set( + &mut config.premature_finalizer_prevention_optimize, + premature_finalizer_prevention_optimize, + ); } if let Some(llvm) = toml.llvm {