Bug 1261720 (part 2) - Move ClassExtension::isWrappedNative into js::Class::flags. r=jorendorff.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 04 Apr 2016 08:47:15 +1000
changeset 329611 32598dbf8f233575c5dd492eb05dd324b53d1d6a
parent 329610 b9f349b8151b9bc165318bda2eaed0ede209d50e
child 329612 d6836561de7b0f96c977cc2e1f5b348030a7107d
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1261720
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1261720 (part 2) - Move ClassExtension::isWrappedNative into js::Class::flags. r=jorendorff. This saves 10 KiB of static data on 64-bit, and half that on 32-bit.
dom/base/nsGlobalWindow.cpp
dom/bindings/Codegen.py
dom/bindings/SimpleGlobalObject.cpp
dom/plugins/base/nsJSNPRuntime.cpp
js/public/Class.h
js/src/builtin/WeakMapObject.cpp
js/src/jsapi-tests/testBug604087.cpp
js/src/jsapi-tests/testWeakMap.cpp
js/src/jsfriendapi.h
js/src/proxy/Proxy.cpp
js/src/vm/ArrayBufferObject.cpp
js/src/vm/UnboxedObject.cpp
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -754,17 +754,16 @@ protected:
                     JS::Handle<JSObject*> proxy,
                     JS::Handle<jsid> id) const;
 
   bool AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
                                   JS::AutoIdVector &props) const;
 };
 
 static const js::ClassExtension OuterWindowProxyClassExtension = PROXY_MAKE_EXT(
-    false,   /* isWrappedNative */
     nsOuterWindowProxy::ObjectMoved
 );
 
 const js::Class OuterWindowProxyClass = PROXY_CLASS_WITH_EXT(
     "Proxy",
     0, /* additional class flags */
     &OuterWindowProxyClassExtension);
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -436,17 +436,16 @@ class CGDOMJSClass(CGThing):
         else:
             resolveHook = "nullptr"
             mayResolveHook = "nullptr"
             enumerateHook = "nullptr"
 
         return fill(
             """
             static const js::ClassExtension sClassExtension = {
-              false,   /* isWrappedNative */
               nullptr, /* weakmapKeyDelegateOp */
               ${objectMoved} /* objectMovedOp */
             };
 
             static const DOMJSClass sClass = {
               { "${name}",
                 ${flags},
                 ${addProperty}, /* addProperty */
@@ -505,17 +504,16 @@ class CGDOMProxyJSClass(CGThing):
         # we don't want people ever adding that to any interface other than
         # HTMLAllCollection.  So just hardcode it here.
         if self.descriptor.interface.identifier.name == "HTMLAllCollection":
             flags.append("JSCLASS_EMULATES_UNDEFINED")
         objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache else 'nullptr'
         return fill(
             """
             static const js::ClassExtension sClassExtension = PROXY_MAKE_EXT(
-                false,   /* isWrappedNative */
                 ${objectMoved}
             );
 
             static const DOMJSClass sClass = {
               PROXY_CLASS_WITH_EXT("${name}",
                                    ${flags},
                                    &sClassExtension),
               $*{descriptor}
--- a/dom/bindings/SimpleGlobalObject.cpp
+++ b/dom/bindings/SimpleGlobalObject.cpp
@@ -66,17 +66,16 @@ static void
 SimpleGlobal_moved(JSObject *obj, const JSObject *old)
 {
   SimpleGlobalObject* globalObject =
     static_cast<SimpleGlobalObject*>(JS_GetPrivate(obj));
   globalObject->UpdateWrapper(obj, old);
 }
 
 static const js::ClassExtension SimpleGlobalClassExtension = {
-  false,
   nullptr,
   SimpleGlobal_moved
 };
 
 const js::Class SimpleGlobalClass = {
     "",
     JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS,
     nullptr,
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -214,17 +214,16 @@ static bool
 NPObjWrapper_toPrimitive(JSContext *cx, unsigned argc, JS::Value *vp);
 
 static bool
 CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
                      JS::Handle<jsid> id,  NPVariant* getPropertyResult,
                      JS::MutableHandle<JS::Value> vp);
 
 const static js::ClassExtension sNPObjectJSWrapperClassExtension = {
-    false,                                                /* isWrappedNative */
     nullptr,                                              /* weakmapKeyDelegateOp */
     NPObjWrapper_ObjectMoved
 };
 
 const static js::ObjectOps sNPObjectJSWrapperObjectOps = {
     nullptr, // lookupProperty
     nullptr, // defineProperty
     nullptr, // hasProperty
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -583,22 +583,16 @@ struct ClassSpec
             return delegatedClassSpec()->finishInitHook();
         return finishInit_;
     }
 };
 
 struct ClassExtension
 {
     /**
-     * isWrappedNative is true only if the class is an XPCWrappedNative.
-     * WeakMaps use this to override the wrapper disposal optimization.
-     */
-    bool                isWrappedNative;
-
-    /**
      * If an object is used as a key in a weakmap, it may be desirable for the
      * garbage collector to keep that object around longer than it otherwise
      * would. A common case is when the key is a wrapper around an object in
      * another compartment, and we want to avoid collecting the wrapper (and
      * removing the weakmap entry) as long as the wrapped object is alive. In
      * that case, the wrapped object is returned by the wrapper's
      * weakmapKeyDelegateOp hook. As long as the wrapper is used as a weakmap
      * key, it will not be collected (and remain in the weakmap) until the
@@ -656,16 +650,20 @@ struct JSClass {
 
     void* reserved[3];
 };
 
 #define JSCLASS_HAS_PRIVATE             (1<<0)  // objects have private slot
 #define JSCLASS_DELAY_METADATA_BUILDER  (1<<1)  // class's initialization code
                                                 // will call
                                                 // SetNewObjectMetadata itself
+#define JSCLASS_IS_WRAPPED_NATIVE       (1<<2)  // class is an XPCWrappedNative.
+                                                // WeakMaps use this to override
+                                                // the wrapper disposal
+                                                // mechanism.
 #define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)  // private is (nsISupports*)
 #define JSCLASS_IS_DOMJSCLASS           (1<<4)  // objects are DOM
 #define JSCLASS_HAS_XRAYED_CONSTRUCTOR  (1<<5)  // if wrapped by an xray
                                                 // wrapper, the builtin
                                                 // class's constructor won't
                                                 // be unwrapped and invoked.
                                                 // Instead, the constructor is
                                                 // resolved in the caller's
@@ -797,16 +795,20 @@ struct Class
     bool isDOMClass() const {
         return flags & JSCLASS_IS_DOMJSCLASS;
     }
 
     bool shouldDelayMetadataBuilder() const {
         return flags & JSCLASS_DELAY_METADATA_BUILDER;
     }
 
+    bool isWrappedNative() const {
+        return flags & JSCLASS_IS_WRAPPED_NATIVE;
+    }
+
     static size_t offsetOfFlags() { return offsetof(Class, flags); }
 
     bool specDefined()         const { return spec ? spec->defined()   : false; }
     bool specDependent()       const { return spec ? spec->dependent() : false; }
     JSProtoKey specParentKey() const { return spec ? spec->parentKey() : JSProto_Null; }
     bool specShouldDefineConstructor()
                                const { return spec ? spec->shouldDefineConstructor() : true; }
     ClassObjectCreationOp specCreateConstructorHook()
@@ -819,17 +821,16 @@ struct Class
                                const { return spec ? spec->constructorProperties()   : nullptr; }
     const JSFunctionSpec* specPrototypeFunctions()
                                const { return spec ? spec->prototypeFunctions()      : nullptr; }
     const JSPropertySpec* specPrototypeProperties()
                                const { return spec ? spec->prototypeProperties()     : nullptr; }
     FinishClassInitOp specFinishInitHook()
                                const { return spec ? spec->finishInitHook()          : nullptr; }
 
-    bool extIsWrappedNative()  const { return ext ? ext->isWrappedNative             : false; }
     JSWeakmapKeyDelegateOp extWeakmapKeyDelegateOp()
                                const { return ext ? ext->weakmapKeyDelegateOp        : nullptr; }
     JSObjectMovedOp extObjectMovedOp()
                                const { return ext ? ext->objectMovedOp               : nullptr; }
 
     LookupPropertyOp getOpsLookupProperty() const { return ops ? ops->lookupProperty : nullptr; }
     DefinePropertyOp getOpsDefineProperty() const { return ops ? ops->defineProperty : nullptr; }
     HasPropertyOp    getOpsHasProperty()    const { return ops ? ops->hasProperty    : nullptr; }
--- a/js/src/builtin/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -106,18 +106,18 @@ js::WeakMap_delete(JSContext* cx, unsign
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsWeakMap, WeakMap_delete_impl>(cx, args);
 }
 
 static bool
 TryPreserveReflector(JSContext* cx, HandleObject obj)
 {
-    if (obj->getClass()->extIsWrappedNative() ||
-        (obj->getClass()->flags & JSCLASS_IS_DOMJSCLASS) ||
+    if (obj->getClass()->isWrappedNative() ||
+        obj->getClass()->isDOMClass() ||
         (obj->is<ProxyObject>() &&
          obj->as<ProxyObject>().handler()->family() == GetDOMProxyHandlerFamily()))
     {
         MOZ_ASSERT(cx->runtime()->preserveWrapperCallback);
         if (!cx->runtime()->preserveWrapperCallback(cx, obj)) {
             JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_WEAKMAP_KEY);
             return false;
         }
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -10,17 +10,16 @@
 #include "jsobj.h"
 #include "jswrapper.h"
 
 #include "jsapi-tests/tests.h"
 
 #include "vm/ProxyObject.h"
 
 static const js::ClassExtension OuterWrapperClassExtension = PROXY_MAKE_EXT(
-    false,   /* isWrappedNative */
     nullptr  /* objectMoved */
 );
 
 const js::Class OuterWrapperClass = PROXY_CLASS_WITH_EXT(
     "Proxy",
     0, /* additional class flags */
     &OuterWrapperClassExtension);
 
--- a/js/src/jsapi-tests/testWeakMap.cpp
+++ b/js/src/jsapi-tests/testWeakMap.cpp
@@ -148,17 +148,16 @@ static void DelegateObjectMoved(JSObject
 static JSObject* GetKeyDelegate(JSObject* obj)
 {
     return keyDelegate;
 }
 
 JSObject* newKey()
 {
     static const js::ClassExtension keyClassExtension = {
-        false,
         GetKeyDelegate
     };
 
     static const js::Class keyClass = {
         "keyWithDelegate",
         JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1),
         nullptr, /* addProperty */
         nullptr, /* delProperty */
@@ -204,17 +203,16 @@ JSObject* newCCW(JS::HandleObject source
             return nullptr;
     }
     return object;
 }
 
 JSObject* newDelegate()
 {
     static const js::ClassExtension delegateClassExtension = {
-        false,
         nullptr,
         DelegateObjectMoved
     };
 
     static const js::Class delegateClass = {
         "delegate",
         JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_RESERVED_SLOTS(1),
         nullptr, /* addProperty */
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -318,19 +318,18 @@ extern JS_FRIEND_DATA(const js::ClassExt
 extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
 
 /*
  * Helper Macros for creating JSClasses that function as proxies.
  *
  * NB: The macro invocation must be surrounded by braces, so as to
  *     allow for potential JSClass extensions.
  */
-#define PROXY_MAKE_EXT(isWrappedNative, objectMoved)                    \
+#define PROXY_MAKE_EXT(objectMoved)                                     \
     {                                                                   \
-        isWrappedNative,                                                \
         js::proxy_WeakmapKeyDelegate,                                   \
         objectMoved                                                     \
     }
 
 #define PROXY_CLASS_WITH_EXT(name, flags, extPtr)                                       \
     {                                                                                   \
         name,                                                                           \
         js::Class::NON_NATIVE |                                                         \
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -712,17 +712,16 @@ js::proxy_GetElements(JSContext* cx, Han
 
 JSString*
 js::proxy_FunToString(JSContext* cx, HandleObject proxy, unsigned indent)
 {
     return Proxy::fun_toString(cx, proxy, indent);
 }
 
 const ClassExtension js::ProxyClassExtension = PROXY_MAKE_EXT(
-    false,   /* isWrappedNative */
     js::proxy_ObjectMoved
 );
 
 const ObjectOps js::ProxyObjectOps = {
     js::proxy_LookupProperty,
     js::proxy_DefineProperty,
     js::proxy_HasProperty,
     js::proxy_GetProperty,
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -92,17 +92,16 @@ js::ToClampedIndex(JSContext* cx, Handle
  */
 
 const Class ArrayBufferObject::protoClass = {
     "ArrayBufferPrototype",
     JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer)
 };
 
 static const ClassExtension ArrayBufferObjectClassExtension = {
-    false,      /* isWrappedNative */
     nullptr,    /* weakmapKeyDelegateOp */
     ArrayBufferObject::objectMoved
 };
 
 const Class ArrayBufferObject::class_ = {
     "ArrayBuffer",
     JSCLASS_DELAY_METADATA_BUILDER |
     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) |
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -1587,17 +1587,16 @@ UnboxedArrayObject::obj_enumerate(JSCont
 
     if (!enumerableOnly && !properties.append(NameToId(cx->names().length)))
         return false;
 
     return true;
 }
 
 static const ClassExtension UnboxedArrayObjectClassExtension = {
-    false,      /* isWrappedNative */
     nullptr,    /* weakmapKeyDelegateOp */
     UnboxedArrayObject::objectMoved
 };
 
 static const ObjectOps UnboxedArrayObjectObjectOps = {
     UnboxedArrayObject::obj_lookupProperty,
     UnboxedArrayObject::obj_defineProperty,
     UnboxedArrayObject::obj_hasProperty,
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -546,17 +546,16 @@ sandbox_addProperty(JSContext* cx, Handl
         return false;
 
     return true;
 }
 
 #define XPCONNECT_SANDBOX_CLASS_METADATA_SLOT (XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET)
 
 static const js::ClassExtension SandboxClassExtension = {
-    false,        /* isWrappedNative */
     nullptr,      /* weakmapKeyDelegateOp */
     sandbox_moved /* objectMovedOp */
 };
 
 static const js::Class SandboxClass = {
     "Sandbox",
     XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(1),
     nullptr, nullptr, nullptr, nullptr,
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -616,24 +616,24 @@ XPC_WN_NoHelper_Resolve(JSContext* cx, H
                                  true, wrapper, wrapper, nullptr,
                                  JSPROP_ENUMERATE |
                                  JSPROP_READONLY |
                                  JSPROP_PERMANENT,
                                  resolvedp);
 }
 
 static const js::ClassExtension XPC_WN_JSClassExtension = {
-    true,    // isWrappedNative
     nullptr, // weakmapKeyDelegateOp
     WrappedNativeObjectMoved
 };
 
 const js::Class XPC_WN_NoHelper_JSClass = {
     "XPCWrappedNative_NoHelper",    // name;
     WRAPPER_FLAGS |
+    JSCLASS_IS_WRAPPED_NATIVE |
     JSCLASS_PRIVATE_IS_NSISUPPORTS, // flags
 
     /* Mandatory non-null function pointer members. */
     XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty
     XPC_WN_CantDeletePropertyStub,     // delProperty
     nullptr,                           // getProperty
     nullptr,                           // setProperty
 
@@ -972,17 +972,19 @@ XPCNativeScriptableShared::XPCNativeScri
     // Initialize the js::Class.
 
     memset(&mJSClass, 0, sizeof(mJSClass));
     mJSClass.name = aName;  // take ownership
 
     if (!aPopulate)
         return;
 
-    mJSClass.flags = WRAPPER_FLAGS | JSCLASS_PRIVATE_IS_NSISUPPORTS;
+    mJSClass.flags = WRAPPER_FLAGS |
+                     JSCLASS_PRIVATE_IS_NSISUPPORTS |
+                     JSCLASS_IS_WRAPPED_NATIVE;
 
     if (mFlags.IsGlobalObject())
         mJSClass.flags |= XPCONNECT_GLOBAL_FLAGS;
 
     JSAddPropertyOp addProperty;
     if (mFlags.WantAddProperty())
         addProperty = XPC_WN_Helper_AddProperty;
     else if (mFlags.UseJSStubForAddProperty())
@@ -1253,17 +1255,16 @@ XPC_WN_ModsAllowed_Proto_Resolve(JSConte
     return DefinePropertyIfFound(ccx, obj, id,
                                  self->GetSet(), nullptr, nullptr,
                                  self->GetScope(),
                                  true, nullptr, nullptr, si,
                                  JSPROP_ENUMERATE, resolvep);
 }
 
 static const js::ClassExtension XPC_WN_Shared_Proto_ClassExtension = {
-    false,      /* isWrappedNative */
     nullptr,    /* weakmapKeyDelegateOp */
     XPC_WN_Shared_Proto_ObjectMoved
 };
 
 const js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass = {
     "XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name;
     WRAPPER_FLAGS, // flags;
 
@@ -1483,17 +1484,16 @@ XPC_WN_TearOff_ObjectMoved(JSObject* obj
 
 // Make sure WRAPPER_FLAGS has no reserved slots, so our XPC_WN_TEAROFF_RESERVED_SLOTS value is OK.
 
 static_assert(((WRAPPER_FLAGS >> JSCLASS_RESERVED_SLOTS_SHIFT) &
                JSCLASS_RESERVED_SLOTS_MASK) == 0,
               "WRAPPER_FLAGS should not include any reserved slots");
 
 static const js::ClassExtension XPC_WN_Tearoff_JSClassExtension = {
-    false,                                 // isWrappedNative
     nullptr,                               // weakmapKeyDelegateOp
     XPC_WN_TearOff_ObjectMoved
 };
 
 const js::Class XPC_WN_Tearoff_JSClass = {
     "WrappedNative_TearOff",                   // name;
     WRAPPER_FLAGS |
     JSCLASS_HAS_RESERVED_SLOTS(XPC_WN_TEAROFF_RESERVED_SLOTS), // flags;
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -380,17 +380,17 @@ CreateGlobalObject(JSContext* cx, const 
     // The constructor automatically attaches the scope to the compartment private
     // of |global|.
     (void) new XPCWrappedNativeScope(cx, global);
 
 #ifdef DEBUG
     // Verify that the right trace hook is called. Note that this doesn't
     // work right for wrapped globals, since the tracing situation there is
     // more complicated. Manual inspection shows that they do the right thing.
-    if (!((const js::Class*)clasp)->extIsWrappedNative())
+    if (!((const js::Class*)clasp)->isWrappedNative())
     {
         VerifyTraceProtoAndIfaceCacheCalledTracer trc(JS_GetRuntime(cx));
         TraceChildren(&trc, GCCellPtr(global.get()));
         MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
     }
 #endif
 
     if (clasp->flags & JSCLASS_DOM_GLOBAL) {
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -214,17 +214,17 @@ extern const char XPC_XPCONNECT_CONTRACT
 #define WRAPPER_FLAGS JSCLASS_HAS_PRIVATE
 
 #define INVALID_OBJECT ((JSObject*)1)
 
 // If IS_WN_CLASS for the JSClass of an object is true, the object is a
 // wrappednative wrapper, holding the XPCWrappedNative in its private slot.
 static inline bool IS_WN_CLASS(const js::Class* clazz)
 {
-    return clazz->extIsWrappedNative();
+    return clazz->isWrappedNative();
 }
 
 static inline bool IS_WN_REFLECTOR(JSObject* obj)
 {
     return IS_WN_CLASS(js::GetObjectClass(obj));
 }
 
 /***************************************************************************