--- 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");