Bug 1050774 - Record script execution in timeline view. r=bholley

This commit is contained in:
Kannan Vijayan 2014-11-13 16:22:24 -05:00
parent 7561ef2a15
commit 41f6d8a7aa
8 changed files with 102 additions and 5 deletions

View File

@ -13,6 +13,8 @@ var gRGB_TO_HSL = {
"rgb(96, 201, 58)": "hsl(104,57%,51%)",
"rgb(240, 195, 111)": "hsl(39,82%,69%)",
"rgb(227, 155, 22)": "hsl(39,82%,49%)",
"rgb(204, 204, 204)": "hsl(0,0%,80%)",
"rgb(153, 153, 153)": "hsl(0,0%,60%)",
};
let test = Task.async(function*() {

View File

@ -55,7 +55,13 @@ const TIMELINE_BLUEPRINT = {
fill: "hsl(0,0%,80%)",
stroke: "hsl(0,0%,60%)",
label: L10N.getStr("timeline.label.consoleTime")
}
},
"Javascript": {
group: 4,
fill: "hsl(0,0%,80%)",
stroke: "hsl(0,0%,60%)",
label: L10N.getStr("timeline.label.javascript")
},
};
// Exported symbols.

View File

@ -38,6 +38,7 @@ timeline.records=RECORDS
timeline.label.styles=Styles
timeline.label.reflow=Reflow
timeline.label.paint=Paint
timeline.label.javascript=Javascript
timeline.label.domevent=DOM Event
timeline.label.consoleTime=Console

View File

@ -854,7 +854,8 @@ nsDocShell::nsDocShell():
mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
mFrameType(eFrameTypeRegular),
mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
mParentCharsetSource(0)
mParentCharsetSource(0),
mJSRunToCompletionDepth(0)
{
mHistoryID = ++gDocshellIDCounter;
if (gDocShellCount++ == 0) {
@ -890,6 +891,8 @@ nsDocShell::nsDocShell():
nsDocShell::~nsDocShell()
{
MOZ_ASSERT(!mProfileTimelineRecording);
Destroy();
nsCOMPtr<nsISHistoryInternal>
@ -2829,14 +2832,15 @@ NS_IMETHODIMP
nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
bool currentValue;
GetRecordProfileTimelineMarkers(&currentValue);
bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
if (currentValue != aValue) {
if (aValue) {
++gProfileTimelineRecordingsCount;
UseEntryScriptProfiling();
mProfileTimelineRecording = true;
} else {
--gProfileTimelineRecordingsCount;
UnuseEntryScriptProfiling();
mProfileTimelineRecording = false;
ClearProfileTimelineMarkers();
}
@ -13608,6 +13612,30 @@ nsDocShell::GetURLSearchParams()
return mURLSearchParams;
}
void
nsDocShell::NotifyJSRunToCompletionStart()
{
bool timelineOn = nsIDocShell::GetRecordProfileTimelineMarkers();
// If first start, mark interval start.
if (timelineOn && mJSRunToCompletionDepth == 0) {
AddProfileTimelineMarker("Javascript", TRACING_INTERVAL_START);
}
mJSRunToCompletionDepth++;
}
void
nsDocShell::NotifyJSRunToCompletionStop()
{
bool timelineOn = nsIDocShell::GetRecordProfileTimelineMarkers();
// If last stop, mark interval end.
mJSRunToCompletionDepth--;
if (timelineOn && mJSRunToCompletionDepth == 0) {
AddProfileTimelineMarker("Javascript", TRACING_INTERVAL_END);
}
}
void
nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString &aProvider,
const nsString &aKeyword) {

View File

@ -950,6 +950,10 @@ private:
nsWeakPtr mOpener;
nsWeakPtr mOpenedRemote;
// A depth count of how many times NotifyRunToCompletionStart
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;
// True if recording profiles.
bool mProfileTimelineRecording;

View File

@ -54,7 +54,7 @@ interface nsITabParent;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(da8f78f1-8f20-4d6d-be56-fe53e177b630)]
[scriptable, builtinclass, uuid(4e3de242-0b2a-4cf0-81b5-a5fe8628431c)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -1026,6 +1026,14 @@ interface nsIDocShell : nsIDocShellTreeItem
// URLSearchParams for the window.location is owned by the docShell.
[noscript,notxpcom] URLSearchParams getURLSearchParams();
/**
* Notify DocShell when the browser is about to start executing JS, and after
* that execution has stopped. This only occurs when the Timeline devtool
* is collecting information.
*/
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStart();
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStop();
/**
* This attribute determines whether a document which is not about:blank has
* already be loaded by this docShell.

View File

@ -12,6 +12,7 @@
#include "xpcprivate.h" // For AutoCxPusher guts
#include "xpcpublic.h"
#include "nsIGlobalObject.h"
#include "nsIDocShell.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
#include "nsContentUtils.h"
@ -70,8 +71,26 @@ public:
ScriptSettingsStackEntry *entry = EntryPoint();
return entry ? entry->mGlobalObject : nullptr;
}
};
static unsigned long gRunToCompletionListeners = 0;
void
UseEntryScriptProfiling()
{
MOZ_ASSERT(NS_IsMainThread());
++gRunToCompletionListeners;
}
void
UnuseEntryScriptProfiling()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gRunToCompletionListeners > 0);
--gRunToCompletionListeners;
}
void
InitScriptSettings()
{
@ -497,14 +516,30 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
aCx ? aCx : FindJSContext(aGlobalObject))
, ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
, mWebIDLCallerPrincipal(nullptr)
, mDocShellForJSRunToCompletion(nullptr)
{
MOZ_ASSERT(aGlobalObject);
MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.
MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject));
if (aIsMainThread && gRunToCompletionListeners > 0) {
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobalObject);
if (window) {
mDocShellForJSRunToCompletion = window->GetDocShell();
}
}
if (mDocShellForJSRunToCompletion) {
mDocShellForJSRunToCompletion->NotifyJSRunToCompletionStart();
}
}
AutoEntryScript::~AutoEntryScript()
{
if (mDocShellForJSRunToCompletion) {
mDocShellForJSRunToCompletion->NotifyJSRunToCompletionStop();
}
// GC when we pop a script entry point. This is a useful heuristic that helps
// us out on certain (flawed) benchmarks like sunspider, because it lets us
// avoid GCing during the timing loop.

View File

@ -21,6 +21,7 @@ class nsPIDOMWindow;
class nsGlobalWindow;
class nsIScriptContext;
class nsIDocument;
class nsIDocShell;
namespace mozilla {
namespace dom {
@ -63,6 +64,16 @@ private:
void InitScriptSettings();
void DestroyScriptSettings();
/*
* Static helpers in ScriptSettings which track the number of listeners
* of Javascript RunToCompletion events. These should be used by the code in
* nsDocShell::SetRecordProfileTimelineMarkers to indicate to script
* settings that script run-to-completion needs to be monitored.
* SHOULD BE CALLED ONLY BY MAIN THREAD.
*/
void UseEntryScriptProfiling();
void UnuseEntryScriptProfiling();
// To implement a web-compatible browser, it is often necessary to obtain the
// global object that is "associated" with the currently-running code. This
// process is made more complicated by the fact that, historically, different
@ -331,6 +342,8 @@ private:
// can't go away until then either.
nsIPrincipal* mWebIDLCallerPrincipal;
friend nsIPrincipal* GetWebIDLCallerPrincipal();
nsIDocShell* mDocShellForJSRunToCompletion;
};
/*