author | Gerald Squelart <gsquelart@mozilla.com> |
Wed, 11 Aug 2021 03:27:50 +0000 | |
changeset 588520 | e3d5648f410e154df54a19f6731da2e16659e52c |
parent 588519 | c1effaec69ba51040c57f35243d0fe673cf4f360 |
child 588521 | 92c07c54be8adca59a0a4e22076b244ceab0e2e9 |
push id | 38694 |
push user | archaeopteryx@coole-files.de |
push date | Wed, 11 Aug 2021 09:37:02 +0000 |
treeherder | mozilla-central@857bc25bbf76 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | florian |
bugs | 1721569 |
milestone | 93.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mozglue/baseprofiler/core/ProfileBuffer.cpp +++ b/mozglue/baseprofiler/core/ProfileBuffer.cpp @@ -44,17 +44,17 @@ uint64_t ProfileBuffer::AddEntry(const P return AddEntry(mEntries, aEntry).ConvertToProfileBufferIndex(); } /* static */ ProfileBufferBlockIndex ProfileBuffer::AddThreadIdEntry( ProfileChunkedBuffer& aProfileChunkedBuffer, BaseProfilerThreadId aThreadId) { return AddEntry(aProfileChunkedBuffer, - ProfileBufferEntry::ThreadId(aThreadId.ToNumber())); + ProfileBufferEntry::ThreadId(aThreadId)); } uint64_t ProfileBuffer::AddThreadIdEntry(BaseProfilerThreadId aThreadId) { return AddThreadIdEntry(mEntries, aThreadId).ConvertToProfileBufferIndex(); } void ProfileBuffer::CollectCodeLocation( const char* aLabel, const char* aStr, uint32_t aFrameFlags,
--- a/mozglue/baseprofiler/core/ProfileBufferEntry.cpp +++ b/mozglue/baseprofiler/core/ProfileBufferEntry.cpp @@ -58,16 +58,24 @@ ProfileBufferEntry::ProfileBufferEntry(K memcpy(mStorage, &aInt64, sizeof(aInt64)); } ProfileBufferEntry::ProfileBufferEntry(Kind aKind, uint64_t aUint64) : mKind(aKind) { memcpy(mStorage, &aUint64, sizeof(aUint64)); } +ProfileBufferEntry::ProfileBufferEntry(Kind aKind, + BaseProfilerThreadId aThreadId) + : mKind(aKind) { + static_assert(std::is_trivially_copyable_v<BaseProfilerThreadId>); + static_assert(sizeof(aThreadId) <= sizeof(mStorage)); + memcpy(mStorage, &aThreadId, sizeof(aThreadId)); +} + const char* ProfileBufferEntry::GetString() const { const char* result; memcpy(&result, mStorage, sizeof(result)); return result; } void* ProfileBufferEntry::GetPtr() const { void* result; @@ -94,16 +102,23 @@ int64_t ProfileBufferEntry::GetInt64() c } uint64_t ProfileBufferEntry::GetUint64() const { uint64_t result; memcpy(&result, mStorage, sizeof(result)); return result; } +BaseProfilerThreadId ProfileBufferEntry::GetThreadId() const { + BaseProfilerThreadId result; + static_assert(std::is_trivially_copyable_v<BaseProfilerThreadId>); + memcpy(&result, mStorage, sizeof(result)); + return result; +} + void ProfileBufferEntry::CopyCharsInto(char (&aOutArray)[kNumChars]) const { memcpy(aOutArray, mStorage, kNumChars); } // END ProfileBufferEntry //////////////////////////////////////////////////////////////////////// // As mentioned in ProfileBufferEntry.h, the JSON format contains many @@ -577,18 +592,17 @@ BaseProfilerThreadId ProfileBuffer::Stre if (!e.Has()) { break; } // Due to the skip_to_next_sample block above, if we have an entry here it // must be a ThreadId entry. MOZ_ASSERT(e.Get().IsThreadId()); - BaseProfilerThreadId threadId = - BaseProfilerThreadId::FromNumber(e.Get().GetInt()); + BaseProfilerThreadId threadId = e.Get().GetThreadId(); e.Next(); // Ignore samples that are for the wrong thread. if (threadId != aThreadId && aThreadId.IsSpecified()) { continue; } MOZ_ASSERT( @@ -1204,18 +1218,17 @@ bool ProfileBuffer::DuplicateLastSample( if (e.CurPos() != *aLastSample) { // The last sample is no longer within the buffer range, so we cannot // use it. Reset the stored buffer position to Nothing(). aLastSample.reset(); return false; } MOZ_RELEASE_ASSERT(e.Has() && e.Get().IsThreadId() && - BaseProfilerThreadId::FromNumber(e.Get().GetInt()) == - aThreadId); + e.Get().GetThreadId() == aThreadId); e.Next(); // Go through the whole entry and duplicate it, until we find the next // one. while (e.Has()) { switch (e.Get().GetKind()) { case ProfileBufferEntry::Kind::Pause:
--- a/mozglue/baseprofiler/core/ProfileBufferEntry.h +++ b/mozglue/baseprofiler/core/ProfileBufferEntry.h @@ -36,16 +36,17 @@ class ProfileBufferEntry { // aString must be a static string. ProfileBufferEntry(Kind aKind, const char* aString); ProfileBufferEntry(Kind aKind, char aChars[kNumChars]); ProfileBufferEntry(Kind aKind, void* aPtr); ProfileBufferEntry(Kind aKind, double aDouble); ProfileBufferEntry(Kind aKind, int64_t aInt64); ProfileBufferEntry(Kind aKind, uint64_t aUint64); ProfileBufferEntry(Kind aKind, int aInt); + ProfileBufferEntry(Kind aKind, BaseProfilerThreadId aThreadId); public: #define CTOR(KIND, TYPE, SIZE) \ static ProfileBufferEntry KIND(TYPE aVal) { \ return ProfileBufferEntry(Kind::KIND, aVal); \ } FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(CTOR) #undef CTOR @@ -69,16 +70,17 @@ class ProfileBufferEntry { uint8_t mStorage[kNumChars]; const char* GetString() const; void* GetPtr() const; double GetDouble() const; int GetInt() const; int64_t GetInt64() const; uint64_t GetUint64() const; + BaseProfilerThreadId GetThreadId() const; void CopyCharsInto(char (&aOutArray)[kNumChars]) const; }; // Packed layout: 1 byte for the tag + 8 bytes for the value. static_assert(sizeof(ProfileBufferEntry) == 9, "bad ProfileBufferEntry size"); class UniqueStacks { public:
--- a/mozglue/baseprofiler/core/ProfiledThreadData.cpp +++ b/mozglue/baseprofiler/core/ProfiledThreadData.cpp @@ -170,16 +170,20 @@ BaseProfilerThreadId StreamSamplesAndMar { aBuffer.StreamMarkersToJSON(aWriter, aThreadId, aProcessStartTime, aSinceTime, aUniqueStacks); } aWriter.EndArray(); } aWriter.EndObject(); + // Tech note: If `ToNumber()` returns a uint64_t, the conversion to int64_t is + // "implementation-defined" before C++20. This is acceptable here, because + // this is a one-way conversion to a unique identifier that's used to visually + // separate data by thread on the front-end. aWriter.IntProperty( "pid", static_cast<int64_t>(profiler_current_process_id().ToNumber())); aWriter.IntProperty("tid", static_cast<int64_t>(aThreadId.IsSpecified() ? aThreadId.ToNumber() : processedThreadId.ToNumber())); return processedThreadId;
--- a/mozglue/baseprofiler/core/platform.cpp +++ b/mozglue/baseprofiler/core/platform.cpp @@ -3360,18 +3360,19 @@ ProfilingStack* profiler_register_thread DEBUG_LOG("profiler_register_thread(%s)", aName); MOZ_RELEASE_ASSERT(CorePS::Exists()); PSAutoLock lock; if (RegisteredThread* thread = FindCurrentThreadRegisteredThread(lock); thread) { - LOG("profiler_register_thread(%s) - thread %d already registered as %s", - aName, int(profiler_current_thread_id().ToNumber()), + LOG("profiler_register_thread(%s) - thread %" PRIu64 + " already registered as %s", + aName, uint64_t(profiler_current_thread_id().ToNumber()), thread->Info()->Name()); // TODO: Use new name. This is currently not possible because the // RegisteredThread's ThreadInfo cannot be changed. // In the meantime, we record a marker that could be used in the frontend. std::string text("Thread "); text += std::to_string(profiler_current_thread_id().ToNumber()); text += " \""; text += thread->Info()->Name(); @@ -3411,18 +3412,19 @@ void profiler_unregister_thread() { // Clear the pointer to the RegisteredThread object that we're about to // destroy. TLSRegisteredThread::SetRegisteredThread(lock, nullptr); // Remove the thread from the list of registered threads. This deletes the // registeredThread object. CorePS::RemoveRegisteredThread(lock, registeredThread); } else { - LOG("profiler_unregister_thread() - thread %d already unregistered", - (profiler_current_thread_id().ToNumber())); + LOG("profiler_unregister_thread() - thread %" PRIu64 + " already unregistered", + uint64_t(profiler_current_thread_id().ToNumber())); // We cannot record a marker on this thread because it was already // unregistered. Send it to the main thread (unless this *is* already the // main thread, which has been unregistered); this may be useful to catch // mismatched register/unregister pairs in Firefox. if (BaseProfilerThreadId tid = profiler_current_thread_id(); tid != profiler_main_thread_id()) { BASE_PROFILER_MARKER_TEXT( "profiler_unregister_thread again", OTHER_Profiling,
--- a/mozglue/baseprofiler/lul/LulMain.cpp +++ b/mozglue/baseprofiler/lul/LulMain.cpp @@ -680,25 +680,25 @@ class PriMap { // a logging sink, for debugging. void (*mLog)(const char*); }; //////////////////////////////////////////////////////////////// // LUL // //////////////////////////////////////////////////////////////// -#define LUL_LOG(_str) \ - do { \ - char buf[200]; \ - SprintfLiteral(buf, "LUL: pid %d tid %d lul-obj %p: %s", \ - int(profiler_current_process_id().ToNumber()), \ - int(profiler_current_thread_id().ToNumber()), this, \ - (_str)); \ - buf[sizeof(buf) - 1] = 0; \ - mLog(buf); \ +#define LUL_LOG(_str) \ + do { \ + char buf[200]; \ + SprintfLiteral(buf, "LUL: pid %" PRIu64 " tid %" PRIu64 " lul-obj %p: %s", \ + uint64_t(profiler_current_process_id().ToNumber()), \ + uint64_t(profiler_current_thread_id().ToNumber()), this, \ + (_str)); \ + buf[sizeof(buf) - 1] = 0; \ + mLog(buf); \ } while (0) LUL::LUL(void (*aLog)(const char*)) : mLog(aLog), mAdminMode(true), mAdminThreadId(profiler_current_thread_id()), mPriMap(new PriMap(aLog)), mSegArray(new SegArray()),
--- a/mozglue/baseprofiler/public/ProfileBufferEntryKinds.h +++ b/mozglue/baseprofiler/public/ProfileBufferEntryKinds.h @@ -2,16 +2,18 @@ /* 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 ProfileBufferEntryKinds_h #define ProfileBufferEntryKinds_h +#include "mozilla/BaseProfilerUtils.h" + #include <cstdint> namespace mozilla { // This is equal to sizeof(double), which is the largest non-char variant in // |u|. static constexpr size_t ProfileBufferEntryNumChars = 8; @@ -30,17 +32,18 @@ static constexpr size_t ProfileBufferEnt MACRO(LineNumber, int, sizeof(int)) \ MACRO(ColumnNumber, int, sizeof(int)) \ MACRO(NativeLeafAddr, void*, sizeof(void*)) \ MACRO(Pause, double, sizeof(double)) \ MACRO(Resume, double, sizeof(double)) \ MACRO(PauseSampling, double, sizeof(double)) \ MACRO(ResumeSampling, double, sizeof(double)) \ MACRO(Responsiveness, double, sizeof(double)) \ - MACRO(ThreadId, int, sizeof(int)) \ + MACRO(ThreadId, ::mozilla::baseprofiler::BaseProfilerThreadId, \ + sizeof(::mozilla::baseprofiler::BaseProfilerThreadId)) \ MACRO(Time, double, sizeof(double)) \ MACRO(TimeBeforeCompactStack, double, sizeof(double)) \ MACRO(CounterId, void*, sizeof(void*)) \ MACRO(CounterKey, uint64_t, sizeof(uint64_t)) \ MACRO(Number, uint64_t, sizeof(uint64_t)) \ MACRO(Count, int64_t, sizeof(int64_t)) \ MACRO(ProfilerOverheadTime, double, sizeof(double)) \ MACRO(ProfilerOverheadDuration, double, sizeof(double))
--- a/mozglue/tests/TestBaseProfiler.cpp +++ b/mozglue/tests/TestBaseProfiler.cpp @@ -3792,19 +3792,19 @@ MOZ_NEVER_INLINE unsigned long long Fibo BASE_PROFILER_MARKER_TEXT("fib", OTHER, MarkerTiming::IntervalUntilNowFrom(start), std::to_string(DEPTH)); } return f2 + f1; } void TestProfiler() { - printf("TestProfiler starting -- pid: %d, tid: %d\n", - int(baseprofiler::profiler_current_process_id().ToNumber()), - int(baseprofiler::profiler_current_thread_id().ToNumber())); + printf("TestProfiler starting -- pid: %" PRIu64 ", tid: %" PRIu64 "\n", + uint64_t(baseprofiler::profiler_current_process_id().ToNumber()), + uint64_t(baseprofiler::profiler_current_thread_id().ToNumber())); // ::SleepMilli(10000); TestProfilerDependencies(); { printf("profiler_init()...\n"); AUTO_BASE_PROFILER_INIT; @@ -4556,19 +4556,20 @@ void TestPredefinedMarkers() { # endif PrintMarkers(buffer); printf("TestPredefinedMarkers done\n"); } void TestProfilerMarkers() { - printf("TestProfilerMarkers -- pid: %d, tid: %d\n", - int(mozilla::baseprofiler::profiler_current_process_id().ToNumber()), - int(mozilla::baseprofiler::profiler_current_thread_id().ToNumber())); + printf( + "TestProfilerMarkers -- pid: %" PRIu64 ", tid: %" PRIu64 "\n", + uint64_t(mozilla::baseprofiler::profiler_current_process_id().ToNumber()), + uint64_t(mozilla::baseprofiler::profiler_current_thread_id().ToNumber())); // ::SleepMilli(10000); TestUniqueJSONStrings(); TestMarkerCategory(); TestMarkerThreadId(); TestMarkerNoPayload(); TestUserMarker(); TestPredefinedMarkers(); @@ -4636,19 +4637,19 @@ void TestProfilerMarkers() { #if defined(XP_WIN) int wmain() #else int main() #endif // defined(XP_WIN) { #ifdef MOZ_GECKO_PROFILER - printf("BaseTestProfiler -- pid: %d, tid: %d\n", - int(baseprofiler::profiler_current_process_id().ToNumber()), - int(baseprofiler::profiler_current_thread_id().ToNumber())); + printf("BaseTestProfiler -- pid: %" PRIu64 ", tid: %" PRIu64 "\n", + uint64_t(baseprofiler::profiler_current_process_id().ToNumber()), + uint64_t(baseprofiler::profiler_current_thread_id().ToNumber())); // ::SleepMilli(10000); #endif // MOZ_GECKO_PROFILER TestProfilerUtils(); // Note that there are two `TestProfiler{,Markers}` functions above, depending // on whether MOZ_GECKO_PROFILER is #defined. TestProfiler(); TestProfilerMarkers();
--- a/tools/profiler/core/ProfileBuffer.cpp +++ b/tools/profiler/core/ProfileBuffer.cpp @@ -44,17 +44,17 @@ ProfileBufferBlockIndex ProfileBuffer::A uint64_t ProfileBuffer::AddEntry(const ProfileBufferEntry& aEntry) { return AddEntry(mEntries, aEntry).ConvertToProfileBufferIndex(); } /* static */ ProfileBufferBlockIndex ProfileBuffer::AddThreadIdEntry( ProfileChunkedBuffer& aProfileChunkedBuffer, ProfilerThreadId aThreadId) { return AddEntry(aProfileChunkedBuffer, - ProfileBufferEntry::ThreadId(aThreadId.ToNumber())); + ProfileBufferEntry::ThreadId(aThreadId)); } uint64_t ProfileBuffer::AddThreadIdEntry(ProfilerThreadId aThreadId) { return AddThreadIdEntry(mEntries, aThreadId).ConvertToProfileBufferIndex(); } void ProfileBuffer::CollectCodeLocation( const char* aLabel, const char* aStr, uint32_t aFrameFlags,
--- a/tools/profiler/core/ProfileBufferEntry.cpp +++ b/tools/profiler/core/ProfileBufferEntry.cpp @@ -64,16 +64,23 @@ ProfileBufferEntry::ProfileBufferEntry(K memcpy(mStorage, &aInt64, sizeof(aInt64)); } ProfileBufferEntry::ProfileBufferEntry(Kind aKind, uint64_t aUint64) : mKind(aKind) { memcpy(mStorage, &aUint64, sizeof(aUint64)); } +ProfileBufferEntry::ProfileBufferEntry(Kind aKind, ProfilerThreadId aThreadId) + : mKind(aKind) { + static_assert(std::is_trivially_copyable_v<ProfilerThreadId>); + static_assert(sizeof(aThreadId) <= sizeof(mStorage)); + memcpy(mStorage, &aThreadId, sizeof(aThreadId)); +} + const char* ProfileBufferEntry::GetString() const { const char* result; memcpy(&result, mStorage, sizeof(result)); return result; } void* ProfileBufferEntry::GetPtr() const { void* result; @@ -100,16 +107,23 @@ int64_t ProfileBufferEntry::GetInt64() c } uint64_t ProfileBufferEntry::GetUint64() const { uint64_t result; memcpy(&result, mStorage, sizeof(result)); return result; } +ProfilerThreadId ProfileBufferEntry::GetThreadId() const { + ProfilerThreadId result; + static_assert(std::is_trivially_copyable_v<ProfilerThreadId>); + memcpy(&result, mStorage, sizeof(result)); + return result; +} + void ProfileBufferEntry::CopyCharsInto(char (&aOutArray)[kNumChars]) const { memcpy(aOutArray, mStorage, kNumChars); } // END ProfileBufferEntry //////////////////////////////////////////////////////////////////////// struct TypeInfo { @@ -811,18 +825,17 @@ ProfilerThreadId ProfileBuffer::StreamSa if (!e.Has()) { break; } // Due to the skip_to_next_sample block above, if we have an entry here it // must be a ThreadId entry. MOZ_ASSERT(e.Get().IsThreadId()); - ProfilerThreadId threadId = - ProfilerThreadId::FromNumber(e.Get().GetInt()); + ProfilerThreadId threadId = e.Get().GetThreadId(); e.Next(); // Ignore samples that are for the wrong thread. if (threadId != aThreadId && aThreadId.IsSpecified()) { continue; } MOZ_ASSERT( @@ -1105,18 +1118,17 @@ void ProfileBuffer::AddJITInfoForRange(u while (e.Has() && !e.Get().IsThreadId()) { e.Next(); } if (!e.Has()) { break; } MOZ_ASSERT(e.Get().IsThreadId()); - ProfilerThreadId threadId = - ProfilerThreadId::FromNumber(e.Get().GetInt()); + ProfilerThreadId threadId = e.Get().GetThreadId(); e.Next(); // Ignore samples that are for a different thread. if (threadId != aThreadId) { continue; } if (e.Has() && e.Get().IsTime()) { @@ -1609,18 +1621,17 @@ bool ProfileBuffer::DuplicateLastSample( if (e.CurPos() != *aLastSample) { // The last sample is no longer within the buffer range, so we cannot // use it. Reset the stored buffer position to Nothing(). aLastSample.reset(); return false; } MOZ_RELEASE_ASSERT(e.Has() && e.Get().IsThreadId() && - ProfilerThreadId::FromNumber(e.Get().GetInt()) == - aThreadId); + e.Get().GetThreadId() == aThreadId); e.Next(); // Go through the whole entry and duplicate it, until we find the next // one. while (e.Has()) { switch (e.Get().GetKind()) { case ProfileBufferEntry::Kind::Pause:
--- a/tools/profiler/core/ProfileBufferEntry.h +++ b/tools/profiler/core/ProfileBufferEntry.h @@ -14,16 +14,17 @@ #include "gtest/MozGtestFriend.h" #include "js/ProfilingCategory.h" #include "mozilla/Attributes.h" #include "mozilla/HashFunctions.h" #include "mozilla/HashTable.h" #include "mozilla/Maybe.h" #include "mozilla/ProfileBufferEntryKinds.h" #include "mozilla/ProfileJSONWriter.h" +#include "mozilla/ProfilerUtils.h" #include "mozilla/UniquePtr.h" #include "mozilla/Variant.h" #include "mozilla/Vector.h" #include "nsString.h" class ProfilerCodeAddressService; struct JSContext; @@ -40,16 +41,17 @@ class ProfileBufferEntry { // aString must be a static string. ProfileBufferEntry(Kind aKind, const char* aString); ProfileBufferEntry(Kind aKind, char aChars[kNumChars]); ProfileBufferEntry(Kind aKind, void* aPtr); ProfileBufferEntry(Kind aKind, double aDouble); ProfileBufferEntry(Kind aKind, int64_t aInt64); ProfileBufferEntry(Kind aKind, uint64_t aUint64); ProfileBufferEntry(Kind aKind, int aInt); + ProfileBufferEntry(Kind aKind, ProfilerThreadId aThreadId); public: #define CTOR(KIND, TYPE, SIZE) \ static ProfileBufferEntry KIND(TYPE aVal) { \ return ProfileBufferEntry(Kind::KIND, aVal); \ } FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(CTOR) #undef CTOR @@ -73,16 +75,17 @@ class ProfileBufferEntry { uint8_t mStorage[kNumChars]; const char* GetString() const; void* GetPtr() const; double GetDouble() const; int GetInt() const; int64_t GetInt64() const; uint64_t GetUint64() const; + ProfilerThreadId GetThreadId() const; void CopyCharsInto(char (&aOutArray)[kNumChars]) const; }; // Packed layout: 1 byte for the tag + 8 bytes for the value. static_assert(sizeof(ProfileBufferEntry) == 9, "bad ProfileBufferEntry size"); // Contains all the information about JIT frames that is needed to stream stack // frames for JitReturnAddr entries in the profiler buffer.
--- a/tools/profiler/core/ProfiledThreadData.cpp +++ b/tools/profiler/core/ProfiledThreadData.cpp @@ -283,16 +283,20 @@ ProfilerThreadId StreamSamplesAndMarkers { aBuffer.StreamMarkersToJSON(aWriter, aThreadId, aProcessStartTime, aSinceTime, aUniqueStacks); } aWriter.EndArray(); } aWriter.EndObject(); + // Tech note: If `ToNumber()` returns a uint64_t, the conversion to int64_t is + // "implementation-defined" before C++20. This is acceptable here, because + // this is a one-way conversion to a unique identifier that's used to visually + // separate data by thread on the front-end. aWriter.IntProperty( "pid", static_cast<int64_t>(profiler_current_process_id().ToNumber())); aWriter.IntProperty("tid", static_cast<int64_t>(aThreadId.IsSpecified() ? aThreadId.ToNumber() : processedThreadId.ToNumber())); return processedThreadId;
--- a/tools/profiler/core/memory_hooks.cpp +++ b/tools/profiler/core/memory_hooks.cpp @@ -91,17 +91,22 @@ static bool profiler_add_native_allocati return mozilla::MakeStringSpan("Native allocation"); } static void StreamJSONMarkerData( mozilla::baseprofiler::SpliceableJSONWriter& aWriter, int64_t aSize, uintptr_t aMemoryAddress, ProfilerThreadId aThreadId) { aWriter.IntProperty("size", aSize); aWriter.IntProperty("memoryAddress", static_cast<int64_t>(aMemoryAddress)); - aWriter.IntProperty("threadId", aThreadId.ToNumber()); + // Tech note: If `ToNumber()` returns a uint64_t, the conversion to + // int64_t is "implementation-defined" before C++20. This is acceptable + // here, because this is a one-way conversion to a unique identifier + // that's used to visually separate data by thread on the front-end. + aWriter.IntProperty("threadId", + static_cast<int64_t>(aThreadId.ToNumber())); } static mozilla::MarkerSchema MarkerTypeDisplay() { return mozilla::MarkerSchema::SpecialFrontendLocation{}; } }; profiler_add_marker("Native allocation", geckoprofiler::category::OTHER, {MarkerThreadId::MainThread(), MarkerStack::Capture()},
--- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -1602,18 +1602,19 @@ AutoProfilerLabel::ProfilingStackOwnerTL void AutoProfilerLabel::ProfilingStackOwnerTLS::Init() { MOZ_ASSERT(sState == State::Uninitialized, "Already initialized"); sState = sProfilingStackOwnerTLS.init() ? State::Initialized : State::Unavailable; } void ProfilingStackOwner::DumpStackAndCrash() const { fprintf(stderr, - "ProfilingStackOwner::DumpStackAndCrash() thread id: %d, size: %u\n", - int(profiler_current_thread_id().ToNumber()), + "ProfilingStackOwner::DumpStackAndCrash() thread id: %" PRIu64 + ", size: %u\n", + uint64_t(profiler_current_thread_id().ToNumber()), unsigned(mProfilingStack.stackSize())); js::ProfilingStackFrame* allFrames = mProfilingStack.frames; for (uint32_t i = 0; i < mProfilingStack.stackSize(); i++) { js::ProfilingStackFrame& frame = allFrames[i]; if (frame.isLabelFrame()) { fprintf(stderr, "%u: label frame, sp=%p, label='%s' (%s)\n", unsigned(i), frame.stackAddress(), frame.label(), frame.dynamicString() ? frame.dynamicString() : "-"); @@ -5496,18 +5497,19 @@ ProfilingStack* profiler_register_thread if (RegisteredThread* thread = TLSRegisteredThread::RegisteredThread(lock)) { MOZ_RELEASE_ASSERT(IsRegisteredThreadInRegisteredThreadsList(lock, thread), "Thread being re-registered is not in registered thread " "list even though its TLS is non-null"); MOZ_RELEASE_ASSERT( thread->Info()->ThreadId() == profiler_current_thread_id(), "Thread being re-registered has changed its TID"); - LOG("profiler_register_thread(%s) - thread %d already registered as %s", - aName, int(profiler_current_thread_id().ToNumber()), + LOG("profiler_register_thread(%s) - thread %" PRIu64 + " already registered as %s", + aName, uint64_t(profiler_current_thread_id().ToNumber()), thread->Info()->Name()); // TODO: Use new name. This is currently not possible because the // RegisteredThread's ThreadInfo cannot be changed. // In the meantime, we record a marker that could be used in the frontend. nsCString text("Thread "); text.AppendInt(profiler_current_thread_id().ToNumber()); text.AppendLiteral(" \""); text.AppendASCII(thread->Info()->Name()); @@ -5580,18 +5582,19 @@ void profiler_unregister_thread() { } else { // There are two ways TLSRegisteredThread::RegisteredThread() might be // empty. // // - TLSRegisteredThread::Init() failed in locked_register_thread(). // // - We've already called profiler_unregister_thread() for this thread. // (Whether or not it should, this does happen in practice.) - LOG("profiler_unregister_thread() - thread %d already unregistered", - int(profiler_current_thread_id().ToNumber())); + LOG("profiler_unregister_thread() - thread %" PRIu64 + " already unregistered", + uint64_t(profiler_current_thread_id().ToNumber())); // We cannot record a marker on this thread because it was already // unregistered. Send it to the main thread (unless this *is* already the // main thread, which has been unregistered); this may be useful to catch // mismatched register/unregister pairs in Firefox. if (ProfilerThreadId tid = profiler_current_thread_id(); tid != profiler_main_thread_id()) { nsCString threadIdString; threadIdString.AppendInt(tid.ToNumber());
--- a/tools/profiler/core/platform.h +++ b/tools/profiler/core/platform.h @@ -50,28 +50,28 @@ namespace mozilla { struct SymbolTable; } extern mozilla::LazyLogModule gProfilerLog; // These are for MOZ_LOG="prof:3" or higher. It's the default logging level for // the profiler, and should be used sparingly. #define LOG_TEST MOZ_LOG_TEST(gProfilerLog, mozilla::LogLevel::Info) -#define LOG(arg, ...) \ - MOZ_LOG(gProfilerLog, mozilla::LogLevel::Info, \ - ("[%d] " arg, int(profiler_current_process_id().ToNumber()), \ - ##__VA_ARGS__)) +#define LOG(arg, ...) \ + MOZ_LOG(gProfilerLog, mozilla::LogLevel::Info, \ + ("[%" PRIu64 "d] " arg, \ + uint64_t(profiler_current_process_id().ToNumber()), ##__VA_ARGS__)) // These are for MOZ_LOG="prof:4" or higher. It should be used for logging that // is somewhat more verbose than LOG. #define DEBUG_LOG_TEST MOZ_LOG_TEST(gProfilerLog, mozilla::LogLevel::Debug) -#define DEBUG_LOG(arg, ...) \ - MOZ_LOG(gProfilerLog, mozilla::LogLevel::Debug, \ - ("[%d] " arg, int(profiler_current_process_id().ToNumber()), \ - ##__VA_ARGS__)) +#define DEBUG_LOG(arg, ...) \ + MOZ_LOG(gProfilerLog, mozilla::LogLevel::Debug, \ + ("[%" PRIu64 "] " arg, \ + uint64_t(profiler_current_process_id().ToNumber()), ##__VA_ARGS__)) typedef uint8_t* Address; // ---------------------------------------------------------------------------- // Miscellaneous class PlatformData;
--- a/tools/profiler/gecko/ProfilerIOInterposeObserver.cpp +++ b/tools/profiler/gecko/ProfilerIOInterposeObserver.cpp @@ -18,17 +18,23 @@ struct FileIOMarker { const ProfilerString8View& aFilename, MarkerThreadId aOperationThreadId) { aWriter.StringProperty("operation", aOperation); aWriter.StringProperty("source", aSource); if (aFilename.Length() != 0) { aWriter.StringProperty("filename", aFilename); } if (!aOperationThreadId.IsUnspecified()) { - aWriter.IntProperty("threadId", aOperationThreadId.ThreadId().ToNumber()); + // Tech note: If `ToNumber()` returns a uint64_t, the conversion to + // int64_t is "implementation-defined" before C++20. This is acceptable + // here, because this is a one-way conversion to a unique identifier + // that's used to visually separate data by thread on the front-end. + aWriter.IntProperty( + "threadId", + static_cast<int64_t>(aOperationThreadId.ThreadId().ToNumber())); } } static MarkerSchema MarkerTypeDisplay() { using MS = MarkerSchema; MS schema{MS::Location::markerChart, MS::Location::markerTable, MS::Location::timelineFileIO}; schema.AddKeyLabelFormatSearchable("operation", "Operation", MS::Format::string,
--- a/tools/profiler/lul/LulMain.cpp +++ b/tools/profiler/lul/LulMain.cpp @@ -794,25 +794,25 @@ class PriMap { // a logging sink, for debugging. void (*mLog)(const char*); }; //////////////////////////////////////////////////////////////// // LUL // //////////////////////////////////////////////////////////////// -#define LUL_LOG(_str) \ - do { \ - char buf[200]; \ - SprintfLiteral(buf, "LUL: pid %d tid %d lul-obj %p: %s", \ - int(profiler_current_process_id().ToNumber()), \ - int(profiler_current_thread_id().ToNumber()), this, \ - (_str)); \ - buf[sizeof(buf) - 1] = 0; \ - mLog(buf); \ +#define LUL_LOG(_str) \ + do { \ + char buf[200]; \ + SprintfLiteral(buf, "LUL: pid %" PRIu64 " tid %" PRIu64 " lul-obj %p: %s", \ + uint64_t(profiler_current_process_id().ToNumber()), \ + uint64_t(profiler_current_thread_id().ToNumber()), this, \ + (_str)); \ + buf[sizeof(buf) - 1] = 0; \ + mLog(buf); \ } while (0) LUL::LUL(void (*aLog)(const char*)) : mLog(aLog), mAdminMode(true), mAdminThreadId(profiler_current_thread_id()), mPriMap(new PriMap(aLog)), mSegArray(new SegArray()),
--- a/tools/profiler/lul/platform-linux-lul.cpp +++ b/tools/profiler/lul/platform-linux-lul.cpp @@ -65,10 +65,11 @@ void read_procmaps(lul::LUL* aLUL) { // LUL needs a callback for its logging sink. void logging_sink_for_LUL(const char* str) { // These are only printed when Verbose logging is enabled (e.g. with // MOZ_LOG="prof:5"). This is because LUL's logging is much more verbose than // the rest of the profiler's logging, which occurs at the Info (3) and Debug // (4) levels. MOZ_LOG(gProfilerLog, mozilla::LogLevel::Verbose, - ("[%d] %s", int(profiler_current_process_id().ToNumber()), str)); + ("[%" PRIu64 "] %s", + uint64_t(profiler_current_process_id().ToNumber()), str)); }
--- a/tools/profiler/tests/gtest/GeckoProfiler.cpp +++ b/tools/profiler/tests/gtest/GeckoProfiler.cpp @@ -269,18 +269,18 @@ static void JSONRootCheck(const Json::Va const Json::ArrayIndex threadCount = threads.size(); for (Json::ArrayIndex i = 0; i < threadCount; ++i) { GET_JSON(thread, threads[i], Object); EXPECT_HAS_JSON(thread["processType"], String); EXPECT_HAS_JSON(thread["name"], String); EXPECT_HAS_JSON(thread["registerTime"], Double); EXPECT_HAS_JSON(thread["samples"], Object); EXPECT_HAS_JSON(thread["markers"], Object); - EXPECT_HAS_JSON(thread["pid"], UInt); - EXPECT_HAS_JSON(thread["tid"], UInt); + EXPECT_HAS_JSON(thread["pid"], Int64); + EXPECT_HAS_JSON(thread["tid"], Int64); EXPECT_HAS_JSON(thread["stackTable"], Object); EXPECT_HAS_JSON(thread["frameTable"], Object); EXPECT_HAS_JSON(thread["stringTable"], Array); } if (aWithMainThread) { ASSERT_GT(threadCount, 0u); GET_JSON(thread0, threads[0], Object);