thoroughly whack mallocfest in nsID/nsJSID and friends. b=410250, r+sr=jst, a=blocking1.9+
authordwitte@stanford.edu
Fri, 11 Jan 2008 20:30:42 -0800
changeset 10204 1ec9dbd46c1d30de23001a46cc50ef14713cadb8
parent 10203 87bac799cdfc2829b3bd9ae7d6ecb3e4694f9de7
child 10205 25b5544d43146d5d00fc08d0aa0bae17af177735
push idunknown
push userunknown
push dateunknown
reviewersblocking1.9
bugs410250
milestone1.9b3pre
thoroughly whack mallocfest in nsID/nsJSID and friends. b=410250, r+sr=jst, a=blocking1.9+
caps/src/nsNullPrincipal.cpp
caps/src/nsScriptSecurityManager.cpp
content/xbl/src/nsXBLPrototypeBinding.cpp
dom/src/base/nsDOMClassInfo.cpp
dom/src/base/nsScriptNameSpaceManager.cpp
extensions/java/xpcom/src/nsJavaWrapper.cpp
extensions/java/xpcom/src/nsJavaXPTCStub.cpp
extensions/java/xpcom/tools/genifaces/GenerateJavaInterfaces.cpp
extensions/python/xpcom/src/PyIInterfaceInfo.cpp
js/src/xpconnect/idl/xpcjsid.idl
js/src/xpconnect/src/xpccomponents.cpp
js/src/xpconnect/src/xpcconvert.cpp
js/src/xpconnect/src/xpcjsid.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcvariant.cpp
js/src/xpconnect/src/xpcwrappednative.cpp
toolkit/components/places/src/nsNavBookmarks.cpp
xpcom/glue/nsID.cpp
xpcom/glue/nsID.h
xpcom/reflect/xptinfo/src/xptiManifest.cpp
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -41,17 +41,16 @@
  * anything other than itself and chrome; null principals are not
  * same-origin with anything but themselves.
  */
 
 #include "nsNullPrincipal.h"
 #include "nsMemory.h"
 #include "nsIUUIDGenerator.h"
 #include "nsID.h"
-#include "prmem.h" // For PF_Free, 'cause nsID::ToString sucks like that
 #include "nsNetUtil.h"
 #include "nsIClassInfoImpl.h"
 #include "nsNetCID.h"
 
 static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
 
 NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
                             nsIPrincipal,
@@ -100,31 +99,29 @@ nsNullPrincipal::Init()
   nsCOMPtr<nsIUUIDGenerator> uuidgen =
     do_GetService("@mozilla.org/uuid-generator;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsID id;
   rv = uuidgen->GenerateUUIDInPlace(&id);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  char* chars = id.ToString();
-  NS_ENSURE_TRUE(chars, NS_ERROR_OUT_OF_MEMORY);
+  char chars[NSID_LENGTH];
+  id.ToProvidedString(chars);
 
-  PRUint32 suffixLen = strlen(chars);
+  PRUint32 suffixLen = NSID_LENGTH - 1;
   PRUint32 prefixLen = NS_ARRAY_LENGTH(NS_NULLPRINCIPAL_PREFIX) - 1;
 
   // Use an nsCString so we only do the allocation once here and then share
   // with nsJSPrincipals
   nsCString str;
   str.SetCapacity(prefixLen + suffixLen);
 
   str.Append(NS_NULLPRINCIPAL_PREFIX);
   str.Append(chars);
-
-  PR_Free(chars);
   
   if (str.Length() != prefixLen + suffixLen) {
     NS_WARNING("Out of memory allocating null-principal URI");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Use CID so we're sure we get the impl we want.  Note that creating the URI
   // directly is ok because we have our own private URI scheme.  In effect,
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -3067,18 +3067,18 @@ nsScriptSecurityManager::CanCreateInstan
     {
         rv = CheckComponentPermissions(cx, aCID);
     }
     if (NS_FAILED(rv))
 #endif
     {
         //-- Access denied, report an error
         nsCAutoString errorMsg("Permission denied to create instance of class. CID=");
-        nsXPIDLCString cidStr;
-        cidStr += aCID.ToString();
+        char cidStr[NSID_LENGTH];
+        aCID.ToProvidedString(cidStr);
         errorMsg.Append(cidStr);
         SetPendingException(cx, errorMsg.get());
 
 #ifdef DEBUG_CAPS_CanCreateInstance
         printf("DENIED\n");
     }
     else
     {
@@ -3098,18 +3098,18 @@ nsScriptSecurityManager::CanGetService(J
     nsCRT::free(cidStr);
 #endif
 
     nsresult rv = CheckXPCPermissions(nsnull, nsnull);
     if (NS_FAILED(rv))
     {
         //-- Access denied, report an error
         nsCAutoString errorMsg("Permission denied to get service. CID=");
-        nsXPIDLCString cidStr;
-        cidStr += aCID.ToString();
+        char cidStr[NSID_LENGTH];
+        aCID.ToProvidedString(cidStr);
         errorMsg.Append(cidStr);
         SetPendingException(cx, errorMsg.get());
 
 #ifdef DEBUG_CAPS_CanGetService
         printf("DENIED\n");
     }
     else
     {
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -1344,51 +1344,44 @@ nsXBLPrototypeBinding::ConstructInterfac
     char* token = nsCRT::strtok( str, ", ", &newStr );
     while( token != NULL ) {
       // get the InterfaceInfo for the name
       nsCOMPtr<nsIInterfaceInfo> iinfo;
       infoManager->GetInfoForName(token, getter_AddRefs(iinfo));
 
       if (iinfo) {
         // obtain an IID.
-        nsIID* iid = nsnull;
-        iinfo->GetInterfaceIID(&iid);
+        const nsIID* iid = nsnull;
+        iinfo->GetIIDShared(&iid);
 
         if (iid) {
           // We found a valid iid.  Add it to our table.
           nsIIDKey key(*iid);
           mInterfaceTable->Put(&key, mBinding);
 
           // this block adds the parent interfaces of each interface
           // defined in the xbl definition (implements="nsI...")
           nsCOMPtr<nsIInterfaceInfo> parentInfo;
           // if it has a parent, add it to the table
           while (NS_SUCCEEDED(iinfo->GetParent(getter_AddRefs(parentInfo))) && parentInfo) {
-            // free the nsMemory::Clone()ed iid
-            nsMemory::Free(iid);
-
             // get the iid
-            parentInfo->GetInterfaceIID(&iid);
+            parentInfo->GetIIDShared(&iid);
 
             // don't add nsISupports to the table
             if (!iid || iid->Equals(NS_GET_IID(nsISupports)))
               break;
 
             // add the iid to the table
             nsIIDKey parentKey(*iid);
             mInterfaceTable->Put(&parentKey, mBinding);
 
             // look for the next parent
             iinfo = parentInfo;
           }
         }
-
-        // free the nsMemory::Clone()ed iid
-        if (iid)
-          nsMemory::Free(iid);
       }
 
       token = nsCRT::strtok( newStr, ", ", &newStr );
     }
   }
 
   return NS_OK;
 }
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -1701,34 +1701,31 @@ nsDOMClassInfo::RegisterClassProtos(PRIn
   NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
 
   nsCOMPtr<nsIInterfaceInfo> if_info;
   PRBool first = PR_TRUE;
 
   iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
 
   while (if_info) {
-    nsIID *iid = nsnull;
-
-    if_info->GetInterfaceIID(&iid);
+    const nsIID *iid = nsnull;
+
+    if_info->GetIIDShared(&iid);
     NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
 
     if (iid->Equals(NS_GET_IID(nsISupports))) {
-      nsMemory::Free(iid);
-
       break;
     }
 
-    nsXPIDLCString name;
-    if_info->GetName(getter_Copies(name));
+    const char *name = nsnull;
+    if_info->GetNameShared(&name);
+    NS_ENSURE_TRUE(name, NS_ERROR_UNEXPECTED);
 
     nameSpaceManager->RegisterClassProto(CutPrefix(name), iid, &found_old);
 
-    nsMemory::Free(iid);
-
     if (first) {
       first = PR_FALSE;
     } else if (found_old) {
       break;
     }
 
     nsCOMPtr<nsIInterfaceInfo> tmp(if_info);
     tmp->GetParent(getter_AddRefs(if_info));
@@ -5325,17 +5322,19 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
     const nsIID *primary_iid = &NS_GET_IID(nsISupports);
 
     if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
       primary_iid = &name_struct->mIID;
     } else if (ci_data && ci_data->mProtoChainInterface) {
       primary_iid = ci_data->mProtoChainInterface;
     }
 
-    nsXPIDLCString class_parent_name;
+    nsCOMPtr<nsIInterfaceInfo> if_info;
+    nsCOMPtr<nsIInterfaceInfo> parent;
+    const char *class_parent_name = nsnull;
 
     if (!primary_iid->Equals(NS_GET_IID(nsISupports))) {
       rv = DefineInterfaceConstants(cx, class_obj, primary_iid);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Special case for |Node|, which needs constants from Node3
       // too for forwards compatibility.
       if (primary_iid->Equals(NS_GET_IID(nsIDOMNode))) {
@@ -5351,53 +5350,49 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
                                       &NS_GET_IID(nsIDOMNSEvent));
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
       nsCOMPtr<nsIInterfaceInfoManager>
         iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
       NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
 
-      nsCOMPtr<nsIInterfaceInfo> if_info;
       iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
       NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED);
 
-      nsCOMPtr<nsIInterfaceInfo> parent;
-      nsIID *iid = nsnull;
+      const nsIID *iid = nsnull;
 
       if (ci_data && !ci_data->mHasClassInterface) {
-        if_info->GetInterfaceIID(&iid);
+        if_info->GetIIDShared(&iid);
       } else {
         if_info->GetParent(getter_AddRefs(parent));
         NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
 
-        parent->GetInterfaceIID(&iid);
+        parent->GetIIDShared(&iid);
       }
 
       if (iid) {
         if (!iid->Equals(NS_GET_IID(nsISupports))) {
           if (ci_data && !ci_data->mHasClassInterface) {
             // If the class doesn't have a class interface the primary
             // interface is the interface that should be
             // constructor.prototype.__proto__.
 
-            if_info->GetName(getter_Copies(class_parent_name));
+            if_info->GetNameShared(&class_parent_name);
           } else {
             // If the class does have a class interface (or there's no
             // real class for this name) then the parent of the
             // primary interface is what we want on
             // constructor.prototype.__proto__.
 
             NS_ASSERTION(parent, "Whoa, this is bad, null parent here!");
 
-            parent->GetName(getter_Copies(class_parent_name));
+            parent->GetNameShared(&class_parent_name);
           }
         }
-
-        nsMemory::Free(iid);
       }
     }
 
     JSObject *proto = nsnull;
 
     if (class_parent_name) {
       jsval val;
 
--- a/dom/src/base/nsScriptNameSpaceManager.cpp
+++ b/dom/src/base/nsScriptNameSpaceManager.cpp
@@ -306,27 +306,27 @@ nsScriptNameSpaceManager::FillHashWithDO
 
     NS_WARNING("What, no nsIDOM interfaces installed?");
 
     return NS_OK;
   }
 
   PRBool found_old;
   nsCOMPtr<nsIInterfaceInfo> if_info;
-  nsXPIDLCString if_name;
+  const char *if_name = nsnull;
   const nsIID *iid;
 
   for ( ; domInterfaces->IsDone() == NS_ENUMERATOR_FALSE; domInterfaces->Next()) {
     rv = domInterfaces->CurrentItem(getter_AddRefs(entry));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIInterfaceInfo> if_info(do_QueryInterface(entry));
-    if_info->GetName(getter_Copies(if_name));
+    if_info->GetNameShared(&if_name);
     if_info->GetIIDShared(&iid);
-    rv = RegisterInterface(if_name.get() + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
+    rv = RegisterInterface(if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1,
                            iid, &found_old);
 
 #ifdef DEBUG
     NS_ASSERTION(!found_old,
                  "Whaaa, interface name already in hash!");
 #endif
   }
 
--- a/extensions/java/xpcom/src/nsJavaWrapper.cpp
+++ b/extensions/java/xpcom/src/nsJavaWrapper.cpp
@@ -1132,25 +1132,23 @@ FinalizeParams(JNIEnv *env, const nsXPTP
       nsID* iid = static_cast<nsID*>(aVariant.val.p);
 
       if ((aParamInfo.IsOut() || aIsArrayElement) &&
           NS_SUCCEEDED(aInvokeResult))
       {
         // Create the string from nsID
         jstring str = nsnull;
         if (iid) {
-          char* iid_str = iid->ToString();
-          if (iid_str) {
-            str = env->NewStringUTF(iid_str);
-          }
-          if (!iid_str || !str) {
+          char iid_str[NSID_LENGTH];
+          iid->ToProvidedString(iid_str);
+          str = env->NewStringUTF(iid_str);
+          if (!str) {
             rv = NS_ERROR_OUT_OF_MEMORY;
             break;
           }
-          PR_Free(iid_str);
         }
 
         if (aParamInfo.IsRetval() && !aIsArrayElement) {
           *aParam = str;
         } else if (*aParam) {
           // put new string into output array
           env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
         }
--- a/extensions/java/xpcom/src/nsJavaXPTCStub.cpp
+++ b/extensions/java/xpcom/src/nsJavaXPTCStub.cpp
@@ -861,25 +861,23 @@ nsJavaXPTCStub::SetupJavaParams(const ns
         iid = static_cast<nsID*>(aVariant.val.p);
       } else if (aVariant.val.p) {  // 'inout' & 'out'
         nsID** variant = static_cast<nsID**>(aVariant.val.p);
         iid = *variant;
       }
 
       jobject str = nsnull;
       if (iid) {
-        char* iid_str = iid->ToString();
-        if (iid_str) {
-          str = env->NewStringUTF(iid_str);
-        }
-        if (!iid_str || !str) {
+        char iid_str[NSID_LENGTH];
+        iid->ToProvidedString(iid_str);
+        str = env->NewStringUTF(iid_str);
+        if (!str) {
           rv = NS_ERROR_OUT_OF_MEMORY;
           break;
         }
-        PR_Free(iid_str);
       }
 
       if (!aParamInfo.IsOut()) {  // 'in'
         aJValue.l = str;
         aMethodSig.AppendLiteral("Ljava/lang/String;");
       } else {  // 'inout' & 'out'
         if (aVariant.val.p) {
           aJValue.l = env->NewObjectArray(1, stringClass, str);
@@ -1705,9 +1703,9 @@ nsJavaXPTCStub::GetNewOrUsed(JNIEnv* env
     delete stub;
     return rv;
   }
 
   NS_ADDREF(stub);
   *aResult = stub;
 
   return NS_OK;
-}
\ No newline at end of file
+}
--- a/extensions/java/xpcom/tools/genifaces/GenerateJavaInterfaces.cpp
+++ b/extensions/java/xpcom/tools/genifaces/GenerateJavaInterfaces.cpp
@@ -411,54 +411,49 @@ public:
   }
 
   nsresult WriteIID(nsIOutputStream* out, nsIInterfaceInfo* aIInfo)
   {
     static const char kIIDDecl1[] = "  String ";
     static const char kIIDDecl2[] = " =\n    \"";
     static const char kIIDDecl3[] = "\";\n\n";
 
-    nsIID* iid = nsnull;
-    aIInfo->GetInterfaceIID(&iid);
-    if (!iid)
-      return NS_ERROR_OUT_OF_MEMORY;
+    nsIID* iid;
+    aIInfo->GetIIDShared(&iid);
 
     // create iid field name
     nsCAutoString iid_name;
     const char* iface_name;
     aIInfo->GetNameShared(&iface_name);
     if (strncmp("ns", iface_name, 2) == 0) {
       iid_name.Append(NS_LITERAL_CSTRING("NS_"));
       iid_name.Append(iface_name + 2);
     } else {
       iid_name.Append(iface_name);
     }
     iid_name.Append("_IID");
     ToUpperCase(iid_name);
 
     // get iid string
-    char* iid_str = iid->ToString();
-    if (!iid_str)
-      return NS_ERROR_OUT_OF_MEMORY;
+    char iid_str[NSID_LENGTH];
+    iid->ToProvidedString(iid_str);
 
     PRUint32 count;
     nsresult rv = out->Write(kIIDDecl1, sizeof(kIIDDecl1) - 1, &count);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = out->Write(iid_name.get(), iid_name.Length(), &count);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = out->Write(kIIDDecl2, sizeof(kIIDDecl2) - 1, &count);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = out->Write(iid_str, strlen(iid_str), &count);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = out->Write(kIIDDecl3, sizeof(kIIDDecl3) - 1, &count);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // cleanup
-    PR_Free(iid_str);
-    nsMemory::Free(iid);
     return NS_OK;
   }
 
   nsresult WriteConstants(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
                           PRUint16 aParentConstCount)
   {
     static const char kConstDecl1[] = " = ";
     static const char kConstDecl2[] = ";\n\n";
--- a/extensions/python/xpcom/src/PyIInterfaceInfo.cpp
+++ b/extensions/python/xpcom/src/PyIInterfaceInfo.cpp
@@ -86,22 +86,21 @@ static PyObject *PyGetIID(PyObject *self
 
 	nsIInterfaceInfo *pI = GetI(self);
 	if (pI==NULL)
 		return NULL;
 
 	nsIID *iid_ret;
 	nsresult r;
 	Py_BEGIN_ALLOW_THREADS;
-	r = pI->GetInterfaceIID(&iid_ret);
+	r = pI->GetIIDShared(&iid_ret);
 	Py_END_ALLOW_THREADS;
 	if ( NS_FAILED(r) )
 		return PyXPCOM_BuildPyException(r);
 	PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
-	nsMemory::Free(iid_ret);
 	return ret;
 }
 
 static PyObject *PyIsScriptable(PyObject *self, PyObject *args)
 {
 	if (!PyArg_ParseTuple(args, ":IsScriptable"))
 		return NULL;
 
--- a/js/src/xpconnect/idl/xpcjsid.idl
+++ b/js/src/xpconnect/idl/xpcjsid.idl
@@ -35,37 +35,42 @@
  * 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 MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(C86AE131-D101-11d2-9841-006008962422)]
+[ptr] native const_nsID_ptr(const nsID);
+
+[scriptable, uuid(baedc96a-9cee-4b6b-9160-90d257b3c8ef)]
 interface nsIJSID : nsISupports
 {
-    readonly attribute string             name;
-    readonly attribute string             number;
-    [noscript] readonly attribute nsIDPtr id;
-    readonly attribute boolean            valid;
+    readonly attribute string  name;
+    readonly attribute string  number;
+    readonly attribute boolean valid;
 
     boolean equals(in nsIJSID other);
 
     void initialize(in string idString);
 
     string toString();
+
+    // returns a pointer to the internal nsID. this pointer is only valid
+    // while the nsIJSID object remains alive!
+    [notxpcom] const_nsID_ptr getID();
 };
 
-[scriptable, uuid(e08dcda0-d651-11d2-9843-006008962422)]
+[scriptable, uuid(e76ec564-a080-4705-8609-384c755ec91e)]
 interface nsIJSIID : nsIJSID
 {
 };
 
-[scriptable, uuid(e3a24a60-d651-11d2-9843-006008962422)]
+[scriptable, uuid(26b2a374-6eaf-46d4-acaf-1c6be152d36b)]
 interface nsIJSCID : nsIJSID
 {
     nsISupports createInstance();
     nsISupports getService();
 };
 
 /* this goes into the C++ header verbatim. */
 %{ C++
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -617,31 +617,30 @@ nsXPCComponents_InterfacesByID::NewEnume
                 if(NS_ENUMERATOR_FALSE == e->IsDone() &&
                    NS_SUCCEEDED(e->CurrentItem(getter_AddRefs(isup))) && isup)
                 {
                     e->Next();
                     nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(isup));
                     if(iface)
                     {
                         nsIID const *iid;
-                        char* idstr;
+                        char idstr[NSID_LENGTH];
                         JSString* jsstr;
                         PRBool scriptable;
 
                         if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
                            !scriptable)
                         {
                             continue;
                         }
 
-                        if(NS_SUCCEEDED(iface->GetIIDShared(&iid)) &&
-                           nsnull != (idstr = iid->ToString()))
+                        if(NS_SUCCEEDED(iface->GetIIDShared(&iid)))
                         {
+                            iid->ToProvidedString(idstr);
                             jsstr = JS_NewStringCopyZ(cx, idstr);
-                            nsMemory::Free(idstr);
                             if (jsstr &&
                                 JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp))
                             {
                                 return NS_OK;
                             }
                         }
                     }
                 }
--- a/js/src/xpconnect/src/xpcconvert.cpp
+++ b/js/src/xpconnect/src/xpcconvert.cpp
@@ -664,17 +664,18 @@ XPCConvert::JSData2Native(XPCCallContext
                 }
                 // else ...
                 *((const nsID**)d) = nsnull;
                 return JS_TRUE;
             }
 
             if(!JSVAL_IS_OBJECT(s) ||
                (!(obj = JSVAL_TO_OBJECT(s))) ||
-               (!(pid = xpc_JSObjectToID(cx, obj))))
+               (!(pid = xpc_JSObjectToID(cx, obj))) ||
+               (!(pid = (const nsID*) nsMemory::Clone(pid, sizeof(nsID)))))
             {
                 return JS_FALSE;
             }
             *((const nsID**)d) = pid;
             return JS_TRUE;
         }
 
         case nsXPTType::T_ASTRING:        
--- a/js/src/xpconnect/src/xpcjsid.cpp
+++ b/js/src/xpconnect/src/xpcjsid.cpp
@@ -112,24 +112,20 @@ nsJSID::GetNumber(char * *aNumber)
         if(!(mNumber = mID.ToString()))
             mNumber = gNoString;
     }
 
     *aNumber = (char*) nsMemory::Clone(mNumber, strlen(mNumber)+1);
     return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
-NS_IMETHODIMP
-nsJSID::GetId(nsID* *aId)
+NS_IMETHODIMP_(const nsID*)
+nsJSID::GetID()
 {
-    if(!aId)
-        return NS_ERROR_NULL_POINTER;
-
-    *aId = (nsID*) nsMemory::Clone(&mID, sizeof(nsID));
-    return *aId ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+    return &mID;
 }
 
 NS_IMETHODIMP
 nsJSID::GetValid(PRBool *aValid)
 {
     if(!aValid)
         return NS_ERROR_NULL_POINTER;
 
@@ -138,53 +134,48 @@ nsJSID::GetValid(PRBool *aValid)
 }
 
 NS_IMETHODIMP
 nsJSID::Equals(nsIJSID *other, PRBool *_retval)
 {
     if(!_retval)
         return NS_ERROR_NULL_POINTER;
 
-    *_retval = PR_FALSE;
-
     if(!other || mID.Equals(GetInvalidIID()))
+    {
+        *_retval = PR_FALSE;
         return NS_OK;
+    }
 
-    nsID* otherID;
-    if(NS_SUCCEEDED(other->GetId(&otherID)))
-    {
-        *_retval = mID.Equals(*otherID);
-        nsMemory::Free(otherID);
-    }
+    *_retval = other->GetID()->Equals(mID);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsJSID::Initialize(const char *idString)
 {
     if(!idString)
         return NS_ERROR_NULL_POINTER;
 
-    PRBool success = PR_FALSE;
-
-    if(strlen(idString) && mID.Equals(GetInvalidIID()))
+    if(*idString != '\0' && mID.Equals(GetInvalidIID()))
     {
         Reset();
 
         if(idString[0] == '{')
         {
-            nsID id;
-            if(id.Parse((char*)idString))
+            if(mID.Parse(idString))
             {
-                mID = id;
-                success = PR_TRUE;
+                return NS_OK;
             }
+
+            // error - reset to invalid state
+            mID = GetInvalidIID();
         }
     }
-    return success ? NS_OK : NS_ERROR_FAILURE;
+    return NS_ERROR_FAILURE;
 }
 
 PRBool
 nsJSID::InitWithName(const nsID& id, const char *nameString)
 {
     NS_ASSERTION(nameString, "no name");
     Reset();
     mID = id;
@@ -236,16 +227,32 @@ nsJSID::NewID(const char* str)
     {
         NS_ADDREF(idObj);
         if(NS_FAILED(idObj->Initialize(str)))
             NS_RELEASE(idObj);
     }
     return idObj;
 }
 
+//static
+nsJSID*
+nsJSID::NewID(const nsID& id)
+{
+    nsJSID* idObj = new nsJSID();
+    if(idObj)
+    {
+        NS_ADDREF(idObj);
+        idObj->mID = id;
+        idObj->mName = nsnull;
+        idObj->mNumber = nsnull;
+    }
+    return idObj;
+}
+
+
 /***************************************************************************/
 // Class object support so that we can share prototypes of wrapper
 
 // This class exists just so we can have a shared scriptable helper for
 // the nsJSIID class. The instances implement their own helpers. But we
 // needed to be able to indicate to the shared prototypes this single flag:
 // nsIXPCScriptable::DONT_ENUM_STATIC_PROPS. And having a class to do it is
 // the only means we have. Setting this flag on any given instance scriptable
@@ -407,53 +414,49 @@ nsJSIID::~nsJSIID() {}
 
 NS_IMETHODIMP nsJSIID::GetName(char * *aName)
 {
     return mInfo->GetName(aName);    
 }
 
 NS_IMETHODIMP nsJSIID::GetNumber(char * *aNumber)
 {
+    char str[NSID_LENGTH];
     const nsIID* id;
     mInfo->GetIIDShared(&id);
-    char* str = id->ToString();
-    if(!str)
-        return NS_ERROR_OUT_OF_MEMORY;
-    *aNumber = (char*) nsMemory::Clone(str, strlen(str)+1);
-    PR_Free(str);
+    id->ToProvidedString(str);
+    *aNumber = (char*) nsMemory::Clone(str, NSID_LENGTH);
     return *aNumber ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }        
 
-NS_IMETHODIMP nsJSIID::GetId(nsID* *aId)
+NS_IMETHODIMP_(const nsID*) nsJSIID::GetID()
 {
-    return mInfo->GetInterfaceIID((nsIID**)aId);
+    const nsIID* id;
+    mInfo->GetIIDShared(&id);
+    return id;
 }
 
 NS_IMETHODIMP nsJSIID::GetValid(PRBool *aValid)
 {
     *aValid = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP nsJSIID::Equals(nsIJSID *other, PRBool *_retval)
 {
     if(!_retval)
         return NS_ERROR_NULL_POINTER;
 
-    *_retval = PR_FALSE;
-
     if(!other)
+    {
+        *_retval = PR_FALSE;
         return NS_OK;
+    }
 
-    nsID* otherID;
-    if(NS_SUCCEEDED(other->GetId(&otherID)))
-    {
-        mInfo->IsIID((nsIID*)otherID, _retval);
-        nsMemory::Free(otherID);
-    }
+    mInfo->IsIID(other->GetID(), _retval);
     return NS_OK;
 }
 
 NS_IMETHODIMP nsJSIID::Initialize(const char *idString)
 {
     return NS_ERROR_FAILURE;
 }
 
@@ -668,18 +671,18 @@ nsJSCID::nsJSCID()  {}
 nsJSCID::~nsJSCID() {}
 
 NS_IMETHODIMP nsJSCID::GetName(char * *aName)
     {ResolveName(); return mDetails.GetName(aName);}
 
 NS_IMETHODIMP nsJSCID::GetNumber(char * *aNumber)
     {return mDetails.GetNumber(aNumber);}
 
-NS_IMETHODIMP nsJSCID::GetId(nsID* *aId)
-    {return mDetails.GetId(aId);}
+NS_IMETHODIMP_(const nsID*) nsJSCID::GetID()
+    {return &mDetails.ID();}
 
 NS_IMETHODIMP nsJSCID::GetValid(PRBool *aValid)
     {return mDetails.GetValid(aValid);}
 
 NS_IMETHODIMP nsJSCID::Equals(nsIJSID *other, PRBool *_retval)
     {return mDetails.Equals(other, _retval);}
 
 NS_IMETHODIMP nsJSCID::Initialize(const char *idString)
@@ -731,17 +734,39 @@ nsJSCID::NewID(const char* str)
             }
         }
         if(!success)
             NS_RELEASE(idObj);
     }
     return idObj;
 }
 
+static const nsID*
+GetIIDArg(PRUint32 argc, jsval* argv, JSContext* cx)
+{
+    const nsID* iid;
 
+    // If an IID was passed in then use it
+    if(argc)
+    {
+        JSObject* iidobj;
+        jsval val = *argv;
+        if(JSVAL_IS_PRIMITIVE(val) ||
+           !(iidobj = JSVAL_TO_OBJECT(val)) ||
+           !(iid = xpc_JSObjectToID(cx, iidobj)))
+        {
+            return nsnull;
+        }
+    }
+    else
+        iid = &NS_GET_IID(nsISupports);
+
+    return iid;
+}
+ 
 /* nsISupports createInstance (); */
 NS_IMETHODIMP
 nsJSCID::CreateInstance(nsISupports **_retval)
 {
     if(!mDetails.IsValid())
         return NS_ERROR_XPC_BAD_CID;
 
     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
@@ -770,58 +795,43 @@ nsJSCID::CreateInstance(nsISupports **_r
 
     // Do the security check if necessary
 
     XPCContext* xpcc = nsXPConnect::GetContext(cx);
 
     nsIXPCSecurityManager* sm;
     sm = xpcc->GetAppropriateSecurityManager(
                         nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
-    if(sm && NS_FAILED(sm->CanCreateInstance(cx, *mDetails.GetID())))
+    if(sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID())))
     {
         // the security manager vetoed. It should have set an exception.
         ccxp->SetExceptionWasThrown(JS_TRUE);
         return NS_OK;
     }
 
-    nsID iid;
-
     // If an IID was passed in then use it
-    if(argc)
-    {
-        JSObject* iidobj;
-        jsval val = *argv;
-        nsID* piid = nsnull;
-        if(JSVAL_IS_PRIMITIVE(val) ||
-           !(iidobj = JSVAL_TO_OBJECT(val)) ||
-           !(piid = xpc_JSObjectToID(cx, iidobj)))
-        {
-            return NS_ERROR_XPC_BAD_IID;
-        }
-        iid = *piid;
-        nsMemory::Free(piid);
-    }
-    else
-        iid = NS_GET_IID(nsISupports);
+    const nsID* iid = GetIIDArg(argc, argv, cx);
+    if (!iid)
+        return NS_ERROR_XPC_BAD_IID;
 
     nsCOMPtr<nsIComponentManager> compMgr;
     nsresult rv = NS_GetComponentManager(getter_AddRefs(compMgr));
     if (NS_FAILED(rv))
         return NS_ERROR_UNEXPECTED;
 
     nsCOMPtr<nsISupports> inst;
-    rv = compMgr->CreateInstance(*mDetails.GetID(), nsnull, iid, getter_AddRefs(inst));
+    rv = compMgr->CreateInstance(mDetails.ID(), nsnull, *iid, getter_AddRefs(inst));
     NS_ASSERTION(NS_FAILED(rv) || inst, "component manager returned success, but instance is null!");
 
     if(NS_FAILED(rv) || !inst)
         return NS_ERROR_XPC_CI_RETURNED_FAILURE;
 
     JSObject* instJSObj;
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-    rv = xpc->WrapNative(cx, obj, inst, iid, getter_AddRefs(holder));
+    rv = xpc->WrapNative(cx, obj, inst, *iid, getter_AddRefs(holder));
     if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
         return NS_ERROR_XPC_CANT_CREATE_WN;
 
     *vp = OBJECT_TO_JSVAL(instJSObj);
     ccxp->SetReturnValueWasSet(JS_TRUE);
     return NS_OK;
 }
 
@@ -858,57 +868,42 @@ nsJSCID::GetService(nsISupports **_retva
 
     // Do the security check if necessary
 
     XPCContext* xpcc = nsXPConnect::GetContext(cx);
 
     nsIXPCSecurityManager* sm;
     sm = xpcc->GetAppropriateSecurityManager(
                         nsIXPCSecurityManager::HOOK_GET_SERVICE);
-    if(sm && NS_FAILED(sm->CanCreateInstance(cx, *mDetails.GetID())))
+    if(sm && NS_FAILED(sm->CanCreateInstance(cx, mDetails.ID())))
     {
         // the security manager vetoed. It should have set an exception.
         ccxp->SetExceptionWasThrown(JS_TRUE);
         return NS_OK;
     }
 
-    nsID iid;
-
     // If an IID was passed in then use it
-    if(argc)
-    {
-        JSObject* iidobj;
-        jsval val = *argv;
-        nsID* piid = nsnull;
-        if(JSVAL_IS_PRIMITIVE(val) ||
-           !(iidobj = JSVAL_TO_OBJECT(val)) ||
-           !(piid = xpc_JSObjectToID(cx, iidobj)))
-        {
-            return NS_ERROR_XPC_BAD_IID;
-        }
-        iid = *piid;
-        nsMemory::Free(piid);
-    }
-    else
-        iid = NS_GET_IID(nsISupports);
+    const nsID* iid = GetIIDArg(argc, argv, cx);
+    if (!iid)
+        return NS_ERROR_XPC_BAD_IID;
 
     nsCOMPtr<nsIServiceManager> svcMgr;
     nsresult rv = NS_GetServiceManager(getter_AddRefs(svcMgr));
     if (NS_FAILED(rv))
         return rv;
 
     nsCOMPtr<nsISupports> srvc;
-    rv = svcMgr->GetService(*mDetails.GetID(), iid, getter_AddRefs(srvc));
+    rv = svcMgr->GetService(mDetails.ID(), *iid, getter_AddRefs(srvc));
     NS_ASSERTION(NS_FAILED(rv) || srvc, "service manager returned success, but service is null!");
     if(NS_FAILED(rv) || !srvc)
         return NS_ERROR_XPC_GS_RETURNED_FAILURE;
 
     JSObject* instJSObj;
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-    rv = xpc->WrapNative(cx, obj, srvc, iid, getter_AddRefs(holder));
+    rv = xpc->WrapNative(cx, obj, srvc, *iid, getter_AddRefs(holder));
     if(NS_FAILED(rv) || !holder || NS_FAILED(holder->GetJSObject(&instJSObj)))
         return NS_ERROR_XPC_CANT_CREATE_WN;
 
     *vp = OBJECT_TO_JSVAL(instJSObj);
     ccxp->SetReturnValueWasSet(JS_TRUE);
     return NS_OK;
 }
 
@@ -957,74 +952,69 @@ nsJSCID::HasInstance(nsIXPConnectWrapped
 
         // We consider CID equality to be the thing that matters here.
         // This is perhaps debatable.
         nsIClassInfo* ci = other_wrapper->GetClassInfo();
         if(ci)
         {
             nsID cid;
             if(NS_SUCCEEDED(ci->GetClassIDNoAlloc(&cid)))
-                *bp = cid.Equals(*mDetails.GetID());
+                *bp = cid.Equals(mDetails.ID());
         }
     }
     return rv;
 }
 
 /***************************************************************************/
 // additional utilities...
 
 JSObject *
 xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID)
 {
     JSObject *obj = nsnull;
 
-    char* idString = aID.ToString();
-    if(idString)
+    nsCOMPtr<nsIJSID> iid =
+            dont_AddRef(static_cast<nsIJSID*>(nsJSID::NewID(aID)));
+    if(iid)
     {
-        nsCOMPtr<nsIJSID> iid =
-            dont_AddRef(static_cast<nsIJSID*>(nsJSID::NewID(idString)));
-        PR_Free(idString);
-        if(iid)
+        nsXPConnect* xpc = nsXPConnect::GetXPConnect();
+        if(xpc)
         {
-            nsXPConnect* xpc = nsXPConnect::GetXPConnect();
-            if(xpc)
+            nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+            nsresult rv = xpc->WrapNative(cx, jsobj,
+                                          static_cast<nsISupports*>(iid),
+                                          NS_GET_IID(nsIJSID),
+                                          getter_AddRefs(holder));
+            if(NS_SUCCEEDED(rv) && holder)
             {
-                nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-                nsresult rv = xpc->WrapNative(cx, jsobj,
-                                              static_cast<nsISupports*>(iid),
-                                              NS_GET_IID(nsIJSID),
-                                              getter_AddRefs(holder));
-                if(NS_SUCCEEDED(rv) && holder)
-                {
-                    holder->GetJSObject(&obj);
-                }
+                holder->GetJSObject(&obj);
             }
         }
     }
     return obj;
 }
 
-nsID*
+// note: returned pointer is only valid while |obj| remains alive!
+const nsID*
 xpc_JSObjectToID(JSContext *cx, JSObject* obj)
 {
-    nsID* id = nsnull;
     if(!cx || !obj)
         return nsnull;
 
     // NOTE: this call does NOT addref
     XPCWrappedNative* wrapper =
         XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
     if(wrapper &&
        (wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID))  ||
         wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
         wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSCID))))
     {
-        ((nsIJSID*)wrapper->GetIdentityObject())->GetId(&id);
+        return ((nsIJSID*)wrapper->GetIdentityObject())->GetID();
     }
-    return id;
+    return nsnull;
 }
 
 JSBool
 xpc_JSObjectIsID(JSContext *cx, JSObject* obj)
 {
     NS_ASSERTION(cx && obj, "bad param");
     // NOTE: this call does NOT addref
     XPCWrappedNative* wrapper =
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -2839,21 +2839,21 @@ public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIJSID
 
     PRBool InitWithName(const nsID& id, const char *nameString);
     PRBool SetName(const char* name);
     void   SetNameToNoString()
         {NS_ASSERTION(!mName, "name already set"); mName = gNoString;}
     PRBool NameIsSet() const {return nsnull != mName;}
-    const nsID* GetID() const {return &mID;}
-
+    const nsID& ID() const {return mID;}
     PRBool IsValid() const {return !mID.Equals(GetInvalidIID());}
 
     static nsJSID* NewID(const char* str);
+    static nsJSID* NewID(const nsID& id);
 
     nsJSID();
     virtual ~nsJSID();
 protected:
 
     void Reset();
     const nsID& GetInvalidIID() const;
 
@@ -3303,17 +3303,17 @@ private:
 };
 
 
 /***************************************************************************/
 
 extern JSObject*
 xpc_NewIDObject(JSContext *cx, JSObject* jsobj, const nsID& aID);
 
-extern nsID*
+extern const nsID*
 xpc_JSObjectToID(JSContext *cx, JSObject* obj);
 
 extern JSBool
 xpc_JSObjectIsID(JSContext *cx, JSObject* obj);
 
 /***************************************************************************/
 // in xpcdebug.cpp
 
--- a/js/src/xpconnect/src/xpcvariant.cpp
+++ b/js/src/xpconnect/src/xpcvariant.cpp
@@ -315,24 +315,19 @@ JSBool XPCVariant::InitializeData(XPCCal
 
     // leaving only JSObject...
     NS_ASSERTION(JSVAL_IS_OBJECT(mJSVal), "invalid type of jsval!");
     
     JSObject* jsobj = JSVAL_TO_OBJECT(mJSVal);
 
     // Let's see if it is a xpcJSID.
 
-    // XXX It might be nice to have a non-allocing version of xpc_JSObjectToID.
-    nsID* id = xpc_JSObjectToID(ccx, jsobj);
+    const nsID* id = xpc_JSObjectToID(ccx, jsobj);
     if(id)
-    {
-        JSBool success = NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
-        nsMemory::Free((char*)id);
-        return success;
-    }
+        return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
     
     // Let's see if it is a js array object.
 
     jsuint len;
 
     if(JS_IsArrayObject(ccx, jsobj) && JS_GetArrayLength(ccx, jsobj, &len))
     {
         if(!len) 
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -1945,17 +1945,17 @@ XPCWrappedNative::CallMethod(XPCCallCont
     // lot of work
     if(vtblIndex == 0)
     {
         if(argc < 1)
         {
             Throw(NS_ERROR_XPC_NOT_ENOUGH_ARGS, ccx);
             return JS_FALSE;
         }
-        nsID* iid;
+        const nsID* iid;
         JSObject* obj;
         if(!JSVAL_IS_OBJECT(argv[0]) ||
            (!(obj = JSVAL_TO_OBJECT(argv[0]))) ||
            (!(iid = xpc_JSObjectToID(ccx, obj))))
         {
             ThrowBadParam(NS_ERROR_XPC_BAD_CONVERT_JS, 0, ccx);
             return JS_FALSE;
         }
@@ -1966,25 +1966,23 @@ XPCWrappedNative::CallMethod(XPCCallCont
             invokeResult = callee->QueryInterface(*iid, (void**) &qiresult);
         }
 
         xpcc->SetLastResult(invokeResult);
 
         if(NS_FAILED(invokeResult))
         {
             ThrowBadResult(invokeResult, ccx);
-            PR_Free(iid);
             return JS_FALSE;
         }
 
         jsval v = JSVAL_NULL;
         retval = XPCConvert::NativeData2JS(ccx, &v, &qiresult, 
                                            nsXPTType::T_INTERFACE_IS | XPT_TDP_POINTER,
                                            iid, ccx.GetCurrentJSObject(), &err);
-        PR_Free(iid);
         NS_IF_RELEASE(qiresult);
 
         if(!retval)
         {
             ThrowBadParam(err, 0, ccx);
             return JS_FALSE;
         }
 
--- a/toolkit/components/places/src/nsNavBookmarks.cpp
+++ b/toolkit/components/places/src/nsNavBookmarks.cpp
@@ -44,17 +44,16 @@
 #include "nsNetUtil.h"
 #include "nsIDynamicContainer.h"
 #include "nsUnicharUtils.h"
 #include "nsFaviconService.h"
 #include "nsAnnotationService.h"
 #include "nsPrintfCString.h"
 #include "nsAutoLock.h"
 #include "nsIUUIDGenerator.h"
-#include "prmem.h"
 #include "prprf.h"
 
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ID = 0;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Type = 1;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ForeignKey = 2;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Parent = 3;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Position = 4;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Title = 5;
@@ -274,20 +273,19 @@ nsNavBookmarks::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   // generate a new GUID base for this session
   nsCOMPtr<nsIUUIDGenerator> uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   nsID GUID;
   rv = uuidgen->GenerateUUIDInPlace(&GUID);
   NS_ENSURE_SUCCESS(rv, rv);
-  char* GUIDChars = GUID.ToString();
-  NS_ENSURE_TRUE(GUIDChars, NS_ERROR_OUT_OF_MEMORY);
-  mGUIDBase.Assign(NS_ConvertASCIItoUTF16(GUIDChars));
-  PR_Free(GUIDChars);
+  char GUIDChars[NSID_LENGTH];
+  GUID.ToProvidedString(GUIDChars);
+  CopyASCIItoUTF16(GUIDChars, mGUIDBase);
 
   rv = InitRoots();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = transaction.Commit();
   NS_ENSURE_SUCCESS(rv, rv);
 
   mLock = PR_NewLock();
@@ -1734,19 +1732,20 @@ nsNavBookmarks::GetItemGUID(PRInt64 aIte
   nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
   NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
   nsresult rv = annosvc->GetItemAnnotationString(aItemId, GUID_ANNO, aGUID);
 
   if (NS_SUCCEEDED(rv) || rv != NS_ERROR_NOT_AVAILABLE)
     return rv;
 
   nsAutoString tmp;
-  tmp.Assign(mGUIDBase);
   tmp.AppendInt(mItemCount++);
-  aGUID.Assign(tmp);
+  aGUID.SetCapacity(NSID_LENGTH - 1 + tmp.Length());
+  aGUID.Assign(mGUIDBase);
+  aGUID.Append(tmp);
 
   return SetItemGUID(aItemId, aGUID);
 }
 
 NS_IMETHODIMP
 nsNavBookmarks::SetItemGUID(PRInt64 aItemId, const nsAString &aGUID)
 {
   PRInt64 checkId;
--- a/xpcom/glue/nsID.cpp
+++ b/xpcom/glue/nsID.cpp
@@ -121,20 +121,29 @@ PRBool nsID::Parse(const char *aIDStr)
 /*
  * Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
  * format. The string is allocated with PR_Malloc and should be freed by
  * the caller.
  */
 
 char *nsID::ToString() const 
 {
-  char *res = (char*)PR_Malloc(39);    // use PR_Malloc if this is to be freed with nsCRT::free
+  char *res = (char*)PR_Malloc(NSID_LENGTH); // use PR_Malloc if this is to be freed with nsCRT::free
 
   if (res != NULL) {
-    PR_snprintf(res, 39, gIDFormat,
+    PR_snprintf(res, NSID_LENGTH, gIDFormat,
                 m0, (PRUint32) m1, (PRUint32) m2,
                 (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
                 (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
                 (PRUint32) m3[6], (PRUint32) m3[7]);
   }
   return res;
 }
 
+void nsID::ToProvidedString(char (&dest)[NSID_LENGTH]) const 
+{
+  PR_snprintf(dest, NSID_LENGTH, gIDFormat,
+              m0, (PRUint32) m1, (PRUint32) m2,
+              (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
+              (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
+              (PRUint32) m3[6], (PRUint32) m3[7]);
+}
+
--- a/xpcom/glue/nsID.h
+++ b/xpcom/glue/nsID.h
@@ -39,16 +39,18 @@
 #define nsID_h__
 
 #include <string.h>
 
 #ifndef nscore_h___
 #include "nscore.h"
 #endif
 
+#define NSID_LENGTH 39
+
 /**
  * A "unique identifier". This is modeled after OSF DCE UUIDs.
  * @status FROZEN
  */
 
 struct nsID {
   /**
    * @name Identifier values
@@ -90,18 +92,26 @@ struct nsID {
    * nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
    * string into an nsID
    */
   NS_COM_GLUE PRBool Parse(const char *aIDStr);
 
   /**
    * nsID string encoder. Returns an allocated string in 
    * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format. Caller should free string.
+   * YOU SHOULD ONLY USE THIS IF YOU CANNOT USE ToProvidedString() BELOW.
    */
   NS_COM_GLUE char* ToString() const;
+
+  /**
+   * nsID string encoder. Builds a string in 
+   * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format, into a char[NSID_LENGTH]
+   * buffer provided by the caller (for instance, on the stack).
+   */
+  NS_COM_GLUE void ToProvidedString(char (&dest)[NSID_LENGTH]) const;
   //@}
 };
 
 /*
  * Class IDs
  */
 
 typedef nsID nsCID;
--- a/xpcom/reflect/xptinfo/src/xptiManifest.cpp
+++ b/xpcom/reflect/xptinfo/src/xptiManifest.cpp
@@ -91,33 +91,30 @@ CurrentAppDirMatchesPersistentDescriptor
 
 PR_STATIC_CALLBACK(PLDHashOperator)
 xpti_InterfaceWriter(PLDHashTable *table, PLDHashEntryHdr *hdr,
                      PRUint32 number, void *arg)
 {
     xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
     PRFileDesc* fd = (PRFileDesc*)  arg;
 
-    char* iidStr = entry->GetTheIID()->ToString();
-    if(!iidStr)
-        return PL_DHASH_STOP;
+    char iidStr[NSID_LENGTH];
+    entry->GetTheIID()->ToProvidedString(iidStr);
 
     const xptiTypelib& typelib = entry->GetTypelibRecord();
 
     PRBool success =  !!PR_fprintf(fd, "%d,%s,%s,%d,%d,%d\n",
                                    (int) number,
                                    entry->GetTheName(),
                                    iidStr,
                                    (int) typelib.GetFileIndex(),
                                    (int) (typelib.IsZip() ? 
                                    typelib.GetZipItemIndex() : -1),
                                    (int) entry->GetScriptableFlag());
 
-    nsCRT::free(iidStr);
-
     return success ? PL_DHASH_NEXT : PL_DHASH_STOP;
 }
 
 
 // static
 PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
                            xptiWorkingSet*           aWorkingSet)
 {