Bug 1259850 - Start searching from the most specialized csu, r=terrence
☠☠ backed out by 69518db96a4d ☠ ☠
authorSteve Fink <sfink@mozilla.com>
Fri, 25 Mar 2016 15:25:46 -0700
changeset 340763 196ac1f813f9a9489d24ba0c70c1dfb20b404489
parent 340762 b6108a65dc38d298be19b74a30dc683bec69a3b3
child 340764 c6615c7b00838e1d212c6007b4a54b20d71f7ae0
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1259850
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1259850 - Start searching from the most specialized csu, r=terrence Previously, this mostly "worked" purely by chance -- it started gathering method definitions at the 'csu' variable, which JS helpfully hoisted up to the toplevel. It had the last value assigned to csu within the loop, which would have been the basest base class (don't think too hard about the case of multiple inheritance, it was wrong). Then we find all descendants, which was *too* much, but it ended up just making the analysis conservative. MozReview-Commit-ID: 2Ps8gJpztw2
js/src/devtools/rootAnalysis/computeCallgraph.js
--- a/js/src/devtools/rootAnalysis/computeCallgraph.js
+++ b/js/src/devtools/rootAnalysis/computeCallgraph.js
@@ -42,16 +42,34 @@ function processCSU(csuName, csu)
             // Note: not dealing with overloading correctly.
             var name = field.Variable.Name[0];
             var key = csuName + ":" + field.Field[0].Name[0];
             addEntry(classFunctions, key, name);
         }
     }
 }
 
+// Return the nearest ancestor method definition, or all nearest definitions in
+// the case of multiple inheritance.
+function nearestAncestorMethods(csu, method)
+{
+    var key = csu + ":" + method;
+
+    if (classFunctions.has(key))
+        return new Set(classFunctions.get(key));
+
+    var functions = new Set();
+    if (superclasses.has(csu)) {
+        for (var parent of superclasses.get(csu))
+            functions.update(nearestAncestorMethods(parent, method));
+    }
+
+    return functions;
+}
+
 function findVirtualFunctions(initialCSU, field, suppressed)
 {
     var worklist = [initialCSU];
     var functions = new Set();
 
     // Virtual call targets on subclasses of nsISupports may be incomplete,
     // if the interface is scriptable. Just treat all indirect calls on
     // nsISupports objects as potentially GC'ing, except AddRef/Release
@@ -68,17 +86,25 @@ function findVirtualFunctions(initialCSU
             // But push a token saying that we can run arbitrary code.
             functions.add(null);
         }
 
         if (superclasses.has(csu))
             worklist.push(...superclasses.get(csu));
     }
 
-    worklist = [csu];
+    // Now return a list of all the instantiations of the method named 'field'
+    // that could execute on an instance of initialCSU or a descendant class.
+
+    // Start with the class itself, or if it doesn't define the method, all
+    // nearest ancestor definitions.
+    functions.update(nearestAncestorMethods(initialCSU, field));
+
+    // Then recurse through all descendants to add in their definitions.
+    var worklist = [initialCSU];
     while (worklist.length) {
         var csu = worklist.pop();
         var key = csu + ":" + field;
 
         if (classFunctions.has(key))
             functions.update(classFunctions.get(key));
 
         if (subclasses.has(csu))