LCOV - code coverage report
Current view: directory - js/xpconnect/src - XPCWrappedNativeScope.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 368 281 76.4 %
Date: 2012-06-02 Functions: 46 39 84.8 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code, released
      16                 :  * March 31, 1998.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1999
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   John Bandhauer <jband@netscape.com> (original author)
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : /* Class used to manage the wrapped native objects within a JS scope. */
      41                 : 
      42                 : #include "xpcprivate.h"
      43                 : #include "XPCWrapper.h"
      44                 : #include "jsproxy.h"
      45                 : 
      46                 : /***************************************************************************/
      47                 : 
      48                 : #ifdef XPC_TRACK_SCOPE_STATS
      49                 : static int DEBUG_TotalScopeCount;
      50                 : static int DEBUG_TotalLiveScopeCount;
      51                 : static int DEBUG_TotalMaxScopeCount;
      52                 : static int DEBUG_TotalScopeTraversalCount;
      53                 : static bool    DEBUG_DumpedStats;
      54                 : #endif
      55                 : 
      56                 : #ifdef DEBUG
      57           15475 : static void DEBUG_TrackNewScope(XPCWrappedNativeScope* scope)
      58                 : {
      59                 : #ifdef XPC_TRACK_SCOPE_STATS
      60                 :     DEBUG_TotalScopeCount++;
      61                 :     DEBUG_TotalLiveScopeCount++;
      62                 :     if (DEBUG_TotalMaxScopeCount < DEBUG_TotalLiveScopeCount)
      63                 :         DEBUG_TotalMaxScopeCount = DEBUG_TotalLiveScopeCount;
      64                 : #endif
      65           15475 : }
      66                 : 
      67           15471 : static void DEBUG_TrackDeleteScope(XPCWrappedNativeScope* scope)
      68                 : {
      69                 : #ifdef XPC_TRACK_SCOPE_STATS
      70                 :     DEBUG_TotalLiveScopeCount--;
      71                 : #endif
      72           15471 : }
      73                 : 
      74           43529 : static void DEBUG_TrackScopeTraversal()
      75                 : {
      76                 : #ifdef XPC_TRACK_SCOPE_STATS
      77                 :     DEBUG_TotalScopeTraversalCount++;
      78                 : #endif
      79           43529 : }
      80                 : 
      81            1403 : static void DEBUG_TrackScopeShutdown()
      82                 : {
      83                 : #ifdef XPC_TRACK_SCOPE_STATS
      84                 :     if (!DEBUG_DumpedStats) {
      85                 :         DEBUG_DumpedStats = true;
      86                 :         printf("%d XPCWrappedNativeScope(s) were constructed.\n",
      87                 :                DEBUG_TotalScopeCount);
      88                 : 
      89                 :         printf("%d XPCWrappedNativeScopes(s) max alive at one time.\n",
      90                 :                DEBUG_TotalMaxScopeCount);
      91                 : 
      92                 :         printf("%d XPCWrappedNativeScope(s) alive now.\n" ,
      93                 :                DEBUG_TotalLiveScopeCount);
      94                 : 
      95                 :         printf("%d traversals of Scope list.\n",
      96                 :                DEBUG_TotalScopeTraversalCount);
      97                 :     }
      98                 : #endif
      99            1403 : }
     100                 : #else
     101                 : #define DEBUG_TrackNewScope(scope) ((void)0)
     102                 : #define DEBUG_TrackDeleteScope(scope) ((void)0)
     103                 : #define DEBUG_TrackScopeTraversal() ((void)0)
     104                 : #define DEBUG_TrackScopeShutdown() ((void)0)
     105                 : #endif
     106                 : 
     107                 : /***************************************************************************/
     108                 : 
     109                 : XPCWrappedNativeScope* XPCWrappedNativeScope::gScopes = nsnull;
     110                 : XPCWrappedNativeScope* XPCWrappedNativeScope::gDyingScopes = nsnull;
     111                 : 
     112                 : // static
     113                 : XPCWrappedNativeScope*
     114           15475 : XPCWrappedNativeScope::GetNewOrUsed(XPCCallContext& ccx, JSObject* aGlobal, nsISupports* aNative)
     115                 : {
     116                 : 
     117           15475 :     XPCWrappedNativeScope* scope = FindInJSObjectScope(ccx, aGlobal, true);
     118           15475 :     if (!scope)
     119           15475 :         scope = new XPCWrappedNativeScope(ccx, aGlobal, aNative);
     120                 :     else {
     121                 :         // We need to call SetGlobal in order to refresh our cached
     122                 :         // mPrototypeJSObject and to clear mPrototypeNoHelper (so we get a new
     123                 :         // new one if requested in the new scope) in the case where the global
     124                 :         // object is being reused (JS_ClearScope has been called).  NOTE: We are
     125                 :         // only called by nsXPConnect::InitClasses.
     126               0 :         scope->SetGlobal(ccx, aGlobal, aNative);
     127                 :     }
     128           15475 :     if (js::GetObjectClass(aGlobal)->flags & JSCLASS_XPCONNECT_GLOBAL)
     129                 :         JS_SetReservedSlot(aGlobal,
     130                 :                            JSCLASS_GLOBAL_SLOT_COUNT,
     131           15195 :                            PRIVATE_TO_JSVAL(scope));
     132           15475 :     return scope;
     133                 : }
     134                 : 
     135           15475 : XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx,
     136                 :                                              JSObject* aGlobal,
     137                 :                                              nsISupports* aNative)
     138           15475 :     :   mRuntime(ccx.GetRuntime()),
     139           15475 :         mWrappedNativeMap(Native2WrappedNativeMap::newMap(XPC_NATIVE_MAP_SIZE)),
     140           15475 :         mWrappedNativeProtoMap(ClassInfo2WrappedNativeProtoMap::newMap(XPC_NATIVE_PROTO_MAP_SIZE)),
     141           15475 :         mMainThreadWrappedNativeProtoMap(ClassInfo2WrappedNativeProtoMap::newMap(XPC_NATIVE_PROTO_MAP_SIZE)),
     142                 :         mComponents(nsnull),
     143                 :         mNext(nsnull),
     144                 :         mGlobalJSObject(nsnull),
     145                 :         mPrototypeJSObject(nsnull),
     146                 :         mPrototypeNoHelper(nsnull),
     147                 :         mScriptObjectPrincipal(nsnull),
     148           77375 :         mNewDOMBindingsEnabled(ccx.GetRuntime()->NewDOMBindingsEnabled())
     149                 : {
     150                 :     // add ourselves to the scopes list
     151                 :     {   // scoped lock
     152           30950 :         XPCAutoLock lock(mRuntime->GetMapLock());
     153                 : 
     154                 : #ifdef DEBUG
     155          181711 :         for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
     156          166236 :             NS_ASSERTION(aGlobal != cur->GetGlobalJSObject(), "dup object");
     157                 : #endif
     158                 : 
     159           15475 :         mNext = gScopes;
     160           15475 :         gScopes = this;
     161                 : 
     162                 :         // Grab the XPCContext associated with our context.
     163           15475 :         mContext = XPCContext::GetXPCContext(ccx.GetJSContext());
     164           15475 :         mContext->AddScope(this);
     165                 :     }
     166                 : 
     167           15475 :     if (aGlobal)
     168           15475 :         SetGlobal(ccx, aGlobal, aNative);
     169                 : 
     170           15475 :     DEBUG_TrackNewScope(this);
     171           15475 :     MOZ_COUNT_CTOR(XPCWrappedNativeScope);
     172           15475 : }
     173                 : 
     174                 : // static
     175                 : JSBool
     176               0 : XPCWrappedNativeScope::IsDyingScope(XPCWrappedNativeScope *scope)
     177                 : {
     178               0 :     for (XPCWrappedNativeScope *cur = gDyingScopes; cur; cur = cur->mNext) {
     179               0 :         if (scope == cur)
     180               0 :             return true;
     181                 :     }
     182               0 :     return false;
     183                 : }
     184                 : 
     185                 : void
     186           15475 : XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents)
     187                 : {
     188           15475 :     NS_IF_ADDREF(aComponents);
     189           15475 :     NS_IF_RELEASE(mComponents);
     190           15475 :     mComponents = aComponents;
     191           15475 : }
     192                 : 
     193                 : // Dummy JS class to let wrappers w/o an xpc prototype share
     194                 : // scopes. By doing this we avoid allocating a new scope for every
     195                 : // wrapper on creation of the wrapper, and most wrappers won't need
     196                 : // their own scope at all for the lifetime of the wrapper.
     197                 : // WRAPPER_SLOTS is key here (even though there's never anything
     198                 : // in the private data slot in these prototypes), as the number of
     199                 : // reserved slots in this class needs to match that of the wrappers
     200                 : // for the JS engine to share scopes.
     201                 : 
     202                 : js::Class XPC_WN_NoHelper_Proto_JSClass = {
     203                 :     "XPC_WN_NoHelper_Proto_JSClass",// name;
     204                 :     WRAPPER_SLOTS,                  // flags;
     205                 : 
     206                 :     /* Mandatory non-null function pointer members. */
     207                 :     JS_PropertyStub,                // addProperty;
     208                 :     JS_PropertyStub,                // delProperty;
     209                 :     JS_PropertyStub,                // getProperty;
     210                 :     JS_StrictPropertyStub,          // setProperty;
     211                 :     JS_EnumerateStub,               // enumerate;
     212                 :     JS_ResolveStub,                 // resolve;
     213                 :     JS_ConvertStub,                 // convert;
     214                 :     nsnull,                         // finalize;
     215                 : 
     216                 :     /* Optionally non-null members start here. */
     217                 :     nsnull,                         // checkAccess;
     218                 :     nsnull,                         // call;
     219                 :     nsnull,                         // construct;
     220                 :     nsnull,                         // hasInstance;
     221                 :     nsnull,                         // trace;
     222                 : 
     223                 :     JS_NULL_CLASS_EXT,
     224                 :     XPC_WN_NoCall_ObjectOps
     225                 : };
     226                 : 
     227                 : 
     228                 : void
     229           15475 : XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal,
     230                 :                                  nsISupports* aNative)
     231                 : {
     232                 :     // We allow for calling this more than once. This feature is used by
     233                 :     // nsXPConnect::InitClassesWithNewWrappedGlobal.
     234                 : 
     235           15475 :     mGlobalJSObject = aGlobal;
     236           15475 :     mScriptObjectPrincipal = nsnull;
     237                 : 
     238                 :     // Try to find the native global object. If we didn't receive it explicitly,
     239                 :     // we might be able to find it in the private slot.
     240           15475 :     nsISupports* native = aNative;
     241           17733 :     if (!native &&
     242            2258 :         !(~js::GetObjectJSClass(aGlobal)->flags & (JSCLASS_HAS_PRIVATE |
     243            2258 :                                                    JSCLASS_PRIVATE_IS_NSISUPPORTS)))
     244                 :     {
     245                 :         // Get the private. It might be a WN, in which case we dig deeper.
     246            1978 :         native = (nsISupports*)xpc_GetJSPrivate(aGlobal);
     247            3956 :         nsCOMPtr<nsIXPConnectWrappedNative> wn = do_QueryInterface(native);
     248            1978 :         if (wn)
     249               0 :             native = static_cast<XPCWrappedNative*>(native)->GetIdentityObject();
     250                 :     }
     251                 : 
     252                 :     // Now init our script object principal, if the new global has one.
     253           30950 :     nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(native);
     254           15475 :     mScriptObjectPrincipal = sop;
     255                 : 
     256                 :     // Lookup 'globalObject.Object.prototype' for our wrapper's proto
     257                 :     JSObject *objectPrototype =
     258           15475 :         JS_GetObjectPrototype(ccx.GetJSContext(), aGlobal);
     259           15475 :     if (objectPrototype)
     260           15475 :         mPrototypeJSObject = objectPrototype;
     261                 :     else
     262               0 :         NS_ERROR("Can't get globalObject.Object.prototype");
     263                 : 
     264                 :     // Clear the no helper wrapper prototype object so that a new one
     265                 :     // gets created if needed.
     266           15475 :     mPrototypeNoHelper = nsnull;
     267           15475 : }
     268                 : 
     269           46413 : XPCWrappedNativeScope::~XPCWrappedNativeScope()
     270                 : {
     271           15471 :     MOZ_COUNT_DTOR(XPCWrappedNativeScope);
     272           15471 :     DEBUG_TrackDeleteScope(this);
     273                 : 
     274                 :     // We can do additional cleanup assertions here...
     275                 : 
     276           15471 :     if (mWrappedNativeMap) {
     277           15471 :         NS_ASSERTION(0 == mWrappedNativeMap->Count(), "scope has non-empty map");
     278           15471 :         delete mWrappedNativeMap;
     279                 :     }
     280                 : 
     281           15471 :     if (mWrappedNativeProtoMap) {
     282           15471 :         NS_ASSERTION(0 == mWrappedNativeProtoMap->Count(), "scope has non-empty map");
     283           15471 :         delete mWrappedNativeProtoMap;
     284                 :     }
     285                 : 
     286           15471 :     if (mMainThreadWrappedNativeProtoMap) {
     287           15471 :         NS_ASSERTION(0 == mMainThreadWrappedNativeProtoMap->Count(), "scope has non-empty map");
     288           15471 :         delete mMainThreadWrappedNativeProtoMap;
     289                 :     }
     290                 : 
     291           15471 :     if (mContext)
     292            1639 :         mContext->RemoveScope(this);
     293                 : 
     294                 :     // XXX we should assert that we are dead or that xpconnect has shutdown
     295                 :     // XXX might not want to do this at xpconnect shutdown time???
     296           15471 :     NS_IF_RELEASE(mComponents);
     297                 : 
     298           15471 :     JSRuntime *rt = mRuntime->GetJSRuntime();
     299           15471 :     mGlobalJSObject.finalize(rt);
     300           15471 :     mPrototypeJSObject.finalize(rt);
     301           61884 : }
     302                 : 
     303                 : JSObject *
     304          882319 : XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx)
     305                 : {
     306                 :     // We could create this prototype in SetGlobal(), but all scopes
     307                 :     // don't need one, so we save ourselves a bit of space if we
     308                 :     // create these when they're needed.
     309          882319 :     if (!mPrototypeNoHelper) {
     310                 :         mPrototypeNoHelper =
     311                 :             xpc_NewSystemInheritingJSObject(ccx,
     312                 :                                             js::Jsvalify(&XPC_WN_NoHelper_Proto_JSClass),
     313                 :                                             mPrototypeJSObject,
     314           13639 :                                             false, mGlobalJSObject);
     315                 : 
     316           13639 :         NS_ASSERTION(mPrototypeNoHelper,
     317                 :                      "Failed to create prototype for wrappers w/o a helper");
     318                 :     } else {
     319          868680 :         xpc_UnmarkGrayObject(mPrototypeNoHelper);
     320                 :     }
     321                 : 
     322          882319 :     return mPrototypeNoHelper;
     323                 : }
     324                 : 
     325                 : static JSDHashOperator
     326         3488506 : WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
     327                 :                              uint32_t number, void *arg)
     328                 : {
     329         3488506 :     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
     330         3488506 :     if (wrapper->HasExternalReference() && !wrapper->IsWrapperExpired()) {
     331           14701 :         JSTracer* trc = (JSTracer *)arg;
     332           14701 :         JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObjectPreserveColor(),
     333                 :                               "XPCWrappedNative::mFlatJSObject");
     334                 :     }
     335                 : 
     336         3488506 :     return JS_DHASH_NEXT;
     337                 : }
     338                 : 
     339                 : // static
     340                 : void
     341           14728 : XPCWrappedNativeScope::TraceJS(JSTracer* trc, XPCJSRuntime* rt)
     342                 : {
     343                 :     // FIXME The lock may not be necessary during tracing as that serializes
     344                 :     // access to JS runtime. See bug 380139.
     345           29456 :     XPCAutoLock lock(rt->GetMapLock());
     346                 : 
     347                 :     // Do JS_CallTracer for all wrapped natives with external references.
     348          176270 :     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
     349          161542 :         cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingTracer, trc);
     350                 :     }
     351           14728 : }
     352                 : 
     353                 : static JSDHashOperator
     354          317990 : WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr,
     355                 :                        uint32_t number, void *arg)
     356                 : {
     357          317990 :     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
     358                 : 
     359          317990 :     if (wrapper->HasExternalReference()) {
     360                 :         nsCycleCollectionTraversalCallback *cb =
     361             190 :             static_cast<nsCycleCollectionTraversalCallback *>(arg);
     362             190 :         XPCJSRuntime::SuspectWrappedNative(wrapper, *cb);
     363                 :     }
     364                 : 
     365          317990 :     return JS_DHASH_NEXT;
     366                 : }
     367                 : 
     368                 : // static
     369                 : void
     370            1910 : XPCWrappedNativeScope::SuspectAllWrappers(XPCJSRuntime* rt,
     371                 :                                           nsCycleCollectionTraversalCallback& cb)
     372                 : {
     373            3820 :     XPCAutoLock lock(rt->GetMapLock());
     374                 : 
     375           22982 :     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
     376           21072 :         cur->mWrappedNativeMap->Enumerate(WrappedNativeSuspecter, &cb);
     377                 :     }
     378            1910 : }
     379                 : 
     380                 : // static
     381                 : void
     382           14728 : XPCWrappedNativeScope::FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt)
     383                 : {
     384                 :     // FIXME The lock may not be necessary since we are inside JSGC_MARK_END
     385                 :     // callback and GX serializes access to JS runtime. See bug 380139.
     386           29456 :     XPCAutoLock lock(rt->GetMapLock());
     387                 : 
     388                 :     // We are in JSGC_MARK_END and JSGC_FINALIZE_END must always follow it
     389                 :     // calling FinishedFinalizationPhaseOfGC and clearing gDyingScopes in
     390                 :     // KillDyingScopes.
     391           14728 :     NS_ASSERTION(gDyingScopes == nsnull,
     392                 :                  "JSGC_MARK_END without JSGC_FINALIZE_END");
     393                 : 
     394           14728 :     XPCWrappedNativeScope* prev = nsnull;
     395           14728 :     XPCWrappedNativeScope* cur = gScopes;
     396                 : 
     397          190998 :     while (cur) {
     398          161542 :         XPCWrappedNativeScope* next = cur->mNext;
     399                 : 
     400          323084 :         if (cur->mGlobalJSObject &&
     401          323084 :             JS_IsAboutToBeFinalized(cur->mGlobalJSObject)) {
     402           15447 :             cur->mGlobalJSObject.finalize(cx);
     403           15447 :             cur->mScriptObjectPrincipal = nsnull;
     404           15447 :             if (cur->GetCachedDOMPrototypes().IsInitialized())
     405             259 :                  cur->GetCachedDOMPrototypes().Clear();
     406                 :             // Move this scope from the live list to the dying list.
     407           15447 :             if (prev)
     408            4007 :                 prev->mNext = next;
     409                 :             else
     410           11440 :                 gScopes = next;
     411           15447 :             cur->mNext = gDyingScopes;
     412           15447 :             gDyingScopes = cur;
     413           15447 :             cur = nsnull;
     414                 :         } else {
     415          292190 :             if (cur->mPrototypeJSObject &&
     416          292190 :                 JS_IsAboutToBeFinalized(cur->mPrototypeJSObject)) {
     417               0 :                 cur->mPrototypeJSObject.finalize(cx);
     418                 :             }
     419          270250 :             if (cur->mPrototypeNoHelper &&
     420          124155 :                 JS_IsAboutToBeFinalized(cur->mPrototypeNoHelper)) {
     421            1898 :                 cur->mPrototypeNoHelper = nsnull;
     422                 :             }
     423                 :         }
     424          161542 :         if (cur)
     425          146095 :             prev = cur;
     426          161542 :         cur = next;
     427                 :     }
     428           14728 : }
     429                 : 
     430                 : // static
     431                 : void
     432           14728 : XPCWrappedNativeScope::FinishedFinalizationPhaseOfGC(JSContext* cx)
     433                 : {
     434           14728 :     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
     435                 : 
     436                 :     // FIXME The lock may not be necessary since we are inside
     437                 :     // JSGC_FINALIZE_END callback and at this point GC still serializes access
     438                 :     // to JS runtime. See bug 380139.
     439           29456 :     XPCAutoLock lock(rt->GetMapLock());
     440           14728 :     KillDyingScopes();
     441           14728 : }
     442                 : 
     443                 : static JSDHashOperator
     444         2233014 : WrappedNativeMarker(JSDHashTable *table, JSDHashEntryHdr *hdr,
     445                 :                     uint32_t number_t, void *arg)
     446                 : {
     447         2233014 :     ((Native2WrappedNativeMap::Entry*)hdr)->value->Mark();
     448         2233014 :     return JS_DHASH_NEXT;
     449                 : }
     450                 : 
     451                 : // We need to explicitly mark all the protos too because some protos may be
     452                 : // alive in the hashtable but not currently in use by any wrapper
     453                 : static JSDHashOperator
     454          878482 : WrappedNativeProtoMarker(JSDHashTable *table, JSDHashEntryHdr *hdr,
     455                 :                          uint32_t number, void *arg)
     456                 : {
     457          878482 :     ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value->Mark();
     458          878482 :     return JS_DHASH_NEXT;
     459                 : }
     460                 : 
     461                 : // static
     462                 : void
     463           14728 : XPCWrappedNativeScope::MarkAllWrappedNativesAndProtos()
     464                 : {
     465          160823 :     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
     466          146095 :         cur->mWrappedNativeMap->Enumerate(WrappedNativeMarker, nsnull);
     467          146095 :         cur->mWrappedNativeProtoMap->Enumerate(WrappedNativeProtoMarker, nsnull);
     468          146095 :         cur->mMainThreadWrappedNativeProtoMap->Enumerate(WrappedNativeProtoMarker, nsnull);
     469                 :     }
     470                 : 
     471           14728 :     DEBUG_TrackScopeTraversal();
     472           14728 : }
     473                 : 
     474                 : #ifdef DEBUG
     475                 : static JSDHashOperator
     476         2233014 : ASSERT_WrappedNativeSetNotMarked(JSDHashTable *table, JSDHashEntryHdr *hdr,
     477                 :                                  uint32_t number, void *arg)
     478                 : {
     479         2233014 :     ((Native2WrappedNativeMap::Entry*)hdr)->value->ASSERT_SetsNotMarked();
     480         2233014 :     return JS_DHASH_NEXT;
     481                 : }
     482                 : 
     483                 : static JSDHashOperator
     484          878482 : ASSERT_WrappedNativeProtoSetNotMarked(JSDHashTable *table, JSDHashEntryHdr *hdr,
     485                 :                                       uint32_t number, void *arg)
     486                 : {
     487          878482 :     ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value->ASSERT_SetNotMarked();
     488          878482 :     return JS_DHASH_NEXT;
     489                 : }
     490                 : 
     491                 : // static
     492                 : void
     493           14728 : XPCWrappedNativeScope::ASSERT_NoInterfaceSetsAreMarked()
     494                 : {
     495          160823 :     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
     496          146095 :         cur->mWrappedNativeMap->Enumerate(ASSERT_WrappedNativeSetNotMarked, nsnull);
     497          146095 :         cur->mWrappedNativeProtoMap->Enumerate(ASSERT_WrappedNativeProtoSetNotMarked, nsnull);
     498          146095 :         cur->mMainThreadWrappedNativeProtoMap->Enumerate(ASSERT_WrappedNativeProtoSetNotMarked, nsnull);
     499                 :     }
     500           14728 : }
     501                 : #endif
     502                 : 
     503                 : static JSDHashOperator
     504         2233014 : WrappedNativeTearoffSweeper(JSDHashTable *table, JSDHashEntryHdr *hdr,
     505                 :                             uint32_t number, void *arg)
     506                 : {
     507         2233014 :     ((Native2WrappedNativeMap::Entry*)hdr)->value->SweepTearOffs();
     508         2233014 :     return JS_DHASH_NEXT;
     509                 : }
     510                 : 
     511                 : // static
     512                 : void
     513           11922 : XPCWrappedNativeScope::SweepAllWrappedNativeTearOffs()
     514                 : {
     515          158017 :     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
     516          146095 :         cur->mWrappedNativeMap->Enumerate(WrappedNativeTearoffSweeper, nsnull);
     517                 : 
     518           11922 :     DEBUG_TrackScopeTraversal();
     519           11922 : }
     520                 : 
     521                 : // static
     522                 : void
     523           16131 : XPCWrappedNativeScope::KillDyingScopes()
     524                 : {
     525                 :     // always called inside the lock!
     526           16131 :     XPCWrappedNativeScope* cur = gDyingScopes;
     527           47733 :     while (cur) {
     528           15471 :         XPCWrappedNativeScope* next = cur->mNext;
     529           15471 :         delete cur;
     530           15471 :         cur = next;
     531                 :     }
     532           16131 :     gDyingScopes = nsnull;
     533           16131 : }
     534                 : 
     535                 : struct ShutdownData
     536                 : {
     537            1403 :     ShutdownData()
     538                 :         : wrapperCount(0),
     539            1403 :           protoCount(0) {}
     540                 :     int wrapperCount;
     541                 :     int protoCount;
     542                 : };
     543                 : 
     544                 : static JSDHashOperator
     545             781 : WrappedNativeShutdownEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
     546                 :                                 uint32_t number, void *arg)
     547                 : {
     548             781 :     ShutdownData* data = (ShutdownData*) arg;
     549             781 :     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
     550                 : 
     551             781 :     if (wrapper->IsValid()) {
     552             781 :         wrapper->SystemIsBeingShutDown();
     553             781 :         data->wrapperCount++;
     554                 :     }
     555             781 :     return JS_DHASH_REMOVE;
     556                 : }
     557                 : 
     558                 : static JSDHashOperator
     559             126 : WrappedNativeProtoShutdownEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
     560                 :                                      uint32_t number, void *arg)
     561                 : {
     562             126 :     ShutdownData* data = (ShutdownData*) arg;
     563                 :     ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value->
     564             126 :         SystemIsBeingShutDown();
     565             126 :     data->protoCount++;
     566             126 :     return JS_DHASH_REMOVE;
     567                 : }
     568                 : 
     569                 : //static
     570                 : void
     571            1403 : XPCWrappedNativeScope::SystemIsBeingShutDown()
     572                 : {
     573            1403 :     DEBUG_TrackScopeTraversal();
     574            1403 :     DEBUG_TrackScopeShutdown();
     575                 : 
     576            1403 :     int liveScopeCount = 0;
     577                 : 
     578            1403 :     ShutdownData data;
     579                 : 
     580                 :     XPCWrappedNativeScope* cur;
     581                 : 
     582                 :     // First move all the scopes to the dying list.
     583                 : 
     584            1403 :     cur = gScopes;
     585            2830 :     while (cur) {
     586              24 :         XPCWrappedNativeScope* next = cur->mNext;
     587              24 :         cur->mNext = gDyingScopes;
     588              24 :         gDyingScopes = cur;
     589              24 :         cur = next;
     590              24 :         liveScopeCount++;
     591                 :     }
     592            1403 :     gScopes = nsnull;
     593                 : 
     594                 :     // Walk the unified dying list and call shutdown on all wrappers and protos
     595                 : 
     596            1427 :     for (cur = gDyingScopes; cur; cur = cur->mNext) {
     597                 :         // Give the Components object a chance to try to clean up.
     598              24 :         if (cur->mComponents)
     599              24 :             cur->mComponents->SystemIsBeingShutDown();
     600                 : 
     601                 :         // Walk the protos first. Wrapper shutdown can leave dangling
     602                 :         // proto pointers in the proto map.
     603                 :         cur->mWrappedNativeProtoMap->
     604              24 :                 Enumerate(WrappedNativeProtoShutdownEnumerator,  &data);
     605                 :         cur->mMainThreadWrappedNativeProtoMap->
     606              24 :                 Enumerate(WrappedNativeProtoShutdownEnumerator,  &data);
     607                 :         cur->mWrappedNativeMap->
     608              24 :                 Enumerate(WrappedNativeShutdownEnumerator,  &data);
     609                 :     }
     610                 : 
     611                 :     // Now it is safe to kill all the scopes.
     612            1403 :     KillDyingScopes();
     613                 : 
     614                 : #ifdef XPC_DUMP_AT_SHUTDOWN
     615                 :     if (data.wrapperCount)
     616                 :         printf("deleting nsXPConnect  with %d live XPCWrappedNatives\n",
     617                 :                data.wrapperCount);
     618                 :     if (data.protoCount)
     619                 :         printf("deleting nsXPConnect  with %d live XPCWrappedNativeProtos\n",
     620                 :                data.protoCount);
     621                 :     if (liveScopeCount)
     622                 :         printf("deleting nsXPConnect  with %d live XPCWrappedNativeScopes\n",
     623                 :                liveScopeCount);
     624                 : #endif
     625            1403 : }
     626                 : 
     627                 : 
     628                 : /***************************************************************************/
     629                 : 
     630                 : static
     631                 : XPCWrappedNativeScope*
     632         2156634 : GetScopeOfObject(JSObject* obj)
     633                 : {
     634                 :     nsISupports* supports;
     635         2156634 :     js::Class* clazz = js::GetObjectClass(obj);
     636         2156634 :     JSBool isWrapper = IS_WRAPPER_CLASS(clazz);
     637                 : 
     638         2156634 :     if (isWrapper && IS_SLIM_WRAPPER_OBJECT(obj))
     639            7457 :         return GetSlimWrapperProto(obj)->GetScope();
     640                 : 
     641         2149177 :     if (!isWrapper || !(supports = (nsISupports*) xpc_GetJSPrivate(obj)))
     642          610714 :         return nsnull;
     643                 : 
     644                 : #ifdef DEBUG
     645                 :     {
     646         3076926 :         nsCOMPtr<nsIXPConnectWrappedNative> iface = do_QueryInterface(supports);
     647                 : 
     648         1538463 :         NS_ASSERTION(iface, "Uh, how'd this happen?");
     649                 :     }
     650                 : #endif
     651                 : 
     652                 :     // obj is one of our nsXPConnectWrappedNative objects.
     653         1538463 :     return ((XPCWrappedNative*)supports)->GetScope();
     654                 : }
     655                 : 
     656                 : 
     657                 : #ifdef DEBUG
     658               0 : void DEBUG_CheckForComponentsInScope(JSContext* cx, JSObject* obj,
     659                 :                                      JSObject* startingObj,
     660                 :                                      JSBool OKIfNotInitialized,
     661                 :                                      XPCJSRuntime* runtime)
     662                 : {
     663               0 :     if (OKIfNotInitialized)
     664               0 :         return;
     665                 : 
     666               0 :     if (!(JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS))
     667               0 :         return;
     668                 : 
     669               0 :     const char* name = runtime->GetStringName(XPCJSRuntime::IDX_COMPONENTS);
     670                 :     jsval prop;
     671               0 :     if (JS_LookupProperty(cx, obj, name, &prop) && !JSVAL_IS_PRIMITIVE(prop))
     672               0 :         return;
     673                 : 
     674                 :     // This is pretty much always bad. It usually means that native code is
     675                 :     // making a callback to an interface implemented in JavaScript, but the
     676                 :     // document where the JS object was created has already been cleared and the
     677                 :     // global properties of that document's window are *gone*. Generally this
     678                 :     // indicates a problem that should be addressed in the design and use of the
     679                 :     // callback code.
     680               0 :     NS_ERROR("XPConnect is being called on a scope without a 'Components' property!  (stack and details follow)");
     681               0 :     printf("The current JS stack is:\n");
     682               0 :     xpc_DumpJSStack(cx, true, true, true);
     683                 : 
     684               0 :     printf("And the object whose scope lacks a 'Components' property is:\n");
     685               0 :     js_DumpObject(startingObj);
     686                 : 
     687               0 :     JSObject *p = startingObj;
     688               0 :     while (js::IsWrapper(p)) {
     689               0 :         p = js::GetProxyPrivate(p).toObjectOrNull();
     690               0 :         if (!p)
     691               0 :             break;
     692               0 :         printf("which is a wrapper for:\n");
     693               0 :         js_DumpObject(p);
     694                 :     }
     695                 : }
     696                 : #else
     697                 : #define DEBUG_CheckForComponentsInScope(ccx, obj, startingObj, OKIfNotInitialized, runtime) \
     698                 :     ((void)0)
     699                 : #endif
     700                 : 
     701                 : // static
     702                 : XPCWrappedNativeScope*
     703         2156634 : XPCWrappedNativeScope::FindInJSObjectScope(JSContext* cx, JSObject* obj,
     704                 :                                            JSBool OKIfNotInitialized,
     705                 :                                            XPCJSRuntime* runtime)
     706                 : {
     707                 :     XPCWrappedNativeScope* scope;
     708                 : 
     709         2156634 :     if (!obj)
     710               0 :         return nsnull;
     711                 : 
     712                 :     // If this object is itself a wrapped native then we can get the
     713                 :     // scope directly.
     714                 : 
     715         2156634 :     scope = GetScopeOfObject(obj);
     716         2156634 :     if (scope)
     717         1545920 :         return scope;
     718                 : 
     719                 :     // Else we'll have to look up the parent chain to get the scope
     720                 : 
     721         1221428 :     JSAutoEnterCompartment ac;
     722          610714 :     ac.enterAndIgnoreErrors(cx, obj);
     723                 : 
     724                 : #ifdef DEBUG
     725          610714 :     JSObject *startingObj = obj;
     726                 : #endif
     727                 : 
     728          610714 :     obj = JS_GetGlobalForObject(cx, obj);
     729                 : 
     730          610714 :     if (js::GetObjectClass(obj)->flags & JSCLASS_XPCONNECT_GLOBAL) {
     731          610434 :         scope = XPCWrappedNativeScope::GetNativeScope(obj);
     732          610434 :         if (scope)
     733          595239 :             return scope;
     734                 :     }
     735                 : 
     736           15475 :     if (!runtime) {
     737               0 :         runtime = nsXPConnect::GetRuntimeInstance();
     738               0 :         NS_ASSERTION(runtime, "This should never be null!");
     739                 :     }
     740                 : 
     741                 :     // XXX We are assuming that the scope count is low enough that traversing
     742                 :     // the linked list is more reasonable then doing a hashtable lookup.
     743           15475 :     XPCWrappedNativeScope* found = nsnull;
     744                 :     {   // scoped lock
     745           30950 :         XPCAutoLock lock(runtime->GetMapLock());
     746                 : 
     747           15475 :         DEBUG_TrackScopeTraversal();
     748                 : 
     749          181711 :         for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
     750          166236 :             if (obj == cur->GetGlobalJSObject()) {
     751               0 :                 found = cur;
     752               0 :                 break;
     753                 :             }
     754                 :         }
     755                 :     }
     756                 : 
     757           15475 :     if (found) {
     758                 :         // This cannot be called within the map lock!
     759                 :         DEBUG_CheckForComponentsInScope(cx, obj, startingObj,
     760               0 :                                         OKIfNotInitialized, runtime);
     761               0 :         return found;
     762                 :     }
     763                 : 
     764                 :     // Failure to find the scope is only OK if the caller told us it might fail.
     765                 :     // This flag would only be set in the call from
     766                 :     // XPCWrappedNativeScope::GetNewOrUsed
     767           15475 :     NS_ASSERTION(OKIfNotInitialized, "No scope has this global object!");
     768           15475 :     return nsnull;
     769                 : }
     770                 : 
     771                 : /***************************************************************************/
     772                 : 
     773                 : static JSDHashOperator
     774              50 : WNProtoSecPolicyClearer(JSDHashTable *table, JSDHashEntryHdr *hdr,
     775                 :                         uint32_t number, void *arg)
     776                 : {
     777                 :     XPCWrappedNativeProto* proto =
     778              50 :         ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value;
     779              50 :     *(proto->GetSecurityInfoAddr()) = nsnull;
     780              50 :     return JS_DHASH_NEXT;
     781                 : }
     782                 : 
     783                 : // static
     784                 : nsresult
     785               1 : XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(XPCCallContext& ccx)
     786                 : {
     787                 :     // Hold the lock throughout.
     788               2 :     XPCAutoLock lock(ccx.GetRuntime()->GetMapLock());
     789                 : 
     790               7 :     for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
     791               6 :         cur->mWrappedNativeProtoMap->Enumerate(WNProtoSecPolicyClearer, nsnull);
     792               6 :         cur->mMainThreadWrappedNativeProtoMap->Enumerate(WNProtoSecPolicyClearer, nsnull);
     793                 :     }
     794                 : 
     795               1 :     DEBUG_TrackScopeTraversal();
     796                 : 
     797               1 :     return NS_OK;
     798                 : }
     799                 : 
     800                 : static JSDHashOperator
     801               0 : WNProtoRemover(JSDHashTable *table, JSDHashEntryHdr *hdr,
     802                 :                uint32_t number, void *arg)
     803                 : {
     804               0 :     XPCWrappedNativeProtoMap* detachedMap = (XPCWrappedNativeProtoMap*)arg;
     805                 : 
     806                 :     XPCWrappedNativeProto* proto = (XPCWrappedNativeProto*)
     807               0 :         ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value;
     808                 : 
     809               0 :     detachedMap->Add(proto);
     810                 : 
     811               0 :     return JS_DHASH_REMOVE;
     812                 : }
     813                 : 
     814                 : void
     815            2258 : XPCWrappedNativeScope::RemoveWrappedNativeProtos()
     816                 : {
     817            4516 :     XPCAutoLock al(mRuntime->GetMapLock());
     818                 : 
     819                 :     mWrappedNativeProtoMap->Enumerate(WNProtoRemover,
     820            2258 :                                       GetRuntime()->GetDetachedWrappedNativeProtoMap());
     821                 :     mMainThreadWrappedNativeProtoMap->Enumerate(WNProtoRemover,
     822            2258 :                                                 GetRuntime()->GetDetachedWrappedNativeProtoMap());
     823            2258 : }
     824                 : 
     825                 : static PLDHashOperator
     826            2062 : TraceDOMPrototype(const char* aKey, JSObject* aData, void* aClosure)
     827                 : {
     828            2062 :     JSTracer *trc = static_cast<JSTracer*>(aClosure);
     829            2062 :     JS_CALL_OBJECT_TRACER(trc, aData, "DOM prototype");
     830            2062 :     return PL_DHASH_NEXT;
     831                 : }
     832                 : 
     833                 : void
     834          147064 : XPCWrappedNativeScope::TraceDOMPrototypes(JSTracer *trc)
     835                 : {
     836          147064 :     if (mCachedDOMPrototypes.IsInitialized()) {
     837            1935 :         mCachedDOMPrototypes.EnumerateRead(TraceDOMPrototype, trc);
     838                 :     }
     839          147064 : }
     840                 : 
     841                 : /***************************************************************************/
     842                 : 
     843                 : // static
     844                 : void
     845               0 : XPCWrappedNativeScope::DebugDumpAllScopes(PRInt16 depth)
     846                 : {
     847                 : #ifdef DEBUG
     848               0 :     depth-- ;
     849                 : 
     850                 :     // get scope count.
     851               0 :     int count = 0;
     852                 :     XPCWrappedNativeScope* cur;
     853               0 :     for (cur = gScopes; cur; cur = cur->mNext)
     854               0 :         count++ ;
     855                 : 
     856               0 :     XPC_LOG_ALWAYS(("chain of %d XPCWrappedNativeScope(s)", count));
     857               0 :     XPC_LOG_INDENT();
     858               0 :         XPC_LOG_ALWAYS(("gDyingScopes @ %x", gDyingScopes));
     859               0 :         if (depth)
     860               0 :             for (cur = gScopes; cur; cur = cur->mNext)
     861               0 :                 cur->DebugDump(depth);
     862               0 :     XPC_LOG_OUTDENT();
     863                 : #endif
     864               0 : }
     865                 : 
     866                 : #ifdef DEBUG
     867                 : static JSDHashOperator
     868               0 : WrappedNativeMapDumpEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
     869                 :                                uint32_t number, void *arg)
     870                 : {
     871               0 :     ((Native2WrappedNativeMap::Entry*)hdr)->value->DebugDump(*(PRInt16*)arg);
     872               0 :     return JS_DHASH_NEXT;
     873                 : }
     874                 : static JSDHashOperator
     875               0 : WrappedNativeProtoMapDumpEnumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
     876                 :                                     uint32_t number, void *arg)
     877                 : {
     878               0 :     ((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value->DebugDump(*(PRInt16*)arg);
     879               0 :     return JS_DHASH_NEXT;
     880                 : }
     881                 : #endif
     882                 : 
     883                 : void
     884               0 : XPCWrappedNativeScope::DebugDump(PRInt16 depth)
     885                 : {
     886                 : #ifdef DEBUG
     887               0 :     depth-- ;
     888               0 :     XPC_LOG_ALWAYS(("XPCWrappedNativeScope @ %x", this));
     889               0 :     XPC_LOG_INDENT();
     890               0 :         XPC_LOG_ALWAYS(("mRuntime @ %x", mRuntime));
     891               0 :         XPC_LOG_ALWAYS(("mNext @ %x", mNext));
     892               0 :         XPC_LOG_ALWAYS(("mComponents @ %x", mComponents));
     893               0 :         XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject.get()));
     894               0 :         XPC_LOG_ALWAYS(("mPrototypeJSObject @ %x", mPrototypeJSObject.get()));
     895               0 :         XPC_LOG_ALWAYS(("mPrototypeNoHelper @ %x", mPrototypeNoHelper));
     896                 : 
     897               0 :         XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)",         \
     898                 :                         mWrappedNativeMap,                                    \
     899                 :                         mWrappedNativeMap ? mWrappedNativeMap->Count() : 0));
     900                 :         // iterate contexts...
     901               0 :         if (depth && mWrappedNativeMap && mWrappedNativeMap->Count()) {
     902               0 :             XPC_LOG_INDENT();
     903               0 :             mWrappedNativeMap->Enumerate(WrappedNativeMapDumpEnumerator, &depth);
     904               0 :             XPC_LOG_OUTDENT();
     905                 :         }
     906                 : 
     907               0 :         XPC_LOG_ALWAYS(("mWrappedNativeProtoMap @ %x with %d protos(s)",      \
     908                 :                         mWrappedNativeProtoMap,                               \
     909                 :                         mWrappedNativeProtoMap ? mWrappedNativeProtoMap->Count() : 0));
     910                 :         // iterate contexts...
     911               0 :         if (depth && mWrappedNativeProtoMap && mWrappedNativeProtoMap->Count()) {
     912               0 :             XPC_LOG_INDENT();
     913               0 :             mWrappedNativeProtoMap->Enumerate(WrappedNativeProtoMapDumpEnumerator, &depth);
     914               0 :             XPC_LOG_OUTDENT();
     915                 :         }
     916                 : 
     917               0 :         XPC_LOG_ALWAYS(("mMainThreadWrappedNativeProtoMap @ %x with %d protos(s)", \
     918                 :                         mMainThreadWrappedNativeProtoMap,                     \
     919                 :                         mMainThreadWrappedNativeProtoMap ? mMainThreadWrappedNativeProtoMap->Count() : 0));
     920                 :         // iterate contexts...
     921               0 :         if (depth && mMainThreadWrappedNativeProtoMap && mMainThreadWrappedNativeProtoMap->Count()) {
     922               0 :             XPC_LOG_INDENT();
     923               0 :             mMainThreadWrappedNativeProtoMap->Enumerate(WrappedNativeProtoMapDumpEnumerator, &depth);
     924               0 :             XPC_LOG_OUTDENT();
     925                 :         }
     926               0 :     XPC_LOG_OUTDENT();
     927                 : #endif
     928               0 : }
     929                 : 
     930                 : size_t
     931               3 : XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(nsMallocSizeOfFun mallocSizeOf)
     932                 : {
     933               3 :     XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
     934               6 :     XPCAutoLock lock(rt->GetMapLock());
     935                 : 
     936               3 :     size_t n = 0;
     937              62 :     for (XPCWrappedNativeScope *cur = gScopes; cur; cur = cur->mNext) {
     938              59 :         n += cur->SizeOfIncludingThis(mallocSizeOf);
     939                 :     }
     940               3 :     return n;
     941                 : }
     942                 : 
     943                 : size_t
     944              59 : XPCWrappedNativeScope::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
     945                 : {
     946              59 :     size_t n = 0;
     947              59 :     n += mallocSizeOf(this);
     948              59 :     n += mWrappedNativeMap->SizeOfIncludingThis(mallocSizeOf);
     949              59 :     n += mWrappedNativeProtoMap->SizeOfIncludingThis(mallocSizeOf);
     950              59 :     n += mMainThreadWrappedNativeProtoMap->SizeOfIncludingThis(mallocSizeOf);
     951                 : 
     952                 :     // There are other XPCWrappedNativeScope members that could be measured;
     953                 :     // the above ones have been seen by DMD to be worth measuring.  More stuff
     954                 :     // may be added later.
     955                 : 
     956              59 :     return n;
     957                 : }
     958                 : 
     959                 : 

Generated by: LCOV version 1.7