Bug 1444286. Common up the Get*ObjectHandle methods in bindings. r=peterv

This reduces codesize, at the cost of a bit more includes in the binding headers.

MozReview-Commit-ID: 40dLELF36Oh
This commit is contained in:
Boris Zbarsky 2018-03-09 16:04:11 -05:00
Родитель 1ce292d679
Коммит 272ace7ae2
3 изменённых файлов: 75 добавлений и 57 удалений

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

@ -543,6 +543,17 @@ public:
operator CallerType() const { return CallerType::System; }
};
class ProtoAndIfaceCache;
typedef void (*CreateInterfaceObjectsMethod)(JSContext* aCx,
JS::Handle<JSObject*> aGlobal,
ProtoAndIfaceCache& aCache,
bool aDefineOnGlobal);
JS::Handle<JSObject*> GetPerInterfaceObjectHandle(
JSContext* aCx,
size_t aSlotId,
CreateInterfaceObjectsMethod aCreator,
bool aDefineOnGlobal);
} // namespace dom
} // namespace mozilla

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

@ -3805,5 +3805,41 @@ UnprivilegedJunkScopeOrWorkerGlobal()
}
} // namespace binding_detail
JS::Handle<JSObject*>
GetPerInterfaceObjectHandle(JSContext* aCx,
size_t aSlotId,
CreateInterfaceObjectsMethod aCreator,
bool aDefineOnGlobal)
{
/* Make sure our global is sane. Hopefully we can remove this sometime */
JSObject* global = JS::CurrentGlobalOrNull(aCx);
if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
return nullptr;
}
/* Check to see whether the interface objects are already installed */
ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
if (!protoAndIfaceCache.HasEntryInSlot(aSlotId)) {
JS::Rooted<JSObject*> rootedGlobal(aCx, global);
aCreator(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
}
/*
* The object might _still_ be null, but that's OK.
*
* Calling fromMarkedLocation() is safe because protoAndIfaceCache is
* traced by TraceProtoAndIfaceCache() and its contents are never
* changed after they have been set.
*
* Calling address() avoids the read barrier that does gray unmarking, but
* it's not possible for the object to be gray here.
*/
const JS::Heap<JSObject*>& entrySlot =
protoAndIfaceCache.EntrySlotMustExist(aSlotId);
MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
}
} // namespace dom
} // namespace mozilla

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

@ -3400,66 +3400,28 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
"\n").define()
class CGGetPerInterfaceObject(CGAbstractMethod):
"""
A method for getting a per-interface object (a prototype object or interface
constructor object).
"""
def __init__(self, descriptor, name, idPrefix="", extraArgs=[]):
args = [Argument('JSContext*', 'aCx')] + extraArgs
CGAbstractMethod.__init__(self, descriptor, name,
'JS::Handle<JSObject*>', args)
self.id = idPrefix + "id::" + self.descriptor.name
def definition_body(self):
return fill(
"""
/* Make sure our global is sane. Hopefully we can remove this sometime */
JSObject* global = JS::CurrentGlobalOrNull(aCx);
if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
return nullptr;
}
/* Check to see whether the interface objects are already installed */
ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
if (!protoAndIfaceCache.HasEntryInSlot(${id})) {
JS::Rooted<JSObject*> rootedGlobal(aCx, global);
CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
}
/*
* The object might _still_ be null, but that's OK.
*
* Calling fromMarkedLocation() is safe because protoAndIfaceCache is
* traced by TraceProtoAndIfaceCache() and its contents are never
* changed after they have been set.
*
* Calling address() avoids the read read barrier that does gray
* unmarking, but it's not possible for the object to be gray here.
*/
const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(${id});
MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
""",
id=self.id)
class CGGetProtoObjectHandleMethod(CGGetPerInterfaceObject):
class CGGetProtoObjectHandleMethod(CGAbstractMethod):
"""
A method for getting the interface prototype object.
"""
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObjectHandle",
"prototypes::")
CGAbstractMethod.__init__(
self, descriptor, "GetProtoObjectHandle",
'JS::Handle<JSObject*>',
[Argument('JSContext*', 'aCx')],
inline=True)
def definition_body(self):
return dedent("""
return fill(
"""
/* Get the interface prototype object for this class. This will create the
object as needed. */
bool aDefineOnGlobal = true;
return GetPerInterfaceObjectHandle(aCx, prototypes::id::${name},
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
""") + CGGetPerInterfaceObject.definition_body(self)
""",
name=self.descriptor.name)
class CGGetProtoObjectMethod(CGAbstractMethod):
@ -3475,22 +3437,29 @@ class CGGetProtoObjectMethod(CGAbstractMethod):
return "return GetProtoObjectHandle(aCx);\n"
class CGGetConstructorObjectHandleMethod(CGGetPerInterfaceObject):
class CGGetConstructorObjectHandleMethod(CGAbstractMethod):
"""
A method for getting the interface constructor object.
"""
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(
CGAbstractMethod.__init__(
self, descriptor, "GetConstructorObjectHandle",
"constructors::",
extraArgs=[Argument("bool", "aDefineOnGlobal", "true")])
'JS::Handle<JSObject*>',
[Argument('JSContext*', 'aCx'),
Argument('bool', 'aDefineOnGlobal', 'true')],
inline=True)
def definition_body(self):
return dedent("""
return fill(
"""
/* Get the interface object for this class. This will create the object as
needed. */
""") + CGGetPerInterfaceObject.definition_body(self)
return GetPerInterfaceObjectHandle(aCx, constructors::id::${name},
&CreateInterfaceObjects,
aDefineOnGlobal);
""",
name=self.descriptor.name)
class CGGetConstructorObjectMethod(CGAbstractMethod):
@ -14386,6 +14355,7 @@ class CGBindingRoot(CGThing):
jsImplemented = config.getDescriptors(webIDLFile=webIDLFile,
isJSImplemented=True)
bindingDeclareHeaders["nsWeakReference.h"] = jsImplemented
bindingDeclareHeaders["mozilla/dom/PrototypeList.h"] = descriptors
bindingHeaders["nsIGlobalObject.h"] = jsImplemented
bindingHeaders["AtomList.h"] = hasNonEmptyDictionaries or jsImplemented or callbackDescriptors
@ -17332,6 +17302,7 @@ class GlobalGenRoots():
idEnum = CGWrapper(idEnum, post='\n')
curr = CGList([CGGeneric(define="#include <stdint.h>\n\n"),
CGGeneric(declare='#include "jsfriendapi.h"\n\n'),
idEnum])
# Let things know the maximum length of the prototype chain.