From 3442e2556df02aa3512aa90fc71e1650fd9000c2 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Mon, 5 May 2025 20:09:02 -0400 Subject: [PATCH] Use new `run_without_applying_deferred` method in `SingleThreadedExecutor` (#18684) # Objective Simplify code in the `SingleThreadedExecutor` by removing a special case for exclusive systems. The `SingleThreadedExecutor` runs systems without immediately applying deferred buffers. That required calling `run_unsafe()` instead of `run()`, but that would `panic` for exclusive systems, so the code also needed a special case for those. Following #18076 and #18406, we have a `run_without_applying_deferred` method that has the exact behavior we want and works on exclusive systems. ## Solution Replace the code in `SingleThreadedExecutor` that runs systems with a single call to `run_without_applying_deferred()`. Also add this as a wrapper in the `__rust_begin_short_backtrace` module to preserve the special behavior for backtraces. --- crates/bevy_ecs/src/schedule/executor/mod.rs | 27 +++++++++++--- .../src/schedule/executor/single_threaded.rs | 37 +++++-------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/crates/bevy_ecs/src/schedule/executor/mod.rs b/crates/bevy_ecs/src/schedule/executor/mod.rs index 09f01b2289..2fc808bf28 100644 --- a/crates/bevy_ecs/src/schedule/executor/mod.rs +++ b/crates/bevy_ecs/src/schedule/executor/mod.rs @@ -271,38 +271,54 @@ impl IntoSystemSet<()> for ApplyDeferred { mod __rust_begin_short_backtrace { use core::hint::black_box; + #[cfg(feature = "std")] + use crate::world::unsafe_world_cell::UnsafeWorldCell; use crate::{ error::Result, system::{ReadOnlySystem, ScheduleSystem}, - world::{unsafe_world_cell::UnsafeWorldCell, World}, + world::World, }; /// # Safety /// See `System::run_unsafe`. + // This is only used by `MultiThreadedExecutor`, and would be dead code without `std`. + #[cfg(feature = "std")] #[inline(never)] pub(super) unsafe fn run_unsafe(system: &mut ScheduleSystem, world: UnsafeWorldCell) -> Result { let result = system.run_unsafe((), world); + // Call `black_box` to prevent this frame from being tail-call optimized away black_box(()); result } /// # Safety /// See `ReadOnlySystem::run_unsafe`. - #[cfg_attr( - not(feature = "std"), - expect(dead_code, reason = "currently only used with the std feature") - )] + // This is only used by `MultiThreadedExecutor`, and would be dead code without `std`. + #[cfg(feature = "std")] #[inline(never)] pub(super) unsafe fn readonly_run_unsafe( system: &mut dyn ReadOnlySystem, world: UnsafeWorldCell, ) -> O { + // Call `black_box` to prevent this frame from being tail-call optimized away black_box(system.run_unsafe((), world)) } #[inline(never)] pub(super) fn run(system: &mut ScheduleSystem, world: &mut World) -> Result { let result = system.run((), world); + // Call `black_box` to prevent this frame from being tail-call optimized away + black_box(()); + result + } + + #[inline(never)] + pub(super) fn run_without_applying_deferred( + system: &mut ScheduleSystem, + world: &mut World, + ) -> Result { + let result = system.run_without_applying_deferred((), world); + // Call `black_box` to prevent this frame from being tail-call optimized away black_box(()); result } @@ -312,6 +328,7 @@ mod __rust_begin_short_backtrace { system: &mut dyn ReadOnlySystem, world: &mut World, ) -> O { + // Call `black_box` to prevent this frame from being tail-call optimized away black_box(system.run((), world)) } } diff --git a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs index b42f47726d..82e9e354a8 100644 --- a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs @@ -128,33 +128,16 @@ impl SystemExecutor for SingleThreadedExecutor { } let f = AssertUnwindSafe(|| { - if system.is_exclusive() { - if let Err(err) = __rust_begin_short_backtrace::run(system, world) { - error_handler( - err, - ErrorContext::System { - name: system.name(), - last_run: system.get_last_run(), - }, - ); - } - } else { - // Use run_unsafe to avoid immediately applying deferred buffers - let world = world.as_unsafe_world_cell(); - system.update_archetype_component_access(world); - // SAFETY: We have exclusive, single-threaded access to the world and - // update_archetype_component_access is being called immediately before this. - unsafe { - if let Err(err) = __rust_begin_short_backtrace::run_unsafe(system, world) { - error_handler( - err, - ErrorContext::System { - name: system.name(), - last_run: system.get_last_run(), - }, - ); - } - }; + if let Err(err) = + __rust_begin_short_backtrace::run_without_applying_deferred(system, world) + { + error_handler( + err, + ErrorContext::System { + name: system.name(), + last_run: system.get_last_run(), + }, + ); } });