Skip to content

Commit 3442e25

Browse files
authored
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.
1 parent 49f1827 commit 3442e25

File tree

2 files changed

+32
-32
lines changed

2 files changed

+32
-32
lines changed

crates/bevy_ecs/src/schedule/executor/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -271,38 +271,54 @@ impl IntoSystemSet<()> for ApplyDeferred {
271271
mod __rust_begin_short_backtrace {
272272
use core::hint::black_box;
273273

274+
#[cfg(feature = "std")]
275+
use crate::world::unsafe_world_cell::UnsafeWorldCell;
274276
use crate::{
275277
error::Result,
276278
system::{ReadOnlySystem, ScheduleSystem},
277-
world::{unsafe_world_cell::UnsafeWorldCell, World},
279+
world::World,
278280
};
279281

280282
/// # Safety
281283
/// See `System::run_unsafe`.
284+
// This is only used by `MultiThreadedExecutor`, and would be dead code without `std`.
285+
#[cfg(feature = "std")]
282286
#[inline(never)]
283287
pub(super) unsafe fn run_unsafe(system: &mut ScheduleSystem, world: UnsafeWorldCell) -> Result {
284288
let result = system.run_unsafe((), world);
289+
// Call `black_box` to prevent this frame from being tail-call optimized away
285290
black_box(());
286291
result
287292
}
288293

289294
/// # Safety
290295
/// See `ReadOnlySystem::run_unsafe`.
291-
#[cfg_attr(
292-
not(feature = "std"),
293-
expect(dead_code, reason = "currently only used with the std feature")
294-
)]
296+
// This is only used by `MultiThreadedExecutor`, and would be dead code without `std`.
297+
#[cfg(feature = "std")]
295298
#[inline(never)]
296299
pub(super) unsafe fn readonly_run_unsafe<O: 'static>(
297300
system: &mut dyn ReadOnlySystem<In = (), Out = O>,
298301
world: UnsafeWorldCell,
299302
) -> O {
303+
// Call `black_box` to prevent this frame from being tail-call optimized away
300304
black_box(system.run_unsafe((), world))
301305
}
302306

303307
#[inline(never)]
304308
pub(super) fn run(system: &mut ScheduleSystem, world: &mut World) -> Result {
305309
let result = system.run((), world);
310+
// Call `black_box` to prevent this frame from being tail-call optimized away
311+
black_box(());
312+
result
313+
}
314+
315+
#[inline(never)]
316+
pub(super) fn run_without_applying_deferred(
317+
system: &mut ScheduleSystem,
318+
world: &mut World,
319+
) -> Result {
320+
let result = system.run_without_applying_deferred((), world);
321+
// Call `black_box` to prevent this frame from being tail-call optimized away
306322
black_box(());
307323
result
308324
}
@@ -312,6 +328,7 @@ mod __rust_begin_short_backtrace {
312328
system: &mut dyn ReadOnlySystem<In = (), Out = O>,
313329
world: &mut World,
314330
) -> O {
331+
// Call `black_box` to prevent this frame from being tail-call optimized away
315332
black_box(system.run((), world))
316333
}
317334
}

crates/bevy_ecs/src/schedule/executor/single_threaded.rs

+10-27
Original file line numberDiff line numberDiff line change
@@ -128,33 +128,16 @@ impl SystemExecutor for SingleThreadedExecutor {
128128
}
129129

130130
let f = AssertUnwindSafe(|| {
131-
if system.is_exclusive() {
132-
if let Err(err) = __rust_begin_short_backtrace::run(system, world) {
133-
error_handler(
134-
err,
135-
ErrorContext::System {
136-
name: system.name(),
137-
last_run: system.get_last_run(),
138-
},
139-
);
140-
}
141-
} else {
142-
// Use run_unsafe to avoid immediately applying deferred buffers
143-
let world = world.as_unsafe_world_cell();
144-
system.update_archetype_component_access(world);
145-
// SAFETY: We have exclusive, single-threaded access to the world and
146-
// update_archetype_component_access is being called immediately before this.
147-
unsafe {
148-
if let Err(err) = __rust_begin_short_backtrace::run_unsafe(system, world) {
149-
error_handler(
150-
err,
151-
ErrorContext::System {
152-
name: system.name(),
153-
last_run: system.get_last_run(),
154-
},
155-
);
156-
}
157-
};
131+
if let Err(err) =
132+
__rust_begin_short_backtrace::run_without_applying_deferred(system, world)
133+
{
134+
error_handler(
135+
err,
136+
ErrorContext::System {
137+
name: system.name(),
138+
last_run: system.get_last_run(),
139+
},
140+
);
158141
}
159142
});
160143

0 commit comments

Comments
 (0)