Bug 1434965 - Add ForEachTrackedOptimizationTypeInfoLambdaOp. r?njn draft
authorMarkus Stange <mstange@themasta.com>
Mon, 12 Feb 2018 14:48:44 -0500
changeset 754063 c6659ad26a76d967c3b7ce97b16796d32d63186f
parent 754062 bfff6a9a172b3bea5a10066d2e2f67a38de03cee
child 754064 a19d8f1d55841774fc94778b3f61d6698c6f8fc2
push id98744
push userbmo:mstange@themasta.com
push dateMon, 12 Feb 2018 19:50:57 +0000
reviewersnjn
bugs1434965
milestone60.0a1
Bug 1434965 - Add ForEachTrackedOptimizationTypeInfoLambdaOp. r?njn This makes the JSON serialization code for optimization type info a little easier to read. MozReview-Commit-ID: 2auHVmp7hKw
tools/profiler/core/ProfileBufferEntry.cpp
--- a/tools/profiler/core/ProfileBufferEntry.cpp
+++ b/tools/profiler/core/ProfileBufferEntry.cpp
@@ -95,69 +95,67 @@ public:
     mWriter.IntProperty(aName, mIndex++);
   }
 
   ~JSONSchemaWriter() {
     mWriter.EndObject();
   }
 };
 
-class StreamOptimizationTypeInfoOp : public JS::ForEachTrackedOptimizationTypeInfoOp
+struct TypeInfo
 {
-  JSONWriter& mWriter;
-  UniqueJSONStrings& mUniqueStrings;
-  bool mStartedTypeList;
+  Maybe<nsCString> mKeyedBy;
+  Maybe<nsCString> mName;
+  Maybe<nsCString> mLocation;
+  Maybe<unsigned> mLineNumber;
+};
 
+template<typename LambdaT>
+class ForEachTrackedOptimizationTypeInfoLambdaOp : public JS::ForEachTrackedOptimizationTypeInfoOp
+{
 public:
-  StreamOptimizationTypeInfoOp(JSONWriter& aWriter, UniqueJSONStrings& aUniqueStrings)
-    : mWriter(aWriter)
-    , mUniqueStrings(aUniqueStrings)
-    , mStartedTypeList(false)
-  { }
+  // aLambda needs to be a function with the following signature:
+  // void lambda(JS::TrackedTypeSite site, const char* mirType,
+  //             const nsTArray<TypeInfo>& typeset)
+  // aLambda will be called once per entry.
+  explicit ForEachTrackedOptimizationTypeInfoLambdaOp(LambdaT&& aLambda)
+    : mLambda(aLambda)
+  {}
 
+  // This is called 0 or more times per entry, *before* operator() is called
+  // for that entry.
   void readType(const char* keyedBy, const char* name,
-                const char* location, const Maybe<unsigned>& lineno) override {
-    if (!mStartedTypeList) {
-      mStartedTypeList = true;
-      mWriter.StartObjectElement();
-      mWriter.StartArrayProperty("typeset");
-    }
-
-    mWriter.StartObjectElement();
-    {
-      mUniqueStrings.WriteProperty(mWriter, "keyedBy", keyedBy);
-      if (name) {
-        mUniqueStrings.WriteProperty(mWriter, "name", name);
-      }
-      if (location) {
-        mUniqueStrings.WriteProperty(mWriter, "location", location);
-      }
-      if (lineno.isSome()) {
-        mWriter.IntProperty("line", *lineno);
-      }
-    }
-    mWriter.EndObject();
+                const char* location, const Maybe<unsigned>& lineno) override
+  {
+    TypeInfo info = {
+      keyedBy ? Some(nsCString(keyedBy)) : Nothing(),
+      name ? Some(nsCString(name)) : Nothing(),
+      location ? Some(nsCString(location)) : Nothing(),
+      lineno
+    };
+    mTypesetForUpcomingEntry.AppendElement(Move(info));
   }
 
-  void operator()(JS::TrackedTypeSite site, const char* mirType) override {
-    if (mStartedTypeList) {
-      mWriter.EndArray();
-      mStartedTypeList = false;
-    } else {
-      mWriter.StartObjectElement();
-    }
+  void operator()(JS::TrackedTypeSite site, const char* mirType) override
+  {
+    nsTArray<TypeInfo> typeset(Move(mTypesetForUpcomingEntry));
+    mLambda(site, mirType, typeset);
+  }
 
-    {
-      mUniqueStrings.WriteProperty(mWriter, "site", JS::TrackedTypeSiteString(site));
-      mUniqueStrings.WriteProperty(mWriter, "mirType", mirType);
-    }
-    mWriter.EndObject();
-  }
+private:
+  nsTArray<TypeInfo> mTypesetForUpcomingEntry;
+  LambdaT mLambda;
 };
 
+template<typename LambdaT> ForEachTrackedOptimizationTypeInfoLambdaOp<LambdaT>
+MakeForEachTrackedOptimizationTypeInfoLambdaOp(LambdaT&& aLambda)
+{
+  return ForEachTrackedOptimizationTypeInfoLambdaOp<LambdaT>(Move(aLambda));
+}
+
 // As mentioned in ProfileBufferEntry.h, the JSON format contains many
 // arrays whose elements are laid out according to various schemas to help
 // de-duplication. This RAII class helps write these arrays by keeping track of
 // the last non-null element written and adding the appropriate number of null
 // elements when writing new non-null elements. It also automatically opens and
 // closes an array element on the given JSON writer.
 //
 // You grant the AutoArraySchemaWriter exclusive access to the JSONWriter and
@@ -438,18 +436,53 @@ StreamJITFrameOptimizations(SpliceableJS
                             UniqueJSONStrings& aUniqueStrings,
                             JSContext* aContext,
                             const JS::ProfiledFrameHandle& aJITFrame)
 {
   aWriter.StartObjectElement();
   {
     aWriter.StartArrayProperty("types");
     {
-      StreamOptimizationTypeInfoOp typeInfoOp(aWriter, aUniqueStrings);
-      aJITFrame.forEachOptimizationTypeInfo(typeInfoOp);
+      auto op = MakeForEachTrackedOptimizationTypeInfoLambdaOp(
+        [&](JS::TrackedTypeSite site, const char* mirType,
+            const nsTArray<TypeInfo>& typeset) {
+          aWriter.StartObjectElement();
+          {
+            aUniqueStrings.WriteProperty(aWriter, "site",
+                                        JS::TrackedTypeSiteString(site));
+            aUniqueStrings.WriteProperty(aWriter, "mirType", mirType);
+
+            if (!typeset.IsEmpty()) {
+              aWriter.StartArrayProperty("typeset");
+              for (const TypeInfo& typeInfo : typeset) {
+                aWriter.StartObjectElement();
+                {
+                  aUniqueStrings.WriteProperty(aWriter, "keyedBy",
+                                              typeInfo.mKeyedBy->get());
+                  if (typeInfo.mName) {
+                    aUniqueStrings.WriteProperty(aWriter, "name",
+                                                typeInfo.mName->get());
+                  }
+                  if (typeInfo.mLocation) {
+                    aUniqueStrings.WriteProperty(aWriter, "location",
+                                                typeInfo.mLocation->get());
+                  }
+                  if (typeInfo.mLineNumber.isSome()) {
+                    aWriter.IntProperty("line", *typeInfo.mLineNumber);
+                  }
+                }
+                aWriter.EndObject();
+              }
+              aWriter.EndArray();
+            }
+
+          }
+          aWriter.EndObject();
+        });
+      aJITFrame.forEachOptimizationTypeInfo(op);
     }
     aWriter.EndArray();
 
     JS::Rooted<JSScript*> script(aContext);
     jsbytecode* pc;
     aWriter.StartObjectProperty("attempts");
     {
       {