tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit e7ab75c01ac4495846c9f8d480100d9c0de4eaea
parent ee39d4dc9f95f1e654958c17db1aba0079c8130d
Author: Max Leonard Inden <mail@max-inden.de>
Date:   Wed, 29 Oct 2025 15:54:24 +0000

Bug 1968065 - expose Flow Marker API to Rust r=profiler-reviewers,canaltinova

Differential Revision: https://phabricator.services.mozilla.com/D250824

Diffstat:
Mtools/profiler/core/ProfilerBindings.cpp | 7+++++++
Mtools/profiler/public/ProfilerBindings.h | 2++
Mtools/profiler/rust-api/src/marker/mod.rs | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools/profiler/rust-api/src/marker/schema.rs | 8++++++++
4 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/tools/profiler/core/ProfilerBindings.cpp b/tools/profiler/core/ProfilerBindings.cpp @@ -186,6 +186,13 @@ void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema, #endif } +void gecko_profiler_marker_schema_set_stack_based( + mozilla::MarkerSchema* aSchema) { +#ifdef MOZ_GECKO_PROFILER + aSchema->SetIsStackBased(); +#endif +} + void gecko_profiler_marker_schema_add_key_format( mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, mozilla::MarkerSchema::Format aFormat) { diff --git a/tools/profiler/public/ProfilerBindings.h b/tools/profiler/public/ProfilerBindings.h @@ -92,6 +92,8 @@ void gecko_profiler_marker_schema_set_table_label( void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength); +void gecko_profiler_marker_schema_set_stack_based( + mozilla::MarkerSchema* aSchema); // MarkerSchema methods for adding key/key-label values. void gecko_profiler_marker_schema_add_key_format( diff --git a/tools/profiler/rust-api/src/marker/mod.rs b/tools/profiler/rust-api/src/marker/mod.rs @@ -545,3 +545,135 @@ macro_rules! auto_profiler_marker_tracing { // Do nothing if the profiler is not enabled }; } + +/// Flow marker type for Rust code. +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +pub struct FlowStackMarker(pub u64); + +impl FlowStackMarker { + pub fn from_pointer<T>(s: *const T) -> Self { + FlowStackMarker(s as usize as u64) + } +} + +impl ProfilerMarker for FlowStackMarker { + fn marker_type_name() -> &'static str { + "FlowStackRust" + } + + fn stream_json_marker_data(&self, json_writer: &mut JSONWriter) { + fn hex_string(id: u64) -> [u8; 16] { + let mut buf = [0; 16]; + let hex_digits = b"0123456789abcdef"; + for i in 0..16 { + buf[i] = hex_digits[(id >> (60 - i * 4)) as usize & 0xf]; + } + buf + } + + json_writer.unique_string_property("flow", unsafe { + std::str::from_utf8_unchecked(&hex_string(self.0)) + }); + } + + // Flow marker is a bit special because we have the same schema in the C++ + // side. This function will only get called when no Flow markers are + // generated from the C++ side. But, most of the time, this will not be + // called when there is another C++ Flow marker. + fn marker_type_display() -> MarkerSchema { + use crate::marker::schema::*; + let mut schema = MarkerSchema::new(&[Location::MarkerChart, Location::MarkerTable]); + schema.add_key_label_format("flow", "Flow", Format::Flow); + schema.set_stack_based(); + schema + } +} + +/// RAII-style scoped tracing marker for Rust code. +/// This is a Rust-style equivalent of the C++ AUTO_PROFILER_FLOW_MARKER +/// Profiler markers are emitted when an [`AutoProfilerFlowMarker`] is created, +/// and when it is dropped (destroyed). +pub struct AutoProfilerFlowMarker<'a> { + name: &'a str, + category: ProfilingCategoryPair, + options: MarkerOptions, + flow: FlowStackMarker, + // We store the start time separately from the MarkerTiming inside + // MarkerOptions, as once we have "put it in" a marker timing, there's + // currently no API way to "get it out" again. + start: ProfilerTime, +} + +impl<'a> AutoProfilerFlowMarker<'a> { + pub fn new( + name: &'a str, + category: ProfilingCategoryPair, + options: MarkerOptions, + flow: FlowStackMarker, + ) -> Option<AutoProfilerFlowMarker<'a>> { + if !crate::profiler_state::can_accept_markers() { + return None; + } + Some(AutoProfilerFlowMarker { + name, + category, + options, + flow, + start: ProfilerTime::now(), + }) + } +} + +impl<'a> Drop for AutoProfilerFlowMarker<'a> { + fn drop(&mut self) { + // If we have an AutoProfilerFlowMarker object, then the profiler was + // running + accepting markers when it was *created*. We have no + // guarantee that it's still running though, so check again! If the + // profiler has stopped, then there's no point recording the second of a + // pair of markers. + if !crate::profiler_state::can_accept_markers() { + return; + } + // record the ending marker + add_marker( + self.name, + self.category, + self.options + .with_timing(MarkerTiming::interval_until_now_from(self.start.clone())), + self.flow, + ); + } +} + +/// Create an RAII-style tracing marker. See [`AutoProfilerFlowMarker`] for more +/// details. +/// +/// The arguments to this macro correspond exactly to the +/// AutoProfilerFlowMarker::new constructor. +/// +/// Example usage: +/// ```rust +/// auto_profiler_flow_marker!( +/// "BlobRasterization", +/// gecko_profiler_category!(Graphics), +/// Default::default(), +/// flow +/// ); +/// ``` +/// +#[cfg(feature = "enabled")] +#[macro_export] +macro_rules! auto_profiler_flow_marker { + ($name:expr, $category:expr,$options:expr, $payload:expr) => { + let _macro_created_rust_tracing_marker = + $crate::AutoProfilerFlowMarker::new($name, $category, $options, $payload); + }; +} + +#[cfg(not(feature = "enabled"))] +#[macro_export] +macro_rules! auto_profiler_flow_marker { + ($name:expr, $category:expr,$options:expr, $payload:expr) => { + // Do nothing if the profiler is not enabled + }; +} diff --git a/tools/profiler/rust-api/src/marker/schema.rs b/tools/profiler/rust-api/src/marker/schema.rs @@ -110,6 +110,14 @@ impl MarkerSchema { self } + /// Set the marker to be stack based + pub fn set_stack_based(&mut self) -> &mut Self { + unsafe { + bindings::gecko_profiler_marker_schema_set_stack_based(self.ptr); + } + self + } + // Each data element that is streamed by `stream_json_marker_data()` can be // displayed as indicated by using one of the `add_...` function below. // Each `add...` will add a line in the full marker description. Parameters: