예제 #1
0
void
ProfilerMarkerTracing::streamPayloadImp(JSStreamWriter& b)
{
  b.BeginObject();
    streamCommonProps("tracing", b);

    if (GetCategory()) {
      b.NameValue("category", GetCategory());
    }
    if (GetMetaData() != TRACING_DEFAULT) {
      if (GetMetaData() == TRACING_INTERVAL_START) {
        b.NameValue("interval", "start");
      } else if (GetMetaData() == TRACING_INTERVAL_END) {
        b.NameValue("interval", "end");
      }
    }
  b.EndObject();
}
예제 #2
0
void ThreadProfile::StreamJSObject(JSStreamWriter& b)
{
  b.BeginObject();
    // Thread meta data
    if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
      // TODO Add the proper plugin name
      b.NameValue("name", "Plugin");
    } else if (XRE_GetProcessType() == GeckoProcessType_Content) {
      // This isn't going to really help once we have multiple content
      // processes, but it'll do for now.
      b.NameValue("name", "Content");
    } else {
      b.NameValue("name", Name());
    }
    b.NameValue("tid", static_cast<int>(mThreadId));

    b.Name("samples");
    mBuffer->StreamSamplesToJSObject(b, mThreadId, mPseudoStack->mRuntime);

    b.Name("markers");
    mBuffer->StreamMarkersToJSObject(b, mThreadId);
  b.EndObject();
}
예제 #3
0
void ThreadProfile::StreamJSObject(JSStreamWriter& b)
{
  b.BeginObject();
    // Thread meta data
    if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
      // TODO Add the proper plugin name
      b.NameValue("name", "Plugin");
    } else if (XRE_GetProcessType() == GeckoProcessType_Content) {
      // This isn't going to really help once we have multiple content
      // processes, but it'll do for now.
      b.NameValue("name", "Content");
    } else {
      b.NameValue("name", Name());
    }
    b.NameValue("tid", static_cast<int>(mThreadId));

    b.Name("samples");
    b.BeginArray();

      bool sample = false;
      int readPos = mReadPos;
      while (readPos != mLastFlushPos) {
        // Number of tag consumed
        ProfileEntry entry = mEntries[readPos];

        switch (entry.mTagName) {
          case 'r':
            {
              if (sample) {
                b.NameValue("responsiveness", entry.mTagFloat);
              }
            }
            break;
          case 'p':
            {
              if (sample) {
                b.NameValue("power", entry.mTagFloat);
              }
            }
            break;
          case 'R':
            {
              if (sample) {
                b.NameValue("rss", entry.mTagFloat);
              }
            }
            break;
          case 'U':
            {
              if (sample) {
                b.NameValue("uss", entry.mTagFloat);
              }
            }
            break;
          case 'f':
            {
              if (sample) {
                b.NameValue("frameNumber", entry.mTagInt);
              }
            }
            break;
          case 't':
            {
              if (sample) {
                b.NameValue("time", entry.mTagFloat);
              }
            }
            break;
          case 's':
            {
              // end the previous sample if there was one
              if (sample) {
                b.EndObject();
              }
              // begin the next sample
              b.BeginObject();

              sample = true;

              // Seek forward through the entire sample, looking for frames
              // this is an easier approach to reason about than adding more
              // control variables and cases to the loop that goes through the buffer once
              b.Name("frames");
              b.BeginArray();

                b.BeginObject();
                  b.NameValue("location", "(root)");
                b.EndObject();

                int framePos = (readPos + 1) % mEntrySize;
                ProfileEntry frame = mEntries[framePos];
                while (framePos != mLastFlushPos && frame.mTagName != 's') {
                  int incBy = 1;
                  frame = mEntries[framePos];

                  // Read ahead to the next tag, if it's a 'd' tag process it now
                  const char* tagStringData = frame.mTagData;
                  int readAheadPos = (framePos + 1) % mEntrySize;
                  char tagBuff[DYNAMIC_MAX_STRING];
                  // Make sure the string is always null terminated if it fills up
                  // DYNAMIC_MAX_STRING-2
                  tagBuff[DYNAMIC_MAX_STRING-1] = '\0';

                  if (readAheadPos != mLastFlushPos && mEntries[readAheadPos].mTagName == 'd') {
                    tagStringData = processDynamicTag(framePos, &incBy, tagBuff);
                  }

                  // Write one frame. It can have either
                  // 1. only location - 'l' containing a memory address
                  // 2. location and line number - 'c' followed by 'd's,
                  // an optional 'n' and an optional 'y'
                  if (frame.mTagName == 'l') {
                    b.BeginObject();
                      // Bug 753041
                      // We need a double cast here to tell GCC that we don't want to sign
                      // extend 32-bit addresses starting with 0xFXXXXXX.
                      unsigned long long pc = (unsigned long long)(uintptr_t)frame.mTagPtr;
                      snprintf(tagBuff, DYNAMIC_MAX_STRING, "%#llx", pc);
                      b.NameValue("location", tagBuff);
                    b.EndObject();
                  } else if (frame.mTagName == 'c') {
                    b.BeginObject();
                      b.NameValue("location", tagStringData);
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mLastFlushPos &&
                          mEntries[readAheadPos].mTagName == 'n') {
                        b.NameValue("line", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mLastFlushPos &&
                          mEntries[readAheadPos].mTagName == 'y') {
                        b.NameValue("category", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                    b.EndObject();
                  }
                  framePos = (framePos + incBy) % mEntrySize;
                }
              b.EndArray();
            }
            break;
        }
        readPos = (readPos + 1) % mEntrySize;
      }
      if (sample) {
        b.EndObject();
      }
    b.EndArray();

    b.Name("markers");
    b.BeginArray();
      readPos = mReadPos;
      while (readPos != mLastFlushPos) {
        ProfileEntry entry = mEntries[readPos];
        if (entry.mTagName == 'm') {
           entry.getMarker()->StreamJSObject(b);
        }
        readPos = (readPos + 1) % mEntrySize;
      }
    b.EndArray();
  b.EndObject();
}
예제 #4
0
void ProfileBuffer::StreamSamplesToJSObject(JSStreamWriter& b, int aThreadId, JSRuntime* rt)
{
  b.BeginArray();

    bool sample = false;
    int readPos = mReadPos;
    int currentThreadID = -1;
    while (readPos != mWritePos) {
      ProfileEntry entry = mEntries[readPos];
      if (entry.mTagName == 'T') {
        currentThreadID = entry.mTagInt;
      }
      if (currentThreadID == aThreadId) {
        switch (entry.mTagName) {
          case 'r':
            {
              if (sample) {
                b.NameValue("responsiveness", entry.mTagFloat);
              }
            }
            break;
          case 'p':
            {
              if (sample) {
                b.NameValue("power", entry.mTagFloat);
              }
            }
            break;
          case 'R':
            {
              if (sample) {
                b.NameValue("rss", entry.mTagFloat);
              }
            }
            break;
          case 'U':
            {
              if (sample) {
                b.NameValue("uss", entry.mTagFloat);
              }
            }
            break;
          case 'f':
            {
              if (sample) {
                b.NameValue("frameNumber", entry.mTagInt);
              }
            }
            break;
          case 't':
            {
              if (sample) {
                b.NameValue("time", entry.mTagFloat);
              }
            }
            break;
          case 's':
            {
              // end the previous sample if there was one
              if (sample) {
                b.EndObject();
              }
              // begin the next sample
              b.BeginObject();

              sample = true;

              // Seek forward through the entire sample, looking for frames
              // this is an easier approach to reason about than adding more
              // control variables and cases to the loop that goes through the buffer once
              b.Name("frames");
              b.BeginArray();

                b.BeginObject();
                  b.NameValue("location", "(root)");
                b.EndObject();

                int framePos = (readPos + 1) % mEntrySize;
                ProfileEntry frame = mEntries[framePos];
                while (framePos != mWritePos && frame.mTagName != 's' && frame.mTagName != 'T') {
                  int incBy = 1;
                  frame = mEntries[framePos];

                  // Read ahead to the next tag, if it's a 'd' tag process it now
                  const char* tagStringData = frame.mTagData;
                  int readAheadPos = (framePos + 1) % mEntrySize;
                  char tagBuff[DYNAMIC_MAX_STRING];
                  // Make sure the string is always null terminated if it fills up
                  // DYNAMIC_MAX_STRING-2
                  tagBuff[DYNAMIC_MAX_STRING-1] = '\0';

                  if (readAheadPos != mWritePos && mEntries[readAheadPos].mTagName == 'd') {
                    tagStringData = processDynamicTag(framePos, &incBy, tagBuff);
                  }

                  // Write one frame. It can have either
                  // 1. only location - 'l' containing a memory address
                  // 2. location and line number - 'c' followed by 'd's,
                  // an optional 'n' and an optional 'y'
                  if (frame.mTagName == 'l') {
                    b.BeginObject();
                      // Bug 753041
                      // We need a double cast here to tell GCC that we don't want to sign
                      // extend 32-bit addresses starting with 0xFXXXXXX.
                      unsigned long long pc = (unsigned long long)(uintptr_t)frame.mTagPtr;
                      snprintf(tagBuff, DYNAMIC_MAX_STRING, "%#llx", pc);
                      b.NameValue("location", tagBuff);
                    b.EndObject();
                  } else if (frame.mTagName == 'c') {
                    b.BeginObject();
                      b.NameValue("location", tagStringData);
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mWritePos &&
                          mEntries[readAheadPos].mTagName == 'n') {
                        b.NameValue("line", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mWritePos &&
                          mEntries[readAheadPos].mTagName == 'y') {
                        b.NameValue("category", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mWritePos &&
                          mEntries[readAheadPos].mTagName == 'J') {
                        void* pc = mEntries[readAheadPos].mTagPtr;

                        // TODOshu: cannot stream tracked optimization info if
                        // the JS engine has already shut down when streaming.
                        if (rt) {
                          JSScript *optsScript;
                          jsbytecode *optsPC;
                          b.Name("opts");
                          b.BeginArray();
                            StreamOptimizationTypeInfoOp typeInfoOp(b);
                            JS::ForEachTrackedOptimizationTypeInfo(rt, pc, typeInfoOp);
                            StreamOptimizationAttemptsOp attemptOp(b);
                            JS::ForEachTrackedOptimizationAttempt(rt, pc, attemptOp,
                                                                  &optsScript, &optsPC);
                          b.EndArray();
                          b.NameValue("optsLine", JS_PCToLineNumber(optsScript, optsPC));
                        }
                      }
                    b.EndObject();
                  }
                  framePos = (framePos + incBy) % mEntrySize;
                }
              b.EndArray();
            }
            break;
        }
      }
      readPos = (readPos + 1) % mEntrySize;
    }
    if (sample) {
      b.EndObject();
    }
  b.EndArray();
}
예제 #5
0
void TableTicker::StreamJSObject(JSStreamWriter& b)
{
  b.BeginObject();
    // Put shared library info
    b.NameValue("libs", GetSharedLibraryInfoString().c_str());

    // Put meta data
    b.Name("meta");
    StreamMetaJSCustomObject(b);

    // Data of TaskTracer doesn't belong in the circular buffer.
    if (TaskTracer()) {
      b.Name("tasktracer");
      StreamTaskTracer(b);
    }

    // Lists the samples for each ThreadProfile
    b.Name("threads");
    b.BeginArray();

      SetPaused(true);

      {
        mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);

        for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
          // Thread not being profiled, skip it
          if (!sRegisteredThreads->at(i)->Profile())
            continue;

          // Note that we intentionally include ThreadProfile which
          // have been marked for pending delete.

          MutexAutoLock lock(*sRegisteredThreads->at(i)->Profile()->GetMutex());

          sRegisteredThreads->at(i)->Profile()->StreamJSObject(b);
        }
      }

      if (Sampler::CanNotifyObservers()) {
        // Send a event asking any subprocesses (plugins) to
        // give us their information
        SubprocessClosure closure(&b);
        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
        if (os) {
          nsRefPtr<ProfileSaveEvent> pse = new ProfileSaveEvent(SubProcessCallback, &closure);
          os->NotifyObservers(pse, "profiler-subprocess", nullptr);
        }
      }

  #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
      if (ProfileJava()) {
        mozilla::widget::GeckoJavaSampler::PauseJavaProfiling();

        BuildJavaThreadJSObject(b);

        mozilla::widget::GeckoJavaSampler::UnpauseJavaProfiling();
      }
  #endif

      SetPaused(false);
    b.EndArray();

  b.EndObject();
}