Bug 1479962 - Add JS_HAZ_ROOTED_BASE for AutoGCRooter, which assumes all descendants are rooted, r=jonco

--HG--
extra : topic : hazard
extra : rebase_source : a75561cdf2f71e34a630737dcf832d05d95974b0
This commit is contained in:
Steve Fink 2018-07-24 16:52:43 -07:00
Родитель 45873100f5
Коммит b0006a2c76
3 изменённых файлов: 43 добавлений и 26 удалений

Просмотреть файл

@ -26,6 +26,12 @@
// is not itself a GC pointer.
# define JS_HAZ_GC_INVALIDATED __attribute__((tag("Invalidated by GC")))
// Mark a class as a base class of rooted types, eg CustomAutoRooter. All
// descendants of this class will be considered rooted, though classes that
// merely contain these as a field member will not be. "Inherited" by
// templatized types with MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS
# define JS_HAZ_ROOTED_BASE __attribute__((tag("Rooted Base")))
// Mark a type that would otherwise be considered a GC Pointer (eg because it
// contains a JS::Value field) as a non-GC pointer. It is handled almost the
// same in the analysis as a rooted pointer, except it will not be reported as
@ -52,6 +58,7 @@
# define JS_HAZ_GC_POINTER
# define JS_HAZ_ROOTED
# define JS_HAZ_GC_INVALIDATED
# define JS_HAZ_ROOTED_BASE
# define JS_HAZ_NON_GC_POINTER
# define JS_HAZ_GC_CALL
# define JS_HAZ_GC_SUPPRESSED

Просмотреть файл

@ -945,7 +945,7 @@ class JS_PUBLIC_API(AutoGCRooter)
/* No copy or assignment semantics. */
AutoGCRooter(AutoGCRooter& ida) = delete;
void operator=(AutoGCRooter& ida) = delete;
};
} JS_HAZ_ROOTED_BASE;
namespace detail {

Просмотреть файл

@ -15,6 +15,7 @@ var typeInfo = {
'NonGCPointers': {},
'RootedGCThings': {},
'RootedPointers': {},
'RootedBases': {'JS::AutoGCRooter': true},
// RAII types within which we should assume GC is suppressed, eg
// AutoSuppressGC.
@ -36,6 +37,26 @@ var rootedPointers = {};
function processCSU(csu, body)
{
for (let { 'Name': [ annType, tag ] } of (body.Annotation || [])) {
if (annType != 'Tag')
continue;
if (tag == 'GC Pointer')
typeInfo.GCPointers.push(csu);
else if (tag == 'Invalidated by GC')
typeInfo.GCPointers.push(csu);
else if (tag == 'GC Thing')
typeInfo.GCThings.push(csu);
else if (tag == 'Suppressed GC Pointer')
typeInfo.NonGCPointers[csu] = true;
else if (tag == 'Rooted Pointer')
typeInfo.RootedPointers[csu] = true;
else if (tag == 'Rooted Base')
typeInfo.RootedBases[csu] = true;
else if (tag == 'Suppress GC')
typeInfo.GCSuppressors[csu] = true;
}
for (let { 'Base': base } of (body.CSUBaseClass || []))
addBaseClass(csu, base);
@ -52,31 +73,8 @@ function processCSU(csu, body)
if (target.Kind == "CSU")
addNestedStructure(csu, target.Name, fieldName);
}
if (type.Kind == "CSU") {
// Ignore nesting in classes which are AutoGCRooters. We only consider
// types with fields that may not be properly rooted.
if (type.Name == "JS::AutoGCRooter" || type.Name == "JS::CustomAutoRooter")
return;
if (type.Kind == "CSU")
addNestedStructure(csu, type.Name, fieldName);
}
}
for (let { 'Name': [ annType, tag ] } of (body.Annotation || [])) {
if (annType != 'Tag')
continue;
if (tag == 'GC Pointer')
typeInfo.GCPointers.push(csu);
else if (tag == 'Invalidated by GC')
typeInfo.GCPointers.push(csu);
else if (tag == 'GC Thing')
typeInfo.GCThings.push(csu);
else if (tag == 'Suppressed GC Pointer')
typeInfo.NonGCPointers[csu] = true;
else if (tag == 'Rooted Pointer')
typeInfo.RootedPointers[csu] = true;
else if (tag == 'Suppress GC')
typeInfo.GCSuppressors[csu] = true;
}
}
@ -86,6 +84,8 @@ function addNestedStructure(csu, inner, field)
if (!(inner in structureParents))
structureParents[inner] = [];
// Skip fields that are really base classes, to avoid duplicating the base
// fields; addBaseClass already added a "base-N" name.
if (field.match(/^field:\d+$/) && (csu in baseClasses) && (baseClasses[csu].indexOf(inner) != -1))
return;
@ -140,6 +140,16 @@ for (const csu of typeInfo.GCThings)
for (const csu of typeInfo.GCPointers)
addGCPointer(csu);
// Everything that inherits from a "Rooted Base" is considered to be rooted.
// This is for things like CustomAutoRooter and its subclasses.
var basework = Object.keys(typeInfo.RootedBases);
while (basework.length) {
const base = basework.pop();
typeInfo.RootedPointers[base] = true;
if (base in subClasses)
basework.push(...subClasses[base]);
}
// "typeName is a (pointer to a)^'typePtrLevel' GC type because it contains a field
// named 'child' of type 'why' (or pointer to 'why' if fieldPtrLevel == 1), which is
// itself a GCThing or GCPointer."
@ -230,7 +240,7 @@ function addGCPointer(typeName)
// Call a function for a type and every type that contains the type in a field
// or as a base class (which internally is pretty much the same thing --
// sublcasses are structs beginning with the base class and adding on their
// subclasses are structs beginning with the base class and adding on their
// local fields.)
function foreachContainingStruct(typeName, func, seen = new Set())
{