From a90a5cba08fdf6c0ceb95101c275108a152a3aed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:37 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- xpcom/threads/MozPromise.h | 110 +++++++++++++++++++------------------ xpcom/threads/StaticString.h | 102 ++++++++++++++++++++++++++++++++++ xpcom/threads/TaskController.cpp | 2 + xpcom/threads/moz.build | 1 + xpcom/threads/nsIThreadManager.idl | 2 +- xpcom/threads/nsThreadManager.cpp | 4 ++ 6 files changed, 166 insertions(+), 55 deletions(-) create mode 100644 xpcom/threads/StaticString.h (limited to 'xpcom/threads') diff --git a/xpcom/threads/MozPromise.h b/xpcom/threads/MozPromise.h index c53037e119..3155d9ea63 100644 --- a/xpcom/threads/MozPromise.h +++ b/xpcom/threads/MozPromise.h @@ -17,6 +17,7 @@ #include "mozilla/Monitor.h" #include "mozilla/Mutex.h" #include "mozilla/RefPtr.h" +#include "mozilla/StaticString.h" #include "mozilla/UniquePtr.h" #include "mozilla/Variant.h" #include "nsIDirectTaskDispatcher.h" @@ -231,7 +232,7 @@ class MozPromise : public MozPromiseBase { protected: // MozPromise is the public type, and never constructed directly. Construct // a MozPromise::Private, defined below. - MozPromise(const char* aCreationSite, bool aIsCompletionPromise) + MozPromise(StaticString aCreationSite, bool aIsCompletionPromise) : mCreationSite(aCreationSite), mMutex("MozPromise Mutex"), mHaveRequest(false), @@ -241,7 +242,7 @@ class MozPromise : public MozPromiseBase { mMagic4(&mMutex) #endif { - PROMISE_LOG("%s creating MozPromise (%p)", mCreationSite, this); + PROMISE_LOG("%s creating MozPromise (%p)", mCreationSite.get(), this); } public: @@ -257,7 +258,7 @@ class MozPromise : public MozPromiseBase { template [[nodiscard]] static RefPtr CreateAndResolve( - ResolveValueType_&& aResolveValue, const char* aResolveSite) { + ResolveValueType_&& aResolveValue, StaticString aResolveSite) { static_assert(std::is_convertible_v, "Resolve() argument must be implicitly convertible to " "MozPromise's ResolveValueT"); @@ -269,7 +270,7 @@ class MozPromise : public MozPromiseBase { template [[nodiscard]] static RefPtr CreateAndReject( - RejectValueType_&& aRejectValue, const char* aRejectSite) { + RejectValueType_&& aRejectValue, StaticString aRejectSite) { static_assert(std::is_convertible_v, "Reject() argument must be implicitly convertible to " "MozPromise's RejectValueT"); @@ -281,7 +282,7 @@ class MozPromise : public MozPromiseBase { template [[nodiscard]] static RefPtr CreateAndResolveOrReject( - ResolveOrRejectValueType_&& aValue, const char* aSite) { + ResolveOrRejectValueType_&& aValue, StaticString aSite) { RefPtr p = new MozPromise::Private(aSite); p->ResolveOrReject(std::forward(aValue), aSite); return p; @@ -497,7 +498,7 @@ class MozPromise : public MozPromiseBase { RefPtr mPromise; }; - ThenValueBase(nsISerialEventTarget* aResponseTarget, const char* aCallSite) + ThenValueBase(nsISerialEventTarget* aResponseTarget, StaticString aCallSite) : mResponseTarget(aResponseTarget), mCallSite(aCallSite) { MOZ_ASSERT(aResponseTarget); } @@ -526,7 +527,7 @@ class MozPromise : public MozPromiseBase { MOZ_CRASH_UNSAFE_PRINTF( "MozPromise::ThenValue created from '%s' destroyed without being " "either disconnected, resolved, or rejected (dispatchRv: %s)", - mCallSite, + mCallSite.get(), mDispatchRv ? GetStaticErrorName(*mDispatchRv) : "not dispatched"); } @@ -543,8 +544,8 @@ class MozPromise : public MozPromiseBase { PROMISE_LOG( "%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p] " "%s dispatch", - aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting", mCallSite, - r.get(), aPromise, this, + aPromise->mValue.IsResolve() ? "Resolving" : "Rejecting", + mCallSite.get(), r.get(), aPromise, this, aPromise->mUseSynchronousTaskDispatch ? "synchronous" : aPromise->mUseDirectTaskDispatch ? "directtask" : "normal"); @@ -631,7 +632,7 @@ class MozPromise : public MozPromiseBase { #ifdef PROMISE_DEBUG uint32_t mMagic1 = sMagic; #endif - const char* mCallSite; + StaticString mCallSite; #ifdef PROMISE_DEBUG uint32_t mMagic2 = sMagic; #endif @@ -706,7 +707,7 @@ class MozPromise : public MozPromiseBase { public: ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal, ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod, - const char* aCallSite) + StaticString aCallSite) : ThenValueBase(aResponseTarget, aCallSite), mThisVal(aThisVal), mResolveMethod(aResolveMethod), @@ -767,7 +768,7 @@ class MozPromise : public MozPromiseBase { public: ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal, ResolveRejectMethodType aResolveRejectMethod, - const char* aCallSite) + StaticString aCallSite) : ThenValueBase(aResponseTarget, aCallSite), mThisVal(aThisVal), mResolveRejectMethod(aResolveRejectMethod) {} @@ -824,7 +825,7 @@ class MozPromise : public MozPromiseBase { public: ThenValue(nsISerialEventTarget* aResponseTarget, ResolveFunction&& aResolveFunction, - RejectFunction&& aRejectFunction, const char* aCallSite) + RejectFunction&& aRejectFunction, StaticString aCallSite) : ThenValueBase(aResponseTarget, aCallSite) { mResolveFunction.emplace(std::move(aResolveFunction)); mRejectFunction.emplace(std::move(aRejectFunction)); @@ -892,7 +893,7 @@ class MozPromise : public MozPromiseBase { public: ThenValue(nsISerialEventTarget* aResponseTarget, ResolveRejectFunction&& aResolveRejectFunction, - const char* aCallSite) + StaticString aCallSite) : ThenValueBase(aResponseTarget, aCallSite) { mResolveRejectFunction.emplace(std::move(aResolveRejectFunction)); } @@ -945,7 +946,7 @@ class MozPromise : public MozPromiseBase { public: explicit MapValue(nsISerialEventTarget* aResponseTarget, - ResolveFunction&& f, const char* aCallSite) + ResolveFunction&& f, StaticString aCallSite) : ThenValueBase(aResponseTarget, aCallSite), mResolveFunction(Some(std::forward(f))) {} @@ -991,7 +992,7 @@ class MozPromise : public MozPromiseBase { public: explicit MapErrValue(nsISerialEventTarget* aResponseTarget, - RejectFunction&& f, const char* aCallSite) + RejectFunction&& f, StaticString aCallSite) : ThenValueBase(aResponseTarget, aCallSite), mRejectFunction(Some(std::forward(f))) {} @@ -1030,7 +1031,7 @@ class MozPromise : public MozPromiseBase { public: void ThenInternal(already_AddRefed aThenValue, - const char* aCallSite) { + StaticString aCallSite) { PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex); RefPtr thenValue = aThenValue; @@ -1040,7 +1041,7 @@ class MozPromise : public MozPromiseBase { "Using an exclusive promise in a non-exclusive fashion"); mHaveRequest = true; PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]", - aCallSite, this, thenValue.get(), (int)IsPending()); + aCallSite.get(), this, thenValue.get(), (int)IsPending()); if (!IsPending()) { thenValue->Dispatch(this); } else { @@ -1072,7 +1073,7 @@ class MozPromise : public MozPromiseBase { using PromiseType = typename ThenValueType::PromiseType; using Private = typename PromiseType::Private; - ThenCommand(const char* aCallSite, + ThenCommand(StaticString aCallSite, already_AddRefed aThenValue, MozPromise* aReceiver) : mCallSite(aCallSite), mThenValue(aThenValue), mReceiver(aReceiver) {} @@ -1137,7 +1138,7 @@ class MozPromise : public MozPromiseBase { ThenCommand* operator->() { return this; } private: - const char* mCallSite; + StaticString mCallSite; RefPtr mThenValue; RefPtr mReceiver; }; @@ -1146,7 +1147,7 @@ class MozPromise : public MozPromiseBase { template , typename ReturnType = ThenCommand> - ReturnType Then(nsISerialEventTarget* aResponseTarget, const char* aCallSite, + ReturnType Then(nsISerialEventTarget* aResponseTarget, StaticString aCallSite, ThisType* aThisVal, Methods... aMethods) { RefPtr thenValue = new ThenValueType(aResponseTarget, aThisVal, aMethods..., aCallSite); @@ -1156,7 +1157,7 @@ class MozPromise : public MozPromiseBase { template , typename ReturnType = ThenCommand> - ReturnType Then(nsISerialEventTarget* aResponseTarget, const char* aCallSite, + ReturnType Then(nsISerialEventTarget* aResponseTarget, StaticString aCallSite, Functions&&... aFunctions) { RefPtr thenValue = new ThenValueType(aResponseTarget, std::move(aFunctions)..., aCallSite); @@ -1166,7 +1167,7 @@ class MozPromise : public MozPromiseBase { // Shorthand for a `Then` which simply forwards the reject-value, but performs // some additional work with the resolve-value. template - auto Map(nsISerialEventTarget* aResponseTarget, const char* aCallSite, + auto Map(nsISerialEventTarget* aResponseTarget, StaticString aCallSite, Function&& function) { RefPtr> thenValue = new MapValue( aResponseTarget, std::forward(function), aCallSite); @@ -1176,7 +1177,7 @@ class MozPromise : public MozPromiseBase { // Shorthand for a `Then` which simply forwards the resolve-value, but // performs some additional work with the reject-value. template - auto MapErr(nsISerialEventTarget* aResponseTarget, const char* aCallSite, + auto MapErr(nsISerialEventTarget* aResponseTarget, StaticString aCallSite, Function&& function) { RefPtr> thenValue = new MapErrValue( aResponseTarget, std::forward(function), aCallSite); @@ -1185,7 +1186,7 @@ class MozPromise : public MozPromiseBase { } void ChainTo(already_AddRefed aChainedPromise, - const char* aCallSite) { + StaticString aCallSite) { MutexAutoLock lock(mMutex); MOZ_DIAGNOSTIC_ASSERT( !IsExclusive || !mHaveRequest, @@ -1194,7 +1195,7 @@ class MozPromise : public MozPromiseBase { RefPtr chainedPromise = aChainedPromise; PROMISE_LOG( "%s invoking Chain() [this=%p, chainedPromise=%p, isPending=%d]", - aCallSite, this, chainedPromise.get(), (int)IsPending()); + aCallSite.get(), this, chainedPromise.get(), (int)IsPending()); // We want to use the same type of dispatching method with the chained // promises. @@ -1305,7 +1306,7 @@ class MozPromise : public MozPromiseBase { #endif }; - const char* mCreationSite; // For logging + StaticString mCreationSite; // For logging Mutex mMutex MOZ_UNANNOTATED; ResolveOrRejectValue mValue; bool mUseSynchronousTaskDispatch = false; @@ -1335,21 +1336,22 @@ template class MozPromise::Private : public MozPromise { public: - explicit Private(const char* aCreationSite, bool aIsCompletionPromise = false) + explicit Private(StaticString aCreationSite, + bool aIsCompletionPromise = false) : MozPromise(aCreationSite, aIsCompletionPromise) {} template - void Resolve(ResolveValueT_&& aResolveValue, const char* aResolveSite) { + void Resolve(ResolveValueT_&& aResolveValue, StaticString aResolveSite) { PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex); MutexAutoLock lock(mMutex); - PROMISE_LOG("%s resolving MozPromise (%p created at %s)", aResolveSite, - this, mCreationSite); + PROMISE_LOG("%s resolving MozPromise (%p created at %s)", + aResolveSite.get(), this, mCreationSite.get()); if (!IsPending()) { PROMISE_LOG( "%s ignored already resolved or rejected MozPromise (%p created at " "%s)", - aResolveSite, this, mCreationSite); + aResolveSite.get(), this, mCreationSite.get()); return; } mValue.SetResolve(std::forward(aResolveValue)); @@ -1357,17 +1359,17 @@ class MozPromise::Private } template - void Reject(RejectValueT_&& aRejectValue, const char* aRejectSite) { + void Reject(RejectValueT_&& aRejectValue, StaticString aRejectSite) { PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex); MutexAutoLock lock(mMutex); - PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite, this, - mCreationSite); + PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite.get(), + this, mCreationSite.get()); if (!IsPending()) { PROMISE_LOG( "%s ignored already resolved or rejected MozPromise (%p created at " "%s)", - aRejectSite, this, mCreationSite); + aRejectSite.get(), this, mCreationSite.get()); return; } mValue.SetReject(std::forward(aRejectValue)); @@ -1375,17 +1377,17 @@ class MozPromise::Private } template - void ResolveOrReject(ResolveOrRejectValue_&& aValue, const char* aSite) { + void ResolveOrReject(ResolveOrRejectValue_&& aValue, StaticString aSite) { PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex); MutexAutoLock lock(mMutex); - PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)", aSite, - this, mCreationSite); + PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)", + aSite.get(), this, mCreationSite.get()); if (!IsPending()) { PROMISE_LOG( "%s ignored already resolved or rejected MozPromise (%p created at " "%s)", - aSite, this, mCreationSite); + aSite.get(), this, mCreationSite.get()); return; } mValue = std::forward(aValue); @@ -1403,7 +1405,7 @@ class MozPromise::Private mMagic3 == sMagic && mMagic4 == &mMutex); MutexAutoLock lock(mMutex); PROMISE_LOG("%s UseSynchronousTaskDispatch MozPromise (%p created at %s)", - aSite, this, mCreationSite); + aSite, this, mCreationSite.get()); MOZ_ASSERT(IsPending(), "A Promise must not have been already resolved or rejected to " "set dispatch state"); @@ -1420,7 +1422,7 @@ class MozPromise::Private mMagic3 == sMagic && mMagic4 == &mMutex); MutexAutoLock lock(mMutex); PROMISE_LOG("%s UseDirectTaskDispatch MozPromise (%p created at %s)", aSite, - this, mCreationSite); + this, mCreationSite.get()); MOZ_ASSERT(IsPending(), "A Promise must not have been already resolved or rejected to " "set dispatch state"); @@ -1437,7 +1439,7 @@ class MozPromise::Private mMagic3 == sMagic && mMagic4 == &mMutex); MutexAutoLock lock(mMutex); PROMISE_LOG("%s TaskPriority MozPromise (%p created at %s)", aSite, this, - mCreationSite); + mCreationSite.get()); MOZ_ASSERT(IsPending(), "A Promise must not have been already resolved or rejected to " "set dispatch state"); @@ -1478,7 +1480,7 @@ class MozPromiseHolderBase { ~MozPromiseHolderBase() { MOZ_ASSERT(!mPromise); } - already_AddRefed Ensure(const char* aMethodName) { + already_AddRefed Ensure(StaticString aMethodName) { static_cast(this)->Check(); if (!mPromise) { mPromise = new (typename PromiseType::Private)(aMethodName); @@ -1498,7 +1500,7 @@ class MozPromiseHolderBase { } template - void Resolve(ResolveValueType_&& aResolveValue, const char* aMethodName) { + void Resolve(ResolveValueType_&& aResolveValue, StaticString aMethodName) { static_assert(std::is_convertible_v, "Resolve() argument must be implicitly convertible to " @@ -1513,14 +1515,14 @@ class MozPromiseHolderBase { template void ResolveIfExists(ResolveValueType_&& aResolveValue, - const char* aMethodName) { + StaticString aMethodName) { if (!IsEmpty()) { Resolve(std::forward(aResolveValue), aMethodName); } } template - void Reject(RejectValueType_&& aRejectValue, const char* aMethodName) { + void Reject(RejectValueType_&& aRejectValue, StaticString aMethodName) { static_assert(std::is_convertible_v, "Reject() argument must be implicitly convertible to " @@ -1534,7 +1536,7 @@ class MozPromiseHolderBase { template void RejectIfExists(RejectValueType_&& aRejectValue, - const char* aMethodName) { + StaticString aMethodName) { if (!IsEmpty()) { Reject(std::forward(aRejectValue), aMethodName); } @@ -1542,7 +1544,7 @@ class MozPromiseHolderBase { template void ResolveOrReject(ResolveOrRejectValueType_&& aValue, - const char* aMethodName) { + StaticString aMethodName) { static_cast(this)->Check(); MOZ_ASSERT(mPromise); mPromise->ResolveOrReject(std::forward(aValue), @@ -1552,7 +1554,7 @@ class MozPromiseHolderBase { template void ResolveOrRejectIfExists(ResolveOrRejectValueType_&& aValue, - const char* aMethodName) { + StaticString aMethodName) { if (!IsEmpty()) { ResolveOrReject(std::forward(aValue), aMethodName); @@ -1718,7 +1720,7 @@ class ProxyRunnable : public CancelableRunnable { template static RefPtr InvokeAsyncImpl( - nsISerialEventTarget* aTarget, ThisType* aThisVal, const char* aCallerName, + nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName, RefPtr (ThisType::*aMethod)(ArgTypes...), ActualArgTypes&&... aArgs) { MOZ_ASSERT(aTarget); @@ -1758,7 +1760,7 @@ template = 0> static RefPtr InvokeAsync( - nsISerialEventTarget* aTarget, ThisType* aThisVal, const char* aCallerName, + nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName, RefPtr (ThisType::*aMethod)(ArgTypes...), ActualArgTypes&&... aArgs) { static_assert( @@ -1777,7 +1779,7 @@ template = 0> static RefPtr InvokeAsync( - nsISerialEventTarget* aTarget, ThisType* aThisVal, const char* aCallerName, + nsISerialEventTarget* aTarget, ThisType* aThisVal, StaticString aCallerName, RefPtr (ThisType::*aMethod)(ArgTypes...), ActualArgTypes&&... aArgs) { static_assert( @@ -1831,7 +1833,7 @@ constexpr static bool IsRefPtrMozPromise>> = true; // Invoke a function object (e.g., lambda) asynchronously. // Return a promise that the function should eventually resolve or reject. template -static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName, +static auto InvokeAsync(nsISerialEventTarget* aTarget, StaticString aCallerName, Function&& aFunction) -> decltype(aFunction()) { static_assert(!std::is_lvalue_reference_v, "Function object must not be passed by lvalue-ref (to avoid " diff --git a/xpcom/threads/StaticString.h b/xpcom/threads/StaticString.h new file mode 100644 index 0000000000..26c8675b24 --- /dev/null +++ b/xpcom/threads/StaticString.h @@ -0,0 +1,102 @@ +/* -*- 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/. */ + +#ifndef XPCOM_THREADS_STATICSTRING_H_ +#define XPCOM_THREADS_STATICSTRING_H_ + +#include +#include "mozilla/Attributes.h" + +// from "nsStringFwd.h" +template +class nsTLiteralString; +using nsLiteralCString = nsTLiteralString; + +namespace mozilla { +// class StaticString +// +// Wrapper type containing a C-style string which is guaranteed[*] to have been +// created (potentially indirectly) from static data. Primarily intended for +// text that may eventually be sent up via telemetry, to avoid the possibility +// of accidentally exfiltrating PII. +// +// `StaticString`, like `template const char (&str)[N]`, can be +// freely and implicitly converted to `const char *`, to simplify its use as a +// drop-in replacement when detemplatizing functions. +// +// ### Comparison/contrast with `nsLiteralCString` +// +// Concretely, `StaticString` is smaller than `nsLiteralCString`, as it does not +// store the string-length. It's also trivial to construct a `StaticString` from +// the variable `__func__` or the preprocessor token `__FILE__`, which would +// require additional work to be used with the latter's `_ns` constructor. +// +// Conventionally, the primary intended use case of `StaticString` is subtly +// different from that of `nsLiteralCString`: +// * `StaticString` is intended for correctness (etc.) in contexts where the +// consumer of the string requires that it be static. +// * `nsLiteralCString` is more for efficiency in contexts where the source +// string _happens to be_ static, but in which the consumer does not care +// (and so accepts `nsACString const &` or similar). +// +// This is not a hard rule, however, and is notably bent in dom::Promise. (See +// comments below.) +// +// Both are trivially-copyable/-movable/-destructible, guaranteed non-null, and +// can only contain static data. +// +// #### Footnotes +// +// [*] ``` +// CHORUS: "What, never?" +// CAPTAIN: "Well... hardly ever!" +// CHORUS: "He's hardly ever sick of C!" +// -- Gilbert & Sullivan, _H.M.S. Pinafore_ (emended) +// ``` +// +class StaticString { + /* TODO(C++20): convert `constexpr` to `consteval` wherever possible. */ + const char* mStr; // guaranteed nonnull + + public: + template + constexpr MOZ_IMPLICIT StaticString(const char (&str)[N]) : mStr(str) {} + + // `nsLiteralCString` has the same guarantees as `StaticString` (both in being + // nonnull and containing only static data), so it's safe to construct either + // from the other. + // + // At present we only support construction of a `StaticString` from an + // `nsLiteralCString`, since this is zero-cost (the converse would not be), + // and is probably the simplest way to support dom::Promise's interoperation + // with MozPromise. + // + // (A more principled approach, in some sense, would be to create a third type + // `StaticStringWithLength` (or whatever) acting as the lattice-join of the + // two, which could then decay to either one as necessary. This is overkill + // for our current goals... but might be worthwhile if, _e.g._, you really + // need to get `__func__` into an `nsLiteralCString` rather than just an + // `nsDependentCString` for some reason.) + // + constexpr explicit StaticString(nsLiteralCString const& str); + + constexpr StaticString(StaticString const&) = default; + constexpr StaticString(StaticString&&) = default; + ~StaticString() = default; + + constexpr MOZ_IMPLICIT operator const char*() const { return mStr; } + + // Not normally needed, but useful for variadic logging functions. + constexpr const char* get() const { return mStr; } +}; + +// Under the covers, StaticString is as lightweight as a single pointer: it does +// not store the length of its deta. +static_assert(sizeof(StaticString) == sizeof(const char*)); +static_assert(alignof(StaticString) == alignof(const char*)); +} // namespace mozilla + +#endif diff --git a/xpcom/threads/TaskController.cpp b/xpcom/threads/TaskController.cpp index d8c2d5e176..b9559bdb74 100644 --- a/xpcom/threads/TaskController.cpp +++ b/xpcom/threads/TaskController.cpp @@ -16,6 +16,7 @@ #include "mozilla/InputTaskManager.h" #include "mozilla/VsyncTaskManager.h" #include "mozilla/IOInterposer.h" +#include "mozilla/Perfetto.h" #include "mozilla/StaticPtr.h" #include "mozilla/SchedulerGroup.h" #include "mozilla/ScopeExit.h" @@ -135,6 +136,7 @@ class MOZ_RAII AutoProfileTask { # define AUTO_PROFILE_FOLLOWING_TASK(task) \ nsAutoCString name; \ (task)->GetName(name); \ + PERFETTO_TRACE_EVENT("task", perfetto::DynamicString{name.get()}); \ AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE("Task", OTHER, name); \ mozilla::AutoProfileTask PROFILER_RAII(name, (task)->GetPriority()); #else diff --git a/xpcom/threads/moz.build b/xpcom/threads/moz.build index 06d10ad331..09d7649c6f 100644 --- a/xpcom/threads/moz.build +++ b/xpcom/threads/moz.build @@ -70,6 +70,7 @@ EXPORTS.mozilla += [ "SpinEventLoopUntil.h", "StateMirroring.h", "StateWatching.h", + "StaticString.h", "SynchronizedEventQueue.h", "SyncRunnable.h", "TaskController.h", diff --git a/xpcom/threads/nsIThreadManager.idl b/xpcom/threads/nsIThreadManager.idl index 9629cb630a..2c5de409fe 100644 --- a/xpcom/threads/nsIThreadManager.idl +++ b/xpcom/threads/nsIThreadManager.idl @@ -29,7 +29,7 @@ interface nsINestedEventLoopCondition : nsISupports /** * An interface for creating and locating nsIThread instances. */ -[scriptable, uuid(1be89eca-e2f7-453b-8d38-c11ba247f6f3)] +[scriptable, builtinclass, uuid(1be89eca-e2f7-453b-8d38-c11ba247f6f3)] interface nsIThreadManager : nsISupports { /** diff --git a/xpcom/threads/nsThreadManager.cpp b/xpcom/threads/nsThreadManager.cpp index 3ea324a6c6..52c7db1be4 100644 --- a/xpcom/threads/nsThreadManager.cpp +++ b/xpcom/threads/nsThreadManager.cpp @@ -21,6 +21,7 @@ #include "mozilla/InputTaskManager.h" #include "mozilla/Mutex.h" #include "mozilla/NeverDestroyed.h" +#include "mozilla/Perfetto.h" #include "mozilla/Preferences.h" #include "mozilla/ProfilerMarkers.h" #include "mozilla/SpinEventLoopUntil.h" @@ -270,6 +271,9 @@ nsThreadManager::nsThreadManager() nsThreadManager::~nsThreadManager() = default; nsresult nsThreadManager::Init() { + // Initialize perfetto if on Android. + InitPerfetto(); + // Child processes need to initialize the thread manager before they // initialize XPCOM in order to set up the crash reporter. This leads to // situations where we get initialized twice. -- cgit v1.2.3