Bug 1709695 - Only init PropertyInfos and sort IDs for resolving Xray properties once needed. r=nika

Most of the time, a lot of the WebIDL interfaces are never used with Xray wrappers.
We still always initialise the necessary PropertyInfo arrays whenever they're used
normally (not through Xray wrappers). I think we should postpone that initialisation
until we're actually going to use them with Xray wrappers.

Differential Revision: https://phabricator.services.mozilla.com/D114402
This commit is contained in:
Peter Van der Beken 2021-05-07 13:57:24 +00:00
Родитель ef4c757f2c
Коммит 2ffa0654be
4 изменённых файлов: 66 добавлений и 61 удалений

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

@ -1275,8 +1275,8 @@ static inline JSPropertySpec::Name ToPropertySpecName(const char* name) {
}
template <typename SpecT>
static bool InitIdsInternal(JSContext* cx, const Prefable<SpecT>* pref,
PropertyInfo* infos, PropertyType type) {
static bool InitPropertyInfos(JSContext* cx, const Prefable<SpecT>* pref,
PropertyInfo* infos, PropertyType type) {
MOZ_ASSERT(pref);
MOZ_ASSERT(pref->specs);
@ -1308,24 +1308,25 @@ static bool InitIdsInternal(JSContext* cx, const Prefable<SpecT>* pref,
return true;
}
#define INIT_IDS_IF_DEFINED(TypeName) \
{ \
if (nativeProperties->Has##TypeName##s() && \
!InitIdsInternal(cx, nativeProperties->TypeName##s(), \
nativeProperties->TypeName##PropertyInfos(), \
e##TypeName)) { \
return false; \
} \
#define INIT_PROPERTY_INFOS_IF_DEFINED(TypeName) \
{ \
if (nativeProperties->Has##TypeName##s() && \
!InitPropertyInfos(cx, nativeProperties->TypeName##s(), \
nativeProperties->TypeName##PropertyInfos(), \
e##TypeName)) { \
return false; \
} \
}
bool InitIds(JSContext* cx, const NativeProperties* nativeProperties) {
INIT_IDS_IF_DEFINED(StaticMethod);
INIT_IDS_IF_DEFINED(StaticAttribute);
INIT_IDS_IF_DEFINED(Method);
INIT_IDS_IF_DEFINED(Attribute);
INIT_IDS_IF_DEFINED(UnforgeableMethod);
INIT_IDS_IF_DEFINED(UnforgeableAttribute);
INIT_IDS_IF_DEFINED(Constant);
static bool InitPropertyInfos(JSContext* cx,
const NativeProperties* nativeProperties) {
INIT_PROPERTY_INFOS_IF_DEFINED(StaticMethod);
INIT_PROPERTY_INFOS_IF_DEFINED(StaticAttribute);
INIT_PROPERTY_INFOS_IF_DEFINED(Method);
INIT_PROPERTY_INFOS_IF_DEFINED(Attribute);
INIT_PROPERTY_INFOS_IF_DEFINED(UnforgeableMethod);
INIT_PROPERTY_INFOS_IF_DEFINED(UnforgeableAttribute);
INIT_PROPERTY_INFOS_IF_DEFINED(Constant);
// Initialize and sort the index array.
uint16_t* indices = nativeProperties->sortedPropertyIndices;
@ -1341,7 +1342,26 @@ bool InitIds(JSContext* cx, const NativeProperties* nativeProperties) {
return true;
}
#undef INIT_IDS_IF_DEFINED
#undef INIT_PROPERTY_INFOS_IF_DEFINED
static inline bool InitPropertyInfos(
JSContext* aCx, const NativePropertiesHolder& nativeProperties) {
MOZ_ASSERT(NS_IsMainThread());
if (!*nativeProperties.inited) {
if (nativeProperties.regular &&
!InitPropertyInfos(aCx, nativeProperties.regular)) {
return false;
}
if (nativeProperties.chromeOnly &&
!InitPropertyInfos(aCx, nativeProperties.chromeOnly)) {
return false;
}
*nativeProperties.inited = true;
}
return true;
}
void GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
nsWrapperCache* aCache, JS::Handle<JS::Value> aIID,
@ -1678,6 +1698,11 @@ static bool ResolvePrototypeOrConstructor(
const NativePropertiesHolder& nativePropertiesHolder =
nativePropertyHooks->mNativeProperties;
if (!InitPropertyInfos(cx, nativePropertiesHolder)) {
return false;
}
const NativeProperties* nativeProperties = nullptr;
const PropertyInfo* found = nullptr;
@ -1949,6 +1974,10 @@ bool XrayOwnNativePropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
const NativePropertiesHolder& nativeProperties =
nativePropertyHooks->mNativeProperties;
if (!InitPropertyInfos(cx, nativeProperties)) {
return false;
}
if (nativeProperties.regular &&
!XrayOwnPropertyKeys(cx, wrapper, obj, flags, props, type,
nativeProperties.regular)) {
@ -2053,13 +2082,15 @@ JSObject* GetCachedSlotStorageObjectSlow(JSContext* cx,
DEFINE_XRAY_EXPANDO_CLASS(, DefaultXrayExpandoObjectClass, 0);
NativePropertyHooks sEmptyNativePropertyHooks = {nullptr,
nullptr,
nullptr,
{nullptr, nullptr},
prototypes::id::_ID_Count,
constructors::id::_ID_Count,
nullptr};
bool sEmptyNativePropertiesInited = true;
NativePropertyHooks sEmptyNativePropertyHooks = {
nullptr,
nullptr,
nullptr,
{nullptr, nullptr, &sEmptyNativePropertiesInited},
prototypes::id::_ID_Count,
constructors::id::_ID_Count,
nullptr};
const JSClassOps sBoringInterfaceObjectClassClassOps = {
nullptr, /* addProperty */

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

@ -1770,8 +1770,6 @@ static inline bool AtomizeAndPinJSString(JSContext* cx, jsid& id,
return false;
}
bool InitIds(JSContext* cx, const NativeProperties* properties);
void GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
nsWrapperCache* aCache, JS::Handle<JS::Value> aIID,
JS::MutableHandle<JS::Value> aRetval,

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

@ -544,11 +544,12 @@ class CGNativePropertyHooks(CGThing):
return fill(
"""
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks[] = { {
${resolveOwnProperty},
${enumerateOwnProperties},
${deleteNamedProperty},
{ ${regular}, ${chrome} },
{ ${regular}, ${chrome}, &sNativePropertiesInited },
${prototypeID},
${constructorID},
${parentHooks},
@ -2362,11 +2363,12 @@ class CGLegacyFactoryFunctions(CGThing):
return fill(
"""
bool sLegacyFactoryFunctionNativePropertiesInited = true;
const NativePropertyHooks sLegacyFactoryFunctionNativePropertyHooks = {
nullptr,
nullptr,
nullptr,
{ nullptr, nullptr },
{ nullptr, nullptr, &sLegacyFactoryFunctionNativePropertiesInited },
prototypes::id::${name},
${constructorID},
nullptr
@ -3614,36 +3616,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
getConstructorProto=getConstructorProto,
)
idsToInit = []
# There is no need to init any IDs in bindings that don't want Xrays.
if self.descriptor.wantsXrays:
if self.properties.hasNonChromeOnly():
idsToInit.append("sNativeProperties")
if self.properties.hasChromeOnly():
idsToInit.append("sChromeOnlyNativeProperties")
if len(idsToInit) > 0:
initIdCalls = [
"!InitIds(aCx, %s.Upcast())" % (properties) for properties in idsToInit
]
idsInitedFlag = CGGeneric(
"static Atomic<bool, Relaxed> sIdsInited(false);\n"
)
setFlag = CGGeneric("sIdsInited = true;\n")
initIdConditionals = [
CGIfWrapper(CGGeneric("return;\n"), call) for call in initIdCalls
]
initIds = CGList(
[
idsInitedFlag,
CGIfWrapper(
CGList(initIdConditionals + [setFlag]),
"!sIdsInited && NS_IsMainThread()",
),
]
)
else:
initIds = None
if self.descriptor.interface.ctor():
constructArgs = methodLength(self.descriptor.interface.ctor())
else:
@ -3936,7 +3908,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
[
getParentProto,
getConstructorProto,
initIds,
CGGeneric(call),
defineAliases,
unforgeableHolderSetup,

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

@ -384,6 +384,11 @@ typedef NativePropertiesN<7> NativeProperties;
struct NativePropertiesHolder {
const NativeProperties* regular;
const NativeProperties* chromeOnly;
// Points to a static bool that's set to true once the regular and chromeOnly
// NativeProperties have been inited. This is a pointer to a bool instead of
// a bool value because NativePropertiesHolder is stored by value in
// a static const NativePropertyHooks.
bool* inited;
};
// Helper structure for Xrays for DOM binding objects. The same instance is used