--- 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");
{
{