Bug 560647 - add startup timeline instrumentation; r=vlad
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 19 May 2010 19:22:19 -0400
changeset 42480 fc0d96f2b21ea5ad0df76fc03fcc836135a3d1f7
parent 42479 4a33f2f1f6ab220e6b398cbef7e59c5f921e2a34
child 42481 9d6f6c45f8dee9d93712a76676edc61901d15649
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs560647
milestone1.9.3a5pre
Bug 560647 - add startup timeline instrumentation; r=vlad
accessible/src/base/nsAccessibilityService.cpp
content/base/public/mozFlushType.h
content/base/src/nsScriptLoader.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/text/nsPlaintextEditor.cpp
embedding/components/appstartup/src/nsAppStartupNotifier.cpp
gfx/thebes/src/gfxPlatformFontList.h
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
layout/base/nsPresShell.cpp
layout/build/nsContentDLF.cpp
layout/forms/nsTextControlFrame.cpp
layout/style/nsCSSLoader.cpp
modules/libjar/nsZipArchive.cpp
modules/libpr0n/src/imgLoader.cpp
netwerk/base/src/nsIOService.cpp
netwerk/base/src/nsSocketTransportService2.cpp
netwerk/cache/src/nsCacheService.cpp
netwerk/cache/src/nsDiskCacheDevice.cpp
netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
netwerk/cookie/src/nsCookieService.cpp
netwerk/dns/src/nsDNSService2.cpp
netwerk/dns/src/nsEffectiveTLDService.cpp
netwerk/dns/src/nsHostResolver.cpp
netwerk/dns/src/nsIDNService.cpp
netwerk/protocol/http/src/nsHttpHandler.cpp
netwerk/protocol/http/src/nsHttpTransaction.cpp
storage/src/mozStorageConnection.cpp
storage/src/mozStorageConnection.h
storage/src/mozStorageService.cpp
storage/src/mozStorageStatement.cpp
toolkit/components/places/src/nsNavBookmarks.cpp
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/startup/src/nsAppStartup.cpp
toolkit/xre/nsAppRunner.cpp
uriloader/base/nsURILoader.cpp
widget/src/windows/nsWindow.cpp
xpcom/base/FunctionTimer.cpp
xpcom/base/FunctionTimer.h
xpcom/base/nsStackWalk.cpp
xpcom/build/nsXPComInit.cpp
xpcom/components/nsCategoryManager.cpp
xpcom/components/nsComponentManager.cpp
xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
xpcom/threads/nsThread.cpp
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -105,25 +105,29 @@
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
 #ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #endif
 
+#include "mozilla/FunctionTimer.h"
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibilityService
 ////////////////////////////////////////////////////////////////////////////////
 
 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull;
 PRBool nsAccessibilityService::gIsShutdown = PR_TRUE;
 
 nsAccessibilityService::nsAccessibilityService()
 {
+  NS_TIME_FUNCTION;
+
   // Add observers.
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (!observerService)
     return;
 
   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
   nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
--- a/content/base/public/mozFlushType.h
+++ b/content/base/public/mozFlushType.h
@@ -35,16 +35,19 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef mozFlushType_h___
 #define mozFlushType_h___
 
 /**
  * This is the enum used by nsIDocument::FlushPendingNotifications to
  * decide what to flush.
+ *
+ * Please note that if you change these values, you should sync it with the
+ * flushTypeNames array inside PresShell::FlushPendingNotifications.
  */
 enum mozFlushType {
   Flush_Content          = 1, /* flush the content model construction */
   Flush_ContentAndNotify = 2, /* As above, plus flush the frame model
                                  construction and other nsIMutationObserver
                                  notifications. */
   Flush_Style            = 3, /* As above, plus flush style reresolution */
   Flush_Frames           = Flush_Style,
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -71,16 +71,18 @@
 #include "nsThreadUtils.h"
 #include "nsIChannelClassifier.h"
 #include "nsDocShellCID.h"
 #include "nsIContentSecurityPolicy.h"
 #include "prlog.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gCspPRLog;
 #endif
 
 using namespace mozilla::dom;
 
 //////////////////////////////////////////////////////////////
 // Per-request data structure
@@ -651,16 +653,18 @@ nsScriptLoader::ProcessRequest(nsScriptL
 {
   NS_ASSERTION(ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript(),
                "Caller forgot to check ReadyToExecuteScripts()");
 
   NS_ENSURE_ARG(aRequest);
   nsAFlatString* script;
   nsAutoString textData;
 
+  NS_TIME_FUNCTION;
+
   // If there's no script text, we try to get it from the element
   if (aRequest->mIsInline) {
     // XXX This is inefficient - GetText makes multiple
     // copies.
     aRequest->mElement->GetScriptText(textData);
 
     script = &textData;
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -203,16 +203,18 @@
 #include "nsIPopupWindowManager.h"
 
 #include "nsIDragService.h"
 #include "mozilla/dom/Element.h"
 #include "nsFrameLoader.h"
 #include "nsISupportsPrimitives.h"
 #include "nsXPCOMCID.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef MOZ_LOGGING
 // so we can get logging even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDOMLeakPRLog;
@@ -8380,16 +8382,18 @@ void
 nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
 {
   // If a modal dialog is open for this window, return early. Pending
   // timeouts will run when the modal dialog is dismissed.
   if (IsInModalState() || mTimeoutsSuspendDepth) {
     return;
   }
 
+  NS_TIME_FUNCTION;
+
   NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!");
   NS_ASSERTION(!IsFrozen(), "Timeout running on a window in the bfcache!");
 
   nsTimeout *nextTimeout, *timeout;
   nsTimeout *last_expired_timeout, *last_insertion_point;
   nsTimeout dummy_timeout;
   PRUint32 firingDepth = mTimeoutFiringDepth + 1;
 
@@ -8534,16 +8538,18 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
       // Evaluate the timeout expression.
       const PRUnichar *script = handler->GetHandlerText();
       NS_ASSERTION(script, "timeout has no script nor handler text!");
 
       const char *filename = nsnull;
       PRUint32 lineNo = 0;
       handler->GetLocation(&filename, &lineNo);
 
+      NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename, lineNo);
+
       PRBool is_undefined;
       scx->EvaluateString(nsDependentString(script), 
                           GetScriptGlobal(handler->GetScriptTypeID()),
                           timeout->mPrincipal, filename, lineNo,
                           handler->GetScriptVersion(), nsnull,
                           &is_undefined);
     } else {
       // Let the script handler know about the "secret" final argument that
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -112,16 +112,18 @@
 #endif
 #ifdef MOZ_LOGGING
 // Force PR_LOGGING so we can get JS strict warnings even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 #include "prthread.h"
 
+#include "mozilla/FunctionTimer.h"
+
 const size_t gStackSize = 8192;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gJSDiagnostics;
 #endif
 
 // Thank you Microsoft!
 #ifndef WINCE
@@ -1503,16 +1505,19 @@ nsJSContext::EvaluateStringWithValue(con
                                      void *aScopeObject,
                                      nsIPrincipal *aPrincipal,
                                      const char *aURL,
                                      PRUint32 aLineNo,
                                      PRUint32 aVersion,
                                      void* aRetValue,
                                      PRBool* aIsUndefined)
 {
+  NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
+                           __LINE__, aURL, aLineNo);
+
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!mScriptsEnabled) {
     if (aIsUndefined) {
       *aIsUndefined = PR_TRUE;
     }
 
     return NS_OK;
@@ -1681,16 +1686,19 @@ nsJSContext::EvaluateString(const nsAStr
                             void *aScopeObject,
                             nsIPrincipal *aPrincipal,
                             const char *aURL,
                             PRUint32 aLineNo,
                             PRUint32 aVersion,
                             nsAString *aRetValue,
                             PRBool* aIsUndefined)
 {
+  NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
+                           __LINE__, aURL, aLineNo);
+
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!mScriptsEnabled) {
     if (aIsUndefined) {
       *aIsUndefined = PR_TRUE;
     }
 
     if (aRetValue) {
@@ -2006,16 +2014,19 @@ nsresult
 nsJSContext::CompileEventHandler(nsIAtom *aName,
                                  PRUint32 aArgCount,
                                  const char** aArgNames,
                                  const nsAString& aBody,
                                  const char *aURL, PRUint32 aLineNo,
                                  PRUint32 aVersion,
                                  nsScriptObjectHolder &aHandler)
 {
+  NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
+                           __LINE__, aURL, aLineNo);
+
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
   NS_PRECONDITION(!::JS_IsExceptionPending(mContext),
                   "Why are we being called with a pending exception?");
 
   if (!sSecurityManager) {
     NS_ERROR("Huh, we need a script security manager to compile "
@@ -2069,16 +2080,19 @@ nsJSContext::CompileFunction(void* aTarg
                              const char** aArgArray,
                              const nsAString& aBody,
                              const char* aURL,
                              PRUint32 aLineNo,
                              PRUint32 aVersion,
                              PRBool aShared,
                              void** aFunctionObject)
 {
+  NS_TIME_FUNCTION_FMT(1.0, "%s (line %d) (function: %s, url: %s, line: %d)", MOZ_FUNCTION_NAME,
+                       __LINE__, aName.BeginReading(), aURL, aLineNo);
+
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   // Don't compile if aVersion is unknown.  Since the caller is responsible for
   // parsing the version strings, we just check it isn't JSVERSION_UNKNOWN.
   if ((JSVersion)aVersion == JSVERSION_UNKNOWN) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
@@ -2126,16 +2140,19 @@ nsJSContext::CallEventHandler(nsISupport
                               nsIArray *aargv, nsIVariant **arv)
 {
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!mScriptsEnabled) {
     return NS_OK;
   }
 
+  NS_TIME_FUNCTION_FMT(1.0, "%s (line %d) (function: %s)", MOZ_FUNCTION_NAME,
+                       __LINE__, JS_GetFunctionName(static_cast<JSFunction *>(JS_GetPrivate(mContext, static_cast<JSObject *>(aHandler)))));
+
   JSObject* target = nsnull;
   nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
   NS_ENSURE_SUCCESS(rv, rv);
 
   js::AutoObjectRooter targetVal(mContext, target);
   jsval rval = JSVAL_VOID;
 
   // This one's a lot easier than EvaluateString because we don't have to
@@ -2357,16 +2374,18 @@ nsJSContext::Serialize(nsIObjectOutputSt
 
 nsresult
 nsJSContext::Deserialize(nsIObjectInputStream* aStream,
                          nsScriptObjectHolder &aResult)
 {
     JSObject *result = nsnull;
     nsresult rv;
 
+    NS_TIME_FUNCTION_MIN(1.0);
+
     NS_TIMELINE_MARK_FUNCTION("js script deserialize");
 
     PRUint32 size;
     rv = aStream->Read32(&size);
     if (NS_FAILED(rv)) return rv;
 
     char* data;
     rv = aStream->ReadBytes(size, &data);
@@ -3542,16 +3561,18 @@ nsJSContext::ScriptExecuted()
 
   return NS_OK;
 }
 
 //static
 void
 nsJSContext::CC()
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   ++sCCollectCount;
 #ifdef DEBUG_smaug
   printf("Will run cycle collector (%i), %lldms since previous.\n",
          sCCollectCount, (PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
 #endif
   sPreviousCCTime = PR_Now();
   sDelayedCCollectCount = 0;
   sCCSuspectChanges = 0;
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -106,16 +106,18 @@
 #include "nsISelectionDisplay.h"
 #include "nsIInlineSpellChecker.h"
 #include "nsINameSpaceManager.h"
 #include "nsIHTMLDocument.h"
 #include "nsIParserService.h"
 
 #include "nsITransferable.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
 #define NS_ERROR_EDITOR_NO_TEXTNODE  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
 
 #ifdef NS_DEBUG_EDITOR
 static PRBool gNoisy = PR_FALSE;
 #endif
 
 
@@ -1268,16 +1270,18 @@ NS_IMETHODIMP nsEditor::GetInlineSpellCh
 
   NS_IF_ADDREF(*aInlineSpellChecker = mInlineSpellChecker);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsEditor::SyncRealTimeSpell()
 {
+  NS_TIME_FUNCTION;
+
   PRBool enable = GetDesiredSpellCheckState();
 
   nsCOMPtr<nsIInlineSpellChecker> spellChecker;
   GetInlineSpellChecker(enable, getter_AddRefs(spellChecker));
 
   if (spellChecker) {
     spellChecker->SetEnableRealTimeSpell(enable);
   }
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -79,16 +79,18 @@
 #include "nsEventDispatcher.h"
 #include "nsGkAtoms.h"
 
 // Drag & Drop, Clipboard
 #include "nsIClipboard.h"
 #include "nsITransferable.h"
 #include "nsCopySupport.h"
 
+#include "mozilla/FunctionTimer.h"
+
 // prototype for rules creation shortcut
 nsresult NS_NewTextEditRules(nsIEditRules** aInstancePtrResult);
 
 nsPlaintextEditor::nsPlaintextEditor()
 : nsEditor()
 , mIgnoreSpuriousDragEvent(PR_FALSE)
 , mRules(nsnull)
 , mWrapToWindow(PR_FALSE)
@@ -138,16 +140,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIPlaintextEditor)
   NS_INTERFACE_MAP_ENTRY(nsIEditorMailSupport)
 NS_INTERFACE_MAP_END_INHERITING(nsEditor)
 
 
 NS_IMETHODIMP nsPlaintextEditor::Init(nsIDOMDocument *aDoc, 
                                  nsIPresShell   *aPresShell, nsIContent *aRoot, nsISelectionController *aSelCon, PRUint32 aFlags)
 {
+  NS_TIME_FUNCTION;
+
   NS_PRECONDITION(aDoc && aPresShell, "bad arg");
   if (!aDoc || !aPresShell)
     return NS_ERROR_NULL_POINTER;
   
   nsresult res = NS_OK, rulesRes = NS_OK;
   
   if (1)
   {
--- a/embedding/components/appstartup/src/nsAppStartupNotifier.cpp
+++ b/embedding/components/appstartup/src/nsAppStartupNotifier.cpp
@@ -40,41 +40,47 @@
 #include "nsString.h"
 #include "nsXPIDLString.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsAppStartupNotifier.h"
 
+#include "mozilla/FunctionTimer.h"
+
 NS_IMPL_ISUPPORTS1(nsAppStartupNotifier, nsIObserver)
 
 nsAppStartupNotifier::nsAppStartupNotifier()
 {
 }
 
 nsAppStartupNotifier::~nsAppStartupNotifier()
 {
 }
 
 NS_IMETHODIMP nsAppStartupNotifier::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
 {
+    NS_TIME_FUNCTION;
+
     NS_ENSURE_ARG(aTopic);
     nsresult rv;
 
     // now initialize all startup listeners
     nsCOMPtr<nsICategoryManager> categoryManager =
                     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsISimpleEnumerator> enumerator;
     rv = categoryManager->EnumerateCategory(aTopic,
                                getter_AddRefs(enumerator));
     if (NS_FAILED(rv)) return rv;
 
+    NS_TIME_FUNCTION_MARK("EnumerateCategory");
+
     nsCOMPtr<nsISupports> entry;
     while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
         nsCOMPtr<nsISupportsCString> category = do_QueryInterface(entry, &rv);
 
         if (NS_SUCCEEDED(rv)) {
             nsCAutoString categoryEntry;
             rv = category->GetData(categoryEntry);
 
@@ -108,14 +114,17 @@ NS_IMETHODIMP nsAppStartupNotifier::Obse
                 }
                 else {
                   #ifdef NS_DEBUG
                     nsCAutoString warnStr("Cannot create startup observer : ");
                     warnStr += contractId.get();
                     NS_WARNING(warnStr.get());
                   #endif
                 }
+
+                NS_TIME_FUNCTION_MARK("observer: category: %s cid: %s", categoryEntry.get(), nsPromiseFlatCString(contractId).get());
+
             }
         }
     }
 
     return NS_OK;
 }
--- a/gfx/thebes/src/gfxPlatformFontList.h
+++ b/gfx/thebes/src/gfxPlatformFontList.h
@@ -41,32 +41,36 @@
 #include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsHashSets.h"
 
 #include "gfxFontUtils.h"
 #include "gfxFont.h"
 #include "gfxPlatform.h"
 
+#include "mozilla/FunctionTimer.h"
+
 // gfxPlatformFontList is an abstract class for the global font list on the system;
 // concrete subclasses for each platform implement the actual interface to the system fonts.
 // This class exists because we cannot rely on the platform font-finding APIs to behave
 // in sensible/similar ways, particularly with rich, complex OpenType families,
 // so we do our own font family/style management here instead.
 
 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms.
 
 class gfxPlatformFontList : protected gfxFontInfoLoader
 {
 public:
     static gfxPlatformFontList* PlatformFontList() {
         return sPlatformFontList;
     }
 
     static nsresult Init() {
+        NS_TIME_FUNCTION;
+
         NS_ASSERTION(!sPlatformFontList, "What's this doing here?");
         sPlatformFontList = gfxPlatform::GetPlatform()->CreatePlatformFontList();
         if (!sPlatformFontList) return NS_ERROR_OUT_OF_MEMORY;
         sPlatformFontList->InitFontList();
         return NS_OK;
     }
 
     static void Shutdown() {
--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
@@ -82,16 +82,18 @@
 #include "nsIConsoleService.h"
 #include "prmem.h"
 #include "plbase64.h"
 
 #if defined(MOZ_SHARK) || defined(MOZ_CALLGRIND) || defined(MOZ_VTUNE) || defined(MOZ_TRACEVIS)
 #include "jsdbgapi.h"
 #endif
 
+#include "mozilla/FunctionTimer.h"
+
 static const char kJSRuntimeServiceContractID[] = "@mozilla.org/js/xpc/RuntimeService;1";
 static const char kXPConnectServiceContractID[] = "@mozilla.org/js/xpc/XPConnect;1";
 static const char kObserverServiceContractID[] = "@mozilla.org/observer-service;1";
 
 /* Some platforms don't have an implementation of PR_MemMap(). */
 #if !defined(XP_BEOS) && !defined(XP_OS2)
 #define HAVE_PR_MEMMAP
 #endif
@@ -574,16 +576,18 @@ mozJSComponentLoader::sSelf;
 NS_IMPL_ISUPPORTS3(mozJSComponentLoader,
                    nsIModuleLoader,
                    xpcIJSModuleLoader,
                    nsIObserver)
  
 nsresult
 mozJSComponentLoader::ReallyInit()
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     /*
      * Get the JSRuntime from the runtime svc, if possible.
      * We keep a reference around, because it's a Bad Thing if the runtime
      * service gets shut down before we're done.  Bad!
      */
 
@@ -671,16 +675,23 @@ mozJSComponentLoader::ReallyInit()
 }
 
 NS_IMETHODIMP
 mozJSComponentLoader::LoadModule(nsILocalFile* aComponentFile,
                                  nsIModule* *aResult)
 {
     nsresult rv;
 
+#ifdef NS_FUNCTION_TIMER
+    nsAutoString path__(NS_LITERAL_STRING("N/A"));
+    aComponentFile->GetPath(path__);
+    NS_TIME_FUNCTION_FMT("%s (line %d) (file: %s)", MOZ_FUNCTION_NAME,
+                         __LINE__, nsPromiseFlatCString(NS_LossyConvertUTF16toASCII(path__)).BeginReading());
+#endif
+
     nsCAutoString leafName;
     aComponentFile->GetNativeLeafName(leafName);
     if (!StringTail(leafName, 3).LowerCaseEqualsLiteral(".js"))
         return NS_ERROR_INVALID_ARG;
 
     if (!mInitialized) {
         rv = ReallyInit();
         if (NS_FAILED(rv))
@@ -1424,16 +1435,19 @@ mozJSComponentLoader::UnloadModules()
 /* [JSObject] import (in AUTF8String registryLocation,
                       [optional] in JSObject targetObj ); */
 NS_IMETHODIMP
 mozJSComponentLoader::Import(const nsACString & registryLocation)
 {
     // This function should only be called from JS.
     nsresult rv;
 
+    NS_TIME_FUNCTION_FMT("%s (line %d) (file: %s)", MOZ_FUNCTION_NAME,
+                         __LINE__, registryLocation.BeginReading());
+
     nsCOMPtr<nsIXPConnect> xpc =
         do_GetService(kXPConnectServiceContractID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     
     nsAXPCNativeCallContext *cc = nsnull;
     rv = xpc->GetCurrentNativeCallContext(&cc);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -55,16 +55,18 @@
 #include "nsAutoPtr.h"
 #include "nsNetUtil.h"
 #include "nsIProtocolHandler.h"
 #include "nsIFileURL.h"
 
 #include "jsapi.h"
 #include "jsdbgapi.h"
 
+#include "mozilla/FunctionTimer.h"
+
 /* load() error msgs, XXX localize? */
 #define LOAD_ERROR_NOSERVICE "Error creating IO Service."
 #define LOAD_ERROR_NOURI "Error creating URI (invalid URL scheme?)"
 #define LOAD_ERROR_NOSCHEME "Failed to get URI scheme.  This is bad."
 #define LOAD_ERROR_URI_NOT_LOCAL "Trying to load a non-local URI."
 #define LOAD_ERROR_NOSTREAM  "Error opening input stream (invalid filename?)"
 #define LOAD_ERROR_NOCONTENT "ContentLength not available (not a local URL?)"
 #define LOAD_ERROR_BADREAD   "File Read Error."
@@ -83,17 +85,17 @@ mozJSSubScriptLoader::mozJSSubScriptLoad
 mozJSSubScriptLoader::~mozJSSubScriptLoader()    
 {
     /* empty */
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(mozJSSubScriptLoader, mozIJSSubScriptLoader)
 
 NS_IMETHODIMP /* args and return value are delt with using XPConnect and JSAPI */
-mozJSSubScriptLoader::LoadSubScript (const PRUnichar * /*url*/
+mozJSSubScriptLoader::LoadSubScript (const PRUnichar * aURL
                                      /* [, JSObject *target_obj] */)
 {
     /*
      * Loads a local url and evals it into the current cx
      * Synchronous (an async version would be cool too.)
      *   url: The url to load.  Must be local so that it can be loaded
      *        synchronously.
      *   target_obj: Optional object to eval the script onto (defaults to context
@@ -102,16 +104,23 @@ mozJSSubScriptLoader::LoadSubScript (con
      * Should ONLY (O N L Y !) be called from JavaScript code.
      */
     
     /* gotta define most of this stuff up here because of all the gotos,
      * defined the rest up here to be consistent */
     nsresult  rv;
     JSBool    ok;
 
+#ifdef NS_FUNCTION_TIMER
+    NS_TIME_FUNCTION_FMT("%s (line %d) (url: %s)", MOZ_FUNCTION_NAME,
+                         __LINE__, NS_LossyConvertUTF16toASCII(aURL).get());
+#else
+    aURL; // prevent compiler warning
+#endif
+
     /* get JS things from the CallContext */
     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
     if (!xpc) return NS_ERROR_FAILURE;
 
     nsAXPCNativeCallContext *cc = nsnull;
     rv = xpc->GetCurrentNativeCallContext(&cc);
     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -38,16 +38,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* Per JSRuntime object */
 
 #include "xpcprivate.h"
 #include "dom_quickstubs.h"
 
+#include "mozilla/FunctionTimer.h"
+
 /***************************************************************************/
 
 const char* XPCJSRuntime::mStrings[] = {
     "constructor",          // IDX_CONSTRUCTOR
     "toString",             // IDX_TO_STRING
     "toSource",             // IDX_TO_SOURCE
     "lastResult",           // IDX_LAST_RESULT
     "returnCode",           // IDX_RETURN_CODE
@@ -1062,16 +1064,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
    mWatchdogWakeup(nsnull),
    mWatchdogThread(nsnull)
 {
 #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
     DEBUG_WrappedNativeHashtable =
         JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
                          sizeof(JSDHashEntryStub), 128);
 #endif
+    NS_TIME_FUNCTION;
 
     DOM_InitInterfaces();
 
     // these jsids filled in later when we have a JSContext to work with.
     mStrIDs[0] = 0;
 
     mJSRuntime = JS_NewRuntime(32L * 1024L * 1024L); // pref ?
     if(mJSRuntime)
@@ -1134,16 +1137,18 @@ XPCJSRuntime::newXPCJSRuntime(nsXPConnec
     }
     delete self;
     return nsnull;
 }
 
 JSBool
 XPCJSRuntime::OnJSContextNew(JSContext *cx)
 {
+    NS_TIME_FUNCTION;
+
     // if it is our first context then we need to generate our string ids
     JSBool ok = JS_TRUE;
     if(!mStrIDs[0])
     {
         JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024);
         JSAutoRequest ar(cx);
         for(uintN i = 0; i < IDX_TOTAL_COUNT; i++)
         {
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -201,16 +201,32 @@
 #include "nsPlaceholderFrame.h"
 #include "nsCanvasFrame.h"
 
 // Content viewer interfaces
 #include "nsIContentViewer.h"
 #include "imgIEncoder.h"
 #include "gfxPlatform.h"
 
+#include "mozilla/FunctionTimer.h"
+
+#ifdef NS_FUNCTION_TIMER
+#define NS_TIME_FUNCTION_DECLARE_DOCURL                \
+  nsCAutoString docURL__("N/A");                       \
+  nsIURI *uri__ = mDocument->GetDocumentURI();         \
+  if (uri__) uri__->GetSpec(docURL__);
+#define NS_TIME_FUNCTION_WITH_DOCURL                   \
+  NS_TIME_FUNCTION_DECLARE_DOCURL                      \
+  NS_TIME_FUNCTION_MIN_FMT(1.0,                        \
+     "%s (line %d) (document: %s)", MOZ_FUNCTION_NAME, \
+     __LINE__, docURL__.get())
+#else
+#define NS_TIME_FUNCTION_WITH_DOCURL do{} while(0)
+#endif
+
 #include "nsContentCID.h"
 static NS_DEFINE_IID(kRangeCID,     NS_RANGE_CID);
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
 PRBool nsIPresShell::gIsAccessibilityActive = PR_FALSE;
 CapturingContentInfo nsIPresShell::gCaptureInfo;
@@ -1545,16 +1561,18 @@ PresShell::~PresShell()
  */
 nsresult
 PresShell::Init(nsIDocument* aDocument,
                 nsPresContext* aPresContext,
                 nsIViewManager* aViewManager,
                 nsStyleSet* aStyleSet,
                 nsCompatibility aCompatMode)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_PRECONDITION(nsnull != aDocument, "null ptr");
   NS_PRECONDITION(nsnull != aPresContext, "null ptr");
   NS_PRECONDITION(nsnull != aViewManager, "null ptr");
   nsresult result;
 
   if ((nsnull == aDocument) || (nsnull == aPresContext) ||
       (nsnull == aViewManager)) {
     return NS_ERROR_NULL_POINTER;
@@ -1693,16 +1711,18 @@ PresShell::Init(nsIDocument* aDocument,
 #endif // MOZ_SMIL
 
   return NS_OK;
 }
 
 void
 PresShell::Destroy()
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
     "destroy called on presshell while scripts not blocked");
 
 #ifdef MOZ_REFLOW_PERF
   DumpReflows();
   if (mReflowCountMgr) {
     delete mReflowCountMgr;
     mReflowCountMgr = nsnull;
@@ -1931,16 +1951,18 @@ PRBool
 nsIPresShell::GetAuthorStyleDisabled() const
 {
   return mStyleSet->GetAuthorStyleDisabled();
 }
 
 nsresult
 PresShell::SetPreferenceStyleRules(PRBool aForceReflow)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   if (!mDocument) {
     return NS_ERROR_NULL_POINTER;
   }
 
   nsPIDOMWindow *window = mDocument->GetWindow();
 
   // If the document doesn't have a window there's no need to notify
   // its presshell about changes to preferences since the document is
@@ -2019,16 +2041,18 @@ nsresult PresShell::ClearPreferenceStyle
       mPrefStyleSheet = nsnull;
     }
   }
   return result;
 }
 
 nsresult PresShell::CreatePreferenceStyleSheet(void)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_ASSERTION(!mPrefStyleSheet, "prefStyleSheet already exists");
   nsresult result = NS_NewCSSStyleSheet(getter_AddRefs(mPrefStyleSheet));
   if (NS_SUCCEEDED(result)) {
     NS_ASSERTION(mPrefStyleSheet, "null but no error");
     nsCOMPtr<nsIURI> uri;
     result = NS_NewURI(getter_AddRefs(uri), "about:PreferenceStyleSheet", nsnull);
     if (NS_SUCCEEDED(result)) {
       NS_ASSERTION(uri, "null but no error");
@@ -2058,16 +2082,18 @@ nsresult PresShell::CreatePreferenceStyl
 // XXX We want these after the @namespace rule.  Does order matter
 // for these rules, or can we call nsICSSStyleRule::StyleRuleCount()
 // and just "append"?
 static PRUint32 sInsertPrefSheetRulesAt = 1;
 
 nsresult
 PresShell::SetPrefNoScriptRule()
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   nsresult rv = NS_OK;
 
   // also handle the case where print is done from print preview
   // see bug #342439 for more details
   nsIDocument* doc = mDocument;
   if (mPresContext->Type() == nsPresContext::eContext_PrintPreview ||
       mPresContext->Type() == nsPresContext::eContext_Print) {
     while (doc->GetOriginalDocument()) {
@@ -2088,16 +2114,18 @@ PresShell::SetPrefNoScriptRule()
                          sInsertPrefSheetRulesAt, &index);
   }
 
   return rv;
 }
 
 nsresult PresShell::SetPrefNoFramesRule(void)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_ASSERTION(mPresContext,"null prescontext not allowed");
   if (!mPresContext) {
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = NS_OK;
   
   if (!mPrefStyleSheet) {
@@ -2123,16 +2151,18 @@ nsresult PresShell::SetPrefNoFramesRule(
       InsertRuleInternal(NS_LITERAL_STRING("frame, frameset, iframe {display:none!important}"),
                          sInsertPrefSheetRulesAt, &index);
   }
   return rv;
 }
   
 nsresult PresShell::SetPrefLinkRules(void)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_ASSERTION(mPresContext,"null prescontext not allowed");
   if (!mPresContext) {
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv = NS_OK;
   
   if (!mPrefStyleSheet) {
@@ -2198,16 +2228,18 @@ nsresult PresShell::SetPrefLinkRules(voi
                          sInsertPrefSheetRulesAt, &index);
   }
 
   return rv;          
 }
 
 nsresult PresShell::SetPrefFocusRules(void)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_ASSERTION(mPresContext,"null prescontext not allowed");
   nsresult result = NS_OK;
 
   if (!mPresContext)
     result = NS_ERROR_FAILURE;
 
   if (NS_SUCCEEDED(result) && !mPrefStyleSheet)
     result = CreatePreferenceStyleSheet();
@@ -2433,16 +2465,18 @@ PresShell::InitialReflow(nscoord aWidth,
     return NS_OK;
   }
 
   if (!mDocument) {
     // Nothing to do
     return NS_OK;
   }
 
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   NS_ASSERTION(!mDidInitialReflow, "Why are we being called?");
 
   nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
   mDidInitialReflow = PR_TRUE;
 
 #ifdef NS_DEBUG
   if (VERIFY_REFLOW_NOISY_RC & gVerifyReflowFlags) {
     if (mDocument) {
@@ -2504,16 +2538,18 @@ PresShell::InitialReflow(nscoord aWidth,
     }
 
     // nsAutoScriptBlocker going out of scope may have killed us too
     NS_ENSURE_STATE(!mHaveShutDown);
 
     // Run the XBL binding constructors for any new frames we've constructed
     mDocument->BindingManager()->ProcessAttachedQueue();
 
+    NS_TIME_FUNCTION_MARK("XBL binding constructors fired");
+
     // Constructors may have killed us too
     NS_ENSURE_STATE(!mHaveShutDown);
 
     // Now flush out pending restyles before we actually reflow, in
     // case XBL constructors changed styles somewhere.
     {
       nsAutoScriptBlocker scriptBlocker;
       mFrameConstructor->CreateNeededFrames();
@@ -2710,16 +2746,18 @@ void
 PresShell::SetIgnoreFrameDestruction(PRBool aIgnore)
 {
   mIgnoreFrameDestruction = aIgnore;
 }
 
 void
 PresShell::NotifyDestroyingFrame(nsIFrame* aFrame)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   if (!mIgnoreFrameDestruction) {
     mPresContext->StopImagesFor(aFrame);
 
     mFrameConstructor->NotifyDestroyingFrame(aFrame);
 
     for (PRInt32 idx = mDirtyRoots.Length(); idx; ) {
       --idx;
       if (mDirtyRoots[idx] == aFrame) {
@@ -3202,16 +3240,25 @@ PresShell::VerifyHasDirtyRootAncestor(ns
                 "reflowed?");
 }
 #endif
 
 void
 PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
                             nsFrameState aBitToAdd)
 {
+#ifdef NS_FUNCTION_TIMER
+  NS_TIME_FUNCTION_DECLARE_DOCURL;
+  nsCAutoString frameType__("N/A");
+  nsIAtom *atomType__ = aFrame ? aFrame->GetType() : nsnull;
+  if (atomType__) atomType__->ToUTF8String(frameType__);
+  NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, frame type: %s)", MOZ_FUNCTION_NAME,
+                           __LINE__, docURL__.get(), frameType__.get());
+#endif
+
   NS_PRECONDITION(aBitToAdd == NS_FRAME_IS_DIRTY ||
                   aBitToAdd == NS_FRAME_HAS_DIRTY_CHILDREN,
                   "Unexpected bits being added");
   NS_PRECONDITION(aIntrinsicDirty != eStyleChange ||
                   aBitToAdd == NS_FRAME_IS_DIRTY,
                   "bits don't correspond to style change reason");
 
   NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow");
@@ -3433,16 +3480,18 @@ void nsIPresShell::InvalidateAccessibleS
     }
   }
 }
 #endif
 
 nsresult
 PresShell::RecreateFramesFor(nsIContent* aContent)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
   if (!mDidInitialReflow) {
     // Nothing to do here.  In fact, if we proceed and aContent is the
     // root we will crash.
     return NS_OK;
   }
 
   // Don't call RecreateFramesForContent since that is not exported and we want
@@ -3501,16 +3550,18 @@ PresShell::ClearFrameRefs(nsIFrame* aFra
     weakFrame = prev;
   }
 }
 
 nsresult
 PresShell::CreateRenderingContext(nsIFrame *aFrame,
                                   nsIRenderingContext** aResult)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   NS_PRECONDITION(nsnull != aResult, "null ptr");
   if (nsnull == aResult) {
     return NS_ERROR_NULL_POINTER;
   }
 
   nsIWidget* widget = nsnull;
   nsPoint offset(0,0);
   if (mPresContext->IsScreen()) {
@@ -4315,16 +4366,18 @@ PresShell::ClearMouseCapture(nsIView* aV
   // or a drag has started. Otherwise, someone could start capture during
   // the modal dialog or drag.
   gCaptureInfo.mAllowed = PR_FALSE;
 }
 
 nsresult
 PresShell::CaptureHistoryState(nsILayoutHistoryState** aState, PRBool aLeavingPage)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   nsresult rv = NS_OK;
 
   NS_PRECONDITION(nsnull != aState, "null state pointer");
 
   // We actually have to mess with the docshell here, since we want to
   // store the state back in it.
   // XXXbz this isn't really right, since this is being called in the
   // content viewer's Hide() method...  by that point the docshell's
@@ -4550,16 +4603,30 @@ PresShell::IsSafeToFlush() const
 
   return isSafeToFlush;
 }
 
 
 void
 PresShell::FlushPendingNotifications(mozFlushType aType)
 {
+#ifdef NS_FUNCTION_TIMER
+  NS_TIME_FUNCTION_DECLARE_DOCURL;
+  static const char *flushTypeNames[] = {
+    "Flush_Content",
+    "Flush_ContentAndNotify",
+    "Flush_Styles",
+    "Flush_InterruptibleLayout",
+    "Flush_Layout",
+    "Flush_Display"
+  };
+  NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, type: %s)", MOZ_FUNCTION_NAME,
+                           __LINE__, docURL__.get(), flushTypeNames[aType - 1]);
+#endif
+
   NS_ASSERTION(aType >= Flush_Frames, "Why did we get called?");
 
   PRBool isSafeToFlush = IsSafeToFlush();
   isSafeToFlush = isSafeToFlush && nsContentUtils::IsSafeToRunScript();
 
   NS_ASSERTION(!isSafeToFlush || mViewManager, "Must have view manager");
   // Make sure the view manager stays alive while batching view updates.
   nsCOMPtr<nsIViewManager> viewManagerDeathGrip = mViewManager;
@@ -5025,16 +5092,18 @@ PresShell::ComputeRepaintRegionForCopy(n
  * @param aFillRegion clip region for background filling
  *   partial clipping is not implemented yet,
  *   nsnull or IsEmpty - then whole aRect painted
  */
 static inline PRBool
 PrepareContext(const nsRect& aRect, nscolor aBackgroundColor,
                gfxContext* aThebesContext, nsRegion *aFillRegion = nsnull)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
   gfxRect r(0, 0,
             nsPresContext::AppUnitsToFloatCSSPixels(aRect.width),
             nsPresContext::AppUnitsToFloatCSSPixels(aRect.height));
   aThebesContext->Save();
 
   aThebesContext->NewPath();
 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
   aThebesContext->Rectangle(r, PR_TRUE);
@@ -5071,16 +5140,18 @@ PrepareContext(const nsRect& aRect, nsco
   return needsGroup;
 }
 
 nsresult
 PresShell::RenderDocument(const nsRect& aRect, PRUint32 aFlags,
                           nscolor aBackgroundColor,
                           gfxContext* aThebesContext)
 {
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   NS_ENSURE_TRUE(!(aFlags & RENDER_IS_UNTRUSTED), NS_ERROR_NOT_IMPLEMENTED);
 
   // we want the window to be composited as a single image using
   // whatever operator was set; set OPERATOR_OVER here, which is
   // either already the case, or overrides the operator in a group.
   // the original operator will be present when we PopGroup.
 
   PRBool needsGroup = PR_TRUE;
@@ -5177,16 +5248,18 @@ PresShell::RenderDocument(const nsRect& 
  * Clip the display list aList to a range. Returns the clipped
  * rectangle surrounding the range.
  */
 nsRect
 PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
                            nsDisplayList* aList,
                            nsIRange* aRange)
 {
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   // iterate though the display items and add up the bounding boxes of each.
   // This will allow the total area of the frames within the range to be
   // determined. To do this, remove an item from the bottom of the list, check
   // whether it should be part of the range, and if so, append it to the top
   // of the temporary list tmpList. If the item is a text frame at the end of
   // the selection range, wrap it in an nsDisplayClip to clip the display to
   // the portion of the text frame that is part of the selection. Then, append
   // the wrapper to the top of the list. Otherwise, just delete the item and
@@ -5268,16 +5341,18 @@ PresShell::ClipListToRange(nsDisplayList
 
   return surfaceRect;
 }
 
 RangePaintInfo*
 PresShell::CreateRangePaintInfo(nsIDOMRange* aRange,
                                 nsRect& aSurfaceRect)
 {
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   RangePaintInfo* info = nsnull;
 
   nsCOMPtr<nsIRange> range = do_QueryInterface(aRange);
   if (!range)
     return nsnull;
 
   nsIFrame* ancestorFrame;
   nsIFrame* rootFrame = GetRootFrame();
@@ -5339,16 +5414,18 @@ PresShell::CreateRangePaintInfo(nsIDOMRa
 already_AddRefed<gfxASurface>
 PresShell::PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
                                nsISelection* aSelection,
                                nsIRegion* aRegion,
                                nsRect aArea,
                                nsIntPoint& aPoint,
                                nsIntRect* aScreenRect)
 {
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   nsPresContext* pc = GetPresContext();
   if (!pc || aArea.width == 0 || aArea.height == 0)
     return nsnull;
 
   nsIDeviceContext* deviceContext = pc->DeviceContext();
 
   // use the rectangle to create the surface
   nsIntRect pixelArea = aArea.ToOutsidePixels(pc->AppUnitsPerDevPixel());
@@ -5603,16 +5680,27 @@ nscolor PresShell::ComputeBackstopColor(
 
 NS_IMETHODIMP
 PresShell::Paint(nsIView*        aDisplayRoot,
                  nsIView*        aViewToPaint,
                  nsIWidget*      aWidgetToPaint,
                  const nsRegion& aDirtyRegion,
                  PRBool          aPaintDefaultBackground)
 {
+#ifdef NS_FUNCTION_TIMER
+  NS_TIME_FUNCTION_DECLARE_DOCURL;
+  const nsRect& bounds__ = aDirtyRegion.GetBounds();
+  NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, dirty rect: (<%f, %f>, <%f, %f>)",
+                           MOZ_FUNCTION_NAME, __LINE__, docURL__.get(),
+                           NSCoordToFloat(bounds__.x),
+                           NSCoordToFloat(bounds__.y),
+                           NSCoordToFloat(bounds__.XMost()),
+                           NSCoordToFloat(bounds__.YMost()));
+#endif
+
   nsPresContext* presContext = GetPresContext();
   AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
 
   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
   NS_ASSERTION(aDisplayRoot, "null view");
   NS_ASSERTION(aViewToPaint, "null view");
   NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
 
@@ -5856,16 +5944,18 @@ PresShell::HandleEvent(nsIView         *
   NS_ASSERTION(aView, "null view");
 
   if (mIsDestroying || !nsContentUtils::IsSafeToRunScript() ||
       (sDisableNonTestMouseEvents && NS_IS_MOUSE_EVENT(aEvent) &&
        !(aEvent->flags & NS_EVENT_FLAG_SYNTHETIC_TEST_EVENT))) {
     return NS_OK;
   }
 
+  NS_TIME_FUNCTION_MIN(1.0);
+
 #ifdef ACCESSIBILITY
   if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
     // Accessibility events come through OS requests and not from scripts,
     // so it is safe to handle here
     return HandleEventInternal(aEvent, aView, aEventStatus);
   }
 #endif
 
@@ -6325,16 +6415,18 @@ static PRBool CanHandleContextMenuEvent(
 #endif
   return PR_TRUE;
 }
 
 nsresult
 PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
                                nsEventStatus* aStatus)
 {
+  NS_TIME_FUNCTION_MIN(1.0);
+
 #ifdef ACCESSIBILITY
   if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
   {
     nsAccessibleEvent *accEvent = static_cast<nsAccessibleEvent*>(aEvent);
     accEvent->mAccessible = nsnull;
 
     nsCOMPtr<nsIAccessibilityService> accService =
       do_GetService("@mozilla.org/accessibilityService;1");
@@ -7132,16 +7224,18 @@ PresShell::ScheduleReflowOffTimer()
     }
   }
   return PR_TRUE;
 }
 
 PRBool
 PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible)
 {
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   if (mReflowContinueTimer) {
     mReflowContinueTimer->Cancel();
     mReflowContinueTimer = nsnull;
   }
 
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
 
   nsCOMPtr<nsIRenderingContext> rcx;
@@ -7290,16 +7384,18 @@ PresShell::DoVerifyReflow()
     }
   }
 }
 #endif
 
 PRBool
 PresShell::ProcessReflowCommands(PRBool aInterruptible)
 {
+  NS_TIME_FUNCTION_WITH_DOCURL;
+
   PRBool interrupted = PR_FALSE;
   if (0 != mDirtyRoots.Length()) {
 
 #ifdef DEBUG
     if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
       printf("ProcessReflowCommands: begin incremental reflow\n");
     }
 #endif
--- a/layout/build/nsContentDLF.cpp
+++ b/layout/build/nsContentDLF.cpp
@@ -57,16 +57,18 @@
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif
 
 #include "imgILoader.h"
 #include "nsIParser.h"
 #include "nsMimeTypes.h"
 
+#include "mozilla/FunctionTimer.h"
+
 // plugins
 #include "nsIPluginHost.h"
 static NS_DEFINE_CID(kPluginDocumentCID, NS_PLUGINDOCUMENT_CID);
 
 // Factory code for creating variations on html documents
 
 #undef NOISY_REGISTRY
 
@@ -159,16 +161,26 @@ nsContentDLF::CreateInstance(const char*
                              nsIChannel* aChannel,
                              nsILoadGroup* aLoadGroup,
                              const char* aContentType, 
                              nsISupports* aContainer,
                              nsISupports* aExtraInfo,
                              nsIStreamListener** aDocListener,
                              nsIContentViewer** aDocViewer)
 {
+#ifdef NS_FUNCTION_TIMER
+  nsCAutoString channelURL__("N/A");
+  nsCOMPtr<nsIURI> url__;
+  if (aChannel && NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(url__)))) {
+    url__->GetSpec(channelURL__);
+  }
+  NS_TIME_FUNCTION_FMT("%s (line %d) (url: %s)", MOZ_FUNCTION_NAME,
+                       __LINE__, channelURL__.get());
+#endif
+
   // Declare "type" here.  This is because although the variable itself only
   // needs limited scope, we need to use the raw string memory -- as returned
   // by "type.get()" farther down in the function.
   nsCAutoString type;
 
   // Are we viewing source?
 #ifdef MOZ_VIEW_SOURCE
   nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(aChannel);
@@ -305,16 +317,18 @@ nsContentDLF::CreateInstance(const char*
 
 
 NS_IMETHODIMP
 nsContentDLF::CreateInstanceForDocument(nsISupports* aContainer,
                                         nsIDocument* aDocument,
                                         const char *aCommand,
                                         nsIContentViewer** aDocViewerResult)
 {
+  NS_TIME_FUNCTION;
+
   nsresult rv = NS_ERROR_FAILURE;  
 
   do {
     nsCOMPtr<nsIDocumentViewer> docv;
     rv = NS_NewDocumentViewer(getter_AddRefs(docv));
     if (NS_FAILED(rv))
       break;
 
@@ -327,16 +341,18 @@ nsContentDLF::CreateInstanceForDocument(
   return rv;
 }
 
 NS_IMETHODIMP
 nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup,
                                   nsIPrincipal* aPrincipal,
                                   nsIDocument **aDocument)
 {
+  NS_TIME_FUNCTION;
+
   *aDocument = nsnull;
 
   nsresult rv = NS_ERROR_FAILURE;
 
   // create a new blank HTML document
   nsCOMPtr<nsIDocument> blankDoc(do_CreateInstance(kHTMLDocumentCID));
 
   if (blankDoc) {
@@ -401,16 +417,18 @@ nsresult
 nsContentDLF::CreateDocument(const char* aCommand,
                              nsIChannel* aChannel,
                              nsILoadGroup* aLoadGroup,
                              nsISupports* aContainer,
                              const nsCID& aDocumentCID,
                              nsIStreamListener** aDocListener,
                              nsIContentViewer** aDocViewer)
 {
+  NS_TIME_FUNCTION;
+
   nsresult rv = NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIURI> aURL;
   rv = aChannel->GetURI(getter_AddRefs(aURL));
   if (NS_FAILED(rv)) return rv;
 
 #ifdef NOISY_CREATE_DOC
   if (nsnull != aURL) {
@@ -457,16 +475,18 @@ nsContentDLF::CreateXULDocument(const ch
                                 nsIChannel* aChannel,
                                 nsILoadGroup* aLoadGroup,
                                 const char* aContentType,
                                 nsISupports* aContainer,
                                 nsISupports* aExtraInfo,
                                 nsIStreamListener** aDocListener,
                                 nsIContentViewer** aDocViewer)
 {
+  NS_TIME_FUNCTION;
+
   nsresult rv;
   nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXULDocumentCID, &rv);
   if (NS_FAILED(rv)) return rv;
 
   nsCOMPtr<nsIDocumentViewer> docv;
   rv = NS_NewDocumentViewer(getter_AddRefs(docv));
   if (NS_FAILED(rv)) return rv;
 
@@ -555,16 +575,18 @@ nsContentDLF::UnregisterSVG()
 
 NS_IMETHODIMP
 nsContentDLF::RegisterDocumentFactories(nsIComponentManager* aCompMgr,
                                         nsIFile* aPath,
                                         const char *aLocation,
                                         const char *aType,
                                         const nsModuleComponentInfo* aInfo)
 {
+  NS_TIME_FUNCTION;
+
   nsresult rv;
 
   nsCOMPtr<nsICategoryManager> catmgr(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
   if (NS_FAILED(rv)) return rv;
 
   do {
     rv = RegisterTypes(catmgr, gHTMLTypes);
     if (NS_FAILED(rv))
@@ -580,16 +602,18 @@ nsContentDLF::RegisterDocumentFactories(
 }
 
 NS_IMETHODIMP
 nsContentDLF::UnregisterDocumentFactories(nsIComponentManager* aCompMgr,
                                           nsIFile* aPath,
                                           const char* aRegistryLocation,
                                           const nsModuleComponentInfo* aInfo)
 {
+  NS_TIME_FUNCTION;
+
   nsresult rv;
   nsCOMPtr<nsICategoryManager> catmgr(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
   if (NS_FAILED(rv)) return rv;
 
   do {
     rv = UnregisterTypes(catmgr, gHTMLTypes);
     if (NS_FAILED(rv))
       break;
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -116,16 +116,18 @@
 #include "nsIDOMKeyListener.h"
 #include "nsIDOMEventGroup.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsINativeKeyBindings.h"
 #include "nsIJSContextStack.h"
 #include "nsFocusManager.h"
 #include "nsTextEditRules.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #define DEFAULT_COLUMN_WIDTH 20
 
 #include "nsContentCID.h"
 static NS_DEFINE_IID(kRangeCID,     NS_RANGE_CID);
 
 static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
 static NS_DEFINE_CID(kFrameSelectionCID, NS_FRAMESELECTION_CID);
 
@@ -1368,16 +1370,18 @@ nsTextControlFrame::EnsureEditorInitiali
   // never get used.  So, now this method is being called lazily only
   // when we actually need an editor.
 
   // Check if this method has been called already.
   // If so, just return early.
   if (mUseEditor)
     return NS_OK;
 
+  NS_TIME_FUNCTION;
+
   nsIDocument* doc = mContent->GetCurrentDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   nsWeakFrame weakFrame(this);
 
   // Flush out content on our document.  Have to do this, because script
   // blockers don't prevent the sink flushing out content and notifying in the
   // process, which can destroy frames.
--- a/layout/style/nsCSSLoader.cpp
+++ b/layout/style/nsCSSLoader.cpp
@@ -95,16 +95,18 @@
 #include "nsIDOMStyleSheet.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsIDOMCSSImportRule.h"
 #include "nsContentErrors.h"
 
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 
+#include "mozilla/FunctionTimer.h"
+
 /**
  * OVERALL ARCHITECTURE
  *
  * The CSS Loader gets requests to load various sorts of style sheets:
  * inline style from <style> elements, linked style, @import-ed child
  * sheets, non-document sheets.  The loader handles the following tasks:
  *
  * 1) Checking whether the load is allowed: CheckLoadAllowed()
@@ -1377,16 +1379,23 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
   NS_PRECONDITION(aLoadData, "Need a load data");
   NS_PRECONDITION(aLoadData->mURI, "Need a URI to load");
   NS_PRECONDITION(aLoadData->mSheet, "Need a sheet to load into");
   NS_PRECONDITION(aSheetState != eSheetComplete, "Why bother?");
   NS_PRECONDITION(!aLoadData->mUseSystemPrincipal || aLoadData->mSyncLoad,
                   "Shouldn't use system principal for async loads");
   NS_ASSERTION(mLoadingDatas.IsInitialized(), "mLoadingDatas should be initialized by now.");
 
+#ifdef NS_FUNCTION_TIMER
+  nsCAutoString spec__("N/A");
+  if (aLoadData->mURI) aLoadData->mURI->GetSpec(spec__);
+  NS_TIME_FUNCTION_FMT("Loading stylesheet (url: %s, %ssync)",
+                       spec__.get(), aLoadData->mSyncLoad ? "" : "a");
+#endif
+
   LOG_URI("  Load from: '%s'", aLoadData->mURI);
   
   nsresult rv = NS_OK;  
 
   if (!mDocument && !aLoadData->mIsNonDocumentSheet) {
     // No point starting the load; just release all the data and such.
     LOG_WARN(("  No document and not non-document sheet; pre-dropping load"));
     SheetComplete(aLoadData, NS_BINDING_ABORTED);
@@ -1625,16 +1634,22 @@ Loader::ParseSheet(nsIUnicharInputStream
                    SheetLoadData* aLoadData,
                    PRBool& aCompleted)
 {
   LOG(("css::Loader::ParseSheet"));
   NS_PRECONDITION(aStream, "Must have data to parse");
   NS_PRECONDITION(aLoadData, "Must have load data");
   NS_PRECONDITION(aLoadData->mSheet, "Must have sheet to parse into");
 
+#ifdef NS_FUNCTION_TIMER
+  nsCAutoString spec__("N/A");
+  if (aLoadData->mURI) aLoadData->mURI->GetSpec(spec__);
+  NS_TIME_FUNCTION_FMT("Parsing stylesheet (url: %s)", spec__.get());
+#endif
+
   aCompleted = PR_FALSE;
 
   nsCSSParser parser(this, aLoadData->mSheet);
   if (!parser) {
     LOG_ERROR(("  Failed to get CSS parser"));
     SheetComplete(aLoadData, NS_ERROR_OUT_OF_MEMORY);
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -55,16 +55,18 @@
 #include "nsRecyclingAllocator.h"
 #include "prio.h"
 #include "plstr.h"
 #include "prlog.h"
 #include "stdlib.h"
 #include "nsWildCard.h"
 #include "nsZipArchive.h"
 
+#include "mozilla/FunctionTimer.h"
+
 /**
  * Global allocator used with zlib. Destroyed in module shutdown.
  */
 #define NBUCKETS 6
 nsRecyclingAllocator *gZlibAllocator = NULL;
 
 // For placement new used for arena allocations of zip file list
 #include NEW_H
@@ -516,16 +518,18 @@ nsZipItem* nsZipArchive::CreateZipItem()
   return (nsZipItem*)mem;
 }
 
 //---------------------------------------------
 //  nsZipArchive::BuildFileList
 //---------------------------------------------
 nsresult nsZipArchive::BuildFileList()
 {
+  NS_TIME_FUNCTION;
+
   // Get archive size using end pos
   PRUint8* buf;
   PRUint8* startp = mFd->mFileData;
   PRUint8* endp = startp + mFd->mLen;
 
   PRUint32 centralOffset = 0;
   for (buf = endp - ZIPEND_SIZE; buf > startp; buf--)
   {
--- a/modules/libpr0n/src/imgLoader.cpp
+++ b/modules/libpr0n/src/imgLoader.cpp
@@ -70,16 +70,18 @@
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheContainer.h"
 
 // we want to explore making the document own the load group
 // so we can associate the document URI with the load group.
 // until this point, we have an evil hack:
 #include "nsIHttpChannelInternal.h"  
 
+#include "mozilla/FunctionTimer.h"
+
 #if defined(DEBUG_pavlov) || defined(DEBUG_timeless)
 #include "nsISimpleEnumerator.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsXPIDLString.h"
 #include "nsComponentManagerUtils.h"
 
 static void PrintImageDecoders()
@@ -661,16 +663,18 @@ imgCacheQueue & imgLoader::GetCacheQueue
   if (chrome)
     return sChromeCacheQueue;
   else
     return sCacheQueue;
 }
 
 nsresult imgLoader::InitCache()
 {
+  NS_TIME_FUNCTION;
+
   nsresult rv;
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (!os)
     return NS_ERROR_FAILURE;
   
   gCacheObserver = new imgCacheObserver();
   if (!gCacheObserver) 
     return NS_ERROR_OUT_OF_MEMORY;
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -70,16 +70,18 @@
 #include "nsSimpleNestedURI.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsTArray.h"
 #include "nsIConsoleService.h"
 #include "nsIUploadChannel2.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #if defined(XP_WIN) || defined(MOZ_ENABLE_LIBCONIC)
 #include "nsNativeConnectionHelper.h"
 #endif
 
 #define PORT_PREF_PREFIX           "network.security.ports."
 #define PORT_PREF(x)               PORT_PREF_PREFIX x
 #define AUTODIAL_PREF              "network.autodial-helper.enabled"
 #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status"
@@ -180,44 +182,52 @@ nsIOService::nsIOService()
     , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
     , mContentSniffers(NS_CONTENT_SNIFFER_CATEGORY)
 {
 }
 
 nsresult
 nsIOService::Init()
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
     
     // We need to get references to these services so that we can shut them
     // down later. If we wait until the nsIOService is being shut down,
     // GetService will fail at that point.
 
     // TODO(darin): Load the Socket and DNS services lazily.
 
     mSocketTransportService = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     if (NS_FAILED(rv)) {
         NS_WARNING("failed to get socket transport service");
         return rv;
     }
 
+    NS_TIME_FUNCTION_MARK("got SocketTransportService");
+
     mDNSService = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
     if (NS_FAILED(rv)) {
         NS_WARNING("failed to get DNS service");
         return rv;
     }
 
+    NS_TIME_FUNCTION_MARK("got DNS Service");
+
     // XXX hack until xpidl supports error info directly (bug 13423)
     nsCOMPtr<nsIErrorService> errorService = do_GetService(NS_ERRORSERVICE_CONTRACTID);
     if (errorService) {
         errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_NETWORK, NECKO_MSGS_URL);
     }
     else
         NS_WARNING("failed to get error service");
     
+    NS_TIME_FUNCTION_MARK("got Error Service");
+
     // setup our bad port list stuff
     for(int i=0; gBadPortList[i]; i++)
         mRestrictedPortList.AppendElement(gBadPortList[i]);
 
     // Further modifications to the port list come from prefs
     nsCOMPtr<nsIPrefBranch2> prefBranch;
     GetPrefBranch(getter_AddRefs(prefBranch));
     if (prefBranch) {
@@ -234,41 +244,47 @@ nsIOService::Init()
         observerService->AddObserver(this, kProfileChangeNetTeardownTopic, PR_TRUE);
         observerService->AddObserver(this, kProfileChangeNetRestoreTopic, PR_TRUE);
         observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
         observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, PR_TRUE);
     }
     else
         NS_WARNING("failed to get observer service");
         
+    NS_TIME_FUNCTION_MARK("Registered observers");
+
     // Get the allocator ready
     if (!gBufferCache) {
         nsresult rv = NS_OK;
         nsCOMPtr<nsIRecyclingAllocator> recyclingAllocator =
             do_CreateInstance(NS_RECYCLINGALLOCATOR_CONTRACTID, &rv);
 
         if (NS_FAILED(rv))
             return rv;
         rv = recyclingAllocator->Init(gDefaultSegmentCount,
                                       (15 * 60), // 15 minutes
                                       "necko");
 
         NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Was unable to allocate.  No gBufferCache.");
         CallQueryInterface(recyclingAllocator, &gBufferCache);
     }
 
+    NS_TIME_FUNCTION_MARK("Set up the recycling allocator");
+
     gIOService = this;
     
     // go into managed mode if we can
     mNetworkLinkService = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID);
     if (!mNetworkLinkService)
         mManageOfflineStatus = PR_FALSE;
 
     if (mManageOfflineStatus)
         TrackNetworkLinkStatusForOffline();
+    
+    NS_TIME_FUNCTION_MARK("Set up network link service");
 
     return NS_OK;
 }
 
 
 nsIOService::~nsIOService()
 {
     gIOService = nsnull;
--- a/netwerk/base/src/nsSocketTransportService2.cpp
+++ b/netwerk/base/src/nsSocketTransportService2.cpp
@@ -48,16 +48,18 @@
 #include "prnetdb.h"
 #include "prlock.h"
 #include "prerror.h"
 #include "plstr.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch2.h"
 #include "nsServiceManagerUtils.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #if defined(PR_LOGGING)
 PRLogModuleInfo *gSocketTransportLog = nsnull;
 #endif
 
 nsSocketTransportService *gSocketTransportService = nsnull;
 PRThread                 *gSocketThread           = nsnull;
 
 #define SEND_BUFFER_PREF "network.tcp.sendbuffer"
@@ -373,16 +375,18 @@ NS_IMPL_THREADSAFE_ISUPPORTS6(nsSocketTr
                               nsIRunnable,
                               nsPISocketTransportService,
                               nsIObserver)
 
 // called from main thread only
 NS_IMETHODIMP
 nsSocketTransportService::Init()
 {
+    NS_TIME_FUNCTION;
+
     NS_ENSURE_TRUE(mLock, NS_ERROR_OUT_OF_MEMORY);
 
     if (!NS_IsMainThread()) {
         NS_ERROR("wrong thread");
         return NS_ERROR_UNEXPECTED;
     }
 
     if (mInitialized)
@@ -403,32 +407,36 @@ nsSocketTransportService::Init()
         // event object).  if we can't create a pollable event, then we'll
         // have to "busy wait" to implement the socket event queue :-(
         //
         if (!mThreadEvent) {
             NS_WARNING("running socket transport thread without a pollable event");
             LOG(("running socket transport thread without a pollable event"));
         }
     }
+    
+    NS_TIME_FUNCTION_MARK("Created thread");
 
     nsCOMPtr<nsIThread> thread;
     nsresult rv = NS_NewThread(getter_AddRefs(thread), this);
     if (NS_FAILED(rv)) return rv;
     
     {
         nsAutoLock lock(mLock);
         // Install our mThread, protecting against concurrent readers
         thread.swap(mThread);
     }
 
     nsCOMPtr<nsIPrefBranch2> tmpPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (tmpPrefService) 
         tmpPrefService->AddObserver(SEND_BUFFER_PREF, this, PR_FALSE);
     UpdatePrefs();
 
+    NS_TIME_FUNCTION_MARK("UpdatePrefs");
+
     mInitialized = PR_TRUE;
     return NS_OK;
 }
 
 // called from main thread only
 NS_IMETHODIMP
 nsSocketTransportService::Shutdown()
 {
--- a/netwerk/cache/src/nsCacheService.cpp
+++ b/netwerk/cache/src/nsCacheService.cpp
@@ -68,16 +68,17 @@
 #include "nsProxyRelease.h"
 #include "nsVoidArray.h"
 #include "nsDeleteDir.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsNetCID.h"
 #include <math.h>  // for log()
 #include "mozilla/Services.h"
 
+#include "mozilla/FunctionTimer.h"
 
 /******************************************************************************
  * nsCacheProfilePrefObserver
  *****************************************************************************/
 #ifdef XP_MAC
 #pragma mark nsCacheProfilePrefObserver
 #endif
 
@@ -664,16 +665,18 @@ nsCacheService::~nsCacheService()
     PR_DestroyLock(mLock);
     gService = nsnull;
 }
 
 
 nsresult
 nsCacheService::Init()
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(!mInitialized, "nsCacheService already initialized.");
     if (mInitialized)
         return NS_ERROR_ALREADY_INITIALIZED;
 
     if (mLock == nsnull)
         return NS_ERROR_OUT_OF_MEMORY;
 
     CACHE_LOG_INIT();
--- a/netwerk/cache/src/nsDiskCacheDevice.cpp
+++ b/netwerk/cache/src/nsDiskCacheDevice.cpp
@@ -75,16 +75,18 @@
 #include "nsReadableUtils.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsAutoLock.h"
 #include "nsCRT.h"
 #include "nsCOMArray.h"
 #include "nsISimpleEnumerator.h"
 
+#include "mozilla/FunctionTimer.h"
+
 static const char DISK_CACHE_DEVICE_ID[] = { "disk" };
 
 
 /******************************************************************************
  *  nsDiskCacheEvictor
  *
  *  Helper class for nsDiskCacheDevice.
  *
@@ -354,16 +356,18 @@ nsDiskCacheDevice::~nsDiskCacheDevice()
 
 
 /**
  *  methods of nsCacheDevice
  */
 nsresult
 nsDiskCacheDevice::Init()
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     NS_ENSURE_TRUE(!Initialized(), NS_ERROR_FAILURE);
        
     if (!mCacheDirectory)
         return NS_ERROR_FAILURE;
 
     rv = mBindery.Init();
--- a/netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
+++ b/netwerk/cache/src/nsDiskCacheDeviceSQL.cpp
@@ -58,16 +58,18 @@
 #include "mozIStorageService.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageFunction.h"
 #include "mozStorageHelper.h"
 
 #include "nsICacheVisitor.h"
 #include "nsISeekableStream.h"
 
+#include "mozilla/FunctionTimer.h"
+
 static const char OFFLINE_CACHE_DEVICE_ID[] = { "offline" };
 static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
 
 #define LOG(args) CACHE_LOG_DEBUG(args)
 
 static PRUint32 gNextTemporaryClientID = 0;
 
 /*****************************************************************************
@@ -951,16 +953,18 @@ nsOfflineCacheDevice::GetInstance()
 
   NS_IF_ADDREF(cacheService->mOfflineDevice);
   return cacheService->mOfflineDevice;
 }
 
 nsresult
 nsOfflineCacheDevice::Init()
 {
+  NS_TIME_FUNCTION;
+
   NS_ENSURE_TRUE(!mDB, NS_ERROR_ALREADY_INITIALIZED);
 
   // SetCacheParentDirectory must have been called
   NS_ENSURE_TRUE(mCacheDirectory, NS_ERROR_UNEXPECTED);
 
   // make sure the cache directory exists
   nsresult rv = EnsureDir(mCacheDirectory);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/netwerk/cookie/src/nsCookieService.cpp
+++ b/netwerk/cookie/src/nsCookieService.cpp
@@ -67,16 +67,17 @@
 #include "prtime.h"
 #include "prprf.h"
 #include "nsNetUtil.h"
 #include "nsNetCID.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsNetCID.h"
 #include "mozilla/storage.h"
+#include "mozilla/FunctionTimer.h"
 
 /******************************************************************************
  * nsCookieService impl:
  * useful types & constants
  ******************************************************************************/
 
 // XXX_hack. See bug 178993.
 // This is a hack to hide HttpOnly cookies from older browsers
@@ -513,16 +514,18 @@ nsCookieService::nsCookieService()
  , mMaxCookiesPerHost(kMaxCookiesPerHost)
  , mCookiePurgeAge(kCookiePurgeAge)
 {
 }
 
 nsresult
 nsCookieService::Init()
 {
+  NS_TIME_FUNCTION;
+
   if (!mDBState->hostTable.Init()) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv;
   mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/netwerk/dns/src/nsDNSService2.cpp
+++ b/netwerk/dns/src/nsDNSService2.cpp
@@ -53,16 +53,18 @@
 #include "nsDNSPrefetch.h"
 #include "nsProtocolProxyService.h"
 #include "prsystem.h"
 #include "prnetdb.h"
 #include "prmon.h"
 #include "prio.h"
 #include "plstr.h"
 
+#include "mozilla/FunctionTimer.h"
+
 static const char kPrefDnsCacheEntries[]    = "network.dnsCacheEntries";
 static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
 static const char kPrefEnableIDN[]          = "network.enableIDN";
 static const char kPrefIPv4OnlyDomains[]    = "network.dns.ipv4OnlyDomains";
 static const char kPrefDisableIPv6[]        = "network.dns.disableIPv6";
 static const char kPrefDisablePrefetch[]    = "network.dns.disablePrefetch";
 
 //-----------------------------------------------------------------------------
@@ -314,16 +316,18 @@ nsDNSService::~nsDNSService()
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsDNSService, nsIDNSService, nsPIDNSService,
                               nsIObserver)
 
 NS_IMETHODIMP
 nsDNSService::Init()
 {
+    NS_TIME_FUNCTION;
+
     NS_ENSURE_TRUE(!mResolver, NS_ERROR_ALREADY_INITIALIZED);
 
     PRBool firstTime = (mLock == nsnull);
 
     // prefs
     PRUint32 maxCacheEntries  = 400;
     PRUint32 maxCacheLifetime = 3; // minutes
     PRBool   enableIDN        = PR_TRUE;
--- a/netwerk/dns/src/nsEffectiveTLDService.cpp
+++ b/netwerk/dns/src/nsEffectiveTLDService.cpp
@@ -42,29 +42,33 @@
 // complete description of the expected file format and parsing rules, see
 // http://wiki.mozilla.org/Gecko:Effective_TLD_Service
 
 #include "nsEffectiveTLDService.h"
 #include "nsIIDNService.h"
 #include "nsNetUtil.h"
 #include "prnetdb.h"
 
+#include "mozilla/FunctionTimer.h"
+
 NS_IMPL_ISUPPORTS1(nsEffectiveTLDService, nsIEffectiveTLDService)
 
 // ----------------------------------------------------------------------
 
 static const ETLDEntry gEntries[] =
 #include "etld_data.inc"
 ;
 
 // ----------------------------------------------------------------------
 
 nsresult
 nsEffectiveTLDService::Init()
 {
+  NS_TIME_FUNCTION;
+
   // We'll probably have to rehash at least once, since nsTHashtable doesn't
   // use a perfect hash, but at least we'll save a few rehashes along the way.
   // Next optimization here is to precompute the hash using something like
   // gperf, but one step at a time.  :-)
   if (!mHash.Init(NS_ARRAY_LENGTH(gEntries) - 1))
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv;
--- a/netwerk/dns/src/nsHostResolver.cpp
+++ b/netwerk/dns/src/nsHostResolver.cpp
@@ -61,16 +61,18 @@
 #include "prcvar.h"
 #include "prtime.h"
 #include "prlong.h"
 #include "prlog.h"
 #include "pldhash.h"
 #include "plstr.h"
 #include "nsURLHelper.h"
 
+#include "mozilla/FunctionTimer.h"
+
 //----------------------------------------------------------------------------
 
 // Use a persistent thread pool in order to avoid spinning up new threads all the time.
 // In particular, thread creation results in a res_init() call from libc which is 
 // quite expensive.
 //
 // The pool dynamically grows between 0 and MAX_RESOLVER_THREADS in size. New requests
 // go first to an idle thread. If that cannot be found and there are fewer than MAX_RESOLVER_THREADS
@@ -356,16 +358,18 @@ nsHostResolver::~nsHostResolver()
         PR_DestroyLock(mLock);
 
     PL_DHashTableFinish(&mDB);
 }
 
 nsresult
 nsHostResolver::Init()
 {
+    NS_TIME_FUNCTION;
+
     mLock = PR_NewLock();
     if (!mLock)
         return NS_ERROR_OUT_OF_MEMORY;
 
     mIdleThreadCV = PR_NewCondVar(mLock);
     if (!mIdleThreadCV)
         return NS_ERROR_OUT_OF_MEMORY;
 
--- a/netwerk/dns/src/nsIDNService.cpp
+++ b/netwerk/dns/src/nsIDNService.cpp
@@ -43,16 +43,18 @@
 #include "nsIServiceManager.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIObserverService.h"
 #include "nsISupportsPrimitives.h"
 #include "punycode.h"
 
+#include "mozilla/FunctionTimer.h"
+
 //-----------------------------------------------------------------------------
 // RFC 1034 - 3.1. Name space specifications and terminology
 static const PRUint32 kMaxDNSNodeLen = 63;
 
 //-----------------------------------------------------------------------------
 
 #define NS_NET_PREF_IDNTESTBED      "network.IDN_testbed"
 #define NS_NET_PREF_IDNPREFIX       "network.IDN_prefix"
@@ -74,16 +76,18 @@ inline PRBool isOnlySafeChars(const nsAF
 /* Implementation file */
 NS_IMPL_THREADSAFE_ISUPPORTS3(nsIDNService,
                               nsIIDNService,
                               nsIObserver,
                               nsISupportsWeakReference)
 
 nsresult nsIDNService::Init()
 {
+  NS_TIME_FUNCTION;
+
   nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (prefs)
     prefs->GetBranch(NS_NET_PREF_IDNWHITELIST, getter_AddRefs(mIDNWhitelistPrefBranch));
 
   nsCOMPtr<nsIPrefBranch2> prefInternal(do_QueryInterface(prefs));
   if (prefInternal) {
     prefInternal->AddObserver(NS_NET_PREF_IDNTESTBED, this, PR_TRUE); 
     prefInternal->AddObserver(NS_NET_PREF_IDNPREFIX, this, PR_TRUE); 
--- a/netwerk/protocol/http/src/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/src/nsHttpHandler.cpp
@@ -89,16 +89,18 @@
 #include <CoreServices/CoreServices.h>
 #endif
 
 #if defined(XP_OS2)
 #define INCL_DOSMISC
 #include <os2.h>
 #endif
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef DEBUG
 // defined by the socket transport service while active
 extern PRThread *gSocketThread;
 #endif
 
 static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
 static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
 static NS_DEFINE_CID(kCookieServiceCID, NS_COOKIESERVICE_CID);
@@ -206,16 +208,18 @@ nsHttpHandler::~nsHttpHandler()
     nsHttp::DestroyAtomTable();
 
     gHttpHandler = nsnull;
 }
 
 nsresult
 nsHttpHandler::Init()
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     LOG(("nsHttpHandler::Init\n"));
 
     rv = nsHttp::CreateAtomTable();
     if (NS_FAILED(rv))
         return rv;
 
@@ -302,16 +306,18 @@ nsHttpHandler::Init()
  
     StartPruneDeadConnectionsTimer();
     return NS_OK;
 }
 
 nsresult
 nsHttpHandler::InitConnectionMgr()
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     if (!mConnMgr) {
         mConnMgr = new nsHttpConnectionMgr();
         if (!mConnMgr)
             return NS_ERROR_OUT_OF_MEMORY;
         NS_ADDREF(mConnMgr);
     }
--- a/netwerk/protocol/http/src/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/src/nsHttpTransaction.cpp
@@ -56,16 +56,18 @@
 #include "nsISocketTransport.h"
 #include "nsMultiplexInputStream.h"
 #include "nsStringStream.h"
 
 #include "nsComponentManagerUtils.h" // do_CreateInstance
 #include "nsServiceManagerUtils.h"   // do_GetService
 #include "nsIHttpActivityObserver.h"
 
+#include "mozilla/FunctionTimer.h"
+
 //-----------------------------------------------------------------------------
 
 #ifdef DEBUG
 // defined by the socket transport service while active
 extern PRThread *gSocketThread;
 #endif
 
 //-----------------------------------------------------------------------------
@@ -167,16 +169,18 @@ nsHttpTransaction::Init(PRUint8 caps,
                         nsHttpRequestHead *requestHead,
                         nsIInputStream *requestBody,
                         PRBool requestBodyHasHeaders,
                         nsIEventTarget *target,
                         nsIInterfaceRequestor *callbacks,
                         nsITransportEventSink *eventsink,
                         nsIAsyncInputStream **responseBody)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     LOG(("nsHttpTransaction::Init [this=%x caps=%x]\n", this, caps));
 
     NS_ASSERTION(cinfo, "ouch");
     NS_ASSERTION(requestHead, "ouch");
     NS_ASSERTION(target, "ouch");
 
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -591,16 +591,24 @@ Connection::internalClose()
   int srv = ::sqlite3_close(mDBConn);
   NS_ASSERTION(srv == SQLITE_OK,
                "sqlite3_close failed. There are probably outstanding statements that are listed above!");
 
   mDBConn = NULL;
   return convertResultCode(srv);
 }
 
+nsCString
+Connection::getFilename()
+{
+  nsCString leafname;
+  (void)mDatabaseFile->GetNativeLeafName(leafname);
+  return leafname;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //// mozIStorageConnection
 
 NS_IMETHODIMP
 Connection::Close()
 {
   if (!mDBConn)
     return NS_ERROR_NOT_INITIALIZED;
--- a/storage/src/mozStorageConnection.h
+++ b/storage/src/mozStorageConnection.h
@@ -116,16 +116,21 @@ public:
    */
   const nsCOMPtr<nsIThread> threadOpenedOn;
 
   /**
    * Closes the SQLite database, and warns about any non-finalized statements.
    */
   nsresult internalClose();
 
+  /**
+   * Obtains the filename of the connection.  Useful for logging.
+   */
+  nsCString getFilename();
+
 private:
   ~Connection();
 
   /**
    * Sets the database into a closed state so no further actions can be
    * performed.
    *
    * @note mDBConn is set to NULL in this method.
--- a/storage/src/mozStorageService.cpp
+++ b/storage/src/mozStorageService.cpp
@@ -53,16 +53,18 @@
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 
 #include "sqlite3.h"
 
 #include "nsIPromptService.h"
 #include "nsIMemoryReporter.h"
 
+#include "mozilla/FunctionTimer.h"
+
 namespace mozilla {
 namespace storage {
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Service
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(
   Service,
@@ -155,16 +157,18 @@ void
 Service::shutdown()
 {
   NS_IF_RELEASE(sXPConnect);
 }
 
 nsresult
 Service::initialize()
 {
+  NS_TIME_FUNCTION;
+
   int rc;
 
   // Explicitly initialize sqlite3.  Although this is implicitly called by
   // various sqlite3 functions (and the sqlite3_open calls in our case),
   // the documentation suggests calling this directly.  So we do.
   rc = ::sqlite3_initialize();
   if (rc != SQLITE_OK)
     return convertResultCode(rc);
@@ -295,16 +299,22 @@ Service::OpenSpecialDatabase(const char 
   NS_ADDREF(*_connection = msc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Service::OpenDatabase(nsIFile *aDatabaseFile,
                       mozIStorageConnection **_connection)
 {
+#ifdef NS_FUNCTION_TIMER
+  nsCString leafname;
+  (void)aDatabaseFile->GetNativeLeafName(leafname);
+  NS_TIME_FUNCTION_FMT("mozIStorageService::OpenDatabase(%s)", leafname.get());
+#endif
+
   nsRefPtr<Connection> msc = new Connection(this);
   NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
   {
     MutexAutoLock mutex(mMutex);
     nsresult rv = msc->initialize(aDatabaseFile);
     NS_ENSURE_SUCCESS(rv, rv);
   }
@@ -312,16 +322,23 @@ Service::OpenDatabase(nsIFile *aDatabase
   NS_ADDREF(*_connection = msc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Service::OpenUnsharedDatabase(nsIFile *aDatabaseFile,
                               mozIStorageConnection **_connection)
 {
+#ifdef NS_FUNCTION_TIMER
+  nsCString leafname;
+  (void)aDatabaseFile->GetNativeLeafName(leafname);
+  NS_TIME_FUNCTION_FMT("mozIStorageService::OpenUnsharedDatabase(%s)",
+                       leafname.get());
+#endif
+
   nsRefPtr<Connection> msc = new Connection(this);
   NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
   // Initialize the connection, temporarily turning off shared caches so the
   // new connection gets its own cache.  Database connections are assigned
   // caches when they are opened, and they retain those caches for their
   // lifetimes, unaffected by changes to the shared caches setting, so we can
   // disable shared caches temporarily while we initialize the new connection
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -56,16 +56,18 @@
 #include "mozStorageStatementJSHelper.h"
 #include "mozStoragePrivateHelpers.h"
 #include "mozStorageStatementParams.h"
 #include "mozStorageStatementRow.h"
 #include "mozStorageStatement.h"
 
 #include "prlog.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gStorageLog;
 #endif
 
 namespace mozilla {
 namespace storage {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -585,16 +587,19 @@ Statement::Execute()
 }
 
 NS_IMETHODIMP
 Statement::ExecuteStep(PRBool *_moreResults)
 {
   if (!mDBStatement)
     return NS_ERROR_NOT_INITIALIZED;
 
+  NS_TIME_FUNCTION_MIN_FMT(5, "mozIStorageStatement::ExecuteStep(%s) (0x%p)",
+                           mDBConnection->getFilename().get(), mDBStatement);
+
   // Bind any parameters first before executing.
   if (mParamsArray) {
     // If we have more than one row of parameters to bind, they shouldn't be
     // calling this method (and instead use executeAsync).
     if (mParamsArray->length() != 1)
       return NS_ERROR_UNEXPECTED;
 
     BindingParamsArray::iterator row = mParamsArray->begin();
--- a/toolkit/components/places/src/nsNavBookmarks.cpp
+++ b/toolkit/components/places/src/nsNavBookmarks.cpp
@@ -54,16 +54,18 @@
 #include "prprf.h"
 #include "nsILivemarkService.h"
 #include "nsPlacesTriggers.h"
 #include "nsPlacesTables.h"
 #include "nsPlacesIndexes.h"
 #include "nsPlacesMacros.h"
 #include "Helpers.h"
 
+#include "mozilla/FunctionTimer.h"
+
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ID = 0;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Type = 1;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_PlaceID = 2;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Parent = 3;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Position = 4;
 const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Title = 5;
 
 // These columns sit to the right of the kGetInfoIndex_* columns.
@@ -122,16 +124,18 @@ NS_IMPL_ISUPPORTS3(nsNavBookmarks,
                    nsINavBookmarksService,
                    nsINavHistoryObserver,
                    nsIAnnotationObserver)
 
 
 nsresult
 nsNavBookmarks::Init()
 {
+  NS_TIME_FUNCTION;
+
   nsNavHistory* history = nsNavHistory::GetHistoryService();
   NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
   mDBConn = history->GetStorageConnection();
   NS_ENSURE_STATE(mDBConn);
 
   // TODO: we could consider roots changes as schema changes, and init them
   // only if the database has been created/updated, history.databaseStatus
   // can tell us that.
--- a/toolkit/components/places/src/nsNavHistory.cpp
+++ b/toolkit/components/places/src/nsNavHistory.cpp
@@ -74,16 +74,18 @@
 #include "nsPlacesTables.h"
 #include "nsPlacesIndexes.h"
 #include "nsPlacesTriggers.h"
 #include "nsPlacesMacros.h"
 #include "SQLFunctions.h"
 #include "Helpers.h"
 #include "History.h"
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef MOZ_XUL
 #include "nsIAutoCompleteInput.h"
 #include "nsIAutoCompletePopup.h"
 #endif
 
 using namespace mozilla::places;
 
 // Microsecond timeout for "recent" events such as typed and bookmark following.
@@ -413,16 +415,18 @@ nsNavHistory::~nsNavHistory()
   if (gHistoryService == this)
     gHistoryService = nsnull;
 }
 
 
 nsresult
 nsNavHistory::Init()
 {
+  NS_TIME_FUNCTION;
+
   nsCOMPtr<nsIPrefService> prefService =
     do_GetService(NS_PREFSERVICE_CONTRACTID);
   nsCOMPtr<nsIPrefBranch> placesBranch;
   NS_ENSURE_TRUE(prefService, NS_ERROR_OUT_OF_MEMORY);
   nsresult rv = prefService->GetBranch(PREF_PLACES_BRANCH_BASE,
                                        getter_AddRefs(placesBranch));
   NS_ENSURE_SUCCESS(rv, rv);
   mPrefBranch = do_QueryInterface(placesBranch);
--- a/toolkit/components/startup/src/nsAppStartup.cpp
+++ b/toolkit/components/startup/src/nsAppStartup.cpp
@@ -65,16 +65,18 @@
 
 #include "prprf.h"
 #include "nsCRT.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsWidgetsCID.h"
 #include "nsAppShellCID.h"
 #include "mozilla/Services.h"
 
+#include "mozilla/FunctionTimer.h"
+
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 class nsAppExitEvent : public nsRunnable {
 private:
   nsRefPtr<nsAppStartup> mService;
 
 public:
   nsAppExitEvent(nsAppStartup *service) : mService(service) {}
@@ -102,27 +104,32 @@ nsAppStartup::nsAppStartup() :
   mRestart(PR_FALSE),
   mNeedsRestart(PR_FALSE)
 { }
 
 
 nsresult
 nsAppStartup::Init()
 {
+  NS_TIME_FUNCTION;
   nsresult rv;
 
   // Create widget application shell
   mAppShell = do_GetService(kAppShellCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  NS_TIME_FUNCTION_MARK("Got AppShell service");
+
   nsCOMPtr<nsIObserverService> os =
     mozilla::services::GetObserverService();
   if (!os)
     return NS_ERROR_FAILURE;
 
+  NS_TIME_FUNCTION_MARK("Got Observer service");
+
   os->AddObserver(this, "quit-application-forced", PR_TRUE);
   os->AddObserver(this, "profile-change-teardown", PR_TRUE);
   os->AddObserver(this, "xul-window-registered", PR_TRUE);
   os->AddObserver(this, "xul-window-destroyed", PR_TRUE);
 
   return NS_OK;
 }
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -205,16 +205,18 @@
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #include "nsIPrefService.h"
 #endif
 
 #ifdef MOZ_IPC
 #include "base/command_line.h"
 #endif
 
+#include "mozilla/FunctionTimer.h"
+
 #ifdef WINCE
 class WindowsMutex {
 public:
   WindowsMutex(const wchar_t *name) {
     mHandle = CreateMutexW(0, FALSE, name);
   }
 
   ~WindowsMutex() {
@@ -1223,43 +1225,54 @@ nsSingletonFactory::LockFactory(PRBool)
 }
 
 /**
  * Set our windowcreator on the WindowWatcher service.
  */
 nsresult
 ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native)
 {
+  NS_TIME_FUNCTION;
   nsresult rv;
 
   nsCOMPtr<nsIComponentRegistrar> registrar
     (do_QueryInterface(mServiceManager));
   NS_ASSERTION(registrar, "Where's the component registrar?");
 
   nsCOMPtr<nsIFactory> nativeFactory = new nsSingletonFactory(native);
   NS_ENSURE_TRUE(nativeFactory, NS_ERROR_OUT_OF_MEMORY);
 
   rv = registrar->RegisterFactory(kNativeAppSupportCID,
                                   "Native App Support",
                                   NS_NATIVEAPPSUPPORT_CONTRACTID,
                                   nativeFactory);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  NS_TIME_FUNCTION_MARK("RegisterFactory done");
+
   // Inform the chrome registry about OS accessibility
   nsCOMPtr<nsIToolkitChromeRegistry> cr =
     mozilla::services::GetToolkitChromeRegistryService();
+  NS_TIME_FUNCTION_MARK("Got ToolkitChromeRegistry service");
+
   if (cr)
     cr->CheckForOSAccessibility();
 
+  NS_TIME_FUNCTION_MARK("OS Accessibility check");
+
   nsCOMPtr<nsIWindowCreator> creator (do_GetService(NS_APPSTARTUP_CONTRACTID));
   if (!creator) return NS_ERROR_UNEXPECTED;
 
+  NS_TIME_FUNCTION_MARK("Got AppStartup service");
+
   nsCOMPtr<nsIWindowWatcher> wwatch
     (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
+  
+  NS_TIME_FUNCTION_MARK("Got WindowWatcher service");
 
   return wwatch->SetWindowCreator(creator);
 }
 
 /**
  * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
  */
 class ScopedLogging
@@ -3327,29 +3340,65 @@ XRE_main(int argc, char* argv[], const n
 
     PRBool needsRestart = PR_FALSE;
     PRBool appInitiatedRestart = PR_FALSE;
 
     MOZ_SPLASHSCREEN_UPDATE(30);
 
     NS_TIME_FUNCTION_MARK("Next: ScopedXPCOMStartup");
 
+    NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup");
+
     // Allows the user to forcefully bypass the restart process at their
     // own risk. Useful for debugging or for tinderboxes where child 
     // processes can be problematic.
     {
       // Start the real application
       ScopedXPCOMStartup xpcom;
       rv = xpcom.Initialize();
+      NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Initialize");
       NS_ENSURE_SUCCESS(rv, 1); 
       rv = xpcom.DoAutoreg();
+      NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: DoAutoreg");
+
+
+#ifdef NS_FUNCTION_TIMER
+      // initialize some common services, so we don't pay the cost for these at odd times later on;
+      // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs
+      {
+        nsCOMPtr<nsISupports> comp;
+
+        comp = do_GetService("@mozilla.org/preferences-service;1");
+        NS_TIME_FUNCTION_MARK("Pref Service");
+
+        comp = do_GetService("@mozilla.org/network/socket-transport-service;1");
+        NS_TIME_FUNCTION_MARK("Socket Transport Service");
+
+        comp = do_GetService("@mozilla.org/network/dns-service;1");
+        NS_TIME_FUNCTION_MARK("DNS Service");
+
+        comp = do_GetService("@mozilla.org/network/io-service;1");
+        NS_TIME_FUNCTION_MARK("IO Service");
+
+        comp = do_GetService("@mozilla.org/chrome/chrome-registry;1");
+        NS_TIME_FUNCTION_MARK("Chrome Registry Service");
+
+        comp = do_GetService("@mozilla.org/focus-event-suppressor-service;1");
+        NS_TIME_FUNCTION_MARK("Focus Event Suppressor Service");
+      }
+#endif
+
       rv |= xpcom.RegisterProfileService();
+      NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: RegisterProfileService");
       rv |= xpcom.SetWindowCreator(nativeApp);
+      NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: SetWindowCreator");
       NS_ENSURE_SUCCESS(rv, 1);
 
+      NS_TIME_FUNCTION_MARK("ScopedXPCOMStartup: Done");
+
 #ifdef MOZ_CRASHREPORTER
       // tell the crash reporter to also send the release channel
       nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
       if (NS_SUCCEEDED(rv)) {
         nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
         rv = prefs->GetDefaultBranch(nsnull, getter_AddRefs(defaultPrefBranch));
 
         if (NS_SUCCEEDED(rv)) {
@@ -3378,20 +3427,24 @@ XRE_main(int argc, char* argv[], const n
           nsCOMPtr<nsIObserver> startupNotifier
             (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
           NS_ENSURE_SUCCESS(rv, 1);
 
           startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
           NS_TIMELINE_LEAVE("startupNotifier");
         }
 
+        NS_TIME_FUNCTION_MARK("Finished startupNotifier");
+
         nsCOMPtr<nsIAppStartup2> appStartup
           (do_GetService(NS_APPSTARTUP_CONTRACTID));
         NS_ENSURE_TRUE(appStartup, 1);
 
+        NS_TIME_FUNCTION_MARK("Created AppStartup");
+
         if (gDoMigration) {
           nsCOMPtr<nsIFile> file;
           dirProvider.GetAppDir()->Clone(getter_AddRefs(file));
           file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
           nsINIParser parser;
           nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
           nsresult rv = parser.Init(localFile);
           if (NS_SUCCEEDED(rv)) {
@@ -3408,18 +3461,23 @@ XRE_main(int argc, char* argv[], const n
         // Profile Migration
         if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
           gDoMigration = PR_FALSE;
           nsCOMPtr<nsIProfileMigrator> pm
             (do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
           if (pm)
             pm->Migrate(&dirProvider);
         }
+
+        NS_TIME_FUNCTION_MARK("Profile migration");
+
         dirProvider.DoStartup();
 
+        NS_TIME_FUNCTION_MARK("dirProvider.DoStartup() (profile-after-change)");
+
         PRBool shuttingDown = PR_FALSE;
         appStartup->GetShuttingDown(&shuttingDown);
 
         nsCOMPtr<nsICommandLineRunner> cmdLine;
 
         nsCOMPtr<nsIFile> workingDir;
         rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
         NS_ENSURE_SUCCESS(rv, 1);
@@ -3435,16 +3493,18 @@ XRE_main(int argc, char* argv[], const n
           /* Special-case services that need early access to the command
              line. */
           nsCOMPtr<nsIObserverService> obsService =
             mozilla::services::GetObserverService();
           if (obsService) {
             obsService->NotifyObservers(cmdLine, "command-line-startup", nsnull);
           }
 
+          NS_TIME_FUNCTION_MARK("Early command line init");
+
           NS_TIME_FUNCTION_MARK("Next: prepare for Run");
 
           if (!upgraded)
             appStartup->GetNeedsRestart(&needsRestart);
 
           // We want to restart no more than 2 times. The first restart,
           // NO_EM_RESTART == "0" , and the second time, "1".
           char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
@@ -3464,16 +3524,18 @@ XRE_main(int argc, char* argv[], const n
           SaveToEnv("XRE_PROFILE_PATH=");
           SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
           SaveToEnv("XRE_PROFILE_NAME=");
           SaveToEnv("XRE_START_OFFLINE=");
           SaveToEnv("XRE_IMPORT_PROFILES=");
           SaveToEnv("NO_EM_RESTART=");
           SaveToEnv("XUL_APP_FILE=");
           SaveToEnv("XRE_BINARY_PATH=");
+    
+          NS_TIME_FUNCTION_MARK("env munging");
 
           if (!shuttingDown) {
             NS_TIME_FUNCTION_MARK("Next: CreateHiddenWindow");
 
             NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
             rv = appStartup->CreateHiddenWindow();
             NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
             NS_ENSURE_SUCCESS(rv, 1);
@@ -3506,16 +3568,18 @@ XRE_main(int argc, char* argv[], const n
 
             MOZ_SPLASHSCREEN_UPDATE(70);
 
             nsCOMPtr<nsIObserverService> obsService =
               mozilla::services::GetObserverService();
             if (obsService)
               obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);
 
+            NS_TIME_FUNCTION_MARK("final-ui-startup done");
+
             appStartup->GetShuttingDown(&shuttingDown);
           }
 
           if (!shuttingDown) {
             rv = cmdLine->Run();
             NS_ENSURE_SUCCESS_LOG(rv, 1);
 
             appStartup->GetShuttingDown(&shuttingDown);
@@ -3535,29 +3599,33 @@ XRE_main(int argc, char* argv[], const n
 #endif /* MOZ_ENABLE_XREMOTE */
 
             // enable win32 DDE responses and Mac appleevents responses
             nativeApp->Enable();
           }
 
           NS_TIME_FUNCTION_MARK("Next: Run");
 
+          NS_TIME_FUNCTION_MARK("appStartup->Run");
+
           MOZ_SPLASHSCREEN_UPDATE(90);
           {
             NS_TIMELINE_ENTER("appStartup->Run");
             rv = appStartup->Run();
             NS_TIMELINE_LEAVE("appStartup->Run");
             if (NS_FAILED(rv)) {
               NS_ERROR("failed to run appstartup");
               gLogConsoleErrors = PR_TRUE;
             }
           }
 
           NS_TIME_FUNCTION_MARK("Next: Finish");
 
+          NS_TIME_FUNCTION_MARK("appStartup->Run done");
+
           // Check for an application initiated restart.  This is one that
           // corresponds to nsIAppStartup.quit(eRestart)
           if (rv == NS_SUCCESS_RESTART_APP) {
             needsRestart = PR_TRUE;
             appInitiatedRestart = PR_TRUE;
           }
 
           if (!shuttingDown) {
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -75,16 +75,29 @@
 
 #include "nsIMIMEHeaderParam.h"
 #include "nsNetCID.h"
 
 #include "nsMimeTypes.h"
 
 #include "nsDocLoader.h"
 
+#include "mozilla/FunctionTimer.h"
+#ifdef NS_FUNCTION_TIMER
+#define TIME_URILOADER_FUNCTION(req)                         \
+    nsCAutoString name__("N/A");                             \
+    (req)->GetName(name__);                                  \
+    NS_TIME_FUNCTION_FMT("%s (line %d) (request: %s)",       \
+                         MOZ_FUNCTION_NAME,                  \
+                         __LINE__,                           \
+                         name__.get())
+#else
+#define TIME_URILOADER_FUNCTION(req) do {} while(0)
+#endif
+
 #ifdef PR_LOGGING
 PRLogModuleInfo* nsURILoader::mLog = nsnull;
 #endif
 
 #define LOG(args) PR_LOG(nsURILoader::mLog, PR_LOG_DEBUG, args)
 #define LOG_ERROR(args) PR_LOG(nsURILoader::mLog, PR_LOG_ERROR, args)
 #define LOG_ENABLED() PR_LOG_TEST(nsURILoader::mLog, PR_LOG_DEBUG)
 
@@ -219,16 +232,18 @@ nsresult nsDocumentOpenInfo::Prepare()
 
   // ask our window context if it has a uri content listener...
   m_contentListener = do_GetInterface(m_originalContext, &rv);
   return rv;
 }
 
 NS_IMETHODIMP nsDocumentOpenInfo::OnStartRequest(nsIRequest *request, nsISupports * aCtxt)
 {
+  TIME_URILOADER_FUNCTION(request);
+
   LOG(("[0x%p] nsDocumentOpenInfo::OnStartRequest", this));
   
   nsresult rv = NS_OK;
 
   //
   // Deal with "special" HTTP responses:
   // 
   // - In the case of a 204 (No Content) or 205 (Reset Content) response, do
@@ -292,29 +307,33 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStar
   LOG(("  OnStartRequest returning: 0x%08X", rv));
   
   return rv;
 }
 
 NS_IMETHODIMP nsDocumentOpenInfo::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt,
                                                   nsIInputStream * inStr, PRUint32 sourceOffset, PRUint32 count)
 {
+  TIME_URILOADER_FUNCTION(request);
+
   // if we have retarged to the end stream listener, then forward the call....
   // otherwise, don't do anything
 
   nsresult rv = NS_OK;
   
   if (m_targetStreamListener)
     rv = m_targetStreamListener->OnDataAvailable(request, aCtxt, inStr, sourceOffset, count);
   return rv;
 }
 
 NS_IMETHODIMP nsDocumentOpenInfo::OnStopRequest(nsIRequest *request, nsISupports *aCtxt, 
                                                 nsresult aStatus)
 {
+  TIME_URILOADER_FUNCTION(request);
+
   LOG(("[0x%p] nsDocumentOpenInfo::OnStopRequest", this));
   
   if ( m_targetStreamListener)
   {
     nsCOMPtr<nsIStreamListener> listener(m_targetStreamListener);
 
     // If this is a multipart stream, we could get another
     // OnStartRequest after this... reset state.
@@ -327,16 +346,18 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStop
   // In the case of multiplexed streams (such as multipart/x-mixed-replace)
   // these stream listener methods could be called again :-)
   //
   return NS_OK;
 }
 
 nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports * aCtxt)
 {
+  TIME_URILOADER_FUNCTION(request);
+
   LOG(("[0x%p] nsDocumentOpenInfo::DispatchContent for type '%s'", this, mContentType.get()));
 
   NS_PRECONDITION(!m_targetStreamListener,
                   "Why do we already have a target stream listener?");
   
   nsresult rv;
   nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
   if (!aChannel) {
@@ -604,16 +625,18 @@ nsresult nsDocumentOpenInfo::DispatchCon
 }
 
 nsresult
 nsDocumentOpenInfo::ConvertData(nsIRequest *request,
                                 nsIURIContentListener* aListener,
                                 const nsACString& aSrcContentType,
                                 const nsACString& aOutContentType)
 {
+  TIME_URILOADER_FUNCTION(request);
+
   LOG(("[0x%p] nsDocumentOpenInfo::ConvertData from '%s' to '%s'", this,
        PromiseFlatCString(aSrcContentType).get(),
        PromiseFlatCString(aOutContentType).get()));
 
   NS_PRECONDITION(aSrcContentType != aOutContentType,
                   "ConvertData called when the two types are the same!");
   nsresult rv = NS_OK;
 
@@ -660,16 +683,18 @@ nsDocumentOpenInfo::ConvertData(nsIReque
                                              request,
                                              getter_AddRefs(m_targetStreamListener));
 }
 
 PRBool
 nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener,
                                        nsIChannel* aChannel)
 {
+  TIME_URILOADER_FUNCTION(aChannel);
+
   LOG(("[0x%p] nsDocumentOpenInfo::TryContentListener; mFlags = 0x%x",
        this, mFlags));
 
   NS_PRECONDITION(aListener, "Must have a non-null listener");
   NS_PRECONDITION(aChannel, "Must have a channel");
   
   PRBool listenerWantsContent = PR_FALSE;
   nsXPIDLCString typeToUse;
@@ -804,16 +829,18 @@ NS_IMETHODIMP nsURILoader::UnRegisterCon
 }
 
 NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel, 
                                    PRBool aIsContentPreferred,
                                    nsIInterfaceRequestor *aWindowContext)
 {
   NS_ENSURE_ARG_POINTER(channel);
 
+  TIME_URILOADER_FUNCTION(channel);
+
 #ifdef PR_LOGGING
   if (LOG_ENABLED()) {
     nsCOMPtr<nsIURI> uri;
     channel->GetURI(getter_AddRefs(uri));
     nsCAutoString spec;
     uri->GetAsciiSpec(spec);
     LOG(("nsURILoader::OpenURI for %s", spec.get()));
   }
@@ -851,16 +878,18 @@ nsresult nsURILoader::OpenChannel(nsICha
                                   PRUint32 aFlags,
                                   nsIInterfaceRequestor* aWindowContext,
                                   PRBool aChannelIsOpen,
                                   nsIStreamListener** aListener)
 {
   NS_ASSERTION(channel, "Trying to open a null channel!");
   NS_ASSERTION(aWindowContext, "Window context must not be null");
 
+  TIME_URILOADER_FUNCTION(channel);
+
 #ifdef PR_LOGGING
   if (LOG_ENABLED()) {
     nsCOMPtr<nsIURI> uri;
     channel->GetURI(getter_AddRefs(uri));
     nsCAutoString spec;
     uri->GetAsciiSpec(spec);
     LOG(("nsURILoader::OpenChannel for %s", spec.get()));
   }
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -204,16 +204,18 @@
 #include "nsWindowDefs.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #ifdef WINCE_WINDOWS_MOBILE
 #include "nsGfxCIID.h"
 #endif
 
+#include "mozilla/FunctionTimer.h"
+
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: Variables
  **
  ** nsWindow Class static initializations and global variables. 
  **
  **************************************************************
@@ -1087,17 +1089,17 @@ NS_METHOD nsWindow::Show(PRBool bState)
 #ifdef NS_FUNCTION_TIMER
   static bool firstShow = true;
   if (firstShow &&
       (mWindowType == eWindowType_toplevel ||
        mWindowType == eWindowType_dialog ||
        mWindowType == eWindowType_popup))
   {
     firstShow = false;
-    mozilla::FunctionTimer::LogMessage("First toplevel/dialog/popup showing");
+    mozilla::FunctionTimer::LogMessage("@ First toplevel/dialog/popup showing");
   }
 #endif
 
   PRBool wasVisible = mIsVisible;
   // Set the status now so that anyone asking during ShowWindow or
   // SetWindowPos would get the correct answer.
   mIsVisible = bState;
 
@@ -3877,16 +3879,20 @@ nsWindow::IPCWindowProcHandler(UINT& msg
  * The main Windows event procedures and associated
  * message processing methods.
  *
  **************************************************************/
 
 // The WndProc procedure for all nsWindows in this toolkit
 LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
+  NS_TIME_FUNCTION_MIN_FMT(5.0, "%s (line %d) (hWnd: %p, msg: %p, wParam: %p, lParam: %p",
+                           MOZ_FUNCTION_NAME, __LINE__, hWnd, msg,
+                           wParam, lParam);
+
   // Get the window which caused the event and ask it to process the message
   nsWindow *someWindow = GetNSWindowPtr(hWnd);
 
 #ifdef MOZ_IPC
   if (someWindow)
     someWindow->IPCWindowProcHandler(msg, wParam, lParam);
 #endif
 
--- a/xpcom/base/FunctionTimer.cpp
+++ b/xpcom/base/FunctionTimer.cpp
@@ -46,29 +46,32 @@
 #include <string.h>
 
 #include "prenv.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #ifdef _MSC_VER
 #define vsnprintf _vsnprintf
+#include <windows.h>
+#include <mmsystem.h>
 #endif
 
 using namespace mozilla;
 
 // This /must/ come before the call to InitTimers below,
 // or its constructor will be called after we've already
 // assigned the Now() value to it.
 static TimeStamp sAppStart;
 
-FunctionTimerLog *FunctionTimer::sLog = nsnull;
+nsAutoPtr<FunctionTimerLog> FunctionTimer::sLog;
 char *FunctionTimer::sBuf1 = nsnull;
 char *FunctionTimer::sBuf2 = nsnull;
 int FunctionTimer::sBufSize = FunctionTimer::InitTimers();
+unsigned FunctionTimer::sDepth = 0;
 
 int
 FunctionTimer::InitTimers()
 {
     if (PR_GetEnv("MOZ_FT") == NULL)
         return 0;
 
     // ensure that this is initialized before us
@@ -90,22 +93,31 @@ FunctionTimerLog::FunctionTimerLog(const
         mFile = stderr;
     } else {
         FILE *fp = fopen(fname, "wb");
         if (!fp) {
             NS_WARNING("FunctionTimerLog: Failed to open file specified, logging disabled!");
         }
         mFile = fp;
     }
+
+#ifdef _MSC_VER
+    // Get 1ms resolution on Windows
+    timeBeginPeriod(1);
+#endif
 }
 
 FunctionTimerLog::~FunctionTimerLog()
 {
     if (mFile && mFile != stdout && mFile != stderr)
         fclose((FILE*)mFile);
+
+#ifdef _MSC_VER
+    timeEndPeriod(1);
+#endif
 }
 
 void
 FunctionTimerLog::LogString(const char *str)
 {
     if (mFile) {
         TimeDuration elapsed = TimeStamp::Now() - sAppStart;
         fprintf((FILE*)mFile, "[% 9.2f] %s\n", elapsed.ToSeconds() * 1000.0, str);
--- a/xpcom/base/FunctionTimer.h
+++ b/xpcom/base/FunctionTimer.h
@@ -38,45 +38,55 @@
 
 #ifndef mozilla_FunctionTimer_h
 #define mozilla_FunctionTimer_h
 
 #include <stdarg.h>
 
 #include "mozilla/TimeStamp.h"
 #include "nscore.h"
+#include "nsAutoPtr.h"
 
 #if defined(NS_FORCE_FUNCTION_TIMER) && !defined(NS_FUNCTION_TIMER)
 #define NS_FUNCTION_TIMER
 #endif
 
 /*
  * Shortcut macros
  */
 
 #ifdef NS_FUNCTION_TIMER
 
+#ifdef __GNUC__
+#define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define MOZ_FUNCTION_NAME __FUNCTION__
+#else
+#warning "Define a suitable MOZ_FUNCTION_NAME for this platform"
+#define MOZ_FUNCTION_NAME ""
+#endif
+
 // Add a timer for this function, from this declaration until the
 // function returns.  The function name will be used as the
 // log string, and both function entry and exit will be printed.
 #define NS_TIME_FUNCTION                                                \
-    mozilla::FunctionTimer ft__autogen("%s (line %d)", __FUNCTION__, __LINE__)
+    mozilla::FunctionTimer ft__autogen("%s (line %d)", MOZ_FUNCTION_NAME, __LINE__)
 
 // Add a timer for this block, but print only a) if the exit time is
 // greater than the given number of milliseconds; or b) if the
 // mark-to-mark time is greater than the given number of milliseconds.
 // No function entry will be printed.  If the value given is negative,
 // no function entry or exit will ever be printed, but all marks will.
 #define NS_TIME_FUNCTION_MIN(_ms)                                       \
-    mozilla::FunctionTimer ft__autogen((_ms), "%s (line %d)", __FUNCTION__, __LINE__)
+    mozilla::FunctionTimer ft__autogen((_ms), "%s (line %d)", MOZ_FUNCTION_NAME, __LINE__)
 
 // Add a timer for this block, but print only marks, not function
 // entry and exit.  The same as calling the above macro with a negative value.
 #define NS_TIME_FUNCTION_MARK_ONLY                                    \
-    mozilla::FunctionTimer ft__autogen((-1), "%s (line %d)", __FUNCTION__, __LINE__)
+    mozilla::FunctionTimer ft__autogen((-1), "%s (line %d)", MOZ_FUNCTION_NAME, __LINE__)
 
 // Add a timer for this block, using the printf-style format.
 // Both function entry and exit will be printed.
 #define NS_TIME_FUNCTION_FMT(...)                                       \
     mozilla::FunctionTimer ft__autogen(__VA_ARGS__)
 
 // Add a timer for this block, using the given minimum number of
 // milliseconds and the given printf-style format.  No function entry
@@ -126,22 +136,23 @@ public:
     void LogString(const char *str);
 
 private:
     void *mFile;
 };
 
 class NS_COM FunctionTimer
 {
-    static FunctionTimerLog* sLog;
+    static nsAutoPtr<FunctionTimerLog> sLog;
     static char *sBuf1;
     static char *sBuf2;
     static int sBufSize;
+    static unsigned sDepth;
 
-    enum { BUF_LOG_LENGTH = 256 };
+    enum { BUF_LOG_LENGTH = 1024 };
 
 public:
     static int InitTimers();
 
     static int ft_vsnprintf(char *str, int maxlen, const char *fmt, va_list args);
     static int ft_snprintf(char *str, int maxlen, const char *fmt, ...);
 
     static void LogMessage(const char *s, ...) {
@@ -151,106 +162,112 @@ public:
         if (sLog) {
             ft_vsnprintf(sBuf1, sBufSize, s, ap);
             sLog->LogString(sBuf1);
         }
 
         va_end(ap);
     }
 
+private:
+    void Init(const char *s, va_list ap) {
+        if (mEnabled) {
+            TimeInit();
+
+            ft_vsnprintf(mString, BUF_LOG_LENGTH, s, ap);
+
+            ft_snprintf(sBuf1, sBufSize, "> (% 3d)%*s|%s%s", mDepth, mDepth, " ", mHasMinMs ? "?MINMS " : "", mString);
+            sLog->LogString(sBuf1);
+        }
+    }
+
 public:
     inline void TimeInit() {
-        if (sLog) {
+        if (mEnabled) {
             mStart = TimeStamp::Now();
             mLastMark = mStart;
         }
     }
 
     inline double Elapsed() {
-        if (sLog)
+        if (mEnabled)
             return (TimeStamp::Now() - mStart).ToSeconds() * 1000.0;
         return 0.0;
     }
 
     inline double ElapsedSinceMark() {
-        if (sLog)
+        if (mEnabled)
             return (TimeStamp::Now() - mLastMark).ToSeconds() * 1000.0;
         return 0.0;
     }
 
     FunctionTimer(double minms, const char *s, ...)
-        : mMinMs(minms)
+        : mMinMs(minms), mHasMinMs(PR_TRUE),
+          mEnabled(sLog && s && *s), mDepth(++sDepth)
     {
         va_list ap;
         va_start(ap, s);
 
-        if (sLog) {
-            TimeInit();
-
-            ft_vsnprintf(mString, BUF_LOG_LENGTH, s, ap);
-        }
+        Init(s, ap);
 
         va_end(ap);
     }
 
     FunctionTimer(const char *s, ...)
-        : mMinMs(0.0)
+        : mMinMs(0.0), mHasMinMs(PR_FALSE),
+          mEnabled(sLog && s && *s), mDepth(++sDepth)
     {
         va_list ap;
         va_start(ap, s);
 
-        if (sLog) {
-            TimeInit();
-
-            ft_vsnprintf(mString, BUF_LOG_LENGTH, s, ap);
-
-            ft_snprintf(sBuf1, sBufSize, "> %s", mString);
-            sLog->LogString(sBuf1);
-        }
+        Init(s, ap);
 
         va_end(ap);
     }
 
     void Mark(const char *s, ...)
     {
         va_list ap;
         va_start(ap, s);
 
-        if (sLog) {
+        if (mEnabled) {
             ft_vsnprintf(sBuf1, sBufSize, s, ap);
 
             TimeStamp now(TimeStamp::Now());
             double ms = (now - mStart).ToSeconds() * 1000.0;
             double msl = (now - mLastMark).ToSeconds() * 1000.0;
             mLastMark = now;
 
-            if (msl > mMinMs) {
-                ft_snprintf(sBuf2, sBufSize, "%s- %9.2f ms (%9.2f ms total) - %s [%s]", mMinMs < 0.0 ? "" : "*", msl, ms, mString, sBuf1);
-                sLog->LogString(sBuf2);
-            }
+            ft_snprintf(sBuf2, sBufSize, "* (% 3d)%*s|%s%9.2f ms (%9.2f ms total) - %s [%s]", mDepth, mDepth, " ",
+                (!mHasMinMs || mMinMs < 0.0 || msl > mMinMs) ? "<MINMS " : "", msl, ms, mString, sBuf1);
+            sLog->LogString(sBuf2);
         }
 
         va_end(ap);
     }
 
     ~FunctionTimer() {
-        if (sLog) {
+        if (mEnabled) {
             TimeStamp now(TimeStamp::Now());
             double ms = (now - mStart).ToSeconds() * 1000.0;
             double msl = (now - mLastMark).ToSeconds() * 1000.0;
 
-            if (mMinMs < 0.0 || (mMinMs >= 0.0 && msl > mMinMs)) {
-                ft_snprintf(sBuf1, sBufSize, "%s %9.2f ms (%9.2f ms total) - %s", mMinMs < 0.0 ? "<" : "*", msl, ms, mString);
-                sLog->LogString(sBuf1);
-            }
+            ft_snprintf(sBuf1, sBufSize, "< (% 3d)%*s|%s%9.2f ms (%9.2f ms total) - %s", mDepth, mDepth, " ",
+                (!mHasMinMs || (mMinMs >= 0.0 && msl > mMinMs)) ? "" : "<MINMS ", msl, ms, mString);
+            sLog->LogString(sBuf1);
         }
+
+        --sDepth;
     }
 
     TimeStamp mStart, mLastMark;
+    const double mMinMs;
     char mString[BUF_LOG_LENGTH+1];
-    double mMinMs;
+    const PRBool mHasMinMs;
+    const PRBool mEnabled;
+    const unsigned mDepth;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_FunctionTimer_h
 
 
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -45,16 +45,17 @@
 #if defined(_WIN32) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)) && !defined(WINCE) // WIN32 x86 stack walking code
 
 #include "nscore.h"
 #include <windows.h>
 #include <process.h>
 #include <stdio.h>
 #include "plstr.h"
 #include "nsMemory.h" // for NS_ARRAY_LENGTH
+#include "mozilla/FunctionTimer.h"
 
 #include "nspr.h"
 #if defined(_M_IX86) || defined(_M_AMD64)
 #include <imagehlp.h>
 // We need a way to know if we are building for WXP (or later), as if we are, we
 // need to use the newer 64-bit APIs. API_VERSION_NUMBER seems to fit the bill.
 // A value of 9 indicates we want to use the new APIs.
 #if API_VERSION_NUMBER >= 9
@@ -596,16 +597,18 @@ WalkStackThread(void* aData)
 
     while ((msgRet = ::GetMessage(&msg, (HWND)-1, 0, 0)) != 0) {
         if (msgRet == -1) {
             PrintError("GetMessage");
         } else {
             DWORD ret;
 
             struct WalkStackData *data = (WalkStackData *)msg.lParam;
+            if (!data)
+              continue;
 
             // Don't suspend the calling thread until it's waiting for
             // us; otherwise the number of frames on the stack could vary.
             ret = ::WaitForSingleObject(data->eventStart, INFINITE);
             if (ret != WAIT_OBJECT_0)
                 PrintError("WaitForSingleObject");
 
             // Suspend the calling thread, dump his stack, and then resume him.
@@ -940,16 +943,18 @@ PRBool
 EnsureSymInitialized()
 {
     static PRBool gInitialized = PR_FALSE;
     PRBool retStat;
 
     if (gInitialized)
         return gInitialized;
 
+    NS_TIME_FUNCTION;
+
     if (!EnsureImageHlpInitialized())
         return PR_FALSE;
 
     _SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
     retStat = _SymInitialize(GetCurrentPIDorHandle(), NULL, TRUE);
     if (!retStat)
         PrintError("SymInitialize");
 
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -138,16 +138,17 @@ NS_DECL_CLASSINFO(nsStringInputStream)
 #include "nsMacUtilsImpl.h"
 #endif
 
 #include "nsSystemInfo.h"
 #include "nsMemoryReporterManager.h"
 
 #include <locale.h>
 #include "mozilla/Services.h"
+#include "mozilla/FunctionTimer.h"
 
 #ifdef MOZ_IPC
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
 
 #include "mozilla/ipc/BrowserProcessSubThread.h"
 
@@ -470,31 +471,37 @@ NS_InitXPCOM2(nsIServiceManager* *result
 
 EXPORT_XPCOM_API(nsresult)
 NS_InitXPCOM3(nsIServiceManager* *result,
                               nsIFile* binDirectory,
                               nsIDirectoryServiceProvider* appFileLocationProvider,
                               nsStaticModuleInfo const *staticComponents,
                               PRUint32 componentCount)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv = NS_OK;
 
 #ifdef MOZ_ENABLE_LIBXUL
     if (!staticComponents) {
         staticComponents = kPStaticModules;
         componentCount = kStaticModuleCount;
     }
 #endif
 
      // We are not shutting down
     gXPCOMShuttingDown = PR_FALSE;
 
+    NS_TIME_FUNCTION_MARK("Next: log init");
+
     NS_LogInit();
 
 #ifdef MOZ_IPC
+    NS_TIME_FUNCTION_MARK("Next: IPC init");
+
     // Set up chromium libs
     NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
 
     if (!AtExitManager::AlreadyRegistered()) {
         sExitManager = new AtExitManager();
         NS_ENSURE_STATE(sExitManager);
     }
 
@@ -512,34 +519,44 @@ NS_InitXPCOM3(nsIServiceManager* *result
         base::Thread::Options options;
         options.message_loop_type = MessageLoop::TYPE_IO;
         NS_ENSURE_TRUE(ioThread->StartWithOptions(options), NS_ERROR_FAILURE);
 
         sIOThread = ioThread.release();
     }
 #endif
 
+    NS_TIME_FUNCTION_MARK("Next: thread manager init");
+
     // Establish the main thread here.
     rv = nsThreadManager::get()->Init();
     if (NS_FAILED(rv)) return rv;
 
+    NS_TIME_FUNCTION_MARK("Next: timer startup");
+
     // Set up the timer globals/timer thread
     rv = nsTimerImpl::Startup();
     NS_ENSURE_SUCCESS(rv, rv);
 
 #ifndef WINCE
+    NS_TIME_FUNCTION_MARK("Next: setlocale");
+
     // If the locale hasn't already been setup by our embedder,
     // get us out of the "C" locale and into the system 
     if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
         setlocale(LC_ALL, "");
 #endif
 
 #if defined(XP_UNIX) || defined(XP_OS2)
+    NS_TIME_FUNCTION_MARK("Next: startup native charset utils");
+
     NS_StartupNativeCharsetUtils();
 #endif
+    NS_TIME_FUNCTION_MARK("Next: startup local file");
+
     NS_StartupLocalFile();
 
     StartupSpecialSystemDirectory();
 
     rv = nsDirectoryService::RealInit();
     if (NS_FAILED(rv))
         return rv;
 
@@ -568,16 +585,18 @@ NS_InitXPCOM3(nsIServiceManager* *result
     
     if (appFileLocationProvider) {
         rv = nsDirectoryService::gService->RegisterProvider(appFileLocationProvider);
         if (NS_FAILED(rv)) return rv;
     }
 
 #ifdef MOZ_IPC
     if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
+        NS_TIME_FUNCTION_MARK("Next: IPC command line init");
+
 #ifdef OS_WIN
         CommandLine::Init(0, nsnull);
 #else
         nsCOMPtr<nsIFile> binaryFile;
         nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, 
                                           NS_GET_IID(nsIFile), 
                                           getter_AddRefs(binaryFile));
         NS_ENSURE_STATE(binaryFile);
@@ -592,16 +611,18 @@ NS_InitXPCOM3(nsIServiceManager* *result
         static char const *const argv = { strdup(binaryPath.get()) };
         CommandLine::Init(1, &argv);
 #endif
     }
 #endif
 
     NS_ASSERTION(nsComponentManagerImpl::gComponentManager == NULL, "CompMgr not null at init");
 
+    NS_TIME_FUNCTION_MARK("Next: component manager init");
+
     // Create the Component/Service Manager
     nsComponentManagerImpl *compMgr = new nsComponentManagerImpl();
     if (compMgr == NULL)
         return NS_ERROR_OUT_OF_MEMORY;
     NS_ADDREF(compMgr);
     
     rv = compMgr->Init(staticComponents, componentCount);
     if (NS_FAILED(rv))
@@ -622,24 +643,28 @@ NS_InitXPCOM3(nsIServiceManager* *result
     nsCOMPtr<nsIMemory> memory;
     NS_GetMemoryManager(getter_AddRefs(memory));
     rv = compMgr->RegisterService(kMemoryCID, memory);
     if (NS_FAILED(rv)) return rv;
 
     rv = compMgr->RegisterService(kComponentManagerCID, static_cast<nsIComponentManager*>(compMgr));
     if (NS_FAILED(rv)) return rv;
 
+    NS_TIME_FUNCTION_MARK("Next: cycle collector startup");
+
     rv = nsCycleCollector_startup();
     if (NS_FAILED(rv)) return rv;
 
     // 2. Register the global services with the component manager so that
     //    clients can create new objects.
 
     // Category Manager
     {
+      NS_TIME_FUNCTION_MARK("Next: category manager factory init");
+
       nsCOMPtr<nsIFactory> categoryManagerFactory;
       if ( NS_FAILED(rv = NS_CategoryManagerGetFactory(getter_AddRefs(categoryManagerFactory))) )
         return rv;
 
       NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
 
       rv = compMgr->RegisterFactory(kCategoryManagerCID,
                                     NS_CATEGORYMANAGER_CLASSNAME,
@@ -664,34 +689,44 @@ NS_InitXPCOM3(nsIServiceManager* *result
 
         registrar->
           RegisterFactory(kSimpleUnicharStreamFactoryCID,
                           "nsSimpleUnicharStreamFactory",
                           NS_SIMPLE_UNICHAR_STREAM_FACTORY_CONTRACTID,
                           nsSimpleUnicharStreamFactory::GetInstance());
     }
 
+    NS_TIME_FUNCTION_MARK("Next: interface info manager init");
+
     // Pay the cost at startup time of starting this singleton.
     nsIInterfaceInfoManager* iim =
         xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
 
+    NS_TIME_FUNCTION_MARK("Next: try to load compreg.dat");
+
     // "Re-register the world" if compreg.dat doesn't exist
     rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
     if (NS_FAILED(rv)) {
+        NS_TIME_FUNCTION_MARK("Next: try to register all components (compreg.dat not found)");
+
         // If the component registry is out of date, malformed, or incomplete,
         // autoregister the default component directories.
         (void) iim->AutoRegisterInterfaces();
         nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
     }
 
+    NS_TIME_FUNCTION_MARK("Next: register category providers");
+
     // After autoreg, but before we actually instantiate any components,
     // add any services listed in the "xpcom-directory-providers" category
     // to the directory service.
     nsDirectoryService::gService->RegisterCategoryProviders();
 
+    NS_TIME_FUNCTION_MARK("Next: create services from category");
+
     // Notify observers of xpcom autoregistration start
     NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, 
                                   nsnull,
                                   NS_XPCOM_STARTUP_OBSERVER_ID);
     
     return NS_OK;
 }
 
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -57,16 +57,18 @@
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 #include "nsQuickSort.h"
 #include "nsEnumeratorUtils.h"
 #include "nsIProxyObjectManager.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Services.h"
 
+#include "mozilla/FunctionTimer.h"
+
 using namespace mozilla;
 class nsIComponentLoaderManager;
 
 /*
   CategoryDatabase
   contains 0 or more 1-1 mappings of string to Category
   each Category contains 0 or more 1-1 mappings of string keys to string values
 
@@ -846,16 +848,18 @@ NS_CategoryManagerGetFactory( nsIFactory
  * this will attempt to notify the observer with the origin, observerTopic string
  * as parameter.
  */
 NS_COM nsresult
 NS_CreateServicesFromCategory(const char *category,
                               nsISupports *origin,
                               const char *observerTopic)
 {
+    NS_TIME_FUNCTION_FMT("NS_CreateServicesFromCategory: %s (%s)", category, observerTopic ? observerTopic : "(no topic)");
+
     nsresult rv = NS_OK;
     
     int nFailed = 0; 
     nsCOMPtr<nsICategoryManager> categoryManager = 
         do_GetService("@mozilla.org/categorymanager;1", &rv);
     if (!categoryManager) return rv;
 
     nsCOMPtr<nsISimpleEnumerator> enumerator;
@@ -885,17 +889,20 @@ NS_CreateServicesFromCategory(const char
         }
         
         nsCOMPtr<nsISupports> instance = do_GetService(contractID, &rv);
         if (NS_FAILED(rv)) {
             nFailed++;
             continue;
         }
 
+        NS_TIME_FUNCTION_MARK("service: %s", nsPromiseFlatCString(contractID).get());
+
         if (observerTopic) {
             // try an observer, if it implements it.
             nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance, &rv);
             if (NS_SUCCEEDED(rv) && observer)
                 observer->Observe(origin, observerTopic, EmptyString().get());
+            NS_TIME_FUNCTION_MARK(" & observe %s", observerTopic);
         }
     }
     return (nFailed ? NS_ERROR_FAILURE : NS_OK);
 }
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -82,16 +82,17 @@
 #include "nsXPIDLString.h"
 #include "prcmon.h"
 #include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
 #include "nsThreadUtils.h"
 #include "prthread.h"
 #include "private/pprthred.h"
 #include "nsTArray.h"
 #include "prio.h"
+#include "mozilla/FunctionTimer.h"
 
 #include "nsInt64.h"
 #include "nsManifestLineReader.h"
 
 #include NEW_H     // for placement new
 
 
 #ifdef XP_BEOS
@@ -159,16 +160,30 @@ static void GetIDString(const nsID& aCID
     PR_snprintf(buf, UID_STRING_LENGTH, gIDFormat,
                 aCID.m0, (PRUint32) aCID.m1, (PRUint32) aCID.m2,
                 (PRUint32) aCID.m3[0], (PRUint32) aCID.m3[1],
                 (PRUint32) aCID.m3[2], (PRUint32) aCID.m3[3],
                 (PRUint32) aCID.m3[4], (PRUint32) aCID.m3[5],
                 (PRUint32) aCID.m3[6], (PRUint32) aCID.m3[7]);
 }
 
+#ifdef NS_FUNCTION_TIMER
+#define COMPMGR_TIME_FUNCTION_CID(cid)                                          \
+  char cid_buf__[NSID_LENGTH] = { '\0' };                                      \
+  cid.ToProvidedString(cid_buf__);                                             \
+  NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (cid: %s)", MOZ_FUNCTION_NAME, \
+                           __LINE__, cid_buf__)
+#define COMPMGR_TIME_FUNCTION_CONTRACTID(cid)                                  \
+  NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (contractid: %s)", MOZ_FUNCTION_NAME, \
+                           __LINE__, (cid))
+#else
+#define COMPMGR_TIME_FUNCTION_CID(cid) do {} while (0)
+#define COMPMGR_TIME_FUNCTION_CONTRACTID(cid) do {} while (0)
+#endif
+
 nsresult
 nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
 {
     nsresult rv;
     nsXPIDLCString value;
     nsCOMPtr<nsICategoryManager> catman;
     nsComponentManagerImpl *compMgr = nsComponentManagerImpl::gComponentManager;
     if (!compMgr) {
@@ -599,28 +614,31 @@ nsComponentManagerImpl::nsComponentManag
 }
 
 #define CONTRACTID_HASHTABLE_INITIAL_SIZE	2048
 #define AUTOREGENTRY_HASHTABLE_INITIAL_SIZE	256
 
 nsresult nsComponentManagerImpl::Init(nsStaticModuleInfo const *aStaticModules,
                                       PRUint32 aStaticModuleCount)
 {
+    NS_TIME_FUNCTION;
+
     PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS);
     if (mShuttingDown == NS_SHUTDOWN_INPROGRESS)
         return NS_ERROR_FAILURE;
 
     mShuttingDown = NS_SHUTDOWN_NEVERHAPPENED;
 
     if (nsComponentManagerLog == nsnull)
     {
         nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
     }
 
     // Initialize our arena
+    NS_TIME_FUNCTION_MARK("Next: init component manager arena");
     PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
 
     if (!mFactories.ops) {
         if (!PL_DHashTableInit(&mFactories, &factory_DHashTableOps,
                                0, sizeof(nsFactoryTableEntry),
                                1024)) {
             mFactories.ops = nsnull;
             return NS_ERROR_OUT_OF_MEMORY;
@@ -686,29 +704,33 @@ nsresult nsComponentManagerImpl::Init(ns
     if(!mRegistryFile) {
         NS_WARNING("No Component Registry file was found in the directory service");
         return NS_ERROR_FAILURE;
     }
 
     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
            ("nsComponentManager: Initialized."));
 
+    NS_TIME_FUNCTION_MARK("Next: init native module loader");
     rv = mNativeModuleLoader.Init();
     if (NS_FAILED(rv))
         return rv;
 
+    NS_TIME_FUNCTION_MARK("Next: init static module loader");
     rv = mStaticModuleLoader.Init(aStaticModules, aStaticModuleCount);
     if (NS_FAILED(rv))
         return rv;
 
     return NS_OK;
 }
 
 nsresult nsComponentManagerImpl::Shutdown(void)
 {
+    NS_TIME_FUNCTION;
+
     PR_ASSERT(mShuttingDown == NS_SHUTDOWN_NEVERHAPPENED);
     if (mShuttingDown != NS_SHUTDOWN_NEVERHAPPENED)
         return NS_ERROR_FAILURE;
 
     mShuttingDown = NS_SHUTDOWN_INPROGRESS;
 
     // Shutdown the component manager
     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
@@ -825,16 +847,18 @@ PRBool ReadSectionHeader(nsManifestLineR
             break;
     }
     return PR_FALSE;
 }
 
 nsresult
 nsComponentManagerImpl::ReadPersistentRegistry()
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(mComponentsDir, "nsComponentManager not initialized.");
 
     nsresult rv;
 
     // populate Category Manager. need to get this early so that we don't get
     // skipped by 'goto out'
     mCategoryManager = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv))
@@ -1185,16 +1209,18 @@ AutoRegEntryWriter(nsIHashable *aKey, PR
 }
 
 nsresult
 nsComponentManagerImpl::WritePersistentRegistry()
 {
     if (!mRegistryFile)
         return NS_ERROR_FAILURE;  // this should have been set by Init().
 
+    NS_TIME_FUNCTION;
+
     nsCOMPtr<nsIFile> file;
     mRegistryFile->Clone(getter_AddRefs(file));
     if (!file)
         return NS_ERROR_OUT_OF_MEMORY;
 
     nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
 
     nsCAutoString originalLeafName;
@@ -1544,16 +1570,18 @@ nsComponentManagerImpl::CLSIDToContractI
  * released and not held onto for any longer.
  */
 NS_IMETHODIMP
 nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
                                        nsISupports *aDelegate,
                                        const nsIID &aIID,
                                        void **aResult)
 {
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
     // test this first, since there's no point in creating a component during
     // shutdown -- whether it's available or not would depend on the order it
     // occurs in the list
     if (gXPCOMShuttingDown) {
         // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
         nsXPIDLCString cid, iid;
         cid.Adopt(aClass.ToString());
@@ -1629,16 +1657,18 @@ nsComponentManagerImpl::CreateInstance(c
  * CreateInstance() with classid and iid.
  */
 NS_IMETHODIMP
 nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
                                                    nsISupports *aDelegate,
                                                    const nsIID &aIID,
                                                    void **aResult)
 {
+    COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
+
     NS_ENSURE_ARG_POINTER(aContractID);
 
     // test this first, since there's no point in creating a component during
     // shutdown -- whether it's available or not would depend on the order it
     // occurs in the list
     if (gXPCOMShuttingDown) {
         // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
@@ -1828,16 +1858,19 @@ nsComponentManagerImpl::GetService(const
     }
 
     if (entry && entry->mServiceObject) {
         nsCOMPtr<nsISupports> supports = entry->mServiceObject;
         mon.Exit();
         return supports->QueryInterface(aIID, result);
     }
 
+    // We only care about time when we create the service.
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
     PRThread* currentPRThread = PR_GetCurrentThread();
     NS_ASSERTION(currentPRThread, "This should never be null!");
 
     // Needed to optimize the event loop below.
     nsIThread* currentThread = nsnull;
 
     PRThread* pendingPRThread;
     while ((pendingPRThread = GetPendingServiceThread(aClass))) {
@@ -1931,16 +1964,18 @@ nsComponentManagerImpl::GetService(const
     }
     NS_ADDREF(static_cast<nsISupports*>((*result)));
     return rv;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::RegisterService(const nsCID& aClass, nsISupports* aService)
 {
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
     nsAutoMonitor mon(mMon);
 
     // check to see if we have a factory entry for the service
     nsFactoryEntry *entry = GetFactoryEntry(aClass);
 
     if (!entry) {
         void *mem;
         PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
@@ -1964,16 +1999,18 @@ nsComponentManagerImpl::RegisterService(
 
     entry->mServiceObject = aService;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::UnregisterService(const nsCID& aClass)
 {
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
     nsresult rv = NS_OK;
 
     nsFactoryEntry* entry = nsnull;
 
     nsAutoMonitor mon(mMon);
 
     nsFactoryTableEntry* factoryTableEntry =
         static_cast<nsFactoryTableEntry*>
@@ -1990,16 +2027,18 @@ nsComponentManagerImpl::UnregisterServic
     entry->mServiceObject = nsnull;
     return rv;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::RegisterService(const char* aContractID,
                                         nsISupports* aService)
 {
+    COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
+
     NS_ENSURE_ARG_POINTER(aContractID);
 
     nsAutoMonitor mon(mMon);
 
     // check to see if we have a factory entry for the service
     PRUint32 contractIDLen = strlen(aContractID);
     nsFactoryEntry *entry = GetFactoryEntry(aContractID, contractIDLen);
 
@@ -2040,16 +2079,18 @@ nsComponentManagerImpl::RegisterService(
 }
 
 
 NS_IMETHODIMP
 nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
                                               const nsIID& aIID,
                                               PRBool *result)
 {
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
     // Now we want to get the service if we already got it. If not, we don't want
     // to create an instance of it. mmh!
 
     // test this first, since there's no point in returning a service during
     // shutdown -- whether it's available or not would depend on the order it
     // occurs in the list
     if (gXPCOMShuttingDown) {
         // When processing shutdown, don't process new GetService() requests
@@ -2082,16 +2123,18 @@ nsComponentManagerImpl::IsServiceInstant
     return rv;
 
 }
 
 NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
                                                                         const nsIID& aIID,
                                                                         PRBool *result)
 {
+    COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
+
     // Now we want to get the service if we already got it. If not, we don't want
     // to create an instance of it. mmh!
 
     // test this first, since there's no point in returning a service during
     // shutdown -- whether it's available or not would depend on the order it
     // occurs in the list
     if (gXPCOMShuttingDown) {
         // When processing shutdown, don't process new GetService() requests
@@ -2126,16 +2169,18 @@ NS_IMETHODIMP nsComponentManagerImpl::Is
     }
     return rv;
 }
 
 
 NS_IMETHODIMP
 nsComponentManagerImpl::UnregisterService(const char* aContractID)
 {
+    COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
+
     nsresult rv = NS_OK;
 
     nsAutoMonitor mon(mMon);
 
     nsFactoryEntry *entry = nsnull;
     nsContractIDTableEntry* contractIDTableEntry =
        static_cast<nsContractIDTableEntry*>
                   (PL_DHashTableOperate(&mContractIDs, aContractID,
@@ -2191,16 +2236,19 @@ nsComponentManagerImpl::GetServiceByCont
         // We need to not be holding the service manager's monitor while calling
         // QueryInterface, because it invokes user code which could try to re-enter
         // the service manager, or try to grab some other lock/monitor/condvar
         // and deadlock, e.g. bug 282743.
         mon.Exit();
         return serviceObject->QueryInterface(aIID, result);
     }
 
+    // We only care about time when we create the service.
+    COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
+
     PRThread* currentPRThread = PR_GetCurrentThread();
     NS_ASSERTION(currentPRThread, "This should never be null!");
 
     // Needed to optimize the event loop below.
     nsIThread* currentThread = nsnull;
 
     PRThread* pendingPRThread;
     while ((pendingPRThread = GetPendingServiceThread(entry->mCid))) {
@@ -2300,31 +2348,35 @@ nsComponentManagerImpl::ReleaseService(c
     NS_IF_RELEASE(service);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec,
                                                 char **aRegistryName)
 {
+    NS_TIME_FUNCTION;
+
     nsCAutoString location;
     nsresult rv = RegistryLocationForFile(aSpec, location);
     if (NS_SUCCEEDED(rv)) {
         *aRegistryName = ToNewCString(location);
         if (!*aRegistryName)
             return NS_ERROR_OUT_OF_MEMORY;
     }
 
     return rv;
 }
 
 nsresult
 nsComponentManagerImpl::RegistryLocationForFile(nsIFile* aFile,
                                                 nsCString& aRegistryName)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     if (!mComponentsDir)
         return NS_ERROR_NOT_INITIALIZED;
 
     // First check to see if this component is in the application
     // components directory
     PRBool containedIn;
@@ -2374,16 +2426,18 @@ nsComponentManagerImpl::SpecForRegistryL
     return FileForRegistryLocation(nsDependentCString(aLocation),
                                    (nsILocalFile**) aSpec);
 }
 
 nsresult
 nsComponentManagerImpl::FileForRegistryLocation(const nsCString &aLocation,
                                                 nsILocalFile **aSpec)
 {
+    NS_TIME_FUNCTION;
+
     // i18n: assuming aLocation is encoded for the current locale
 
     nsresult rv;
 
     const nsDependentCSubstring prefix = Substring(aLocation, 0, 4);
 
     /* abs:/full/path/to/libcomponent.so */
     if (prefix.EqualsLiteral(XPCOM_ABSCOMPONENT_PREFIX)) {
@@ -2448,16 +2502,18 @@ nsComponentManagerImpl::FileForRegistryL
  */
 NS_IMETHODIMP
 nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
                                         const char *aClassName,
                                         const char *aContractID,
                                         nsIFactory *aFactory,
                                         PRBool aReplace)
 {
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
     nsAutoMonitor mon(mMon);
 #ifdef PR_LOGGING
     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
     {
         char *buf = aClass.ToString();
         PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
                ("nsComponentManager: RegisterFactory(%s, %s)", buf,
                 (aContractID ? aContractID : "(null)")));
@@ -2604,16 +2660,18 @@ nsComponentManagerImpl::RegisterComponen
                                                 const char *aContractID,
                                                 PRUint32 aContractIDLen,
                                                 const char *aRegistryName,
                                                 PRUint32 aRegistryNameLen,
                                                 PRBool aReplace,
                                                 PRBool aPersist,
                                                 const char *aType)
 {
+    COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
+
     nsresult rv;
 
     nsAutoMonitor mon(mMon);
 
     nsFactoryEntry *entry = GetFactoryEntry(aClass);
 
     // Normalize proid and classname
     const char *contractID = (aContractID && *aContractID) ? aContractID : nsnull;
@@ -2708,16 +2766,18 @@ nsComponentManagerImpl::LoaderForType(Lo
     }
 
     return mLoaderData[aType].loader;
 }
 
 void
 nsComponentManagerImpl::GetAllLoaders()
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(mCategoryManager, "nsComponentManager used uninitialized");
 
     nsCOMPtr<nsISimpleEnumerator> loaderEnum;
     mCategoryManager->EnumerateCategory("module-loader",
                                         getter_AddRefs(loaderEnum));
     nsCOMPtr<nsIUTF8StringEnumerator>
         loaderStrings(do_QueryInterface(loaderEnum));
     if (loaderStrings) {
@@ -2813,16 +2873,18 @@ nsComponentManagerImpl::DeleteContractID
     aData.factory = factory;
     PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
 }
 
 nsresult
 nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
                                           nsIFactory *aFactory)
 {
+    COMPMGR_TIME_FUNCTION_CID(aClass);
+
 #ifdef PR_LOGGING
     if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
     {
         char *buf = aClass.ToString();
         PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
                ("nsComponentManager: UnregisterFactory(%s)", buf));
         if (buf)
             NS_Free(buf);
@@ -2923,16 +2985,18 @@ nsComponentManagerImpl::AutoRegisterImpl
 
 static const char kNL[] = "\r\n";
 
 nsresult
 nsComponentManagerImpl::AutoRegisterDirectory(nsIFile *inDirSpec,
                           nsCOMArray<nsILocalFile>    &aLeftovers,
                           nsTArray<DeferredModule>    &aDeferred)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     nsCOMPtr<nsIFile> componentsList;
     inDirSpec->Clone(getter_AddRefs(componentsList));
     if (componentsList) {
         nsCOMPtr<nsILocalFile> lfComponentsList =
             do_QueryInterface(componentsList);
         lfComponentsList->AppendNative(NS_LITERAL_CSTRING("components.list"));
@@ -2981,16 +3045,18 @@ nsComponentManagerImpl::AutoRegisterDire
 }
 
 nsresult
 nsComponentManagerImpl::AutoRegisterComponentsList(nsIFile* inDir,
                                   PRFileDesc* fd,
                                   nsCOMArray<nsILocalFile>& aLeftovers,
                                   nsTArray<DeferredModule>& aDeferred)
 {
+    NS_TIME_FUNCTION;
+
     PRFileInfo info;
     if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info))
         return NS_ErrorAccordingToNSPR();
 
     nsAutoArrayPtr<char> buf(new char[info.size + 1]);
     if (!buf)
         return NS_ERROR_OUT_OF_MEMORY;
 
@@ -3045,16 +3111,18 @@ nsComponentManagerImpl::AutoRegisterComp
     return rv;
 }
 
 nsresult
 nsComponentManagerImpl::AutoRegisterComponent(nsILocalFile*  aComponentFile,
                                    nsTArray<DeferredModule> &aDeferred,
                                    LoaderType                minLoader)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     NS_ASSERTION(minLoader < GetLoaderCount(), "Bad minLoader");
 
     nsCAutoString registryLocation;
     rv = RegistryLocationForFile(aComponentFile, registryLocation);
     if (NS_FAILED(rv))
         return rv;
@@ -3212,16 +3280,18 @@ nsComponentManagerImpl::LoadDeferredModu
         }
     }
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 /* unused */,
                                                 nsIFile *component)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     GetAllLoaders();
 
     nsCAutoString location;
     rv = RegistryLocationForFile(component, location);
     if (NS_FAILED(rv))
         return rv;
@@ -3267,16 +3337,18 @@ nsComponentManagerImpl::IsRegistered(con
     }
     *aRegistered = (nsnull != GetFactoryEntry(aClass));
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(aEnumerator != nsnull, "null ptr");
     if (!aEnumerator)
     {
         return NS_ERROR_NULL_POINTER;
     }
     *aEnumerator = nsnull;
 
     nsresult rv;
@@ -3291,16 +3363,18 @@ nsComponentManagerImpl::EnumerateCLSIDs(
 
     *aEnumerator = static_cast<nsIEnumerator*>(aEnum);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::EnumerateContractIDs(nsIEnumerator** aEnumerator)
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(aEnumerator != nsnull, "null ptr");
     if (!aEnumerator)
     {
         return NS_ERROR_NULL_POINTER;
     }
 
     *aEnumerator = nsnull;
 
@@ -3344,16 +3418,18 @@ ReportLoadFailure(nsIFile* aFile, nsICon
     message.Insert(NS_LITERAL_STRING("Failed to load XPCOM component: "), 0);
 
     aCS->LogStringMessage(message.get());
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::AutoRegister(nsIFile *aSpec)
 {
+    NS_TIME_FUNCTION;
+
     nsresult rv;
 
     if (!mCategoryManager) {
         mCategoryManager = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
         if (NS_FAILED(rv))
             return rv;
     }
 
@@ -3537,16 +3613,18 @@ nsComponentManagerImpl::IsContractIDRegi
     else
         *_retval = PR_FALSE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(aEnumerator != nsnull, "null ptr");
 
     if (!aEnumerator)
         return NS_ERROR_NULL_POINTER;
 
     *aEnumerator = nsnull;
 
     nsresult rv;
@@ -3560,16 +3638,18 @@ nsComponentManagerImpl::EnumerateCIDs(ns
 
     *aEnumerator = static_cast<nsISimpleEnumerator*>(aEnum);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
 {
+    NS_TIME_FUNCTION;
+
     NS_ASSERTION(aEnumerator != nsnull, "null ptr");
     if (!aEnumerator)
         return NS_ERROR_NULL_POINTER;
 
     *aEnumerator = nsnull;
 
     nsresult rv;
     PLDHashTableEnumeratorImpl *aEnum;
--- a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
+++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* Implementation of xptiInterfaceInfoManager. */
 
 #include "xptiprivate.h"
 #include "nsDependentString.h"
 #include "nsString.h"
 #include "nsArrayEnumerator.h"
+#include "mozilla/FunctionTimer.h"
 
 #define NS_ZIPLOADER_CONTRACTID NS_XPTLOADER_CONTRACTID_PREFIX "zip"
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(xptiInterfaceInfoManager, 
                               nsIInterfaceInfoManager,
                               nsIInterfaceInfoSuperManager)
 
 static xptiInterfaceInfoManager* gInterfaceInfoManager = nsnull;
@@ -56,16 +57,19 @@ static int gCallCount = 0;
 #endif
 
 // static
 xptiInterfaceInfoManager*
 xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef()
 {
     if(!gInterfaceInfoManager)
     {
+        NS_TIME_FUNCTION;
+
+        NS_TIME_FUNCTION_MARK("Next: build file search path");
         nsCOMPtr<nsISupportsArray> searchPath;
         BuildFileSearchPath(getter_AddRefs(searchPath));
         if(!searchPath)
         {
             NS_ERROR("can't get xpt search path!");    
             return nsnull;
         }
 
@@ -79,31 +83,34 @@ xptiInterfaceInfoManager::GetInterfaceIn
         NS_ADDREF(gInterfaceInfoManager);
 
         if(!gInterfaceInfoManager->IsValid())
         {
             NS_RELEASE(gInterfaceInfoManager);
         }
         else
         {
+            NS_TIME_FUNCTION_MARK("Next: read xpti manifest");
             PRBool mustAutoReg = 
                     !xptiManifest::Read(gInterfaceInfoManager, 
                                         &gInterfaceInfoManager->mWorkingSet);
 #ifdef DEBUG
             {
             // This sets what will be returned by GetOpenLogFile().
             xptiAutoLog autoLog(gInterfaceInfoManager, 
                                 gInterfaceInfoManager->mAutoRegLogFile, PR_TRUE);
             LOG_AUTOREG(("debug build forced autoreg after %s load of manifest\n", mustAutoReg ? "FAILED" : "successful"));
         
             mustAutoReg = PR_TRUE;
             }
 #endif // DEBUG
-            if(mustAutoReg)
+            if(mustAutoReg) {
+                NS_TIME_FUNCTION_MARK("Next: auto register interfaces");
                 gInterfaceInfoManager->AutoRegisterInterfaces();
+            }
         }
     }
     return gInterfaceInfoManager;
 }
 
 void
 xptiInterfaceInfoManager::FreeInterfaceInfoManager()
 {
@@ -1879,16 +1886,18 @@ NS_IMETHODIMP xptiInterfaceInfoManager::
     PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayPrefixAppender, &args);
     
     return array->Enumerate(_retval);
 }
 
 /* void autoRegisterInterfaces (); */
 NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
 {
+    NS_TIME_FUNCTION;
+
     nsCOMPtr<nsISupportsArray> fileList;
     AutoRegMode mode;
     PRBool ok;
 
     nsAutoLock lock(xptiInterfaceInfoManager::GetAutoRegLock(this));
 
     xptiWorkingSet workingSet(mSearchPath);
     if(!workingSet.IsValid())
@@ -1897,67 +1906,74 @@ NS_IMETHODIMP xptiInterfaceInfoManager::
     // This sets what will be returned by GetOpenLogFile().
     xptiAutoLog autoLog(this, mAutoRegLogFile, PR_TRUE);
 
     LOG_AUTOREG(("start AutoRegister\n"));
 
     // We re-read the manifest rather than muck with the 'live' one.
     // It is OK if this fails.
     // XXX But we should track failure as a warning.
+    NS_TIME_FUNCTION_MARK("Next: read the manifest");
     ok = xptiManifest::Read(this, &workingSet);
 
     LOG_AUTOREG(("read of manifest %s\n", ok ? "successful" : "FAILED"));
 
     // Grovel for all the typelibs we can find (in .xpt or .zip, .jar,...).
+    NS_TIME_FUNCTION_MARK("Next: build file list");
     if(!BuildFileList(mSearchPath, getter_AddRefs(fileList)) || !fileList)
         return NS_ERROR_UNEXPECTED;
     
     // DEBUG_DumpFileList(fileList);
 
     // Check to see how much work we need to do.
+    NS_TIME_FUNCTION_MARK("Next: determining registration strategy");
     mode = DetermineAutoRegStrategy(mSearchPath, fileList, &workingSet);
 
     switch(mode)
     {
     case NO_FILES_CHANGED:
         LOG_AUTOREG(("autoreg strategy: no files changed\n"));
         LOG_AUTOREG(("successful end of AutoRegister\n"));
         return NS_OK;
     case FILES_ADDED_ONLY:
         LOG_AUTOREG(("autoreg strategy: files added only\n"));
+        NS_TIME_FUNCTION_MARK("Next: adding only new files");
         if(!AddOnlyNewFilesFromFileList(mSearchPath, fileList, &workingSet))
         {
             LOG_AUTOREG(("FAILED to add new files\n"));
             return NS_ERROR_UNEXPECTED;
         }
         break;
     case FULL_VALIDATION_REQUIRED:
         LOG_AUTOREG(("autoreg strategy: doing full validation merge\n"));
+        NS_TIME_FUNCTION_MARK("Next: full validation merge");
         if(!DoFullValidationMergeFromFileList(mSearchPath, fileList, &workingSet))
         {
             LOG_AUTOREG(("FAILED to do full validation\n"));
             return NS_ERROR_UNEXPECTED;
         }
         break;
     default:
         NS_ERROR("switch missing a case");
         return NS_ERROR_UNEXPECTED;
     }
 
     // Failure to write the manifest is not fatal in production builds.
     // However, this would require the next startup to find and read all the
     // xpt files. This will make that startup slower. If this ever becomes a 
     // chronic problem for anyone, then we'll want to figure out why!
     
+    NS_TIME_FUNCTION_MARK("Next: writing manifest");
     if(!xptiManifest::Write(this, &workingSet))
     {
         LOG_AUTOREG(("FAILED to write manifest\n"));
         NS_ERROR("Failed to write xpti manifest!");
     }
     
+    NS_TIME_FUNCTION_MARK("Next: merging working sets");
     if(!MergeWorkingSets(&mWorkingSet, &workingSet))
     {
         LOG_AUTOREG(("FAILED to merge into live workingset\n"));
         return NS_ERROR_UNEXPECTED;
     }
 
 //    DEBUG_DumpFileListInWorkingSet(mWorkingSet);
 
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -41,16 +41,25 @@
 #include "nsIClassInfoImpl.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsAutoLock.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "prlog.h"
 #include "nsThreadUtilsInternal.h"
 
+#include "mozilla/FunctionTimer.h"
+#if defined(NS_FUNCTION_TIMER) && defined(_MSC_VER)
+#include "nsTimerImpl.h"
+#include "nsStackWalk.h"
+#endif
+#ifdef NS_FUNCTION_TIMER
+#include "nsCRT.h"
+#endif
+
 #ifdef PR_LOGGING
 static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
 #endif
 #define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
 
 NS_DECL_CI_INTERFACE_GETTER(nsThread)
 
 nsIThreadObserver* nsThread::sGlobalObserver;
@@ -515,16 +524,27 @@ nsThread::ProcessNextEvent(PRBool mayWai
     // Scope for |event| to make sure that its destructor fires while
     // mRunningEvent has been incremented, since that destructor can
     // also do work.
 
     // If we are shutting down, then do not wait for new events.
     nsCOMPtr<nsIRunnable> event;
     mEvents->GetEvent(mayWait && !ShuttingDown(), getter_AddRefs(event));
 
+#ifdef NS_FUNCTION_TIMER
+    char message[1024] = {'\0'};
+    if (NS_IsMainThread()) {
+        mozilla::FunctionTimer::ft_snprintf(message, sizeof(message), 
+                                            "@ Main Thread Event %p", (void*)event.get());
+    }
+    // If message is empty, it means that we're not on the main thread, and
+    // FunctionTimer won't time this function.
+    NS_TIME_FUNCTION_MIN_FMT(5.0, message);
+#endif
+
     *result = (event.get() != nsnull);
 
     if (event) {
       LOG(("THRD(%p) running [%p]\n", this, event.get()));
       event->Run();
     } else if (mayWait) {
       NS_ASSERTION(ShuttingDown(),
                    "This should only happen when shutting down");