Bug 267767 - Make XPCOM memory management functions frozen exports. r=darin sr=shaver
git-svn-id: svn://10.0.0.236/trunk@165320 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include "nsILocalFile.h"
|
||||
|
||||
#ifdef STANDALONE_PROFILEDIRSERVICE
|
||||
#define MOZILLA_STRICT_API
|
||||
#include "nsEmbedString.h"
|
||||
#else
|
||||
#include "nsString.h"
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "nsProfileStringTypes.h"
|
||||
#include "nsProfileLock.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
#include <Processes.h>
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
*/
|
||||
|
||||
#ifdef STANDALONE_PROFILEDIRSERVICE
|
||||
#define MOZILLA_STRICT_API
|
||||
#include "nsEmbedString.h"
|
||||
|
||||
typedef nsEmbedString nsString;
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
* nsIMemory: interface to allocate and deallocate memory. Also provides
|
||||
* for notifications in low-memory situations.
|
||||
*
|
||||
* The frozen exported symbols NS_Alloc, NS_Realloc, and NS_Free
|
||||
* provide a more efficient way to access XPCOM memory allocation. Using
|
||||
* those symbols is preferred to using the methods on this interface.
|
||||
*
|
||||
* A client that wishes to be notified of low memory situations (for
|
||||
* example, because the client maintains a large memory cache that
|
||||
* could be released when memory is tight) should register with the
|
||||
|
||||
@@ -35,14 +35,22 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsMemoryImpl.h"
|
||||
#include "prmem.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsIThread.h"
|
||||
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIThread.h"
|
||||
|
||||
#include "prmem.h"
|
||||
#include "plevent.h"
|
||||
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
@@ -56,216 +64,6 @@
|
||||
#undef NS_MEMORY_FLUSHER_THREAD
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if defined(XDEBUG_waterson)
|
||||
#define NS_TEST_MEMORY_FLUSHER
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A runnable that is used to periodically check the status
|
||||
* of the system, determine if too much memory is in use,
|
||||
* and if so, trigger a "memory flush".
|
||||
*/
|
||||
class MemoryFlusher : public nsIRunnable
|
||||
{
|
||||
protected:
|
||||
nsMemoryImpl* mMemoryImpl; // WEAK, it owns us.
|
||||
PRBool mRunning;
|
||||
PRIntervalTime mTimeout;
|
||||
PRLock* mLock;
|
||||
PRCondVar* mCVar;
|
||||
|
||||
MemoryFlusher(nsMemoryImpl* aMemoryImpl);
|
||||
|
||||
enum {
|
||||
kInitialTimeout = 60 /*seconds*/
|
||||
};
|
||||
|
||||
private:
|
||||
~MemoryFlusher();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a memory flusher.
|
||||
* @param aResult the memory flusher
|
||||
* @param aMemoryImpl the owning nsMemoryImpl object
|
||||
* @return NS_OK if the memory flusher was created successfully
|
||||
*/
|
||||
static nsresult
|
||||
Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
/**
|
||||
* Stop the memory flusher.
|
||||
*/
|
||||
nsresult Stop();
|
||||
};
|
||||
|
||||
|
||||
MemoryFlusher::MemoryFlusher(nsMemoryImpl* aMemoryImpl)
|
||||
: mMemoryImpl(aMemoryImpl),
|
||||
mRunning(PR_FALSE),
|
||||
mTimeout(PR_SecondsToInterval(kInitialTimeout)),
|
||||
mLock(nsnull),
|
||||
mCVar(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryFlusher::~MemoryFlusher()
|
||||
{
|
||||
if (mLock)
|
||||
PR_DestroyLock(mLock);
|
||||
|
||||
if (mCVar)
|
||||
PR_DestroyCondVar(mCVar);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
MemoryFlusher::Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl)
|
||||
{
|
||||
MemoryFlusher* result = new MemoryFlusher(aMemoryImpl);
|
||||
if (! result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
do {
|
||||
if ((result->mLock = PR_NewLock()) == nsnull)
|
||||
break;
|
||||
|
||||
if ((result->mCVar = PR_NewCondVar(result->mLock)) == nsnull)
|
||||
break;
|
||||
|
||||
NS_ADDREF(*aResult = result);
|
||||
return NS_OK;
|
||||
} while (0);
|
||||
|
||||
// Something bad happened if we get here...
|
||||
delete result;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryFlusher, nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP
|
||||
MemoryFlusher::Run()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mRunning = PR_TRUE;
|
||||
|
||||
while (1) {
|
||||
PRStatus status;
|
||||
|
||||
{
|
||||
nsAutoLock l(mLock);
|
||||
if (! mRunning) {
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
status = PR_WaitCondVar(mCVar, mTimeout);
|
||||
}
|
||||
|
||||
if (status != PR_SUCCESS) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! mRunning) {
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
PRBool isLowMemory;
|
||||
rv = mMemoryImpl->IsLowMemory(&isLowMemory);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
#ifdef NS_TEST_MEMORY_FLUSHER
|
||||
// Fire the flusher *every* time
|
||||
isLowMemory = PR_TRUE;
|
||||
#endif
|
||||
|
||||
if (isLowMemory) {
|
||||
mMemoryImpl->FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
mRunning = PR_FALSE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
MemoryFlusher::Stop()
|
||||
{
|
||||
if (mRunning) {
|
||||
nsAutoLock l(mLock);
|
||||
mRunning = PR_FALSE;
|
||||
PR_NotifyCondVar(mCVar);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsMemoryImpl* gMemory = nsnull;
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryImpl, nsIMemory)
|
||||
|
||||
NS_METHOD
|
||||
nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInstancePtr);
|
||||
NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
|
||||
if (gMemory && NS_SUCCEEDED(gMemory->QueryInterface(aIID, aInstancePtr)))
|
||||
return NS_OK;
|
||||
|
||||
nsMemoryImpl* mm = new nsMemoryImpl();
|
||||
if (mm == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
do {
|
||||
rv = mm->QueryInterface(aIID, aInstancePtr);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mm->mFlushLock = PR_NewLock();
|
||||
if (! mm->mFlushLock)
|
||||
break;
|
||||
|
||||
rv = NS_OK;
|
||||
} while (0);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
delete mm;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsMemoryImpl::nsMemoryImpl()
|
||||
: mFlusher(nsnull),
|
||||
mFlushLock(nsnull),
|
||||
mIsFlushing(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
nsMemoryImpl::~nsMemoryImpl()
|
||||
{
|
||||
if (mFlushLock)
|
||||
PR_DestroyLock(mFlushLock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures
|
||||
|
||||
@@ -316,35 +114,66 @@ reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max)
|
||||
|
||||
#endif // NS_OUT_OF_MEMORY_TESTER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(XDEBUG_waterson)
|
||||
#define NS_TEST_MEMORY_FLUSHER
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP_(void *)
|
||||
#ifdef NS_MEMORY_FLUSHER_THREAD
|
||||
/**
|
||||
* A runnable that is used to periodically check the status
|
||||
* of the system, determine if too much memory is in use,
|
||||
* and if so, trigger a "memory flush".
|
||||
*/
|
||||
|
||||
class MemoryFlusher : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
// We don't use the generic macros because we are a special static object
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aResult);
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) { return 1; }
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) { return 1; }
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
nsresult Init();
|
||||
void StopAndJoin();
|
||||
|
||||
private:
|
||||
static PRBool sRunning;
|
||||
static PRIntervalTime sTimeout;
|
||||
static PRLock* sLock;
|
||||
static PRCondVar* sCVar;
|
||||
static nsIThread* sThread;
|
||||
|
||||
enum {
|
||||
kInitialTimeout = 60 /*seconds*/
|
||||
};
|
||||
};
|
||||
|
||||
static MemoryFlusher sGlobalMemoryFlusher;
|
||||
|
||||
#endif // NS_MEMORY_FLUSHER_THREAD
|
||||
|
||||
static nsMemoryImpl sGlobalMemory;
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE1(nsMemoryImpl, nsIMemory)
|
||||
|
||||
NS_IMETHODIMP_(void*)
|
||||
nsMemoryImpl::Alloc(PRSize size)
|
||||
{
|
||||
NS_ASSERTION(size, "nsMemoryImpl::Alloc of 0");
|
||||
void* result = MALLOC1(size);
|
||||
if (! result) {
|
||||
// Request an asynchronous flush
|
||||
FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
|
||||
}
|
||||
return result;
|
||||
return NS_Alloc(size);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void *)
|
||||
nsMemoryImpl::Realloc(void * ptr, PRSize size)
|
||||
NS_IMETHODIMP_(void*)
|
||||
nsMemoryImpl::Realloc(void* ptr, PRSize size)
|
||||
{
|
||||
void* result = REALLOC1(ptr, size);
|
||||
if (! result) {
|
||||
// Request an asynchronous flush
|
||||
FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
|
||||
}
|
||||
return result;
|
||||
return NS_Realloc(ptr, size);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsMemoryImpl::Free(void * ptr)
|
||||
nsMemoryImpl::Free(void* ptr)
|
||||
{
|
||||
PR_Free(ptr);
|
||||
NS_Free(ptr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -397,6 +226,38 @@ nsMemoryImpl::IsLowMemory(PRBool *result)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMemoryImpl::Startup()
|
||||
{
|
||||
#ifdef NS_MEMORY_FLUSHER_THREAD
|
||||
sFlushLock = PR_NewLock();
|
||||
if (!sFlushLock) return NS_ERROR_FAILURE;
|
||||
|
||||
return sGlobalMemoryFlusher.Init();
|
||||
#else
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsMemoryImpl::Shutdown()
|
||||
{
|
||||
#ifdef NS_MEMORY_FLUSHER_THREAD
|
||||
sGlobalMemoryFlusher.StopAndJoin();
|
||||
#endif
|
||||
|
||||
if (sFlushLock) PR_DestroyLock(sFlushLock);
|
||||
sFlushLock = nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void **aResult)
|
||||
{
|
||||
NS_ENSURE_NO_AGGREGATION(outer);
|
||||
return sGlobalMemory.QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
|
||||
{
|
||||
@@ -427,18 +288,18 @@ nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
|
||||
|
||||
{
|
||||
// Are we already flushing?
|
||||
nsAutoLock l(mFlushLock);
|
||||
if (mIsFlushing)
|
||||
nsAutoLock l(sFlushLock);
|
||||
if (sIsFlushing)
|
||||
return NS_OK;
|
||||
|
||||
// Well, we are now!
|
||||
mIsFlushing = PR_TRUE;
|
||||
sIsFlushing = PR_TRUE;
|
||||
}
|
||||
|
||||
// Run the flushers immediately if we can; otherwise, proxy to the
|
||||
// UI thread an run 'em asynchronously.
|
||||
if (aImmediate) {
|
||||
rv = RunFlushers(this, aReason);
|
||||
rv = RunFlushers(aReason);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIEventQueueService> eqs = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
|
||||
@@ -446,10 +307,10 @@ nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
|
||||
nsCOMPtr<nsIEventQueue> eq;
|
||||
rv = eqs->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eq));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PL_InitEvent(&mFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent);
|
||||
mFlushEvent.mReason = aReason;
|
||||
PL_InitEvent(&sFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent);
|
||||
sFlushEvent.mReason = aReason;
|
||||
|
||||
rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &mFlushEvent));
|
||||
rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &sFlushEvent));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,17 +319,17 @@ nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryImpl::RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason)
|
||||
nsMemoryImpl::RunFlushers(const PRUnichar* aReason)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
|
||||
if (os) {
|
||||
os->NotifyObservers(aSelf, "memory-pressure", aReason);
|
||||
os->NotifyObservers(this, "memory-pressure", aReason);
|
||||
}
|
||||
|
||||
{
|
||||
// Done flushing
|
||||
nsAutoLock l(aSelf->mFlushLock);
|
||||
aSelf->mIsFlushing = PR_FALSE;
|
||||
nsAutoLock l(sFlushLock);
|
||||
sIsFlushing = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -477,10 +338,9 @@ nsMemoryImpl::RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason)
|
||||
void*
|
||||
nsMemoryImpl::HandleFlushEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsMemoryImpl* self = NS_STATIC_CAST(nsMemoryImpl*, PL_GetEventOwner(aEvent));
|
||||
FlushEvent* event = NS_REINTERPRET_CAST(FlushEvent*, aEvent);
|
||||
|
||||
RunFlushers(self, event->mReason);
|
||||
sGlobalMemory.RunFlushers(event->mReason);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -490,59 +350,159 @@ nsMemoryImpl::DestroyFlushEvent(PLEvent* aEvent)
|
||||
// no-op, since mEvent is a member of nsMemoryImpl
|
||||
}
|
||||
|
||||
static void
|
||||
EnsureGlobalMemoryService()
|
||||
PRLock*
|
||||
nsMemoryImpl::sFlushLock;
|
||||
|
||||
PRBool
|
||||
nsMemoryImpl::sIsFlushing = PR_FALSE;
|
||||
|
||||
nsMemoryImpl::FlushEvent
|
||||
nsMemoryImpl::sFlushEvent;
|
||||
|
||||
extern "C" NS_EXPORT void*
|
||||
NS_Alloc(PRSize size)
|
||||
{
|
||||
if (gMemory) return;
|
||||
nsresult rv = nsMemoryImpl::Create(nsnull, NS_GET_IID(nsIMemory), (void**)&gMemory);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "nsMemoryImpl::Create failed");
|
||||
NS_ASSERTION(gMemory, "improper xpcom initialization");
|
||||
NS_ASSERTION(size, "NS_Alloc of size 0");
|
||||
|
||||
void* result = MALLOC1(size);
|
||||
if (! result) {
|
||||
// Request an asynchronous flush
|
||||
sGlobalMemory.FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryImpl::Startup()
|
||||
extern "C" NS_EXPORT void*
|
||||
NS_Realloc(void* ptr, PRSize size)
|
||||
{
|
||||
EnsureGlobalMemoryService();
|
||||
if (! gMemory)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ASSERTION(size, "NS_Realloc of size 0");
|
||||
void* result = REALLOC1(ptr, size);
|
||||
if (! result) {
|
||||
// Request an asynchronous flush
|
||||
sGlobalMemory.FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT void
|
||||
NS_Free(void* ptr)
|
||||
{
|
||||
PR_Free(ptr);
|
||||
}
|
||||
|
||||
#ifdef NS_MEMORY_FLUSHER_THREAD
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE1(MemoryFlusher, nsIRunnable);
|
||||
|
||||
NS_IMETHODIMP
|
||||
MemoryFlusher::Run()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Create and start a memory flusher thread
|
||||
rv = MemoryFlusher::Create(&gMemory->mFlusher, gMemory);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
sRunning = PR_TRUE;
|
||||
|
||||
rv = NS_NewThread(getter_AddRefs(gMemory->mFlusherThread),
|
||||
gMemory->mFlusher,
|
||||
0, /* XXX use default stack size? */
|
||||
PR_JOINABLE_THREAD);
|
||||
while (1) {
|
||||
PRStatus status;
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
#endif
|
||||
{
|
||||
nsAutoLock l(sLock);
|
||||
if (! sRunning) {
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemoryImpl::Shutdown()
|
||||
{
|
||||
if (gMemory) {
|
||||
#ifdef NS_MEMORY_FLUSHER_THREAD
|
||||
if (gMemory->mFlusher) {
|
||||
// Stop the runnable...
|
||||
gMemory->mFlusher->Stop();
|
||||
NS_RELEASE(gMemory->mFlusher);
|
||||
|
||||
// ...and wait for the thread to exit
|
||||
if (gMemory->mFlusherThread)
|
||||
gMemory->mFlusherThread->Join();
|
||||
status = PR_WaitCondVar(sCVar, sTimeout);
|
||||
}
|
||||
|
||||
if (status != PR_SUCCESS) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! sRunning) {
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
PRBool isLowMemory;
|
||||
rv = sGlobalMemory.IsLowMemory(&isLowMemory);
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
#ifdef NS_TEST_MEMORY_FLUSHER
|
||||
// Fire the flusher *every* time
|
||||
isLowMemory = PR_TRUE;
|
||||
#endif
|
||||
|
||||
NS_RELEASE(gMemory);
|
||||
gMemory = nsnull;
|
||||
if (isLowMemory) {
|
||||
sGlobalMemory.FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
sRunning = PR_FALSE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MemoryFlusher::Init()
|
||||
{
|
||||
sTimeout = PR_SecondsToInterval(kInitialTimeout);
|
||||
sLock = PR_NewLock();
|
||||
if (!sLock) return NS_ERROR_FAILURE;
|
||||
|
||||
sCVar = PR_NewCondVar(sLock);
|
||||
if (!sCVar) return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_NewThread(&sThread,
|
||||
this,
|
||||
0, /* XXX use default stack size? */
|
||||
PR_JOINABLE_THREAD);
|
||||
}
|
||||
|
||||
void
|
||||
MemoryFlusher::StopAndJoin()
|
||||
{
|
||||
if (sRunning) {
|
||||
{
|
||||
nsAutoLock l(sLock);
|
||||
sRunning = PR_FALSE;
|
||||
PR_NotifyCondVar(sCVar);
|
||||
}
|
||||
|
||||
if (sThread)
|
||||
sThread->Join();
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(sThread);
|
||||
|
||||
if (sLock)
|
||||
PR_DestroyLock(sLock);
|
||||
|
||||
if (sCVar)
|
||||
PR_DestroyCondVar(sCVar);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
MemoryFlusher::sRunning;
|
||||
|
||||
PRIntervalTime
|
||||
MemoryFlusher::sTimeout;
|
||||
|
||||
PRLock*
|
||||
MemoryFlusher::sLock;
|
||||
|
||||
PRCondVar*
|
||||
MemoryFlusher::sCVar;
|
||||
|
||||
nsIThread*
|
||||
MemoryFlusher::sThread;
|
||||
|
||||
#endif // NS_MEMORY_FLUSHER_THREAD
|
||||
|
||||
nsresult
|
||||
NS_GetMemoryManager(nsIMemory* *result)
|
||||
{
|
||||
return sGlobalMemory.QueryInterface(NS_GET_IID(nsIMemory), (void**) result);
|
||||
}
|
||||
|
||||
@@ -38,54 +38,45 @@
|
||||
#ifndef nsMemoryImpl_h__
|
||||
#define nsMemoryImpl_h__
|
||||
|
||||
#include "nsMemory.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMemory.h"
|
||||
#include "prlock.h"
|
||||
#include "plevent.h"
|
||||
|
||||
struct PRLock;
|
||||
class MemoryFlusher;
|
||||
// nsMemoryImpl is a static object. We can do this because it doesn't have
|
||||
// a constructor/destructor or any instance members. Please don't add
|
||||
// instance member variables, only static member variables.
|
||||
|
||||
class nsMemoryImpl : public nsIMemory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
// We don't use the generic macros because we are a special static object
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aResult);
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void) { return 1; }
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) { return 1; }
|
||||
|
||||
NS_DECL_NSIMEMORY
|
||||
|
||||
nsMemoryImpl();
|
||||
static NS_HIDDEN_(nsresult) Startup();
|
||||
static NS_HIDDEN_(void) Shutdown();
|
||||
static NS_METHOD Create(nsISupports* outer,
|
||||
const nsIID& aIID, void **aResult);
|
||||
|
||||
nsresult FlushMemory(const PRUnichar* aReason, PRBool aImmediate);
|
||||
|
||||
// called from xpcom initialization/finalization:
|
||||
static nsresult Startup();
|
||||
static nsresult Shutdown();
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
|
||||
|
||||
private:
|
||||
~nsMemoryImpl();
|
||||
NS_HIDDEN_(nsresult) FlushMemory(const PRUnichar* aReason, PRBool aImmediate);
|
||||
|
||||
protected:
|
||||
MemoryFlusher* mFlusher;
|
||||
nsCOMPtr<nsIThread> mFlusherThread;
|
||||
|
||||
PRLock* mFlushLock;
|
||||
PRBool mIsFlushing;
|
||||
|
||||
struct FlushEvent {
|
||||
PLEvent mEvent;
|
||||
const PRUnichar* mReason;
|
||||
};
|
||||
|
||||
FlushEvent mFlushEvent;
|
||||
NS_HIDDEN_(nsresult) RunFlushers(const PRUnichar* aReason);
|
||||
static NS_HIDDEN_(void*) PR_CALLBACK HandleFlushEvent(PLEvent* aEvent);
|
||||
static NS_HIDDEN_(void) PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent);
|
||||
|
||||
static nsresult RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason);
|
||||
static PRLock* sFlushLock;
|
||||
static PRBool sIsFlushing;
|
||||
|
||||
static void* PR_CALLBACK HandleFlushEvent(PLEvent* aEvent);
|
||||
static void PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent);
|
||||
static FlushEvent sFlushEvent;
|
||||
};
|
||||
|
||||
#endif // nsMemoryImpl_h__
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
# define NS_NewNativeLocalFile NS_NewNativeLocalFile_P
|
||||
# define NS_GetDebug NS_GetDebug_P
|
||||
# define NS_GetTraceRefcnt NS_GetTraceRefcnt_P
|
||||
# define NS_Alloc NS_Alloc_P
|
||||
# define NS_Realloc NS_Realloc_P
|
||||
# define NS_Free NS_Free_P
|
||||
#endif
|
||||
|
||||
#include "nscore.h"
|
||||
@@ -208,6 +211,52 @@ NS_NewNativeLocalFile(const nsACString &path,
|
||||
PRBool followLinks,
|
||||
nsILocalFile* *result);
|
||||
|
||||
/**
|
||||
* Allocates a block of memory of a particular size. If the memory cannot
|
||||
* be allocated (because of an out-of-memory condition), null is returned.
|
||||
*
|
||||
* @status FROZEN
|
||||
*
|
||||
* @param size The size of the block to allocate
|
||||
* @result The block of memory
|
||||
* @note This function is thread-safe.
|
||||
*/
|
||||
extern "C" NS_COM void*
|
||||
NS_Alloc(PRSize size);
|
||||
|
||||
/**
|
||||
* Reallocates a block of memory to a new size.
|
||||
*
|
||||
* @status FROZEN
|
||||
*
|
||||
* @param ptr The block of memory to reallocate. This block must originally
|
||||
have been allocated by NS_Alloc or NS_Realloc
|
||||
* @param size The new size. If 0, frees the block like NS_Free
|
||||
* @result The reallocated block of memory
|
||||
* @note This function is thread-safe.
|
||||
*
|
||||
* If ptr is null, this function behaves like NS_Alloc.
|
||||
* If s is the size of the block to which ptr points, the first min(s, size)
|
||||
* bytes of ptr's block are copied to the new block. If the allocation
|
||||
* succeeds, ptr is freed and a pointer to the new block is returned. If the
|
||||
* allocation fails, ptr is not freed and null is returned. The returned
|
||||
* value may be the same as ptr.
|
||||
*/
|
||||
extern "C" NS_COM void*
|
||||
NS_Realloc(void* ptr, PRSize size);
|
||||
|
||||
/**
|
||||
* Frees a block of memory. Null is a permissible value, in which case no
|
||||
* action is taken.
|
||||
*
|
||||
* @status FROZEN
|
||||
*
|
||||
* @param ptr The block of memory to free. This block must originally have
|
||||
* been allocated by NS_Alloc or NS_Realloc
|
||||
* @note This function is thread-safe.
|
||||
*/
|
||||
extern "C" NS_COM void
|
||||
NS_Free(void* ptr);
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_GetDebug(nsIDebug* *result);
|
||||
|
||||
@@ -43,11 +43,11 @@
|
||||
#ifndef MOZILLA_STRICT_API
|
||||
# define NS_RegisterXPCOMExitRoutine NS_RegisterXPCOMExitRoutine_P
|
||||
# define NS_UnregisterXPCOMExitRoutine NS_UnregisterXPCOMExitRoutine_P
|
||||
# define NS_GetFrozenFunctions NS_GetFrozenFunctions_P
|
||||
#endif
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsStringAPI.h"
|
||||
|
||||
class nsStringContainer;
|
||||
class nsCStringContainer;
|
||||
@@ -111,8 +111,12 @@ typedef nsresult (* CStringSetDataFunc)(nsACString&, const char*, PRUint32);
|
||||
typedef nsresult (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32);
|
||||
typedef nsresult (* CStringCopyFunc)(nsACString &, const nsACString &);
|
||||
|
||||
typedef nsresult (* CStringToUTF16)(const nsACString &, PRUint32, const nsAString &);
|
||||
typedef nsresult (* UTF16ToCString)(const nsAString &, PRUint32, const nsACString &);
|
||||
typedef nsresult (* CStringToUTF16)(const nsACString &, nsCStringEncoding, nsAString &);
|
||||
typedef nsresult (* UTF16ToCString)(const nsAString &, nsCStringEncoding, nsACString &);
|
||||
|
||||
typedef void* (* AllocFunc)(PRSize size);
|
||||
typedef void* (* ReallocFunc)(void* ptr, PRSize size);
|
||||
typedef void (* FreeFunc)(void* ptr);
|
||||
|
||||
// PRIVATE
|
||||
typedef nsresult (* RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority);
|
||||
@@ -155,6 +159,9 @@ typedef struct XPCOMFunctions{
|
||||
UTF16ToCString utf16ToCString;
|
||||
StringCloneDataFunc stringCloneData;
|
||||
CStringCloneDataFunc cstringCloneData;
|
||||
AllocFunc allocFunc;
|
||||
ReallocFunc reallocFunc;
|
||||
FreeFunc freeFunc;
|
||||
|
||||
} XPCOMFunctions;
|
||||
|
||||
|
||||
@@ -384,21 +384,6 @@ static const nsModuleComponentInfo components[] = {
|
||||
|
||||
const int components_length = sizeof(components) / sizeof(components[0]);
|
||||
|
||||
// gMemory will be freed during shutdown.
|
||||
static nsIMemory* gMemory = nsnull;
|
||||
nsresult NS_COM NS_GetMemoryManager(nsIMemory* *result)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (!gMemory)
|
||||
{
|
||||
rv = nsMemoryImpl::Create(nsnull,
|
||||
NS_GET_IID(nsIMemory),
|
||||
(void**)&gMemory);
|
||||
}
|
||||
NS_IF_ADDREF(*result = gMemory);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// gDebug will be freed during shutdown.
|
||||
static nsIDebug* gDebug = nsnull;
|
||||
nsresult NS_COM NS_GetDebug(nsIDebug** result)
|
||||
@@ -856,7 +841,6 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
||||
|
||||
EmptyEnumeratorImpl::Shutdown();
|
||||
nsMemoryImpl::Shutdown();
|
||||
NS_IF_RELEASE(gMemory);
|
||||
|
||||
nsThread::Shutdown();
|
||||
NS_PurgeAtomTable();
|
||||
@@ -876,65 +860,3 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#define GET_FUNC(_tag, _decl, _name) \
|
||||
functions->_tag = (_decl) PR_FindSymbol(xpcomLib, _name); \
|
||||
if (!functions->_tag) goto end
|
||||
|
||||
nsresult NS_COM PR_CALLBACK
|
||||
NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* libraryPath)
|
||||
{
|
||||
if (!functions)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (functions->version != XPCOM_GLUE_VERSION)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRLibrary *xpcomLib = PR_LoadLibrary(libraryPath);
|
||||
if (!xpcomLib)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
GET_FUNC(init, InitFunc, "NS_InitXPCOM2");
|
||||
GET_FUNC(shutdown, ShutdownFunc, "NS_ShutdownXPCOM");
|
||||
GET_FUNC(getServiceManager, GetServiceManagerFunc, "NS_GetServiceManager");
|
||||
GET_FUNC(getComponentManager, GetComponentManagerFunc, "NS_GetComponentManager");
|
||||
GET_FUNC(getComponentRegistrar, GetComponentRegistrarFunc, "NS_GetComponentRegistrar");
|
||||
GET_FUNC(getMemoryManager, GetMemoryManagerFunc, "NS_GetMemoryManager");
|
||||
GET_FUNC(newLocalFile, NewLocalFileFunc, "NS_NewLocalFile");
|
||||
GET_FUNC(newNativeLocalFile, NewNativeLocalFileFunc, "NS_NewNativeLocalFile");
|
||||
GET_FUNC(registerExitRoutine, RegisterXPCOMExitRoutineFunc, "NS_RegisterXPCOMExitRoutine");
|
||||
GET_FUNC(unregisterExitRoutine, UnregisterXPCOMExitRoutineFunc, "NS_UnregisterXPCOMExitRoutine");
|
||||
|
||||
// these functions were added post 1.4 (need to check size of |functions|)
|
||||
if (functions->size > offsetof(XPCOMFunctions, getTraceRefcnt)) {
|
||||
GET_FUNC(getDebug, GetDebugFunc, "NS_GetDebug");
|
||||
GET_FUNC(getTraceRefcnt, GetTraceRefcntFunc, "NS_GetTraceRefcnt");
|
||||
}
|
||||
|
||||
// these functions were added post 1.6 (need to check size of |functions|)
|
||||
if (functions->size > offsetof(XPCOMFunctions, cstringCloneData)) {
|
||||
GET_FUNC(stringContainerInit, StringContainerInitFunc, "NS_StringContainerInit");
|
||||
GET_FUNC(stringContainerFinish, StringContainerFinishFunc, "NS_StringContainerFinish");
|
||||
GET_FUNC(stringGetData, StringGetDataFunc, "NS_StringGetData");
|
||||
GET_FUNC(stringSetData, StringSetDataFunc, "NS_StringSetData");
|
||||
GET_FUNC(stringSetDataRange, StringSetDataRangeFunc, "NS_StringSetDataRange");
|
||||
GET_FUNC(stringCopy, StringCopyFunc, "NS_StringCopy");
|
||||
GET_FUNC(cstringContainerInit, CStringContainerInitFunc, "NS_CStringContainerInit");
|
||||
GET_FUNC(cstringContainerFinish, CStringContainerFinishFunc, "NS_CStringContainerFinish");
|
||||
GET_FUNC(cstringGetData, CStringGetDataFunc, "NS_CStringGetData");
|
||||
GET_FUNC(cstringSetData, CStringSetDataFunc, "NS_CStringSetData");
|
||||
GET_FUNC(cstringSetDataRange, CStringSetDataRangeFunc, "NS_CStringSetDataRange");
|
||||
GET_FUNC(cstringCopy, CStringCopyFunc, "NS_CStringCopy");
|
||||
GET_FUNC(cstringToUTF16, CStringToUTF16, "NS_CStringToUTF16");
|
||||
GET_FUNC(utf16ToCString, UTF16ToCString, "NS_UTF16ToCString");
|
||||
GET_FUNC(stringCloneData, StringCloneDataFunc, "NS_StringCloneData");
|
||||
GET_FUNC(cstringCloneData, CStringCloneDataFunc, "NS_CStringCloneData");
|
||||
}
|
||||
|
||||
rv = NS_OK;
|
||||
end:
|
||||
PR_UnloadLibrary(xpcomLib); // the library is refcnt'ed above by the caller.
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,9 @@ DIRS = standalone
|
||||
MODULE = xpcom
|
||||
LIBRARY_NAME = xpcomglue_s
|
||||
|
||||
REQUIRES = $(NULL)
|
||||
REQUIRES = \
|
||||
string \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../build \
|
||||
|
||||
@@ -40,89 +40,25 @@
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
|
||||
static nsIMemory* gMemory = nsnull;
|
||||
|
||||
static NS_METHOD FreeGlobalMemory(void)
|
||||
{
|
||||
NS_IF_RELEASE(gMemory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#define ENSURE_ALLOCATOR \
|
||||
(gMemory ? PR_TRUE : (PRBool)(SetupGlobalMemory() != nsnull))
|
||||
|
||||
static nsIMemory*
|
||||
SetupGlobalMemory()
|
||||
{
|
||||
NS_ASSERTION(!gMemory, "bad call");
|
||||
NS_GetMemoryManager(&gMemory);
|
||||
NS_ASSERTION(gMemory, "can't get memory manager!");
|
||||
NS_RegisterXPCOMExitRoutine(FreeGlobalMemory, 0);
|
||||
return gMemory;
|
||||
}
|
||||
|
||||
#ifdef XPCOM_GLUE
|
||||
nsresult GlueStartupMemory()
|
||||
{
|
||||
NS_ASSERTION(!gMemory, "bad call");
|
||||
NS_GetMemoryManager(&gMemory);
|
||||
NS_ASSERTION(gMemory, "can't get memory manager!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void GlueShutdownMemory()
|
||||
{
|
||||
NS_IF_RELEASE(gMemory);
|
||||
}
|
||||
#endif
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsMemory static helper routines
|
||||
|
||||
NS_COM_GLUE void*
|
||||
nsMemory::Alloc(PRSize size)
|
||||
{
|
||||
if (!ENSURE_ALLOCATOR)
|
||||
return nsnull;
|
||||
|
||||
return gMemory->Alloc(size);
|
||||
}
|
||||
|
||||
NS_COM_GLUE void*
|
||||
nsMemory::Realloc(void* ptr, PRSize size)
|
||||
{
|
||||
if (!ENSURE_ALLOCATOR)
|
||||
return nsnull;
|
||||
|
||||
return gMemory->Realloc(ptr, size);
|
||||
}
|
||||
|
||||
NS_COM_GLUE void
|
||||
nsMemory::Free(void* ptr)
|
||||
{
|
||||
if (!ENSURE_ALLOCATOR)
|
||||
return;
|
||||
|
||||
gMemory->Free(ptr);
|
||||
}
|
||||
|
||||
NS_COM_GLUE nsresult
|
||||
nsMemory::HeapMinimize(PRBool aImmediate)
|
||||
{
|
||||
if (!ENSURE_ALLOCATOR)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIMemory> mem;
|
||||
nsresult rv = NS_GetMemoryManager(getter_AddRefs(mem));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return gMemory->HeapMinimize(aImmediate);
|
||||
return mem->HeapMinimize(aImmediate);
|
||||
}
|
||||
|
||||
NS_COM_GLUE void*
|
||||
nsMemory::Clone(const void* ptr, PRSize size)
|
||||
{
|
||||
if (!ENSURE_ALLOCATOR)
|
||||
return nsnull;
|
||||
|
||||
void* newPtr = gMemory->Alloc(size);
|
||||
void* newPtr = NS_Alloc(size);
|
||||
if (newPtr)
|
||||
memcpy(newPtr, ptr, size);
|
||||
return newPtr;
|
||||
@@ -131,12 +67,11 @@ nsMemory::Clone(const void* ptr, PRSize size)
|
||||
NS_COM_GLUE nsIMemory*
|
||||
nsMemory::GetGlobalMemoryService()
|
||||
{
|
||||
if (!ENSURE_ALLOCATOR)
|
||||
return nsnull;
|
||||
nsIMemory* mem;
|
||||
nsresult rv = NS_GetMemoryManager(&mem);
|
||||
if (NS_FAILED(rv)) return nsnull;
|
||||
|
||||
nsIMemory* result = gMemory;
|
||||
NS_IF_ADDREF(result);
|
||||
return result;
|
||||
return mem;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#ifndef nsMemory_h__
|
||||
#define nsMemory_h__
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsIMemory.h"
|
||||
|
||||
#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
|
||||
@@ -63,11 +64,17 @@
|
||||
class nsMemory
|
||||
{
|
||||
public:
|
||||
static NS_COM_GLUE void* Alloc(size_t size);
|
||||
static NS_COM_GLUE void* Realloc(void* ptr, size_t size);
|
||||
static NS_COM_GLUE void Free(void* ptr);
|
||||
static NS_HIDDEN_(void*) Alloc(size_t size)
|
||||
{ return NS_Alloc(size); }
|
||||
|
||||
static NS_HIDDEN_(void*) Realloc(void* ptr, PRSize size)
|
||||
{ return NS_Realloc(ptr, size); }
|
||||
|
||||
static NS_HIDDEN_(void) Free(void* ptr)
|
||||
{ NS_Free(ptr); }
|
||||
|
||||
static NS_COM_GLUE nsresult HeapMinimize(PRBool aImmediate);
|
||||
static NS_COM_GLUE void* Clone(const void* ptr, size_t size);
|
||||
static NS_COM_GLUE void* Clone(const void* ptr, PRSize size);
|
||||
static NS_COM_GLUE nsIMemory* GetGlobalMemoryService(); // AddRefs
|
||||
};
|
||||
|
||||
@@ -105,7 +112,7 @@ public:
|
||||
PRInt32 iter_ = PRInt32(size); \
|
||||
while (--iter_ >= 0) \
|
||||
freeFunc((array)[iter_]); \
|
||||
nsMemory::Free((array)); \
|
||||
NS_Free((array)); \
|
||||
PR_END_MACRO
|
||||
|
||||
// convenience macros for commonly used calls. mmmmm. syntactic sugar.
|
||||
@@ -121,7 +128,7 @@ public:
|
||||
* @param array The array to be freed.
|
||||
*/
|
||||
#define NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(size, array) \
|
||||
NS_FREE_XPCOM_POINTER_ARRAY((size), (array), nsMemory::Free)
|
||||
NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_Free)
|
||||
|
||||
/**
|
||||
* Macro to free an array of pointers to nsISupports (or classes
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "nsXPCOMGlue.h"
|
||||
|
||||
#include "nspr.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsGREDirServiceProvider.h"
|
||||
@@ -54,9 +53,7 @@
|
||||
|
||||
void GRE_AddGREToEnvironment();
|
||||
|
||||
// functions provided by nsMemory.cpp and nsDebug.cpp
|
||||
nsresult GlueStartupMemory();
|
||||
void GlueShutdownMemory();
|
||||
// functions provided by nsDebug.cpp
|
||||
nsresult GlueStartupDebug();
|
||||
void GlueShutdownDebug();
|
||||
|
||||
@@ -152,13 +149,6 @@ nsresult XPCOMGlueStartup(const char* xpcomFile)
|
||||
if (NS_FAILED(rv))
|
||||
goto bail;
|
||||
|
||||
// startup the nsMemory
|
||||
rv = GlueStartupMemory();
|
||||
if (NS_FAILED(rv)) {
|
||||
GlueShutdownDebug();
|
||||
goto bail;
|
||||
}
|
||||
|
||||
GRE_AddGREToEnvironment();
|
||||
return NS_OK;
|
||||
|
||||
@@ -177,8 +167,6 @@ nsresult XPCOMGlueShutdown()
|
||||
return NS_OK;
|
||||
#else
|
||||
|
||||
GlueShutdownMemory();
|
||||
|
||||
GlueShutdownDebug();
|
||||
|
||||
if (xpcomLib) {
|
||||
@@ -411,7 +399,7 @@ NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest)
|
||||
NS_CStringToUTF16(const nsACString &aSrc, nsCStringEncoding aSrcEncoding, nsAString &aDest)
|
||||
{
|
||||
if (!xpcomFunctions.cstringToUTF16)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@@ -419,13 +407,36 @@ NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDes
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest)
|
||||
NS_UTF16ToCString(const nsAString &aSrc, nsCStringEncoding aDestEncoding, nsACString &aDest)
|
||||
{
|
||||
if (!xpcomFunctions.utf16ToCString)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest);
|
||||
}
|
||||
|
||||
extern "C" NS_COM void*
|
||||
NS_Alloc(PRSize size)
|
||||
{
|
||||
if (!xpcomFunctions.allocFunc)
|
||||
return nsnull;
|
||||
return xpcomFunctions.allocFunc(size);
|
||||
}
|
||||
|
||||
extern "C" NS_COM void*
|
||||
NS_Realloc(void* ptr, PRSize size)
|
||||
{
|
||||
if (!xpcomFunctions.reallocFunc)
|
||||
return nsnull;
|
||||
return xpcomFunctions.reallocFunc(ptr, size);
|
||||
}
|
||||
|
||||
extern "C" NS_COM void
|
||||
NS_Free(void* ptr)
|
||||
{
|
||||
if (xpcomFunctions.freeFunc)
|
||||
xpcomFunctions.freeFunc(ptr);
|
||||
}
|
||||
|
||||
#endif // #ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING
|
||||
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
#ifndef nsEmbedString_h___
|
||||
#define nsEmbedString_h___
|
||||
|
||||
#ifndef MOZILLA_STRICT_API
|
||||
#error nsEmbedString requires defining MOZILLA_STRICT_API
|
||||
#endif
|
||||
|
||||
#include "nsStringAPI.h"
|
||||
|
||||
class nsEmbedString : public nsStringContainer
|
||||
|
||||
@@ -637,14 +637,14 @@ NS_UTF16ToCString(const nsAString &aSource, nsCStringEncoding aDestEncoding,
|
||||
* internal definition of these classes from nsAString.h in the Mozilla tree.
|
||||
*/
|
||||
|
||||
#ifndef _IMPL_NS_STRINGAPI
|
||||
#ifdef MOZILLA_STRICT_API
|
||||
#define nsAString_external nsAString
|
||||
#define nsACString_external nsACString
|
||||
#endif
|
||||
|
||||
class nsAString_external
|
||||
{
|
||||
#ifndef _IMPL_NS_STRINGAPI
|
||||
#ifdef MOZILLA_STRICT_API
|
||||
|
||||
public:
|
||||
typedef PRUnichar char_type;
|
||||
@@ -718,7 +718,7 @@ public:
|
||||
|
||||
NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); }
|
||||
|
||||
#endif // _IMPL_NS_STRINGAPI
|
||||
#endif // MOZILLA_STRICT_API
|
||||
|
||||
private:
|
||||
void *v;
|
||||
@@ -726,7 +726,7 @@ private:
|
||||
|
||||
class nsACString_external
|
||||
{
|
||||
#ifndef _IMPL_NS_STRINGAPI
|
||||
#ifdef MOZILLA_STRICT_API
|
||||
|
||||
public:
|
||||
typedef char char_type;
|
||||
@@ -800,7 +800,7 @@ public:
|
||||
|
||||
NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); }
|
||||
|
||||
#endif // _IMPL_NS_STRINGAPI
|
||||
#endif // MOZILLA_STRICT_API
|
||||
|
||||
private:
|
||||
void *v;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
* Benjamin Smedberg <bsmedberg@covad.net>
|
||||
*
|
||||
* 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
|
||||
@@ -38,6 +39,70 @@
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "nsStringAPI.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const XPCOMFunctions kFrozenFunctions = {
|
||||
XPCOM_GLUE_VERSION,
|
||||
sizeof(XPCOMFunctions),
|
||||
&NS_InitXPCOM2_P,
|
||||
&NS_ShutdownXPCOM_P,
|
||||
&NS_GetServiceManager_P,
|
||||
&NS_GetComponentManager_P,
|
||||
&NS_GetComponentRegistrar_P,
|
||||
&NS_GetMemoryManager_P,
|
||||
&NS_NewLocalFile_P,
|
||||
&NS_NewNativeLocalFile_P,
|
||||
&NS_RegisterXPCOMExitRoutine_P,
|
||||
&NS_UnregisterXPCOMExitRoutine_P,
|
||||
|
||||
// these functions were added post 1.4
|
||||
&NS_GetDebug_P,
|
||||
&NS_GetTraceRefcnt_P,
|
||||
|
||||
// these functions were added post 1.6
|
||||
&NS_StringContainerInit,
|
||||
&NS_StringContainerFinish,
|
||||
&NS_StringGetData,
|
||||
&NS_StringSetData,
|
||||
&NS_StringSetDataRange,
|
||||
&NS_StringCopy,
|
||||
&NS_CStringContainerInit,
|
||||
&NS_CStringContainerFinish,
|
||||
&NS_CStringGetData,
|
||||
&NS_CStringSetData,
|
||||
&NS_CStringSetDataRange,
|
||||
&NS_CStringCopy,
|
||||
&NS_CStringToUTF16,
|
||||
&NS_UTF16ToCString,
|
||||
&NS_StringCloneData,
|
||||
&NS_CStringCloneData,
|
||||
|
||||
// these functions were added post 1.7 (Firefox 1.0)
|
||||
&NS_Alloc_P,
|
||||
&NS_Realloc_P,
|
||||
&NS_Free_P
|
||||
};
|
||||
|
||||
extern "C" NS_EXPORT nsresult
|
||||
NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* /* libraryPath */)
|
||||
{
|
||||
if (!functions)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (functions->version != XPCOM_GLUE_VERSION)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 size = functions->size;
|
||||
if (size > sizeof(XPCOMFunctions))
|
||||
size = sizeof(XPCOMFunctions);
|
||||
|
||||
size -= offsetof(XPCOMFunctions, init);
|
||||
|
||||
memcpy(&functions->init, &kFrozenFunctions.init, size);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stubs for nsXPCOM.h
|
||||
*/
|
||||
@@ -136,9 +201,23 @@ NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
|
||||
return NS_UnregisterXPCOMExitRoutine_P(exitRoutine);
|
||||
}
|
||||
|
||||
#undef NS_GetFrozenFunctions
|
||||
extern "C" NS_EXPORT nsresult
|
||||
NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath)
|
||||
#undef NS_Alloc
|
||||
extern "C" NS_EXPORT void*
|
||||
NS_Alloc(PRSize size)
|
||||
{
|
||||
return NS_GetFrozenFunctions_P(entryPoints, libraryPath);
|
||||
return NS_Alloc_P(size);
|
||||
}
|
||||
|
||||
#undef NS_Realloc
|
||||
extern "C" NS_EXPORT void*
|
||||
NS_Realloc(void* ptr, PRSize size)
|
||||
{
|
||||
return NS_Realloc_P(ptr, size);
|
||||
}
|
||||
|
||||
#undef NS_Free
|
||||
extern "C" NS_EXPORT void
|
||||
NS_Free(void* ptr)
|
||||
{
|
||||
NS_Free_P(ptr);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define MOZILLA_STRICT_API
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsStringAPI.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
Reference in New Issue
Block a user