Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes
XPCJSRuntime Class Reference

#include <xpcprivate.h>

Collaboration diagram for XPCJSRuntime:
Collaboration graph
[legend]

List of all members.

Public Types

enum  {
  IDX_CONSTRUCTOR = 0, IDX_TO_STRING, IDX_TO_SOURCE, IDX_LAST_RESULT,
  IDX_RETURN_CODE, IDX_VALUE, IDX_QUERY_INTERFACE, IDX_COMPONENTS,
  IDX_WRAPPED_JSOBJECT, IDX_OBJECT, IDX_FUNCTION, IDX_PROTOTYPE,
  IDX_CREATE_INSTANCE, IDX_ITEM, IDX_TOTAL_COUNT
}

Public Member Functions

JSRuntimeGetJSRuntime () const
nsXPConnectGetXPConnect () const
nsIJSRuntimeServiceGetJSRuntimeService () const
JSObject2WrappedJSMapGetWrappedJSMap () const
IID2WrappedJSClassMapGetWrappedJSClassMap () const
IID2NativeInterfaceMapGetIID2NativeInterfaceMap () const
ClassInfo2NativeSetMapGetClassInfo2NativeSetMap () const
NativeSetMapGetNativeSetMap () const
IID2ThisTranslatorMapGetThisTranslatorMap () const
XPCNativeScriptableSharedMapGetNativeScriptableSharedMap () const
XPCWrappedNativeProtoMapGetDyingWrappedNativeProtoMap () const
XPCWrappedNativeProtoMapGetDetachedWrappedNativeProtoMap () const
XPCNativeWrapperMapGetExplicitNativeWrapperMap () const
XPCLockGetMapLock () const
XPCContextGetXPCContext (JSContext *cx)
XPCContextSyncXPCContextList (JSContext *cx=nsnull)
JSBool GetMainThreadOnlyGC () const
void SetMainThreadOnlyGC (JSBool b)
JSBool GetDeferReleases () const
void SetDeferReleases (JSBool b)
JSBool DeferredRelease (nsISupports *obj)
JSBool GetDoingFinalization () const
jsid GetStringID (uintN index) const
jsval GetStringJSVal (uintN index) const
const char * GetStringName (uintN index) const
void DebugDump (PRInt16 depth)
void SystemIsBeingShutDown (XPCCallContext *ccx)
PRThreadGetThreadRunningGC () const
 ~XPCJSRuntime ()

Static Public Member Functions

static XPCJSRuntimenewXPCJSRuntime (nsXPConnect *aXPConnect, nsIJSRuntimeService *aJSRuntimeService)
static JSBool JS_DLL_CALLBACK GCCallback (JSContext *cx, JSGCStatus status)

Private Member Functions

 XPCJSRuntime ()
 XPCJSRuntime (nsXPConnect *aXPConnect, nsIJSRuntimeService *aJSRuntimeService)
JSContext2XPCContextMapGetContextMap () const
JSBool GenerateStringIDs (JSContext *cx)
void PurgeXPCContextList ()

Private Attributes

jsid mStrIDs [IDX_TOTAL_COUNT]
jsval mStrJSVals [IDX_TOTAL_COUNT]
nsXPConnectmXPConnect
JSRuntimemJSRuntime
nsIJSRuntimeServicemJSRuntimeService
JSContext2XPCContextMapmContextMap
JSObject2WrappedJSMapmWrappedJSMap
IID2WrappedJSClassMapmWrappedJSClassMap
IID2NativeInterfaceMapmIID2NativeInterfaceMap
ClassInfo2NativeSetMapmClassInfo2NativeSetMap
NativeSetMapmNativeSetMap
IID2ThisTranslatorMapmThisTranslatorMap
XPCNativeScriptableSharedMapmNativeScriptableSharedMap
XPCWrappedNativeProtoMapmDyingWrappedNativeProtoMap
XPCWrappedNativeProtoMapmDetachedWrappedNativeProtoMap
XPCNativeWrapperMapmExplicitNativeWrapperMap
XPCLockmMapLock
PRThreadmThreadRunningGC
nsVoidArray mWrappedJSToReleaseArray
nsVoidArray mNativesToReleaseArray
JSBool mMainThreadOnlyGC
JSBool mDeferReleases
JSBool mDoingFinalization

Static Private Attributes

static const char * mStrings [IDX_TOTAL_COUNT]

Detailed Description

Definition at line 520 of file xpcprivate.h.


Member Enumeration Documentation

anonymous enum
Enumerator:
IDX_CONSTRUCTOR 
IDX_TO_STRING 
IDX_TO_SOURCE 
IDX_LAST_RESULT 
IDX_RETURN_CODE 
IDX_VALUE 
IDX_QUERY_INTERFACE 
IDX_COMPONENTS 
IDX_WRAPPED_JSOBJECT 
IDX_OBJECT 
IDX_FUNCTION 
IDX_PROTOTYPE 
IDX_CREATE_INSTANCE 
IDX_ITEM 
IDX_TOTAL_COUNT 

Definition at line 584 of file xpcprivate.h.

         {
        IDX_CONSTRUCTOR             = 0 ,
        IDX_TO_STRING               ,
        IDX_TO_SOURCE               ,
        IDX_LAST_RESULT             ,
        IDX_RETURN_CODE             ,
        IDX_VALUE                   ,
        IDX_QUERY_INTERFACE         ,
        IDX_COMPONENTS              ,
        IDX_WRAPPED_JSOBJECT        ,
        IDX_OBJECT                  ,
        IDX_FUNCTION                ,
        IDX_PROTOTYPE               ,
        IDX_CREATE_INSTANCE         ,
        IDX_ITEM                    ,
#ifdef XPC_IDISPATCH_SUPPORT
        IDX_ACTIVEX_OBJECT          ,
        IDX_COM_OBJECT              ,
        IDX_ACTIVEX_SUPPORTS        ,
#endif
        IDX_TOTAL_COUNT // just a count of the above
    };

Constructor & Destructor Documentation

Definition at line 648 of file xpcjsruntime.cpp.

{
#ifdef XPC_DUMP_AT_SHUTDOWN
    {
    // count the total JSContexts in use
    JSContext* iter = nsnull;
    int count = 0;
    while(JS_ContextIterator(mJSRuntime, &iter))
        count ++;
    if(count)
        printf("deleting XPCJSRuntime with %d live JSContexts\n", count);
    }
#endif

    // clean up and destroy maps...

    if(mContextMap)
    {
        PurgeXPCContextList();
        delete mContextMap;
    }

    if(mWrappedJSMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mWrappedJSMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live wrapped JSObject\n", (int)count);
#endif
        mWrappedJSMap->Enumerate(WrappedJSShutdownMarker, mJSRuntime);
        delete mWrappedJSMap;
    }

    if(mWrappedJSClassMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mWrappedJSClassMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live nsXPCWrappedJSClass\n", (int)count);
#endif
        delete mWrappedJSClassMap;
    }

    if(mIID2NativeInterfaceMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mIID2NativeInterfaceMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live XPCNativeInterfaces\n", (int)count);
#endif
        delete mIID2NativeInterfaceMap;
    }

    if(mClassInfo2NativeSetMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mClassInfo2NativeSetMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live XPCNativeSets\n", (int)count);
#endif
        delete mClassInfo2NativeSetMap;
    }

    if(mNativeSetMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mNativeSetMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live XPCNativeSets\n", (int)count);
#endif
        delete mNativeSetMap;
    }

    if(mMapLock)
        XPCAutoLock::DestroyLock(mMapLock);
    NS_IF_RELEASE(mJSRuntimeService);

    if(mThisTranslatorMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mThisTranslatorMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live ThisTranslator\n", (int)count);
#endif
        delete mThisTranslatorMap;
    }

#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
    if(DEBUG_WrappedNativeHashtable)
    {
        int LiveWrapperCount = 0;
        JS_DHashTableEnumerate(DEBUG_WrappedNativeHashtable,
                               DEBUG_WrapperChecker, &LiveWrapperCount);
        if(LiveWrapperCount)
            printf("deleting XPCJSRuntime with %d live XPCWrappedNative (found in wrapper check)\n", (int)LiveWrapperCount);
        JS_DHashTableDestroy(DEBUG_WrappedNativeHashtable);
    }
#endif

    if(mNativeScriptableSharedMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mNativeScriptableSharedMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live XPCNativeScriptableShared\n", (int)count);
#endif
        delete mNativeScriptableSharedMap;
    }

    if(mDyingWrappedNativeProtoMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mDyingWrappedNativeProtoMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live but dying XPCWrappedNativeProto\n", (int)count);
#endif
        delete mDyingWrappedNativeProtoMap;
    }

    if(mDetachedWrappedNativeProtoMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mDetachedWrappedNativeProtoMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live detached XPCWrappedNativeProto\n", (int)count);
#endif
        delete mDetachedWrappedNativeProtoMap;
    }

    if(mExplicitNativeWrapperMap)
    {
#ifdef XPC_DUMP_AT_SHUTDOWN
        uint32 count = mExplicitNativeWrapperMap->Count();
        if(count)
            printf("deleting XPCJSRuntime with %d live explicit XPCNativeWrapper\n", (int)count);
#endif
        delete mExplicitNativeWrapperMap;
    }

    // unwire the readable/JSString sharing magic
    XPCStringConvert::ShutdownDOMStringFinalizer();

    XPCConvert::RemoveXPCOMUCStringFinalizer();

    gOldJSGCCallback = NULL;
    gOldJSContextCallback = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

XPCJSRuntime::XPCJSRuntime ( nsXPConnect aXPConnect,
nsIJSRuntimeService aJSRuntimeService 
) [private]

Definition at line 796 of file xpcjsruntime.cpp.

 : mXPConnect(aXPConnect),
   mJSRuntime(nsnull),
   mJSRuntimeService(aJSRuntimeService),
   mContextMap(JSContext2XPCContextMap::newMap(XPC_CONTEXT_MAP_SIZE)),
   mWrappedJSMap(JSObject2WrappedJSMap::newMap(XPC_JS_MAP_SIZE)),
   mWrappedJSClassMap(IID2WrappedJSClassMap::newMap(XPC_JS_CLASS_MAP_SIZE)),
   mIID2NativeInterfaceMap(IID2NativeInterfaceMap::newMap(XPC_NATIVE_INTERFACE_MAP_SIZE)),
   mClassInfo2NativeSetMap(ClassInfo2NativeSetMap::newMap(XPC_NATIVE_SET_MAP_SIZE)),
   mNativeSetMap(NativeSetMap::newMap(XPC_NATIVE_SET_MAP_SIZE)),
   mThisTranslatorMap(IID2ThisTranslatorMap::newMap(XPC_THIS_TRANSLATOR_MAP_SIZE)),
   mNativeScriptableSharedMap(XPCNativeScriptableSharedMap::newMap(XPC_NATIVE_JSCLASS_MAP_SIZE)),
   mDyingWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DYING_NATIVE_PROTO_MAP_SIZE)),
   mDetachedWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DETACHED_NATIVE_PROTO_MAP_SIZE)),
   mExplicitNativeWrapperMap(XPCNativeWrapperMap::newMap(XPC_NATIVE_WRAPPER_MAP_SIZE)),
   mMapLock(XPCAutoLock::NewLock("XPCJSRuntime::mMapLock")),
   mThreadRunningGC(nsnull),
   mWrappedJSToReleaseArray(),
   mNativesToReleaseArray(),
   mMainThreadOnlyGC(JS_FALSE),
   mDeferReleases(JS_FALSE),
   mDoingFinalization(JS_FALSE)
{
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
    DEBUG_WrappedNativeHashtable =
        JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
                         sizeof(JSDHashEntryStub), 128);
#endif

    // these jsids filled in later when we have a JSContext to work with.
    mStrIDs[0] = 0;

    if(mJSRuntimeService)
    {
        NS_ADDREF(mJSRuntimeService);
        mJSRuntimeService->GetRuntime(&mJSRuntime);
    }

    NS_ASSERTION(!gOldJSGCCallback, "XPCJSRuntime created more than once");
    if(mJSRuntime)
    {
        gOldJSContextCallback = JS_SetContextCallback(mJSRuntime,
                                                      ContextCallback);
        gOldJSGCCallback = JS_SetGCCallbackRT(mJSRuntime, GCCallback);
    }

    // Install a JavaScript 'debugger' keyword handler in debug builds only
#ifdef DEBUG
    if(mJSRuntime && !mJSRuntime->debuggerHandler)
        xpc_InstallJSDebuggerKeywordHandler(mJSRuntime);
#endif
}

Here is the call graph for this function:


Member Function Documentation

Definition at line 1056 of file xpcjsruntime.cpp.

{
#ifdef DEBUG
    depth--;
    XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", this));
        XPC_LOG_INDENT();
        XPC_LOG_ALWAYS(("mXPConnect @ %x", mXPConnect));
        XPC_LOG_ALWAYS(("mJSRuntime @ %x", mJSRuntime));
        XPC_LOG_ALWAYS(("mMapLock @ %x", mMapLock));
        XPC_LOG_ALWAYS(("mJSRuntimeService @ %x", mJSRuntimeService));

        XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)", \
                         &mWrappedJSToReleaseArray,
                         mWrappedJSToReleaseArray.Count()));

        XPC_LOG_ALWAYS(("mContextMap @ %x with %d context(s)", \
                         mContextMap, mContextMap ? mContextMap->Count() : 0));
        // iterate contexts...
        if(depth && mContextMap && mContextMap->Count())
        {
            XPC_LOG_INDENT();
            mContextMap->Enumerate(ContextMapDumpEnumerator, &depth);
            XPC_LOG_OUTDENT();
        }

        XPC_LOG_ALWAYS(("mWrappedJSClassMap @ %x with %d wrapperclasses(s)", \
                         mWrappedJSClassMap, mWrappedJSClassMap ? \
                                            mWrappedJSClassMap->Count() : 0));
        // iterate wrappersclasses...
        if(depth && mWrappedJSClassMap && mWrappedJSClassMap->Count())
        {
            XPC_LOG_INDENT();
            mWrappedJSClassMap->Enumerate(WrappedJSClassMapDumpEnumerator, &depth);
            XPC_LOG_OUTDENT();
        }
        XPC_LOG_ALWAYS(("mWrappedJSMap @ %x with %d wrappers(s)", \
                         mWrappedJSMap, mWrappedJSMap ? \
                                            mWrappedJSMap->Count() : 0));
        // iterate wrappers...
        if(depth && mWrappedJSMap && mWrappedJSMap->Count())
        {
            XPC_LOG_INDENT();
            mWrappedJSMap->Enumerate(WrappedJSMapDumpEnumerator, &depth);
            XPC_LOG_OUTDENT();
        }

        XPC_LOG_ALWAYS(("mIID2NativeInterfaceMap @ %x with %d interface(s)", \
                         mIID2NativeInterfaceMap, mIID2NativeInterfaceMap ? \
                                    mIID2NativeInterfaceMap->Count() : 0));

        XPC_LOG_ALWAYS(("mClassInfo2NativeSetMap @ %x with %d sets(s)", \
                         mClassInfo2NativeSetMap, mClassInfo2NativeSetMap ? \
                                    mClassInfo2NativeSetMap->Count() : 0));

        XPC_LOG_ALWAYS(("mThisTranslatorMap @ %x with %d translator(s)", \
                         mThisTranslatorMap, mThisTranslatorMap ? \
                                    mThisTranslatorMap->Count() : 0));

        XPC_LOG_ALWAYS(("mNativeSetMap @ %x with %d sets(s)", \
                         mNativeSetMap, mNativeSetMap ? \
                                    mNativeSetMap->Count() : 0));

        // iterate sets...
        if(depth && mNativeSetMap && mNativeSetMap->Count())
        {
            XPC_LOG_INDENT();
            mNativeSetMap->Enumerate(NativeSetDumpEnumerator, &depth);
            XPC_LOG_OUTDENT();
        }

        XPC_LOG_OUTDENT();
#endif
}

Here is the call graph for this function:

JSBool XPCJSRuntime::DeferredRelease ( nsISupports *  obj)

Definition at line 1003 of file xpcjsruntime.cpp.

{
    NS_ASSERTION(obj, "bad param");
    NS_ASSERTION(GetDeferReleases(), "bad call");

    XPCLock* lock = GetMainThreadOnlyGC() ? nsnull : GetMapLock();
    {
        XPCAutoLock al(lock); // lock if necessary
        if(!mNativesToReleaseArray.Count())
        {
            // This array sometimes has 1000's
            // of entries, and usually has 50-200 entries. Avoid lots
            // of incremental grows.  We compact it down when we're done.
            mNativesToReleaseArray.SizeTo(256);
        }
        return mNativesToReleaseArray.AppendElement(obj);
    }        
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool XPCJSRuntime::GCCallback ( JSContext cx,
JSGCStatus  status 
) [static]

Definition at line 253 of file xpcjsruntime.cpp.

{
    nsVoidArray* dyingWrappedJSArray;

    XPCJSRuntime* self = nsXPConnect::GetRuntime();
    if(self)
    {
        switch(status)
        {
            case JSGC_BEGIN:
            {
                if(self->GetMainThreadOnlyGC() &&
                   PR_GetCurrentThread() != nsXPConnect::GetMainThread())
                {
                    return JS_FALSE;
                }
                break;
            }
            case JSGC_MARK_END:
            {
                NS_ASSERTION(!self->mDoingFinalization, "bad state");
    
                // mThreadRunningGC indicates that GC is running
                { // scoped lock
                    XPCAutoLock lock(self->GetMapLock());
                    NS_ASSERTION(!self->mThreadRunningGC, "bad state");
                    self->mThreadRunningGC = PR_GetCurrentThread();
                }

                // Skip this part if XPConnect is shutting down. We get into
                // bad locking problems with the thread iteration otherwise.
                if(!self->GetXPConnect()->IsShuttingDown())
                {
                    PRLock* threadLock = XPCPerThreadData::GetLock();
                    if(threadLock)
                    { // scoped lock
                        nsAutoLock lock(threadLock);

                        XPCPerThreadData* iterp = nsnull;
                        XPCPerThreadData* thread;

                        while(nsnull != (thread =
                                     XPCPerThreadData::IterateThreads(&iterp)))
                        {
                            // Mark those AutoMarkingPtr lists!
                            thread->MarkAutoRootsBeforeJSFinalize(cx);
                        }
                    }
                }

                dyingWrappedJSArray = &self->mWrappedJSToReleaseArray;
                {
                    XPCLock* lock = self->GetMainThreadOnlyGC() ?
                                    nsnull : self->GetMapLock();

                    XPCAutoLock al(lock); // lock the wrapper map if necessary
                    JSDyingJSObjectData data = {cx, dyingWrappedJSArray};

                    // Add any wrappers whose JSObjects are to be finalized to
                    // this array. Note that this is a nsVoidArray because
                    // we do not want to be changing the refcount of these wrappers.
                    // We add them to the array now and Release the array members
                    // later to avoid the posibility of doing any JS GCThing
                    // allocations during the gc cycle.
                    self->mWrappedJSMap->
                        Enumerate(WrappedJSDyingJSObjectFinder, &data);
                }

                // Do cleanup in NativeInterfaces. This part just finds 
                // member cloned function objects that are about to be 
                // collected. It does not deal with collection of interfaces or
                // sets at this point.
                CX_AND_XPCRT_Data data = {cx, self};

                self->mIID2NativeInterfaceMap->
                    Enumerate(NativeInterfaceGC, &data);

                // Find dying scopes...
                XPCWrappedNativeScope::FinishedMarkPhaseOfGC(cx, self);

                self->mDoingFinalization = JS_TRUE;
                break;
            }
            case JSGC_FINALIZE_END:
            {
                NS_ASSERTION(self->mDoingFinalization, "bad state");
                self->mDoingFinalization = JS_FALSE;

                // Release all the members whose JSObjects are now known
                // to be dead.

                dyingWrappedJSArray = &self->mWrappedJSToReleaseArray;
                XPCLock* mapLock = self->GetMainThreadOnlyGC() ?
                                   nsnull : self->GetMapLock();
                while(1)
                {
                    nsXPCWrappedJS* wrapper;
                    {
                        XPCAutoLock al(mapLock); // lock if necessary
                        PRInt32 count = dyingWrappedJSArray->Count();
                        if(!count)
                        {
                            dyingWrappedJSArray->Compact();
                            break;
                        }
                        wrapper = NS_STATIC_CAST(nsXPCWrappedJS*,
                                    dyingWrappedJSArray->ElementAt(count-1));
                        dyingWrappedJSArray->RemoveElementAt(count-1);
                    }
                    NS_RELEASE(wrapper);
                }


#ifdef XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING
                printf("--------------------------------------------------------------\n");
                int setsBefore = (int) self->mNativeSetMap->Count();
                int ifacesBefore = (int) self->mIID2NativeInterfaceMap->Count();
#endif

                // We use this occasion to mark and sweep NativeInterfaces,
                // NativeSets, and the WrappedNativeJSClasses...

                // Do the marking...
                XPCWrappedNativeScope::MarkAllWrappedNativesAndProtos();

                self->mDetachedWrappedNativeProtoMap->
                    Enumerate(DetachedWrappedNativeProtoMarker, nsnull);

                // Mark the sets used in the call contexts. There is a small
                // chance that a wrapper's set will change *while* a call is
                // happening which uses that wrapper's old interfface set. So,
                // we need to do this marking to avoid collecting those sets
                // that might no longer be otherwise reachable from the wrappers
                // or the wrapperprotos.

                // Skip this part if XPConnect is shutting down. We get into
                // bad locking problems with the thread iteration otherwise.
                if(!self->GetXPConnect()->IsShuttingDown())
                {
                    PRLock* threadLock = XPCPerThreadData::GetLock();
                    if(threadLock)
                    { // scoped lock
                        nsAutoLock lock(threadLock);

                        XPCPerThreadData* iterp = nsnull;
                        XPCPerThreadData* thread;

                        while(nsnull != (thread =
                                     XPCPerThreadData::IterateThreads(&iterp)))
                        {
                            // Mark those AutoMarkingPtr lists!
                            thread->MarkAutoRootsAfterJSFinalize();

                            XPCCallContext* ccxp = thread->GetCallContext();
                            while(ccxp)
                            {
                                // Deal with the strictness of callcontext that
                                // complains if you ask for a set when
                                // it is in a state where the set could not
                                // possibly be valid.
                                if(ccxp->CanGetSet())
                                {
                                    XPCNativeSet* set = ccxp->GetSet();
                                    if(set)
                                        set->Mark();
                                }
                                if(ccxp->CanGetInterface())
                                {
                                    XPCNativeInterface* iface = ccxp->GetInterface();
                                    if(iface)
                                        iface->Mark();
                                }
                                ccxp = ccxp->GetPrevCallContext();
                            }
                        }
                    }
                }

                // Do the sweeping...

                // We don't want to sweep the JSClasses at shutdown time.
                // At this point there may be JSObjects using them that have
                // been removed from the other maps.
                if(!self->GetXPConnect()->IsShuttingDown())
                {
                    self->mNativeScriptableSharedMap->
                        Enumerate(JSClassSweeper, nsnull);
                }

                self->mClassInfo2NativeSetMap->
                    Enumerate(NativeUnMarkedSetRemover, nsnull);

                self->mNativeSetMap->
                    Enumerate(NativeSetSweeper, nsnull);

                CX_AND_XPCRT_Data data = {cx, self};

                self->mIID2NativeInterfaceMap->
                    Enumerate(NativeInterfaceSweeper, &data);

#ifdef DEBUG
                XPCWrappedNativeScope::ASSERT_NoInterfaceSetsAreMarked();
#endif

#ifdef XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING
                int setsAfter = (int) self->mNativeSetMap->Count();
                int ifacesAfter = (int) self->mIID2NativeInterfaceMap->Count();

                printf("\n");
                printf("XPCNativeSets:        before: %d  collected: %d  remaining: %d\n",
                       setsBefore, setsBefore - setsAfter, setsAfter);
                printf("XPCNativeInterfaces:  before: %d  collected: %d  remaining: %d\n",
                       ifacesBefore, ifacesBefore - ifacesAfter, ifacesAfter);
                printf("--------------------------------------------------------------\n");
#endif

                // Sweep scopes needing cleanup
                XPCWrappedNativeScope::FinishedFinalizationPhaseOfGC(cx);

                // Now we are going to recycle any unused WrappedNativeTearoffs.
                // We do this by iterating all the live callcontexts (on all
                // threads!) and marking the tearoffs in use. And then we
                // iterate over all the WrappedNative wrappers and sweep their
                // tearoffs.
                //
                // This allows us to perhaps minimize the growth of the
                // tearoffs. And also makes us not hold references to interfaces
                // on our wrapped natives that we are not actually using.
                //
                // XXX We may decide to not do this on *every* gc cycle.

                // Skip this part if XPConnect is shutting down. We get into
                // bad locking problems with the thread iteration otherwise.
                if(!self->GetXPConnect()->IsShuttingDown())
                {
                    PRLock* threadLock = XPCPerThreadData::GetLock();
                    if(threadLock)
                    {
                        // Do the marking...
                        
                        { // scoped lock
                            nsAutoLock lock(threadLock);

                            XPCPerThreadData* iterp = nsnull;
                            XPCPerThreadData* thread;

                            while(nsnull != (thread =
                                     XPCPerThreadData::IterateThreads(&iterp)))
                            {
                                XPCCallContext* ccxp = thread->GetCallContext();
                                while(ccxp)
                                {
                                    // Deal with the strictness of callcontext that
                                    // complains if you ask for a tearoff when
                                    // it is in a state where the tearoff could not
                                    // possibly be valid.
                                    if(ccxp->CanGetTearOff())
                                    {
                                        XPCWrappedNativeTearOff* to = 
                                            ccxp->GetTearOff();
                                        if(to)
                                            to->Mark();
                                    }
                                    ccxp = ccxp->GetPrevCallContext();
                                }
                            }
                        }
    
                        // Do the sweeping...
                        XPCWrappedNativeScope::SweepAllWrappedNativeTearOffs();
                    }
                }

                // Now we need to kill the 'Dying' XPCWrappedNativeProtos.
                // We transfered these native objects to this table when their
                // JSObject's were finalized. We did not destroy them immediately
                // at that point because the ordering of JS finalization is not
                // deterministic and we did not yet know if any wrappers that
                // might still be referencing the protos where still yet to be
                // finalized and destroyed. We *do* know that the protos'
                // JSObjects would not have been finalized if there were any
                // wrappers that referenced the proto but where not themselves
                // slated for finalization in this gc cycle. So... at this point
                // we know that any and all wrappers that might have been
                // referencing the protos in the dying list are themselves dead.
                // So, we can safely delete all the protos in the list.

                self->mDyingWrappedNativeProtoMap->
                    Enumerate(DyingProtoKiller, nsnull);


                // mThreadRunningGC indicates that GC is running.
                // Clear it and notify waiters.
                { // scoped lock
                    XPCAutoLock lock(self->GetMapLock());
                    NS_ASSERTION(self->mThreadRunningGC == PR_GetCurrentThread(), "bad state");
                    self->mThreadRunningGC = nsnull;
                    xpc_NotifyAll(self->GetMapLock());
                }

                break;
            }
            case JSGC_END:
            {
                // NOTE that this event happens outside of the gc lock in
                // the js engine. So this could be simultaneous with the
                // events above.

                XPCLock* lock = self->GetMainThreadOnlyGC() ?
                                nsnull : self->GetMapLock();

                // Do any deferred released of native objects.
                if(self->GetDeferReleases())
                {
                    nsVoidArray* array = &self->mNativesToReleaseArray;
#ifdef XPC_TRACK_DEFERRED_RELEASES
                    printf("XPC - Begin deferred Release of %d nsISupports pointers\n",
                           array->Count());
#endif
                    while(1)
                    {
                        nsISupports* obj;
                        {
                            XPCAutoLock al(lock); // lock if necessary
                            PRInt32 count = array->Count();
                            if(!count)
                            {
                                array->Compact();
                                break;
                            }
                            obj = NS_REINTERPRET_CAST(nsISupports*,
                                    array->ElementAt(count-1));
                            array->RemoveElementAt(count-1);
                        }
                        NS_RELEASE(obj);
                    }
#ifdef XPC_TRACK_DEFERRED_RELEASES
                    printf("XPC - End deferred Releases\n");
#endif
                }
                break;
            }
            default:
                break;
        }
    }

    // always chain to old GCCallback if non-null.
    return gOldJSGCCallback ? gOldJSGCCallback(cx, status) : JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 985 of file xpcjsruntime.cpp.

{
    NS_PRECONDITION(!mStrIDs[0],"string ids generated twice!");
    for(uintN i = 0; i < IDX_TOTAL_COUNT; i++)
    {
        JSString* str = JS_InternString(cx, mStrings[i]);
        if(!str || !JS_ValueToId(cx, STRING_TO_JSVAL(str), &mStrIDs[i]))
        {
            mStrIDs[0] = 0;
            return JS_FALSE;
        }

        mStrJSVals[i] = STRING_TO_JSVAL(str);
    }
    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 540 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 655 of file xpcprivate.h.

{return mContextMap;}

Definition at line 569 of file xpcprivate.h.

{return mDeferReleases;}

Here is the caller graph for this function:

Definition at line 555 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 578 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 552 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 558 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 537 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 526 of file xpcprivate.h.

{return mJSRuntime;}

Here is the caller graph for this function:

Definition at line 529 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 566 of file xpcprivate.h.

Here is the caller graph for this function:

XPCLock* XPCJSRuntime::GetMapLock ( ) const [inline]

Definition at line 561 of file xpcprivate.h.

{return mMapLock;}

Here is the caller graph for this function:

Definition at line 549 of file xpcprivate.h.

Here is the caller graph for this function:

Definition at line 543 of file xpcprivate.h.

        {return mNativeSetMap;}

Here is the caller graph for this function:

jsid XPCJSRuntime::GetStringID ( uintN  index) const [inline]

Definition at line 607 of file xpcprivate.h.

    {
        NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
        return mStrIDs[index];
    }

Here is the caller graph for this function:

jsval XPCJSRuntime::GetStringJSVal ( uintN  index) const [inline]

Definition at line 612 of file xpcprivate.h.

    {
        NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
        return mStrJSVals[index];
    }

Here is the caller graph for this function:

const char* XPCJSRuntime::GetStringName ( uintN  index) const [inline]

Definition at line 617 of file xpcprivate.h.

    {
        NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
        return mStrings[index];
    }

Here is the caller graph for this function:

Definition at line 546 of file xpcprivate.h.

        {return mThisTranslatorMap;}

Here is the caller graph for this function:

Definition at line 629 of file xpcprivate.h.

{return mThreadRunningGC;}

Here is the caller graph for this function:

Definition at line 534 of file xpcprivate.h.

        {return mWrappedJSClassMap;}

Here is the caller graph for this function:

Definition at line 531 of file xpcprivate.h.

        {return mWrappedJSMap;}

Here is the caller graph for this function:

Definition at line 884 of file xpcjsruntime.cpp.

{
    XPCContext* xpcc;

    // find it in the map.

    { // scoped lock
        XPCAutoLock lock(GetMapLock());
        xpcc = mContextMap->Find(cx);
    }

    // else resync with the JSRuntime's JSContext list and see if it is found
    if(!xpcc)
        xpcc = SyncXPCContextList(cx);
    return xpcc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 527 of file xpcprivate.h.

{return mXPConnect;}

Here is the caller graph for this function:

XPCJSRuntime * XPCJSRuntime::newXPCJSRuntime ( nsXPConnect aXPConnect,
nsIJSRuntimeService aJSRuntimeService 
) [static]

Definition at line 852 of file xpcjsruntime.cpp.

{
    NS_PRECONDITION(aXPConnect,"bad param");
    NS_PRECONDITION(aJSRuntimeService,"bad param");

    XPCJSRuntime* self;

    self = new XPCJSRuntime(aXPConnect,
                            aJSRuntimeService);

    if(self                                  &&
       self->GetJSRuntime()                  &&
       self->GetContextMap()                 &&
       self->GetWrappedJSMap()               &&
       self->GetWrappedJSClassMap()          &&
       self->GetIID2NativeInterfaceMap()     &&
       self->GetClassInfo2NativeSetMap()     &&
       self->GetNativeSetMap()               &&
       self->GetThisTranslatorMap()          &&
       self->GetNativeScriptableSharedMap()  &&
       self->GetDyingWrappedNativeProtoMap() &&
       self->GetExplicitNativeWrapperMap()   &&
       self->GetMapLock())
    {
        return self;
    }
    delete self;
    return nsnull;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 975 of file xpcjsruntime.cpp.

{
    // hold the map lock through this whole thing
    XPCAutoLock lock(GetMapLock());

    // get rid of all XPCContexts
    mContextMap->Enumerate(PurgeContextsCB, nsnull);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 570 of file xpcprivate.h.

        {/* If deferring is turned off while any are pending they'll leak! */
         NS_ASSERTION((mDeferReleases && b) || 
                      !mNativesToReleaseArray.Count(), "bad"); 
         mDeferReleases = b;}

Definition at line 567 of file xpcprivate.h.

Definition at line 919 of file xpcjsruntime.cpp.

{
    // hold the map lock through this whole thing
    XPCAutoLock lock(GetMapLock());

    XPCContext* found = nsnull;

    // add XPCContexts that represent any JSContexts we have not seen before
    JSContext *cur, *iter = nsnull;
    while(nsnull != (cur = JS_ContextIterator(mJSRuntime, &iter)))
    {
        XPCContext* xpcc = mContextMap->Find(cur);

        if(!xpcc)
        {
            xpcc = XPCContext::newXPCContext(this, cur);
            if(xpcc)
                mContextMap->Add(xpcc);
        }
        if(xpcc)
        {
            xpcc->Mark();
        }

        // if it is our first context then we need to generate our string ids
        if(!mStrIDs[0])
            GenerateStringIDs(cur);

        if(cx && cx == cur)
            found = xpcc;
    }
    // get rid of any XPCContexts that represent dead JSContexts
    mContextMap->Enumerate(SweepContextsCB, 0);

    XPCPerThreadData* tls = XPCPerThreadData::GetData();
    if(tls)
    {
        if(found)
            tls->SetRecentContext(cx, found);
        else
            tls->ClearRecentContext();
    }

    return found;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 641 of file xpcjsruntime.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 671 of file xpcprivate.h.

Definition at line 667 of file xpcprivate.h.

Definition at line 683 of file xpcprivate.h.

Definition at line 676 of file xpcprivate.h.

Definition at line 684 of file xpcprivate.h.

Definition at line 675 of file xpcprivate.h.

Definition at line 677 of file xpcprivate.h.

Definition at line 670 of file xpcprivate.h.

Definition at line 665 of file xpcprivate.h.

Definition at line 666 of file xpcprivate.h.

Definition at line 682 of file xpcprivate.h.

Definition at line 678 of file xpcprivate.h.

Definition at line 674 of file xpcprivate.h.

Definition at line 672 of file xpcprivate.h.

Definition at line 681 of file xpcprivate.h.

Definition at line 661 of file xpcprivate.h.

const char * XPCJSRuntime::mStrings [static, private]
Initial value:
 {
    "constructor",          
    "toString",             
    "toSource",             
    "lastResult",           
    "returnCode",           
    "value",                
    "QueryInterface",       
    "Components",           
    "wrappedJSObject",      
    "Object",               
    "Function",             
    "prototype",            
    "createInstance",       
    "item"                  





}

Definition at line 660 of file xpcprivate.h.

Definition at line 662 of file xpcprivate.h.

Definition at line 673 of file xpcprivate.h.

Definition at line 679 of file xpcprivate.h.

Definition at line 669 of file xpcprivate.h.

Definition at line 668 of file xpcprivate.h.

Definition at line 680 of file xpcprivate.h.

Definition at line 664 of file xpcprivate.h.


The documentation for this class was generated from the following files: