Bug 934698 - Suppress nsISupports.{AddRef,Release} when called directly, r=bhackett

DONBUILD because NPOTB yet
This commit is contained in:
Steve Fink 2013-11-05 09:10:31 -08:00
parent 7f5af0f86e
commit d0546965ac
5 changed files with 38 additions and 14 deletions

View File

@ -236,7 +236,9 @@ function edgeCanGC(edge)
var field = callee.Exp[0].Field;
var csuName = field.FieldCSU.Type.Name;
var fullFieldName = csuName + "." + field.Name[0];
return fieldCallCannotGC(csuName, fullFieldName) ? null : fullFieldName;
if (fieldCallCannotGC(csuName, fullFieldName))
return null;
return (fullFieldName in suppressedFunctions) ? null : fullFieldName;
}
assert(callee.Exp[0].Kind == "Var");
var calleeName = callee.Exp[0].Variable.Name[0];

View File

@ -69,8 +69,6 @@ var ignoreCallees = {
"js::Class.trace" : true,
"js::Class.finalize" : true,
"JSRuntime.destroyPrincipals" : true,
"nsISupports.AddRef" : true,
"nsISupports.Release" : true, // makes me a bit nervous; this is a bug but can happen
"nsIGlobalObject.GetGlobalJSObject" : true, // virtual but no implementation can GC
"nsAXPCNativeCallContext.GetJSContext" : true,
"js::jit::MDefinition.op" : true, // macro generated virtuals just return a constant

View File

@ -49,7 +49,7 @@ function processCSU(csuName, csu)
}
}
function findVirtualFunctions(csu, field)
function findVirtualFunctions(csu, field, suppressed)
{
var worklist = [csu];
@ -60,8 +60,10 @@ function findVirtualFunctions(csu, field)
while (worklist.length) {
var csu = worklist.pop();
if (csu == "nsISupports") {
if (field == "AddRef" || field == "Release")
if (field == "AddRef" || field == "Release") {
suppressed[0] = true;
return [];
}
return null;
}
if (csu in superclasses) {
@ -132,8 +134,16 @@ function getCallees(edge)
var fieldName = field.Name[0];
var csuName = field.FieldCSU.Type.Name;
var functions = null;
if ("FieldInstanceFunction" in field)
functions = findVirtualFunctions(csuName, fieldName);
if ("FieldInstanceFunction" in field) {
var suppressed = [ false ];
functions = findVirtualFunctions(csuName, fieldName, suppressed);
if (suppressed[0]) {
// Field call known to not GC; mark it as suppressed so
// direct invocations will be ignored
callees.push({'kind': "field", 'csu': csuName, 'field': fieldName,
'suppressed': true});
}
}
if (functions) {
// Known set of virtual call targets.
for (var name of functions)
@ -173,14 +183,15 @@ function processBody(caller, body)
for (var edge of body.PEdge) {
if (edge.Kind != "Call")
continue;
var suppressText = "";
var edgeSuppressed = false;
var seen = seenCallees;
if (edge.Index[0] in body.suppressed) {
suppressText = "SUPPRESS_GC ";
edgeSuppressed = true;
seen = seenSuppressedCallees;
}
var prologue = suppressText + memo(caller) + " ";
for (var callee of getCallees(edge)) {
var prologue = (edgeSuppressed || callee.suppressed) ? "SUPPRESS_GC " : "";
prologue += memo(caller) + " ";
if (callee.kind == 'direct') {
if (!(callee.name in seen)) {
seen[name] = true;

View File

@ -48,9 +48,11 @@ try:
print >>refs, line
continue
m = re.match(r"^Function.*has unrooted.*of type.*live across GC call '(.*?)'", line)
m = re.match(r"^Function.*has unrooted.*of type.*live across GC call ('?)(.*?)('?) at \S+:\d+$", line)
if m:
current_gcFunction = m.group(1)
# Function names are surrounded by single quotes. Field calls
# are unquoted.
current_gcFunction = m.group(2)
hazardousGCFunctions.setdefault(current_gcFunction, []).append(line)
hazardOrder.append((current_gcFunction, len(hazardousGCFunctions[current_gcFunction]) - 1))
num_hazards += 1
@ -84,7 +86,10 @@ try:
for gcFunction, index in hazardOrder:
gcHazards = hazardousGCFunctions[gcFunction]
print >>hazards, (gcHazards[index] + gcExplanations[gcFunction])
if gcFunction in gcExplanations:
print >>hazards, (gcHazards[index] + gcExplanations[gcFunction])
else:
print >>hazards, gcHazards[index]
except IOError as e:
print 'Failed: %s' % str(e)

View File

@ -39,6 +39,8 @@ var functionNames = [""];
function loadCallgraph(file)
{
var suppressedFieldCalls = {};
var textLines = snarf(file).split('\n');
for (var line of textLines) {
var match;
@ -62,7 +64,9 @@ function loadCallgraph(file)
var caller = functionNames[match[1]];
var csu = match[2];
var fullfield = csu + "." + match[3];
if (!fieldCallCannotGC(csu, fullfield) && !suppressed)
if (suppressed)
suppressedFieldCalls[fullfield] = true;
else if (!fieldCallCannotGC(csu, fullfield))
addGCFunction(caller, "FieldCall: " + fullfield);
} else if (match = /^D (\d+) (\d+)/.exec(line)) {
var caller = functionNames[match[1]];
@ -100,6 +104,10 @@ function loadCallgraph(file)
delete gcFunctions[name];
}
for (var name in suppressedFieldCalls) {
suppressedFunctions[name] = true;
}
for (var gcName of [ 'jsgc.cpp:void Collect(JSRuntime*, uint8, int64, uint32, uint32)',
'void js::MinorGC(JSRuntime*, uint32)' ])
{