diff --git a/mozilla/xpcom/base/nscore.h b/mozilla/xpcom/base/nscore.h index ee609532b3a..c4fab8c247a 100644 --- a/mozilla/xpcom/base/nscore.h +++ b/mozilla/xpcom/base/nscore.h @@ -121,6 +121,8 @@ #define NS_COM NS_EXPORT #elif _IMPL_NS_COM_OFF #define NS_COM +#elif XPCOM_GLUE +#define NS_COM #else #define NS_COM NS_IMPORT #endif diff --git a/mozilla/xpcom/build/nsXPCOM.h b/mozilla/xpcom/build/nsXPCOM.h index 4adebee9367..b4fbff671bd 100644 --- a/mozilla/xpcom/build/nsXPCOM.h +++ b/mozilla/xpcom/build/nsXPCOM.h @@ -79,6 +79,8 @@ class nsIMemory; * @see nsIDirectoryServiceProvider * * @return NS_OK for success; + * NS_ERROR_NOT_INITIALIZED if static globals were not initialied, which + * can happen if XPCOM is reloaded, but did not completly shutdown. * other error codes indicate a failure during initialisation. * */ diff --git a/mozilla/xpcom/build/nsXPCOMPrivate.h b/mozilla/xpcom/build/nsXPCOMPrivate.h index 0cc3aacc656..2f2bc33607d 100644 --- a/mozilla/xpcom/build/nsXPCOMPrivate.h +++ b/mozilla/xpcom/build/nsXPCOMPrivate.h @@ -39,6 +39,7 @@ #define nsXPComPrivate_h__ #include "nscore.h" +#include "nsXPCOM.h" /** * Private Method to register an exit routine. This method * allows you to setup a callback that will be called from @@ -68,6 +69,44 @@ NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority); extern "C" NS_COM nsresult NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine); + +// PUBLIC +typedef nsresult (PR_CALLBACK *InitFunc)(nsIServiceManager* *result, nsIFile* binDirectory, nsIDirectoryServiceProvider* appFileLocationProvider); +typedef nsresult (PR_CALLBACK *ShutdownFunc)(nsIServiceManager* servMgr); +typedef nsresult (PR_CALLBACK *GetServiceManagerFunc)(nsIServiceManager* *result); +typedef nsresult (PR_CALLBACK *GetComponentManagerFunc)(nsIComponentManager* *result); +typedef nsresult (PR_CALLBACK *GetComponentRegistrarFunc)(nsIComponentRegistrar* *result); +typedef nsresult (PR_CALLBACK *GetMemoryManagerFunc)(nsIMemory* *result); +typedef nsresult (PR_CALLBACK *NewLocalFileFunc)(const nsAString &path, PRBool followLinks, nsILocalFile* *result); +typedef nsresult (PR_CALLBACK *NewNativeLocalFileFunc)(const nsACString &path, PRBool followLinks, nsILocalFile* *result); +// PRIVATE +typedef nsresult (PR_CALLBACK *RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority); +typedef nsresult (PR_CALLBACK *UnregisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine); + +typedef struct XPCOMFunctions{ + PRUint32 version; + PRUint32 size; + + InitFunc init; + ShutdownFunc shutdown; + GetServiceManagerFunc getServiceManager; + GetComponentManagerFunc getComponentManager; + GetComponentRegistrarFunc getComponentRegistrar; + GetMemoryManagerFunc getMemoryManager; + NewLocalFileFunc newLocalFile; + NewNativeLocalFileFunc newNativeLocalFile; + + RegisterXPCOMExitRoutineFunc registerExitRoutine; + UnregisterXPCOMExitRoutineFunc unregisterExitRoutine; +} XPCOMFunctions; + +typedef nsresult (PR_CALLBACK *GetFrozenFunctionsFunc)(XPCOMFunctions *entryPoints); +extern "C" NS_COM nsresult +NS_GetFrozenFunctions(XPCOMFunctions *entryPoints); + +// think hard before changing this +#define XPCOM_GLUE_VERSION 1 + #endif diff --git a/mozilla/xpcom/build/nsXPComInit.cpp b/mozilla/xpcom/build/nsXPComInit.cpp index 8b5b5e499f2..bee504e21c3 100644 --- a/mozilla/xpcom/build/nsXPComInit.cpp +++ b/mozilla/xpcom/build/nsXPComInit.cpp @@ -193,6 +193,12 @@ nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL; nsIProperties *gDirectoryService = NULL; PRBool gXPCOMShuttingDown = PR_FALSE; +// If XPCOM is unloaded, we need a way to ensure that all statics have been +// reinitalized when reloading. Here we create a boolean which is initialized +// to true. During shutdown, this boolean with set to false. When we startup, +// this boolean will be checked and if the value is not true, startup will fail. +static PRBool gXPCOMHasGlobalsBeenInitalized = PR_TRUE; + // For each class that wishes to support nsIClassInfo, add a line like this // NS_DECL_CLASSINFO(nsMyClass) @@ -309,6 +315,10 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result, nsIFile* binDirectory, nsIDirectoryServiceProvider* appFileLocationProvider) { + + if (!gXPCOMHasGlobalsBeenInitalized) + return NS_ERROR_NOT_INITIALIZED; + nsresult rv = NS_OK; // We are not shutting down @@ -510,6 +520,29 @@ NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine) return okay ? NS_OK : NS_ERROR_FAILURE; } +nsresult NS_COM +NS_GetFrozenFunctions(XPCOMFunctions *functions) +{ + if (!functions) + return NS_ERROR_OUT_OF_MEMORY; + + if (functions->version != XPCOM_GLUE_VERSION) + return NS_ERROR_FAILURE; + + functions->init = &NS_InitXPCOM2; + functions->shutdown = &NS_ShutdownXPCOM; + functions->getServiceManager = &NS_GetServiceManager; + functions->getComponentManager = &NS_GetComponentManager; + functions->getComponentRegistrar = &NS_GetComponentRegistrar; + functions->getMemoryManager = &NS_GetMemoryManager; + functions->newLocalFile = &NS_NewLocalFile; + functions->newNativeLocalFile = &NS_NewNativeLocalFile; + + functions->registerExitRoutine = &NS_RegisterXPCOMExitRoutine; + functions->unregisterExitRoutine = &NS_UnregisterXPCOMExitRoutine; + + return NS_OK; +} // // NS_ShutdownXPCOM() @@ -643,6 +676,7 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr) NS_ShutdownLeakDetector(); #endif + gXPCOMHasGlobalsBeenInitalized = PR_FALSE; return NS_OK; } diff --git a/mozilla/xpcom/components/xcDll.cpp b/mozilla/xpcom/components/xcDll.cpp index 1f7c81836e1..226242b007a 100644 --- a/mozilla/xpcom/components/xcDll.cpp +++ b/mozilla/xpcom/components/xcDll.cpp @@ -152,7 +152,7 @@ nsDll::Init(const char *libPersistentDescriptor) nsDll::~nsDll(void) { -#if 0 +#if DEBUG_dougt // The dll gets deleted when the dllStore is destroyed. This happens on // app shutdown. At that point, unloading dlls can cause crashes if we have // - dll dependencies diff --git a/mozilla/xpcom/glue/Makefile.in b/mozilla/xpcom/glue/Makefile.in index 2b8694532fa..bced632c8ad 100644 --- a/mozilla/xpcom/glue/Makefile.in +++ b/mozilla/xpcom/glue/Makefile.in @@ -30,7 +30,6 @@ include $(srcdir)/objs.mk DIRS = standalone MODULE = xpcom -XPIDL_MODULE = xpcom_glue LIBRARY_NAME = xpcomglue_s REQUIRES = $(NULL) diff --git a/mozilla/xpcom/glue/standalone/Makefile.in b/mozilla/xpcom/glue/standalone/Makefile.in index 78e1c3aa713..2de4dc77606 100644 --- a/mozilla/xpcom/glue/standalone/Makefile.in +++ b/mozilla/xpcom/glue/standalone/Makefile.in @@ -45,12 +45,21 @@ include $(srcdir)/../objs.mk MODULE = xpcom LIBRARY_NAME = xpcomglue +REQUIRES = string \ + $(NULL) + + LOCAL_INCLUDES = \ -I$(srcdir)/../../build \ $(NULL) CPPSRCS = \ $(XPCOM_GLUE_SRC_LCSRCS) \ + nsXPCOMGlue.cpp \ + $(NULL) + +EXPORTS = \ + nsXPCOMGlue.h \ $(NULL) SDK_BINARY = \ @@ -78,7 +87,7 @@ else $(INSTALL) $^ . endif -DEFINES += -D_IMPL_NS_COM_OFF -DXPCOM_GLUE +DEFINES += -DXPCOM_GLUE ifeq ($(OS_ARCH),WINNT) DEFINES += -DWIN32_LEAN_AND_MEAN diff --git a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp new file mode 100644 index 00000000000..737c29ecdf5 --- /dev/null +++ b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -0,0 +1,357 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nspr.h" +#include "prlink.h" +#include "nsMemory.h" +#include "nsXPCOMPrivate.h" + +#if defined(XP_WIN32) +#include // for SetProcessWorkingSetSize() +#include // for _heapmin() +#endif + +static PRLibrary *xpcomLib = nsnull; +static XPCOMFunctions *xpcomFunctions = nsnull; + +#ifdef DEBUG_dougt +#define XPCOM_GLUE_FLUSH_HEAP +#endif + +// seawood tells me there isn't a better way... +#ifdef XP_PC +#define XPCOM_DLL "xpcom32.dll" +#else +#ifdef XP_MAC +#define XPCOM_DLL "XPCOM_DLL" +#else +#define XPCOM_DLL "libxpcom.so" +#endif +#endif + +extern "C" +nsresult NS_COM XPCOMGlueStartup(const char* xpcomFile) +{ + nsresult rv; + const char* libFile; + if (!xpcomFile) + libFile = XPCOM_DLL; + else + libFile = xpcomFile; + + xpcomLib = PR_LoadLibrary(libFile); + if (!xpcomLib) + return NS_ERROR_FAILURE; + + GetFrozenFunctionsFunc function = + (GetFrozenFunctionsFunc)PR_FindSymbol(xpcomLib, "NS_GetFrozenFunctions"); + + if (!function) { + PR_UnloadLibrary(xpcomLib); + xpcomLib = nsnull; + return NS_ERROR_FAILURE; + } + + xpcomFunctions = (XPCOMFunctions*) calloc(1, sizeof(XPCOMFunctions)); + if (!xpcomFunctions){ + PR_UnloadLibrary(xpcomLib); + xpcomLib = nsnull; + return NS_ERROR_FAILURE; + } + + xpcomFunctions->version = XPCOM_GLUE_VERSION; + xpcomFunctions->size = sizeof(XPCOMFunctions); + + rv = (*function)(xpcomFunctions); + if (NS_FAILED(rv)) { + free(xpcomFunctions); + xpcomFunctions = nsnull; + PR_UnloadLibrary(xpcomLib); + xpcomLib = nsnull; + return NS_ERROR_FAILURE; + } + return NS_OK; +} +#ifdef XPCOM_GLUE_FLUSH_HEAP +static void FlushHeap() +{ +#if defined(XP_WIN32) + // Heap compaction and shrink working set now +#ifdef DEBUG_dougt + PRIntervalTime start = PR_IntervalNow(); + int ret = +#endif + _heapmin(); +#ifdef DEBUG_dougt + printf("DEBUG: HeapCompact() %s - %d ms\n", (!ret ? "success" : "FAILED"), + PR_IntervalToMilliseconds(PR_IntervalNow()-start)); +#endif + + // shrink working set if we can + // This function call is available only on winnt and above. + typedef BOOL WINAPI SetProcessWorkingSetProc(HANDLE hProcess, SIZE_T dwMinimumWorkingSetSize, + SIZE_T dwMaximumWorkingSetSize); + SetProcessWorkingSetProc *setProcessWorkingSetSizeP = NULL; + + HMODULE kernel = GetModuleHandle("kernel32.dll"); + if (kernel) { + setProcessWorkingSetSizeP = (SetProcessWorkingSetProc *) + GetProcAddress(kernel, "SetProcessWorkingSetSize"); + } + + if (setProcessWorkingSetSizeP) { + // shrink working set +#ifdef DEBUG_dougt + start = PR_IntervalNow(); +#endif + (*setProcessWorkingSetSizeP)(GetCurrentProcess(), -1, -1); +#ifdef DEBUG_dougt + printf("DEBUG: Honey! I shrunk the resident-set! - %d ms\n", + PR_IntervalToMilliseconds(PR_IntervalNow() - start)); +#endif + } +#endif +} +#endif + +extern "C" +nsresult NS_COM XPCOMGlueShutdown() +{ + if (xpcomFunctions) { + free ((void*)xpcomFunctions); + xpcomFunctions = nsnull; + } + + if (xpcomLib) { + PR_UnloadLibrary(xpcomLib); + xpcomLib = nsnull; + } +#ifdef XPCOM_GLUE_FLUSH_HEAP + // should the application do this instead of us? + FlushHeap(); +#endif + + return NS_OK; +} + +extern "C" NS_COM nsresult +NS_InitXPCOM2(nsIServiceManager* *result, + nsIFile* binDirectory, + nsIDirectoryServiceProvider* appFileLocationProvider) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->init(result, binDirectory, appFileLocationProvider); +} + +extern "C" NS_COM nsresult +NS_ShutdownXPCOM(nsIServiceManager* servMgr) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->shutdown(servMgr); +} + +extern "C" NS_COM nsresult +NS_GetServiceManager(nsIServiceManager* *result) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->getServiceManager(result); +} + +extern "C" NS_COM nsresult +NS_GetComponentManager(nsIComponentManager* *result) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->getComponentManager(result); +} + +extern "C" NS_COM nsresult +NS_GetComponentRegistrar(nsIComponentRegistrar* *result) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->getComponentRegistrar(result); +} + +extern "C" NS_COM nsresult +NS_GetMemoryManager(nsIMemory* *result) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->getMemoryManager(result); +} + +extern "C" NS_COM nsresult +NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->newLocalFile(path, followLinks, result); +} + +extern "C" NS_COM nsresult +NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->newNativeLocalFile(path, followLinks, result); +} + +extern "C" NS_COM nsresult +NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->registerExitRoutine(exitRoutine, priority); +} + +extern "C" NS_COM nsresult +NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine) +{ + if (!xpcomFunctions) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions->unregisterExitRoutine(exitRoutine); +} + +#if DEBUG_dougt + +struct nsTraceRefcntStats { + nsrefcnt mAddRefs; + nsrefcnt mReleases; + nsrefcnt mCreates; + nsrefcnt mDestroys; + double mRefsOutstandingTotal; + double mRefsOutstandingSquared; + double mObjsOutstandingTotal; + double mObjsOutstandingSquared; +}; + +// Function type used by GatherStatistics. For each type that data has +// been gathered for, this function is called with the counts of the +// various operations that have been logged. The function can return +// PR_FALSE if the gathering should stop. +// +// aCurrentStats is the current value of the counters. aPrevStats is +// the previous value of the counters which is established by the +// nsTraceRefcnt::SnapshotStatistics call. +typedef PRBool (PR_CALLBACK *nsTraceRefcntStatFunc) + (const char* aTypeName, + PRUint32 aInstanceSize, + nsTraceRefcntStats* aCurrentStats, + nsTraceRefcntStats* aPrevStats, + void *aClosure); + +class nsTraceRefcnt { +public: + static NS_EXPORT void Startup(){}; + + static NS_EXPORT void Shutdown(){}; + + static NS_EXPORT void LogAddRef(void* aPtr, + nsrefcnt aNewRefCnt, + const char* aTypeName, + PRUint32 aInstanceSize){}; + + static NS_EXPORT void LogRelease(void* aPtr, + nsrefcnt aNewRefCnt, + const char* aTypeName){}; + + static NS_EXPORT void LogNewXPCOM(void* aPtr, + const char* aTypeName, + PRUint32 aInstanceSize, + const char* aFile, + int aLine){}; + + static NS_EXPORT void LogDeleteXPCOM(void* aPtr, + const char* aFile, + int aLine){}; + + static NS_EXPORT nsrefcnt LogAddRefCall(void* aPtr, + nsrefcnt aNewRefcnt, + const char* aFile, + int aLine){return 0;}; + + static NS_EXPORT nsrefcnt LogReleaseCall(void* aPtr, + nsrefcnt aNewRefcnt, + const char* aFile, + int aLine){return 0;}; + + static NS_EXPORT void LogCtor(void* aPtr, const char* aTypeName, + PRUint32 aInstanceSize){}; + + static NS_EXPORT void LogDtor(void* aPtr, const char* aTypeName, + PRUint32 aInstanceSize){}; + + static NS_EXPORT void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject){}; + + static NS_EXPORT void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject){}; + + enum StatisticsType { + ALL_STATS, + NEW_STATS + }; + + static NS_EXPORT nsresult DumpStatistics(StatisticsType type = ALL_STATS, + FILE* out = 0){return NS_ERROR_NOT_IMPLEMENTED;}; + + static NS_EXPORT void ResetStatistics(void){}; + + static NS_EXPORT void GatherStatistics(nsTraceRefcntStatFunc aFunc, + void* aClosure){}; + + static NS_EXPORT void LoadLibrarySymbols(const char* aLibraryName, + void* aLibrayHandle){}; + + static NS_EXPORT void DemangleSymbol(const char * aSymbol, + char * aBuffer, + int aBufLen){}; + + static NS_EXPORT void WalkTheStack(FILE* aStream){}; + + static NS_EXPORT void SetPrefServiceAvailability(PRBool avail){}; + + /** + * Tell nsTraceRefcnt whether refcounting, allocation, and destruction + * activity is legal. This is used to trigger assertions for any such + * activity that occurs because of static constructors or destructors. + */ + static NS_EXPORT void SetActivityIsLegal(PRBool aLegal){}; +}; +#endif diff --git a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.h b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.h new file mode 100644 index 00000000000..6a3990ef73f --- /dev/null +++ b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +class nsILocalFile; + +extern "C" +nsresult NS_COM XPCOMGlueStartup(const char* xpcomFile); + +extern "C" +nsresult NS_COM XPCOMGlueShutdown(); diff --git a/mozilla/xpcom/sample/Makefile.in b/mozilla/xpcom/sample/Makefile.in index 9eddf389854..adc9c630172 100644 --- a/mozilla/xpcom/sample/Makefile.in +++ b/mozilla/xpcom/sample/Makefile.in @@ -36,7 +36,7 @@ MODULE_NAME = nsSampleModule # Ensure that the xpcom classes that we build # do not export themselves -DEFINES += -D_IMPL_NS_COM_OFF +DEFINES += -DXPCOM_GLUE REQUIRES = string \