diff --git a/js/src/xpconnect/src/xpccallcontext.cpp b/js/src/xpconnect/src/xpccallcontext.cpp index fded8d0d1bac..754bead95655 100644 --- a/js/src/xpconnect/src/xpccallcontext.cpp +++ b/js/src/xpconnect/src/xpccallcontext.cpp @@ -98,18 +98,6 @@ XPCCallContext::Init(XPCContext::LangType callerLanguage, jsval *argv, jsval *rval) { - // Mark our internal string wrappers as not used. Make sure we do - // this before any early returns, as the destructor will assert - // based on this. - StringWrapperEntry *se = - reinterpret_cast(&mStringWrapperData); - - PRUint32 i; - for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) - { - se[i].mInUse = PR_FALSE; - } - if(!mXPC) return; @@ -424,15 +412,9 @@ XPCCallContext::~XPCCallContext() } #ifdef DEBUG + for(PRUint32 i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) { - StringWrapperEntry *se = - reinterpret_cast(&mStringWrapperData); - - PRUint32 i; - for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) - { - NS_ASSERTION(!se[i].mInUse, "Uh, string wrapper still in use!"); - } + NS_ASSERTION(!mScratchStrings[i].mInUse, "Uh, string wrapper still in use!"); } #endif @@ -443,13 +425,9 @@ XPCCallContext::~XPCCallContext() XPCReadableJSStringWrapper * XPCCallContext::NewStringWrapper(const PRUnichar *str, PRUint32 len) { - StringWrapperEntry *se = - reinterpret_cast(&mStringWrapperData); - - PRUint32 i; - for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) + for(PRUint32 i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) { - StringWrapperEntry& ent = se[i]; + StringWrapperEntry& ent = mScratchStrings[i]; if(!ent.mInUse) { @@ -457,7 +435,7 @@ XPCCallContext::NewStringWrapper(const PRUnichar *str, PRUint32 len) // Construct the string using placement new. - return new (&ent.mString) XPCReadableJSStringWrapper(str, len); + return new (ent.mString.addr()) XPCReadableJSStringWrapper(str, len); } } @@ -469,20 +447,16 @@ XPCCallContext::NewStringWrapper(const PRUnichar *str, PRUint32 len) void XPCCallContext::DeleteString(nsAString *string) { - StringWrapperEntry *se = - reinterpret_cast(&mStringWrapperData); - - PRUint32 i; - for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) + for(PRUint32 i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i) { - StringWrapperEntry& ent = se[i]; - if(string == &ent.mString) + StringWrapperEntry& ent = mScratchStrings[i]; + if(string == ent.mString.addr()) { // One of our internal strings is no longer in use, mark // it as such and destroy the string. ent.mInUse = PR_FALSE; - ent.mString.~XPCReadableJSStringWrapper(); + ent.mString.addr()->~XPCReadableJSStringWrapper(); return; } diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 357ed32ffade..102643b42e72 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -1254,23 +1254,18 @@ private: // String wrapper entry, holds a string, and a boolean that tells // whether the string is in use or not. + // + // NB: The string is not stored by value so that we avoid the cost of + // construction/destruction. struct StringWrapperEntry { - StringWrapperEntry() - : mInUse(PR_FALSE) - { - } + StringWrapperEntry() : mInUse(PR_FALSE) { } - XPCReadableJSStringWrapper mString; + js::AlignedStorage2 mString; PRBool mInUse; }; - // Reserve space for XPCCCX_STRING_CACHE_SIZE string wrapper - // entries for use on demand. It's important to not make this be - // string class members since we don't want to pay the cost of - // calling the constructors and destructors when the strings - // aren't being used. - char mStringWrapperData[sizeof(StringWrapperEntry) * XPCCCX_STRING_CACHE_SIZE]; + StringWrapperEntry mScratchStrings[XPCCCX_STRING_CACHE_SIZE]; }; class XPCLazyCallContext