Bug 1259850 - Fix constructor recognition, r=terrence
☠☠ backed out by 69518db96a4d ☠ ☠
authorSteve Fink <sfink@mozilla.com>
Thu, 28 Apr 2016 14:19:01 -0700
changeset 338760 0b9dedcf7163ce35e4207a1d8fe33523a9a8f920
parent 338759 b641d01138ab54ec1f6b29232614b338b02d42f1
child 338761 19c13aa9b5ada4d1284a09d8284b3231e0790ebe
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [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 - Fix constructor recognition, r=terrence MozReview-Commit-ID: 46064amRbCQ
js/src/devtools/rootAnalysis/CFG.js
js/src/devtools/rootAnalysis/annotations.js
js/src/devtools/rootAnalysis/computeCallgraph.js
js/src/devtools/rootAnalysis/run-test.py
--- a/js/src/devtools/rootAnalysis/CFG.js
+++ b/js/src/devtools/rootAnalysis/CFG.js
@@ -65,17 +65,17 @@ function allRAIIGuardedCallPoints(bodies
     for (var edge of body.PEdge) {
         if (edge.Kind != "Call")
             continue;
         var callee = edge.Exp[0];
         if (callee.Kind != "Var")
             continue;
         var variable = callee.Variable;
         assert(variable.Kind == "Func");
-        if (!isConstructor(variable.Name))
+        if (!isConstructor(edge.Type, variable.Name))
             continue;
         if (!("PEdgeCallInstance" in edge))
             continue;
         if (edge.PEdgeCallInstance.Exp.Kind != "Var")
             continue;
 
         Array.prototype.push.apply(points, pointsInRAIIScope(bodies, body, edge));
     }
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -319,20 +319,41 @@ function isRootedTypeName(name)
 }
 
 function isUnsafeStorage(typeName)
 {
     typeName = stripUCSAndNamespace(typeName);
     return typeName.startsWith('UniquePtr<');
 }
 
-function isSuppressConstructor(varName)
+function isSuppressConstructor(edgeType, varName)
 {
-    // varName[1] contains the unqualified name
-    return GCSuppressionTypes.indexOf(varName[1]) != -1;
+    // Check whether this could be a constructor
+    if (edgeType.Kind != 'Function')
+        return false;
+    if (!('TypeFunctionCSU' in edgeType))
+        return false;
+    if (edgeType.Type.Kind != 'Void')
+        return false;
+
+    // Check whether the type is a known suppression type.
+    var type = edgeType.TypeFunctionCSU.Type.Name;
+    if (GCSuppressionTypes.indexOf(type) == -1)
+        return false;
+
+    // And now make sure this is the constructor, not some other method on a
+    // suppression type. varName[0] contains the qualified name.
+    var [ mangled, unmangled ] = splitFunction(varName[0]);
+    if (mangled.search(/C\dE/) == -1)
+        return false; // Mangled names of constructors have C<num>E
+    var m = unmangled.match(/([~\w]+)(?:<.*>)?\(/);
+    if (!m)
+        return false;
+    var type_stem = type.replace(/\w+::/g, '').replace(/\<.*\>/g, '');
+    return m[1] == type_stem;
 }
 
 // nsISupports subclasses' methods may be scriptable (or overridden
 // via binary XPCOM), and so may GC. But some fields just aren't going
 // to get overridden with something that can GC.
 function isOverridableField(initialCSU, csu, field)
 {
     if (csu != 'nsISupports')
--- a/js/src/devtools/rootAnalysis/computeCallgraph.js
+++ b/js/src/devtools/rootAnalysis/computeCallgraph.js
@@ -341,16 +341,17 @@ if (theFunctionNameToFind) {
     }
     minStream = maxStream = index;
 }
 
 function process(functionName, functionBodies)
 {
     for (var body of functionBodies)
         body.suppressed = [];
+
     for (var body of functionBodies) {
         for (var [pbody, id] of allRAIIGuardedCallPoints(functionBodies, body, isSuppressConstructor))
             pbody.suppressed[id] = true;
     }
 
     for (var body of functionBodies)
         processBody(functionName, body);
 
--- a/js/src/devtools/rootAnalysis/run-test.py
+++ b/js/src/devtools/rootAnalysis/run-test.py
@@ -34,16 +34,19 @@ parser.add_argument(
     '--cc', default=os.environ.get('CC'),
     help='Path to gcc')
 parser.add_argument(
     '--cxx', default=os.environ.get('CXX'),
     help='Path to g++')
 parser.add_argument(
     '--verbose', '-v', action='store_true',
     help='Display verbose output, including commands executed')
+parser.add_argument(
+    'tests', nargs='*', default=['sixgill-tree', 'suppression', 'hazards'],
+    help='tests to run')
 
 cfg = parser.parse_args()
 
 if not cfg.js:
     exit('Must specify JS binary through environment variable or --js option')
 if not cfg.cc:
     if cfg.gccdir:
         cfg.cc = os.path.join(cfg.gccdir, "bin", "gcc")
@@ -64,18 +67,18 @@ subprocess.check_call([cfg.js, '-e', 'if
 def binpath(prog):
     return os.path.join(cfg.sixgill_bin, prog)
 
 try:
     os.mkdir(os.path.join('t', 'out'))
 except OSError:
     pass
 
-tests = ['sixgill-tree', 'suppression', 'hazards']
-for name in tests:
+for name in cfg.tests:
+    name = os.path.basename(name)
     indir = os.path.join(testdir, name)
     outdir = os.path.join(testdir, 'out', name)
     try:
         os.mkdir(outdir)
     except OSError:
         pass
 
     test = Test(indir, outdir, cfg)