From bd2e5db8c5e84ee1abc4e114b28aaec86197c8af 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 9ee8d743e64a4..47032156e63f1 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -30,7 +30,7 @@ pub struct DynamicQuery<'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 e8983bfa1ddba..b8f7aea257133 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -27,7 +27,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] @@ -116,7 +116,7 @@ where #[inline(always)] fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - (self.dynamic.compute)(qcx.tcx, key) + (self.dynamic.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 0c3fcf25c6550..3f45d518b638f 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -572,18 +572,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 { @@ -641,6 +629,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>, + ) -> Erase> { + #[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 dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> { @@ -653,22 +667,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(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| {