From 36cdce68a1d7c2aaadbea8cc9a76d63888d9b1c8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Jan 2026 23:09:37 +1100 Subject: [PATCH] Use fewer intermediate functions for short backtraces in queries If we make sure that `compute_fn` in the query's vtable is actually named `__rust_begin_short_backtrace`, we can avoid the need for some additional intermediate functions and stack frames. This is similar to how the `get_query_incr` and `get_query_non_incr` functions are actually named `__rust_end_short_backtrace`. --- compiler/rustc_middle/src/query/plumbing.rs | 2 +- compiler/rustc_query_impl/src/lib.rs | 4 +- compiler/rustc_query_impl/src/plumbing.rs | 55 ++++++++++----------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 7b85dac41aeff..20de2895d3133 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -33,7 +33,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub query_cache: usize, pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, - pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, + pub compute_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, pub can_load_from_disk: bool, pub try_load_from_disk: fn( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 382b8750a1ce7..1865cbbbb1ffe 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -25,7 +25,7 @@ use rustc_query_system::query::{ }; use rustc_span::{ErrorGuaranteed, Span}; -use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green}; +use crate::plumbing::{encode_all_query_results, try_mark_green}; use crate::profiling_support::QueryKeyStringCache; #[macro_use] @@ -120,7 +120,7 @@ where #[inline(always)] fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - (self.vtable.compute)(qcx.tcx, key) + (self.vtable.compute_fn)(qcx.tcx, key) } #[inline(always)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index c71352c3fd202..3425aaaf9dfc7 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -575,18 +575,6 @@ macro_rules! expand_if_cached { }; } -/// Don't show the backtrace for query system by default -/// use `RUST_BACKTRACE=full` to show all the backtraces -#[inline(never)] -pub(crate) fn __rust_begin_short_backtrace(f: F) -> T -where - F: FnOnce() -> T, -{ - let result = f(); - std::hint::black_box(()); - result -} - // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_with_all_queries`. macro_rules! define_queries { @@ -645,6 +633,32 @@ macro_rules! define_queries { } } + /// Defines a `compute` function for this query, to be used as a + /// function pointer in the query's vtable. + mod compute_fn { + use super::*; + use ::rustc_middle::query::queries::$name::{Key, Value, provided_to_erased}; + + /// This function would be named `compute`, but we also want it + /// to mark the boundaries of an omitted region in backtraces. + #[inline(never)] + pub(crate) fn __rust_begin_short_backtrace<'tcx>( + tcx: TyCtxt<'tcx>, + key: Key<'tcx>, + ) -> Erased> { + #[cfg(debug_assertions)] + let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); + + // Call the actual provider function for this query. + let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]); + rustc_middle::ty::print::with_reduced_queries!({ + tracing::trace!(?provided_value); + }); + + provided_to_erased(tcx, provided_value) + } + } + pub(crate) fn make_query_vtable<'tcx>() -> QueryVTable<'tcx, queries::$name::Storage<'tcx>> { @@ -657,22 +671,7 @@ macro_rules! define_queries { query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key), execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), - compute: |tcx, key| { - #[cfg(debug_assertions)] - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - __rust_begin_short_backtrace(|| - queries::$name::provided_to_erased( - tcx, - { - let ret = call_provider!([$($modifiers)*][tcx, $name, key]); - rustc_middle::ty::print::with_reduced_queries!({ - tracing::trace!(?ret); - }); - ret - } - ) - ) - }, + compute_fn: self::compute_fn::__rust_begin_short_backtrace, can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false), try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] { |tcx, key, prev_index, index| {