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
--- 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 */