From b1fe6f872fadfdb75d2c5b615a044526dfde3c83 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Thu, 20 Jan 2022 00:23:09 +0000 Subject: [PATCH] Bug 1746090 - Generate gcEdges file with computeCallgraph instead of computeGCFunctions r=jonco Differential Revision: https://phabricator.services.mozilla.com/D133801 --- js/src/devtools/rootAnalysis/analyze.py | 15 ++++++++-- js/src/devtools/rootAnalysis/analyzeRoots.js | 16 ++++------ .../devtools/rootAnalysis/computeCallgraph.js | 11 +++++++ .../rootAnalysis/computeGCFunctions.js | 30 +++++-------------- js/src/devtools/rootAnalysis/mergeJSON.js | 18 +++++++++++ 5 files changed, 53 insertions(+), 37 deletions(-) create mode 100644 js/src/devtools/rootAnalysis/mergeJSON.js diff --git a/js/src/devtools/rootAnalysis/analyze.py b/js/src/devtools/rootAnalysis/analyze.py index 30e727e42c71..896ab022a63c 100755 --- a/js/src/devtools/rootAnalysis/analyze.py +++ b/js/src/devtools/rootAnalysis/analyze.py @@ -120,11 +120,21 @@ JOBS = { "{analysis_scriptdir}/computeCallgraph.js", "{typeInfo}", Output("rawcalls"), + Output("rawEdges"), "{i}", "{n}", ], "multi-output": True, - "outputs": ["rawcalls.{i}.of.{n}"], + "outputs": ["rawcalls.{i}.of.{n}", "gcEdges.{i}.of.{n}"], + }, + "mergeJSON": { + "command": [ + "{js}", + "{analysis_scriptdir}/mergeJSON.js", + MultiInput("{rawEdges}"), + Output("gcEdges"), + ], + "outputs": ["gcEdges.json"], }, "gcFunctions": { "command": [ @@ -135,14 +145,12 @@ JOBS = { Output("callgraph"), Output("gcFunctions"), Output("gcFunctions_list"), - Output("gcEdges"), Output("limitedFunctions_list"), ], "outputs": [ "callgraph.txt", "gcFunctions.txt", "gcFunctions.lst", - "gcEdges.txt", "limitedFunctions.lst", ], }, @@ -432,6 +440,7 @@ steps = [ "gcTypes", "rawcalls", "gcFunctions", + "mergeJSON", "allFunctions", "hazards", "gather-hazards", diff --git a/js/src/devtools/rootAnalysis/analyzeRoots.js b/js/src/devtools/rootAnalysis/analyzeRoots.js index 97b8f82b3b9c..21fef705c46f 100644 --- a/js/src/devtools/rootAnalysis/analyzeRoots.js +++ b/js/src/devtools/rootAnalysis/analyzeRoots.js @@ -33,7 +33,7 @@ try { }, { name: "gcEdges", - default: "gcEdges.txt" + default: "gcEdges.json" }, { name: "limitedFunctions", @@ -78,16 +78,7 @@ text = null; var typeInfo = loadTypeInfo(options.typeInfo); -var gcEdges = {}; -text = snarf(options.gcEdges).split('\n'); -assert(text.pop().length == 0); -for (const line of text) { - var [ block, edge, func ] = line.split(" || "); - if (!(block in gcEdges)) - gcEdges[block] = {} - gcEdges[block][edge] = func; -} -text = null; +var gcEdges = JSON.parse(os.file.readFile(options.gcEdges)); var match; var gcThings = {}; @@ -850,6 +841,9 @@ function process(name, json) { if (attrs) pbody.attrs[id] = attrs; } + for (const edgeAttr of gcEdges[blockIdentifier(body)] || []) { + body.attrs[edgeAttr.Index[0]] |= edgeAttr.attrs; + } } // Special case: std::swap of two refcounted values thinks it can drop the diff --git a/js/src/devtools/rootAnalysis/computeCallgraph.js b/js/src/devtools/rootAnalysis/computeCallgraph.js index 55c5dde804f9..1937f78191fb 100644 --- a/js/src/devtools/rootAnalysis/computeCallgraph.js +++ b/js/src/devtools/rootAnalysis/computeCallgraph.js @@ -23,6 +23,11 @@ var options = parse_options([ type: 'string', default: "rawcalls.txt" }, + { + name: 'gcEdgesOut_filename', + type: 'string', + default: "gcEdges.json" + }, { name: 'batch', default: 1, @@ -41,6 +46,8 @@ var memoized = new Map(); var unmangled2id = new Set(); +var gcEdges = {}; + // Insert a string into the name table and return the ID. Do not use for // functions, which must be handled specially. function getId(name) @@ -417,4 +424,8 @@ for (var nameIndex = start; nameIndex <= end; nameIndex++) { xdb.free_string(data); } +os.file.close(os.file.redirect(options.gcEdgesOut_filename)); + +print(JSON.stringify(gcEdges, null, 4)); + os.file.close(os.file.redirect(origOut)); diff --git a/js/src/devtools/rootAnalysis/computeGCFunctions.js b/js/src/devtools/rootAnalysis/computeGCFunctions.js index 69f7cb92a02d..90705051c911 100644 --- a/js/src/devtools/rootAnalysis/computeGCFunctions.js +++ b/js/src/devtools/rootAnalysis/computeGCFunctions.js @@ -9,6 +9,13 @@ loadRelativeToScript('utility.js'); loadRelativeToScript('annotations.js'); loadRelativeToScript('loadCallgraph.js'); +function usage() { + throw "Usage: computeGCFunctions.js ... --outputs "; +} + +if (typeof scriptArgs[0] != 'string') + usage(); + var start = "Time: " + new Date; try { @@ -37,11 +44,6 @@ try { type: 'string', default: 'gcFunctions.lst' }, - { - name: 'gcEdges', - type: 'string', - default: 'gcEdges.txt' - }, { name: 'limitedFunctions', type: 'string', @@ -92,24 +94,6 @@ for (var name in gcFunctions) { } } -// gcEdges is a list of edges that can GC for more specific reasons than just -// calling a function that is in gcFunctions.txt. -// -// Right now, it is unused. It was meant for ~AutoRealm when it might -// wrap an exception, but anything held live across ~AC will have to be held -// live across the corresponding constructor (and hence the whole scope of the -// AC), and in that case it'll be held live across whatever could create an -// exception within the AC scope. So ~AC edges are redundant. I will leave the -// stub machinery here for now. -printErr("Writing " + options.gcEdges); -redirect(options.gcEdges); -for (var block in gcEdges) { - for (var edge in gcEdges[block]) { - var func = gcEdges[block][edge]; - print([ block, edge, func ].join(" || ")); - } -} - printErr("Writing " + options.limitedFunctions); redirect(options.limitedFunctions); print(JSON.stringify(limitedFunctions, null, 4)); diff --git a/js/src/devtools/rootAnalysis/mergeJSON.js b/js/src/devtools/rootAnalysis/mergeJSON.js new file mode 100644 index 000000000000..56fb3a2ab1c3 --- /dev/null +++ b/js/src/devtools/rootAnalysis/mergeJSON.js @@ -0,0 +1,18 @@ +/* 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/. */ + +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ + +var infiles = [...scriptArgs]; +var outfile = infiles.pop(); + +const output = {}; +for (const filename of infiles) { + const data = JSON.parse(os.file.readFile(filename)); + Object.assign(output, data); +} + +var origOut = os.file.redirect(outfile); +print(JSON.stringify(output, null, 4)); +os.file.close(os.file.redirect(origOut));