mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1259850 - In-source annotations for GC suppression, r=terrence
MozReview-Commit-ID: HaSt3RVV6CM --HG-- extra : rebase_source : 9208edf58765abab960fa7188070704ee5bcbf56
This commit is contained in:
parent
7e06b7d972
commit
7ef77cb0e1
@ -551,7 +551,7 @@ class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertNoAlloc
|
||||
public:
|
||||
AutoSuppressGCAnalysis() : AutoAssertNoAlloc() {}
|
||||
explicit AutoSuppressGCAnalysis(JSRuntime* rt) : AutoAssertNoAlloc(rt) {}
|
||||
};
|
||||
} JS_HAZ_GC_SUPPRESSED;
|
||||
|
||||
/**
|
||||
* Assert that code is only ever called from a GC callback, disable the static
|
||||
|
@ -39,6 +39,8 @@
|
||||
// invalidating GC pointers.
|
||||
# define JS_HAZ_GC_CALL __attribute__((tag("GC Call")))
|
||||
|
||||
# define JS_HAZ_GC_SUPPRESSED __attribute__((tag("Suppress GC")))
|
||||
|
||||
#else
|
||||
|
||||
# define JS_HAZ_GC_THING
|
||||
@ -47,6 +49,7 @@
|
||||
# define JS_HAZ_GC_INVALIDATED
|
||||
# define JS_HAZ_NON_GC_POINTER
|
||||
# define JS_HAZ_GC_CALL
|
||||
# define JS_HAZ_GC_SUPPRESSED
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -72,6 +72,7 @@ def generate_hazards(config, outfilename):
|
||||
'%(gcEdges)s',
|
||||
'%(suppressedFunctions_list)s',
|
||||
'%(gcTypes)s',
|
||||
'%(typeInfo)s',
|
||||
str(i+1), '%(jobs)s',
|
||||
'tmp.%s' % (i+1,)),
|
||||
config)
|
||||
@ -113,7 +114,7 @@ JOBS = { 'dbs':
|
||||
()),
|
||||
|
||||
'callgraph':
|
||||
(('%(js)s', '%(analysis_scriptdir)s/computeCallgraph.js'),
|
||||
(('%(js)s', '%(analysis_scriptdir)s/computeCallgraph.js', '%(typeInfo)s'),
|
||||
'callgraph.txt'),
|
||||
|
||||
'gcFunctions':
|
||||
@ -122,8 +123,9 @@ JOBS = { 'dbs':
|
||||
('gcFunctions.txt', 'gcFunctions.lst', 'gcEdges.txt', 'suppressedFunctions.lst')),
|
||||
|
||||
'gcTypes':
|
||||
(('%(js)s', '%(analysis_scriptdir)s/computeGCTypes.js',),
|
||||
'gcTypes.txt'),
|
||||
(('%(js)s', '%(analysis_scriptdir)s/computeGCTypes.js',
|
||||
'[gcTypes]', '[typeInfo]'),
|
||||
('gcTypes.txt', 'typeInfo.txt')),
|
||||
|
||||
'allFunctions':
|
||||
(('%(sixgill_bin)s/xdbkeys', 'src_body.xdb',),
|
||||
@ -259,8 +261,8 @@ if not data.get('source') and data.get('sixgill_bin'):
|
||||
data['source'] = path.replace("/js/src/jsapi.cpp", "")
|
||||
|
||||
steps = [ 'dbs',
|
||||
'callgraph',
|
||||
'gcTypes',
|
||||
'callgraph',
|
||||
'gcFunctions',
|
||||
'allFunctions',
|
||||
'hazards',
|
||||
|
@ -12,7 +12,7 @@ var functionName;
|
||||
var functionBodies;
|
||||
|
||||
if (typeof scriptArgs[0] != 'string' || typeof scriptArgs[1] != 'string')
|
||||
throw "Usage: analyzeRoots.js [-f function_name] <gcFunctions.lst> <gcEdges.txt> <suppressedFunctions.lst> <gcTypes.txt> [start end [tmpfile]]";
|
||||
throw "Usage: analyzeRoots.js [-f function_name] <gcFunctions.lst> <gcEdges.txt> <suppressedFunctions.lst> <gcTypes.txt> <typeInfo.txt> [start end [tmpfile]]";
|
||||
|
||||
var theFunctionNameToFind;
|
||||
if (scriptArgs[0] == '--function') {
|
||||
@ -20,13 +20,16 @@ if (scriptArgs[0] == '--function') {
|
||||
scriptArgs = scriptArgs.slice(2);
|
||||
}
|
||||
|
||||
var gcFunctionsFile = scriptArgs[0];
|
||||
var gcEdgesFile = scriptArgs[1];
|
||||
var suppressedFunctionsFile = scriptArgs[2];
|
||||
var gcTypesFile = scriptArgs[3];
|
||||
var batch = (scriptArgs[4]|0) || 1;
|
||||
var numBatches = (scriptArgs[5]|0) || 1;
|
||||
var tmpfile = scriptArgs[6] || "tmp.txt";
|
||||
var gcFunctionsFile = scriptArgs[0] || "gcFunctions.lst";
|
||||
var gcEdgesFile = scriptArgs[1] || "gcEdges.txt";
|
||||
var suppressedFunctionsFile = scriptArgs[2] || "suppressedFunctions.lst";
|
||||
var gcTypesFile = scriptArgs[3] || "gcTypes.txt";
|
||||
var typeInfoFile = scriptArgs[4] || "typeInfo.txt";
|
||||
var batch = (scriptArgs[5]|0) || 1;
|
||||
var numBatches = (scriptArgs[6]|0) || 1;
|
||||
var tmpfile = scriptArgs[7] || "tmp.txt";
|
||||
|
||||
GCSuppressionTypes = loadTypeInfo(typeInfoFile)["Suppress GC"];
|
||||
|
||||
var gcFunctions = {};
|
||||
var text = snarf("gcFunctions.lst").split("\n");
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
// RAII types within which we should assume GC is suppressed, eg
|
||||
// AutoSuppressGC.
|
||||
var GCSuppressionTypes = [];
|
||||
|
||||
// Ignore calls made through these function pointers
|
||||
var ignoreIndirectCalls = {
|
||||
"mallocSizeOf" : true,
|
||||
@ -186,6 +190,7 @@ var ignoreFunctions = {
|
||||
// up wrapping a pending exception. See bug 898815 for the heavyweight fix.
|
||||
"void js::AutoCompartment::~AutoCompartment(int32)" : true,
|
||||
"void JSAutoCompartment::~JSAutoCompartment(int32)" : true,
|
||||
"void js::AutoClearTypeInferenceStateOnOOM::~AutoClearTypeInferenceStateOnOOM()" : true,
|
||||
|
||||
// Bug 948646 - the only thing AutoJSContext's constructor calls
|
||||
// is an Init() routine whose entire body is covered with an
|
||||
@ -322,13 +327,7 @@ function isUnsafeStorage(typeName)
|
||||
function isSuppressConstructor(varName)
|
||||
{
|
||||
// varName[1] contains the unqualified name
|
||||
return [
|
||||
"AutoSuppressGC",
|
||||
"AutoAssertGCCallback",
|
||||
"AutoEnterAnalysis",
|
||||
"AutoSuppressGCAnalysis",
|
||||
"AutoIgnoreRootingHazards"
|
||||
].indexOf(varName[1]) != -1;
|
||||
return GCSuppressionTypes.indexOf(varName[1]) != -1;
|
||||
}
|
||||
|
||||
// nsISupports subclasses' methods may be scriptable (or overridden
|
||||
|
@ -12,6 +12,8 @@ if (scriptArgs[0] == '--function') {
|
||||
scriptArgs = scriptArgs.slice(2);
|
||||
}
|
||||
|
||||
var typeInfo_filename = scriptArgs[0] || "typeInfo.txt";
|
||||
|
||||
var subclasses = new Map(); // Map from csu => set of immediate subclasses
|
||||
var superclasses = new Map(); // Map from csu => set of immediate superclasses
|
||||
var classFunctions = new Map(); // Map from "csu:name" => set of full method name
|
||||
@ -306,6 +308,8 @@ function processBody(functionName, body)
|
||||
}
|
||||
}
|
||||
|
||||
GCSuppressionTypes = loadTypeInfo(typeInfo_filename)["Suppress GC"];
|
||||
|
||||
var xdb = xdbLibrary();
|
||||
xdb.open("src_comp.xdb");
|
||||
|
||||
|
@ -5,14 +5,20 @@
|
||||
loadRelativeToScript('utility.js');
|
||||
loadRelativeToScript('annotations.js');
|
||||
|
||||
var gcTypes_filename = scriptArgs[0] || "gcTypes.txt";
|
||||
var typeInfo_filename = scriptArgs[1] || "typeInfo.txt";
|
||||
|
||||
var annotations = {
|
||||
'GCPointers': [],
|
||||
'GCThings': [],
|
||||
'NonGCTypes': {}, // unused
|
||||
'NonGCPointers': {},
|
||||
'RootedPointers': {},
|
||||
'GCSuppressors': {},
|
||||
};
|
||||
|
||||
var gDescriptors = new Map; // Map from descriptor string => Set of typeName
|
||||
|
||||
var structureParents = {}; // Map from field => list of <parent, fieldName>
|
||||
var pointerParents = {}; // Map from field => list of <parent, fieldName>
|
||||
var baseClasses = {}; // Map from struct name => list of base class name strings
|
||||
@ -64,6 +70,8 @@ function processCSU(csu, body)
|
||||
annotations.NonGCPointers[csu] = true;
|
||||
else if (tag == 'Rooted Pointer')
|
||||
annotations.RootedPointers[csu] = true;
|
||||
else if (tag == 'Suppress GC')
|
||||
annotations.GCSuppressors[csu] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,6 +215,26 @@ function addGCPointer(typeName)
|
||||
markGCType(typeName, '<pointer-annotation>', '(annotation)', 1, 0, "");
|
||||
}
|
||||
|
||||
// Add an arbitrary descriptor to a type, and apply it recursively to all base
|
||||
// structs and structs that contain the given typeName as a field.
|
||||
function addDescriptor(typeName, descriptor)
|
||||
{
|
||||
if (!gDescriptors.has(descriptor))
|
||||
gDescriptors.set(descriptor, new Set);
|
||||
let descriptorTypes = gDescriptors.get(descriptor);
|
||||
if (!descriptorTypes.has(typeName)) {
|
||||
descriptorTypes.add(typeName);
|
||||
if (typeName in structureParents) {
|
||||
for (let [holder, field] of structureParents[typeName])
|
||||
addDescriptor(holder, descriptor);
|
||||
}
|
||||
if (typeName in baseClasses) {
|
||||
for (let base of baseClasses[typeName])
|
||||
addDescriptor(base, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var type of listNonGCPointers())
|
||||
annotations.NonGCPointers[type] = true;
|
||||
|
||||
@ -246,6 +274,8 @@ function explain(csu, indent, seen) {
|
||||
}
|
||||
}
|
||||
|
||||
var origOut = os.file.redirect(gcTypes_filename);
|
||||
|
||||
for (var csu in gcTypes) {
|
||||
print("GCThing: " + csu);
|
||||
explain(csu, " ");
|
||||
@ -254,3 +284,16 @@ for (var csu in gcPointers) {
|
||||
print("GCPointer: " + csu);
|
||||
explain(csu, " ");
|
||||
}
|
||||
|
||||
// Redirect output to the typeInfo file and close the gcTypes file.
|
||||
os.file.close(os.file.redirect(typeInfo_filename));
|
||||
|
||||
for (let csu in annotations.GCSuppressors)
|
||||
addDescriptor(csu, 'Suppress GC');
|
||||
|
||||
for (let [descriptor, types] of gDescriptors) {
|
||||
for (let csu of types)
|
||||
print(descriptor + "$$" + csu);
|
||||
}
|
||||
|
||||
os.file.close(os.file.redirect(origOut));
|
||||
|
@ -191,3 +191,21 @@ function* readFileLines_gen(filename)
|
||||
libc.fclose(fp);
|
||||
libc.free(ctypes.void_t.ptr(linebuf));
|
||||
}
|
||||
|
||||
function addToKeyedList(collection, key, entry)
|
||||
{
|
||||
if (!(key in collection))
|
||||
collection[key] = [];
|
||||
collection[key].push(entry);
|
||||
}
|
||||
|
||||
function loadTypeInfo(filename)
|
||||
{
|
||||
var info = {};
|
||||
for (var line of readFileLines_gen(filename)) {
|
||||
line = line.replace(/\n/, "");
|
||||
let [property, name] = line.split("$$");
|
||||
addToKeyedList(info, property, name);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ struct AutoIgnoreRootingHazards {
|
||||
static volatile int depth;
|
||||
AutoIgnoreRootingHazards() { depth++; }
|
||||
~AutoIgnoreRootingHazards() { depth--; }
|
||||
};
|
||||
} JS_HAZ_GC_SUPPRESSED;
|
||||
volatile int AutoIgnoreRootingHazards::depth = 0;
|
||||
|
||||
BEGIN_TEST(testGCStoreBufferRemoval)
|
||||
|
@ -1269,7 +1269,7 @@ MaybeVerifyBarriers(JSContext* cx, bool always = false)
|
||||
* read the comment in vm/Runtime.h above |suppressGC| and take all appropriate
|
||||
* precautions before instantiating this class.
|
||||
*/
|
||||
class MOZ_RAII AutoSuppressGC
|
||||
class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC
|
||||
{
|
||||
int32_t& suppressGC_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user