Bug 1259850 - Fix constructor recognition, r=terrence
authorSteve Fink <sfink@mozilla.com>
Thu, 28 Apr 2016 14:19:01 -0700
changeset 338801 4a346f93e8402778005909ec2648bc1437d71671
parent 338800 810a121696ab26247926c95b7f34070b811e45aa
child 338802 7876b3fd15e63e7baf5ca375089dd9b84c1e44bb
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)