diff options
Diffstat (limited to 'tools/profiler/core/ProfilerBindings.cpp')
-rw-r--r-- | tools/profiler/core/ProfilerBindings.cpp | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/tools/profiler/core/ProfilerBindings.cpp b/tools/profiler/core/ProfilerBindings.cpp new file mode 100644 index 0000000000..c3af5c5b56 --- /dev/null +++ b/tools/profiler/core/ProfilerBindings.cpp @@ -0,0 +1,386 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* FFI functions for Profiler Rust API to call into profiler */ + +#include "ProfilerBindings.h" + +#include "GeckoProfiler.h" + +#include <set> +#include <type_traits> + +void gecko_profiler_register_thread(const char* aName) { + PROFILER_REGISTER_THREAD(aName); +} + +void gecko_profiler_unregister_thread() { PROFILER_UNREGISTER_THREAD(); } + +void gecko_profiler_construct_label(mozilla::AutoProfilerLabel* aAutoLabel, + JS::ProfilingCategoryPair aCategoryPair) { +#ifdef MOZ_GECKO_PROFILER + new (aAutoLabel) mozilla::AutoProfilerLabel( + "", nullptr, aCategoryPair, + uint32_t( + js::ProfilingStackFrame::Flags::LABEL_DETERMINED_BY_CATEGORY_PAIR)); +#endif +} + +void gecko_profiler_destruct_label(mozilla::AutoProfilerLabel* aAutoLabel) { +#ifdef MOZ_GECKO_PROFILER + aAutoLabel->~AutoProfilerLabel(); +#endif +} + +void gecko_profiler_construct_timestamp_now(mozilla::TimeStamp* aTimeStamp) { + new (aTimeStamp) mozilla::TimeStamp(mozilla::TimeStamp::Now()); +} + +void gecko_profiler_clone_timestamp(const mozilla::TimeStamp* aSrcTimeStamp, + mozilla::TimeStamp* aDestTimeStamp) { + new (aDestTimeStamp) mozilla::TimeStamp(*aSrcTimeStamp); +} + +void gecko_profiler_destruct_timestamp(mozilla::TimeStamp* aTimeStamp) { + aTimeStamp->~TimeStamp(); +} + +void gecko_profiler_add_timestamp(const mozilla::TimeStamp* aTimeStamp, + mozilla::TimeStamp* aDestTimeStamp, + double aMicroseconds) { + new (aDestTimeStamp) mozilla::TimeStamp( + *aTimeStamp + mozilla::TimeDuration::FromMicroseconds(aMicroseconds)); +} + +void gecko_profiler_subtract_timestamp(const mozilla::TimeStamp* aTimeStamp, + mozilla::TimeStamp* aDestTimeStamp, + double aMicroseconds) { + new (aDestTimeStamp) mozilla::TimeStamp( + *aTimeStamp - mozilla::TimeDuration::FromMicroseconds(aMicroseconds)); +} + +void gecko_profiler_construct_marker_timing_instant_at( + mozilla::MarkerTiming* aMarkerTiming, const mozilla::TimeStamp* aTime) { +#ifdef MOZ_GECKO_PROFILER + static_assert(std::is_trivially_copyable_v<mozilla::MarkerTiming>); + mozilla::MarkerTiming::UnsafeConstruct(aMarkerTiming, *aTime, + mozilla::TimeStamp{}, + mozilla::MarkerTiming::Phase::Instant); +#endif +} + +void gecko_profiler_construct_marker_timing_instant_now( + mozilla::MarkerTiming* aMarkerTiming) { +#ifdef MOZ_GECKO_PROFILER + static_assert(std::is_trivially_copyable_v<mozilla::MarkerTiming>); + mozilla::MarkerTiming::UnsafeConstruct( + aMarkerTiming, mozilla::TimeStamp::Now(), mozilla::TimeStamp{}, + mozilla::MarkerTiming::Phase::Instant); +#endif +} + +void gecko_profiler_construct_marker_timing_interval( + mozilla::MarkerTiming* aMarkerTiming, const mozilla::TimeStamp* aStartTime, + const mozilla::TimeStamp* aEndTime) { +#ifdef MOZ_GECKO_PROFILER + static_assert(std::is_trivially_copyable_v<mozilla::MarkerTiming>); + mozilla::MarkerTiming::UnsafeConstruct( + aMarkerTiming, *aStartTime, *aEndTime, + mozilla::MarkerTiming::Phase::Interval); +#endif +} + +void gecko_profiler_construct_marker_timing_interval_until_now_from( + mozilla::MarkerTiming* aMarkerTiming, + const mozilla::TimeStamp* aStartTime) { +#ifdef MOZ_GECKO_PROFILER + static_assert(std::is_trivially_copyable_v<mozilla::MarkerTiming>); + mozilla::MarkerTiming::UnsafeConstruct( + aMarkerTiming, *aStartTime, mozilla::TimeStamp::Now(), + mozilla::MarkerTiming::Phase::Interval); +#endif +} + +void gecko_profiler_construct_marker_timing_interval_start( + mozilla::MarkerTiming* aMarkerTiming, const mozilla::TimeStamp* aTime) { +#ifdef MOZ_GECKO_PROFILER + static_assert(std::is_trivially_copyable_v<mozilla::MarkerTiming>); + mozilla::MarkerTiming::UnsafeConstruct( + aMarkerTiming, *aTime, mozilla::TimeStamp{}, + mozilla::MarkerTiming::Phase::IntervalStart); +#endif +} + +void gecko_profiler_construct_marker_timing_interval_end( + mozilla::MarkerTiming* aMarkerTiming, const mozilla::TimeStamp* aTime) { +#ifdef MOZ_GECKO_PROFILER + static_assert(std::is_trivially_copyable_v<mozilla::MarkerTiming>); + mozilla::MarkerTiming::UnsafeConstruct( + aMarkerTiming, mozilla::TimeStamp{}, *aTime, + mozilla::MarkerTiming::Phase::IntervalEnd); +#endif +} + +void gecko_profiler_destruct_marker_timing( + mozilla::MarkerTiming* aMarkerTiming) { +#ifdef MOZ_GECKO_PROFILER + aMarkerTiming->~MarkerTiming(); +#endif +} + +void gecko_profiler_construct_marker_schema( + mozilla::MarkerSchema* aMarkerSchema, + const mozilla::MarkerSchema::Location* aLocations, size_t aLength) { +#ifdef MOZ_GECKO_PROFILER + new (aMarkerSchema) mozilla::MarkerSchema(aLocations, aLength); +#endif +} + +void gecko_profiler_construct_marker_schema_with_special_front_end_location( + mozilla::MarkerSchema* aMarkerSchema) { +#ifdef MOZ_GECKO_PROFILER + new (aMarkerSchema) + mozilla::MarkerSchema(mozilla::MarkerSchema::SpecialFrontendLocation{}); +#endif +} + +void gecko_profiler_destruct_marker_schema( + mozilla::MarkerSchema* aMarkerSchema) { +#ifdef MOZ_GECKO_PROFILER + aMarkerSchema->~MarkerSchema(); +#endif +} + +void gecko_profiler_marker_schema_set_chart_label( + mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength) { +#ifdef MOZ_GECKO_PROFILER + aSchema->SetChartLabel(std::string(aLabel, aLabelLength)); +#endif +} + +void gecko_profiler_marker_schema_set_tooltip_label( + mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength) { +#ifdef MOZ_GECKO_PROFILER + aSchema->SetTooltipLabel(std::string(aLabel, aLabelLength)); +#endif +} + +void gecko_profiler_marker_schema_set_table_label( + mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength) { +#ifdef MOZ_GECKO_PROFILER + aSchema->SetTableLabel(std::string(aLabel, aLabelLength)); +#endif +} + +void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema, + const char* aLabel, + size_t aLabelLength) { +#ifdef MOZ_GECKO_PROFILER + aSchema->SetAllLabels(std::string(aLabel, aLabelLength)); +#endif +} + +void gecko_profiler_marker_schema_add_key_format( + mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, + mozilla::MarkerSchema::Format aFormat) { +#ifdef MOZ_GECKO_PROFILER + aSchema->AddKeyFormat(std::string(aKey, aKeyLength), aFormat); +#endif +} + +void gecko_profiler_marker_schema_add_key_label_format( + mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, + const char* aLabel, size_t aLabelLength, + mozilla::MarkerSchema::Format aFormat) { +#ifdef MOZ_GECKO_PROFILER + aSchema->AddKeyLabelFormat(std::string(aKey, aKeyLength), + std::string(aLabel, aLabelLength), aFormat); +#endif +} + +void gecko_profiler_marker_schema_add_key_format_searchable( + mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, + mozilla::MarkerSchema::Format aFormat, + mozilla::MarkerSchema::Searchable aSearchable) { +#ifdef MOZ_GECKO_PROFILER + aSchema->AddKeyFormatSearchable(std::string(aKey, aKeyLength), aFormat, + aSearchable); +#endif +} + +void gecko_profiler_marker_schema_add_key_label_format_searchable( + mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, + const char* aLabel, size_t aLabelLength, + mozilla::MarkerSchema::Format aFormat, + mozilla::MarkerSchema::Searchable aSearchable) { +#ifdef MOZ_GECKO_PROFILER + aSchema->AddKeyLabelFormatSearchable(std::string(aKey, aKeyLength), + std::string(aLabel, aLabelLength), + aFormat, aSearchable); +#endif +} + +void gecko_profiler_marker_schema_add_static_label_value( + mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength, + const char* aValue, size_t aValueLength) { +#ifdef MOZ_GECKO_PROFILER + aSchema->AddStaticLabelValue(std::string(aLabel, aLabelLength), + std::string(aValue, aValueLength)); +#endif +} + +void gecko_profiler_marker_schema_stream( + mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName, + size_t aNameLength, mozilla::MarkerSchema* aMarkerSchema, + void* aStreamedNamesSet) { +#ifdef MOZ_GECKO_PROFILER + auto* streamedNames = static_cast<std::set<std::string>*>(aStreamedNamesSet); + // std::set.insert(T&&) returns a pair, its `second` is true if the element + // was actually inserted (i.e., it was not there yet.). + const bool didInsert = + streamedNames->insert(std::string(aName, aNameLength)).second; + if (didInsert) { + std::move(*aMarkerSchema) + .Stream(*aWriter, mozilla::Span(aName, aNameLength)); + } +#endif +} + +void gecko_profiler_json_writer_int_property( + mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName, + size_t aNameLength, int64_t aValue) { +#ifdef MOZ_GECKO_PROFILER + aWriter->IntProperty(mozilla::Span(aName, aNameLength), aValue); +#endif +} + +void gecko_profiler_json_writer_float_property( + mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName, + size_t aNameLength, double aValue) { +#ifdef MOZ_GECKO_PROFILER + aWriter->DoubleProperty(mozilla::Span(aName, aNameLength), aValue); +#endif +} + +void gecko_profiler_json_writer_bool_property( + mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName, + size_t aNameLength, bool aValue) { +#ifdef MOZ_GECKO_PROFILER + aWriter->BoolProperty(mozilla::Span(aName, aNameLength), aValue); +#endif +} +void gecko_profiler_json_writer_string_property( + mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName, + size_t aNameLength, const char* aValue, size_t aValueLength) { +#ifdef MOZ_GECKO_PROFILER + aWriter->StringProperty(mozilla::Span(aName, aNameLength), + mozilla::Span(aValue, aValueLength)); +#endif +} + +void gecko_profiler_json_writer_null_property( + mozilla::baseprofiler::SpliceableJSONWriter* aWriter, const char* aName, + size_t aNameLength) { +#ifdef MOZ_GECKO_PROFILER + aWriter->NullProperty(mozilla::Span(aName, aNameLength)); +#endif +} + +void gecko_profiler_add_marker_untyped( + const char* aName, size_t aNameLength, + mozilla::baseprofiler::ProfilingCategoryPair aCategoryPair, + mozilla::MarkerTiming* aMarkerTiming, + mozilla::StackCaptureOptions aStackCaptureOptions) { +#ifdef MOZ_GECKO_PROFILER + profiler_add_marker( + mozilla::ProfilerString8View(aName, aNameLength), + mozilla::MarkerCategory{aCategoryPair}, + mozilla::MarkerOptions( + std::move(*aMarkerTiming), + mozilla::MarkerStack::WithCaptureOptions(aStackCaptureOptions))); +#endif +} + +void gecko_profiler_add_marker_text( + const char* aName, size_t aNameLength, + mozilla::baseprofiler::ProfilingCategoryPair aCategoryPair, + mozilla::MarkerTiming* aMarkerTiming, + mozilla::StackCaptureOptions aStackCaptureOptions, const char* aText, + size_t aTextLength) { +#ifdef MOZ_GECKO_PROFILER + profiler_add_marker( + mozilla::ProfilerString8View(aName, aNameLength), + mozilla::MarkerCategory{aCategoryPair}, + mozilla::MarkerOptions( + std::move(*aMarkerTiming), + mozilla::MarkerStack::WithCaptureOptions(aStackCaptureOptions)), + geckoprofiler::markers::TextMarker{}, + mozilla::ProfilerString8View(aText, aTextLength)); +#endif +} + +void gecko_profiler_add_marker( + const char* aName, size_t aNameLength, + mozilla::baseprofiler::ProfilingCategoryPair aCategoryPair, + mozilla::MarkerTiming* aMarkerTiming, + mozilla::StackCaptureOptions aStackCaptureOptions, uint8_t aMarkerTag, + const uint8_t* aPayload, size_t aPayloadSize) { +#ifdef MOZ_GECKO_PROFILER + // Copy the marker timing and create the marker option. + mozilla::MarkerOptions markerOptions( + std::move(*aMarkerTiming), + mozilla::MarkerStack::WithCaptureOptions(aStackCaptureOptions)); + + // Currently it's not possible to add a threadId option, but we will + // have it soon. + if (markerOptions.ThreadId().IsUnspecified()) { + // If yet unspecified, set thread to this thread where the marker is added. + markerOptions.Set(mozilla::MarkerThreadId::CurrentThread()); + } + + auto& buffer = profiler_get_core_buffer(); + mozilla::Span payload(aPayload, aPayloadSize); + + mozilla::StackCaptureOptions captureOptions = + markerOptions.Stack().CaptureOptions(); + if (captureOptions != mozilla::StackCaptureOptions::NoStack && + // Do not capture a stack if the NoMarkerStacks feature is set. + profiler_active_without_feature(ProfilerFeature::NoMarkerStacks)) { + // A capture was requested, let's attempt to do it here&now. This avoids a + // lot of allocations that would be necessary if capturing a backtrace + // separately. + // TODO use a local on-stack byte buffer to remove last allocation. + // TODO reduce internal profiler stack levels, see bug 1659872. + mozilla::ProfileBufferChunkManagerSingle chunkManager( + mozilla::ProfileBufferChunkManager::scExpectedMaximumStackSize); + mozilla::ProfileChunkedBuffer chunkedBuffer( + mozilla::ProfileChunkedBuffer::ThreadSafety::WithoutMutex, + chunkManager); + markerOptions.StackRef().UseRequestedBacktrace( + profiler_capture_backtrace_into(chunkedBuffer, captureOptions) + ? &chunkedBuffer + : nullptr); + + // This call must be made from here, while chunkedBuffer is in scope. + buffer.PutObjects( + mozilla::ProfileBufferEntryKind::Marker, markerOptions, + mozilla::ProfilerString8View(aName, aNameLength), + mozilla::MarkerCategory{aCategoryPair}, + mozilla::base_profiler_markers_detail::Streaming::DeserializerTag( + aMarkerTag), + mozilla::MarkerPayloadType::Rust, payload); + return; + } + + buffer.PutObjects( + mozilla::ProfileBufferEntryKind::Marker, markerOptions, + mozilla::ProfilerString8View(aName, aNameLength), + mozilla::MarkerCategory{aCategoryPair}, + mozilla::base_profiler_markers_detail::Streaming::DeserializerTag( + aMarkerTag), + mozilla::MarkerPayloadType::Rust, payload); +#endif +} |