summaryrefslogtreecommitdiffstats
path: root/tools/profiler/core/ProfilerBindings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/profiler/core/ProfilerBindings.cpp')
-rw-r--r--tools/profiler/core/ProfilerBindings.cpp386
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
+}