Bug 1369955: Add perfstream::Measure subtree for SpiderMonkey's TraceLogger. draft
authorJim Blandy <jimb@mozilla.com>
Mon, 02 Oct 2017 17:36:35 -0700
changeset 684582 ff4171113cff695ee50ab5a8972956ffdf174a31
parent 684581 49b733ffdcb6e15f338ee212cd964671c4e32931
child 736897 75dd31f7fdf43362b77f7e2487636033abea2a61
push id85652
push userbmo:jimb@mozilla.com
push dateMon, 23 Oct 2017 05:02:44 +0000
bugs1369955
milestone58.0a1
Bug 1369955: Add perfstream::Measure subtree for SpiderMonkey's TraceLogger. As a simple example of a Measure subtree, this adds a 'TraceLogger' subgroup to the SpiderMonkey measure tree. MozReview-Commit-ID: 8ZOi0elKMsL
js/public/Measure.h
js/src/moz.build
js/src/vm/Measure.cpp
js/src/vm/TraceLoggingMeasure.cpp
js/src/vm/TraceLoggingMeasure.h
--- a/js/public/Measure.h
+++ b/js/public/Measure.h
@@ -17,16 +17,19 @@ namespace JS {
 /**
  * Return a tree of SpiderMonkey performance measures.
  *
  * This returns a mozilla::perfstream::Group that is the root of the measure
  * tree for the given JSContext's runtime. See perfstream/Measure.h for an
  * explanation of how to use Groups and Measures.
  *
  * On OOM, return a null UniquePtr.
+ *
+ * See js/src/vm/TraceLoggingMeasure.h for an example of implementing a Measure
+ * for the TraceLogger machinery.
  */
 extern JS_PUBLIC_API(mozilla::perfstream::GroupPtr)
 GetMeasures(JSContext*);
 
 /**
  * Like GetMeasures, but include testing-only measures.
  */
 extern JS_PUBLIC_API(mozilla::perfstream::GroupPtr)
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -431,16 +431,17 @@ if CONFIG['MOZ_INSTRUMENTS']:
     SOURCES += [
         'devtools/Instruments.cpp',
     ]
 
 if CONFIG['ENABLE_TRACE_LOGGING']:
     SOURCES += [
         'vm/TraceLogging.cpp',
         'vm/TraceLoggingGraph.cpp',
+        'vm/TraceLoggingMeasure.cpp',
         'vm/TraceLoggingTypes.cpp',
     ]
 
 if not CONFIG['ENABLE_ION']:
     UNIFIED_SOURCES += [
         'jit/none/Trampoline-none.cpp'
     ]
 elif CONFIG['JS_CODEGEN_X86'] or CONFIG['JS_CODEGEN_X64']:
--- a/js/src/vm/Measure.cpp
+++ b/js/src/vm/Measure.cpp
@@ -12,16 +12,18 @@
 #include "mozilla/Atomics.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Move.h"
 #include "mozilla/perfstream/Measure.h"
 #include "mozilla/perfstream/StaticGroup.h"
 
 #include "jscntxt.h"
 
+#include "vm/TraceLoggingMeasure.h"
+
 using mozilla::ArrayLength;
 using mozilla::Atomic;
 using mozilla::Maybe;
 using mozilla::Move;
 using mozilla::Nothing;
 using mozilla::perfstream::Description;
 using mozilla::perfstream::Group;
 using mozilla::perfstream::GroupPtr;
@@ -137,16 +139,18 @@ class JSMeasuresImpl {
     bool EnumerateMeasures(F functor) const { return true; }
 
     template<typename F>
     bool EnumerateSubgroups(F functor) const {
         // If our JSRuntime is dead, then we have no children.
         if (!checkContext())
             return true;
 
+        if (!functor("TraceLogger", [this]() { return GetTraceLoggerMeasures(cx); }))
+            return false;
         // Add more children here.
 
         if (options & Options::Testing) {
             if (!functor("MeasureTests", [this]() {
                         return mozilla::MakeUnique<MeasureTests>(MeasureTestsImpl());
                     }))
                 return false;
             // Add more testing-only children here.
new file mode 100644
--- /dev/null
+++ b/js/src/vm/TraceLoggingMeasure.cpp
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/. */
+
+#include "vm/TraceLoggingMeasure.h"
+
+#include "mozilla/Maybe.h"
+#include "mozilla/Move.h"
+#include "mozilla/perfstream/Measure.h"
+#include "mozilla/perfstream/StaticGroup.h"
+
+#include <stdint.h>
+
+#include "jscntxt.h"
+
+#include "vm/ErrorReporting.h"
+#include "vm/GlobalObject.h"
+#include "vm/TraceLogging.h"
+#include "vm/TraceLoggingTypes.h"
+
+#include "jscntxtinlines.h"
+
+using mozilla::Move;
+using mozilla::Nothing;
+using mozilla::perfstream::Description;
+using mozilla::perfstream::GroupPtr;
+using mozilla::perfstream::Measure;
+using mozilla::perfstream::MeasurePtr;
+using mozilla::perfstream::StaticGroup;
+using mozilla::Some;
+
+namespace js {
+
+class TraceLoggerMeasure : public Measure {
+    // The context we built this node with.
+    JSContext* cx;
+
+    // The id of the tracelogger item this TraceLoggerMeasure represents.
+    TraceLoggerTextId textId;
+
+  public:
+    TraceLoggerMeasure(JSContext* cx, TraceLoggerTextId textId) : cx(cx), textId(textId) { }
+    TraceLoggerMeasure(const TraceLoggerMeasure& rhs) : cx(rhs.cx), textId(rhs.textId) { }
+    TraceLoggerMeasure(TraceLoggerMeasure&& rhs) : cx(rhs.cx), textId(rhs.textId) { }
+
+    bool Enable() override {
+        check_context([this]() { TraceLogEnableTextId(cx, textId); });
+        return IsEnabled();
+    }
+
+    bool Disable() override {
+        check_context([this]() { TraceLogDisableTextId(cx, textId); });
+        return IsEnabled();
+    }
+
+    bool IsEnabled() const override {
+        return TraceLogTextIdEnabled(textId);
+    }
+
+    Description GetDescription() const override {
+        Description description = {
+            TLTextIdString(textId),
+            nullptr // no metadata
+        };
+        return description;
+    }
+
+  private:
+    template<typename Body>
+    void check_context(Body body) {
+        // The context we built this node with might be dead; we must check
+        // it against TlsContext.get() to verify that it is live before we
+        // use it. (This could have been freed and then reallocated at the
+        // same address, but that should be harmless.)
+        if (cx == TlsContext.get() && CurrentThreadCanAccessRuntime(cx->runtime())) {
+            body();
+            // I believe the js::TraceLog{Enable,Disable}TextId calls never
+            // report OOM, but instead return without doing anything. Verify
+            // that they can never report an exception.
+            MOZ_ASSERT(!cx->isExceptionPending());
+        }
+    }
+};
+
+// For use as the Impl parameter of a StaticGroup.
+class TraceLoggerGroupImpl {
+    JSContext* cx;
+
+  public:
+    explicit TraceLoggerGroupImpl(JSContext* cx) : cx(cx) { }
+    TraceLoggerGroupImpl(const TraceLoggerGroupImpl& rhs) : cx(rhs.cx) { }
+    TraceLoggerGroupImpl(TraceLoggerGroupImpl&& rhs) : cx(rhs.cx) { }
+
+    template<typename F>
+    bool EnumerateMeasures(F functor) const {
+#define CHILD(textId)                                                                           \
+        if (TLTextIdIsTogglable(TraceLogger_ ## textId)) {                                      \
+            if (!functor(#textId, [this] {                                                      \
+                    return mozilla::MakeUnique<TraceLoggerMeasure>(cx, TraceLogger_ ## textId); \
+                }))                                                                             \
+                return false;                                                                   \
+        }
+        TRACELOGGER_TREE_ITEMS(CHILD);
+        TRACELOGGER_LOG_ITEMS(CHILD);
+        return true;
+    }
+
+    template<typename F>
+    bool EnumerateSubgroups(F functor) const { return true; }
+
+    static const Description sDescription;
+    static const char* const metadata[];
+};
+
+const Description TraceLoggerGroupImpl::sDescription = {
+    "TraceLogger",
+    metadata
+};
+
+const char* const TraceLoggerGroupImpl::metadata[] = {
+    "tooltip: Traces of SpiderMonkey JavaScript engine JIT activity and execution.",
+    "help-url: https://github.com/h4writer/tracelogger",
+    nullptr
+};
+
+GroupPtr
+GetTraceLoggerMeasures(JSContext* cx)
+{
+    MOZ_ASSERT(cx);
+    MOZ_ASSERT(cx == TlsContext.get());
+    MOZ_ASSERT(cx->runtime()->activeContext() == cx);
+
+    TraceLoggerGroupImpl impl(cx);
+    return mozilla::MakeUnique<StaticGroup<TraceLoggerGroupImpl>>(Move(impl));
+}
+
+} // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/vm/TraceLoggingMeasure.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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 TraceLoggingMeasure_h
+#define TraceLoggingMeasure_h
+
+#include "mozilla/perfstream/Measure.h"
+
+#include "jspubtd.h"
+
+namespace js {
+
+/**
+ * Return a measure group for TraceLogger.
+ */
+mozilla::perfstream::GroupPtr GetTraceLoggerMeasures(JSContext*);
+
+} // namespace js
+
+#endif /* TraceLoggingMeasure_h */