LCOV - code coverage report
Current view: top level - tools/profiler/core - ThreadInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 11 109 10.1 %
Date: 2017-07-14 16:53:18 Functions: 2 8 25.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "ThreadInfo.h"
       8             : 
       9             : #include "mozilla/DebugOnly.h"
      10             : 
      11             : #if defined(GP_OS_darwin)
      12             : #include <pthread.h>
      13             : #endif
      14             : 
      15             : #ifdef XP_WIN
      16             : #include <process.h>
      17             : #define getpid _getpid
      18             : #else
      19             : #include <unistd.h> // for getpid()
      20             : #endif
      21             : 
      22          75 : ThreadInfo::ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread,
      23          75 :                        void* aStackTop)
      24             :   : mName(strdup(aName))
      25             :   , mThreadId(aThreadId)
      26             :   , mIsMainThread(aIsMainThread)
      27          75 :   , mRacyInfo(mozilla::WrapNotNull(new RacyThreadInfo()))
      28             :   , mPlatformData(AllocPlatformData(aThreadId))
      29             :   , mStackTop(aStackTop)
      30             :   , mIsBeingProfiled(false)
      31             :   , mContext(nullptr)
      32             :   , mJSSampling(INACTIVE)
      33         150 :   , mLastSample()
      34             : {
      35          75 :   MOZ_COUNT_CTOR(ThreadInfo);
      36             : 
      37             :   // We don't have to guess on mac
      38             : #if defined(GP_OS_darwin)
      39             :   pthread_t self = pthread_self();
      40             :   mStackTop = pthread_get_stackaddr_np(self);
      41             : #endif
      42             : 
      43             :   // I don't know if we can assert this. But we should warn.
      44          75 :   MOZ_ASSERT(aThreadId >= 0, "native thread ID is < 0");
      45             :   MOZ_ASSERT(aThreadId <= INT32_MAX, "native thread ID is > INT32_MAX");
      46          75 : }
      47             : 
      48           2 : ThreadInfo::~ThreadInfo()
      49             : {
      50           1 :   MOZ_COUNT_DTOR(ThreadInfo);
      51             : 
      52           1 :   delete mRacyInfo;
      53           1 : }
      54             : 
      55             : void
      56           0 : ThreadInfo::StartProfiling()
      57             : {
      58           0 :   mIsBeingProfiled = true;
      59           0 :   mRacyInfo->ReinitializeOnResume();
      60           0 :   if (mIsMainThread) {
      61           0 :     mResponsiveness.emplace();
      62             :   }
      63           0 : }
      64             : 
      65             : void
      66           0 : ThreadInfo::StopProfiling()
      67             : {
      68           0 :   mResponsiveness.reset();
      69           0 :   mIsBeingProfiled = false;
      70           0 : }
      71             : 
      72             : void
      73           0 : ThreadInfo::StreamJSON(const ProfileBuffer& aBuffer,
      74             :                        SpliceableJSONWriter& aWriter,
      75             :                        const TimeStamp& aProcessStartTime, double aSinceTime)
      76             : {
      77             :   // mUniqueStacks may already be emplaced from FlushSamplesAndMarkers.
      78           0 :   if (!mUniqueStacks.isSome()) {
      79           0 :     mUniqueStacks.emplace(mContext);
      80             :   }
      81             : 
      82           0 :   aWriter.Start(SpliceableJSONWriter::SingleLineStyle);
      83             :   {
      84           0 :     StreamSamplesAndMarkers(Name(), ThreadId(), aBuffer, aWriter,
      85             :                             aProcessStartTime, aSinceTime, mContext,
      86             :                             mSavedStreamedSamples.get(),
      87           0 :                             mSavedStreamedMarkers.get(), *mUniqueStacks);
      88           0 :     mSavedStreamedSamples.reset();
      89           0 :     mSavedStreamedMarkers.reset();
      90             : 
      91           0 :     aWriter.StartObjectProperty("stackTable");
      92             :     {
      93             :       {
      94           0 :         JSONSchemaWriter schema(aWriter);
      95           0 :         schema.WriteField("prefix");
      96           0 :         schema.WriteField("frame");
      97             :       }
      98             : 
      99           0 :       aWriter.StartArrayProperty("data");
     100             :       {
     101           0 :         mUniqueStacks->SpliceStackTableElements(aWriter);
     102             :       }
     103           0 :       aWriter.EndArray();
     104             :     }
     105           0 :     aWriter.EndObject();
     106             : 
     107           0 :     aWriter.StartObjectProperty("frameTable");
     108             :     {
     109             :       {
     110           0 :         JSONSchemaWriter schema(aWriter);
     111           0 :         schema.WriteField("location");
     112           0 :         schema.WriteField("implementation");
     113           0 :         schema.WriteField("optimizations");
     114           0 :         schema.WriteField("line");
     115           0 :         schema.WriteField("category");
     116             :       }
     117             : 
     118           0 :       aWriter.StartArrayProperty("data");
     119             :       {
     120           0 :         mUniqueStacks->SpliceFrameTableElements(aWriter);
     121             :       }
     122           0 :       aWriter.EndArray();
     123             :     }
     124           0 :     aWriter.EndObject();
     125             : 
     126           0 :     aWriter.StartArrayProperty("stringTable");
     127             :     {
     128           0 :       mUniqueStacks->mUniqueStrings.SpliceStringTableElements(aWriter);
     129             :     }
     130           0 :     aWriter.EndArray();
     131             :   }
     132           0 :   aWriter.End();
     133             : 
     134           0 :   mUniqueStacks.reset();
     135           0 : }
     136             : 
     137             : void
     138           0 : StreamSamplesAndMarkers(const char* aName,
     139             :                         int aThreadId,
     140             :                         const ProfileBuffer& aBuffer,
     141             :                         SpliceableJSONWriter& aWriter,
     142             :                         const TimeStamp& aProcessStartTime,
     143             :                         double aSinceTime,
     144             :                         JSContext* aContext,
     145             :                         char* aSavedStreamedSamples,
     146             :                         char* aSavedStreamedMarkers,
     147             :                         UniqueStacks& aUniqueStacks)
     148             : {
     149           0 :   aWriter.StringProperty("processType",
     150           0 :                          XRE_ChildProcessTypeToString(XRE_GetProcessType()));
     151             : 
     152           0 :   aWriter.StringProperty("name", aName);
     153           0 :   aWriter.IntProperty("tid", static_cast<int64_t>(aThreadId));
     154           0 :   aWriter.IntProperty("pid", static_cast<int64_t>(getpid()));
     155             : 
     156           0 :   aWriter.StartObjectProperty("samples");
     157             :   {
     158             :     {
     159           0 :       JSONSchemaWriter schema(aWriter);
     160           0 :       schema.WriteField("stack");
     161           0 :       schema.WriteField("time");
     162           0 :       schema.WriteField("responsiveness");
     163           0 :       schema.WriteField("rss");
     164           0 :       schema.WriteField("uss");
     165             :     }
     166             : 
     167           0 :     aWriter.StartArrayProperty("data");
     168             :     {
     169           0 :       if (aSavedStreamedSamples) {
     170             :         // We would only have saved streamed samples during shutdown
     171             :         // streaming, which cares about dumping the entire buffer, and thus
     172             :         // should have passed in 0 for aSinceTime.
     173           0 :         MOZ_ASSERT(aSinceTime == 0);
     174           0 :         aWriter.Splice(aSavedStreamedSamples);
     175             :       }
     176             :       aBuffer.StreamSamplesToJSON(aWriter, aThreadId, aSinceTime, aContext,
     177           0 :                                   aUniqueStacks);
     178             :     }
     179           0 :     aWriter.EndArray();
     180             :   }
     181           0 :   aWriter.EndObject();
     182             : 
     183           0 :   aWriter.StartObjectProperty("markers");
     184             :   {
     185             :     {
     186           0 :       JSONSchemaWriter schema(aWriter);
     187           0 :       schema.WriteField("name");
     188           0 :       schema.WriteField("time");
     189           0 :       schema.WriteField("data");
     190             :     }
     191             : 
     192           0 :     aWriter.StartArrayProperty("data");
     193             :     {
     194           0 :       if (aSavedStreamedMarkers) {
     195           0 :         MOZ_ASSERT(aSinceTime == 0);
     196           0 :         aWriter.Splice(aSavedStreamedMarkers);
     197             :       }
     198             :       aBuffer.StreamMarkersToJSON(aWriter, aThreadId, aProcessStartTime,
     199           0 :                                   aSinceTime, aUniqueStacks);
     200             :     }
     201           0 :     aWriter.EndArray();
     202             :   }
     203           0 :   aWriter.EndObject();
     204           0 : }
     205             : 
     206             : void
     207           0 : ThreadInfo::FlushSamplesAndMarkers(const TimeStamp& aProcessStartTime,
     208             :                                    ProfileBuffer& aBuffer)
     209             : {
     210             :   // This function is used to serialize the current buffer just before
     211             :   // JSContext destruction.
     212           0 :   MOZ_ASSERT(mContext);
     213             : 
     214             :   // Unlike StreamJSObject, do not surround the samples in brackets by calling
     215             :   // aWriter.{Start,End}BareList. The result string will be a comma-separated
     216             :   // list of JSON object literals that will prepended by StreamJSObject into
     217             :   // an existing array.
     218             :   //
     219             :   // Note that the UniqueStacks instance is persisted so that the frame-index
     220             :   // mapping is stable across JS shutdown.
     221           0 :   mUniqueStacks.emplace(mContext);
     222             : 
     223             :   {
     224           0 :     SpliceableChunkedJSONWriter b;
     225           0 :     b.StartBareList();
     226             :     {
     227           0 :       aBuffer.StreamSamplesToJSON(b, mThreadId, /* aSinceTime = */ 0,
     228           0 :                                   mContext, *mUniqueStacks);
     229             :     }
     230           0 :     b.EndBareList();
     231           0 :     mSavedStreamedSamples = b.WriteFunc()->CopyData();
     232             :   }
     233             : 
     234             :   {
     235           0 :     SpliceableChunkedJSONWriter b;
     236           0 :     b.StartBareList();
     237             :     {
     238           0 :       aBuffer.StreamMarkersToJSON(b, mThreadId, aProcessStartTime,
     239           0 :                                   /* aSinceTime = */ 0, *mUniqueStacks);
     240             :     }
     241           0 :     b.EndBareList();
     242           0 :     mSavedStreamedMarkers = b.WriteFunc()->CopyData();
     243             :   }
     244             : 
     245             :   // Reset the buffer. Attempting to symbolicate JS samples after mContext has
     246             :   // gone away will crash.
     247           0 :   aBuffer.Reset();
     248           0 : }
     249             : 
     250             : size_t
     251           0 : ThreadInfo::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     252             : {
     253           0 :   size_t n = aMallocSizeOf(this);
     254           0 :   n += aMallocSizeOf(mName.get());
     255           0 :   n += mRacyInfo->SizeOfIncludingThis(aMallocSizeOf);
     256             : 
     257             :   // Measurement of the following members may be added later if DMD finds it
     258             :   // is worthwhile:
     259             :   // - mPlatformData
     260             :   // - mSavedStreamedSamples
     261             :   // - mSavedStreamedMarkers
     262             :   // - mUniqueStacks
     263             :   //
     264             :   // The following members are not measured:
     265             :   // - mThread: because it is non-owning
     266             : 
     267           0 :   return n;
     268             : }

Generated by: LCOV version 1.13