Bug 1421651 - Remove obseleted timeline and TimelineMarker code r=canaltinova,webidl,devtools-reviewers,saschanaz,smaug,ochameau

This patch removes the old docshell timeline and timeline markers codebase and replaces them with equivalent Gecko profiler marker. This patch also fixes Bug 1834143, which is a subset of 1421651.

Differential Revision: https://phabricator.services.mozilla.com/D184217
This commit is contained in:
Adam Brouwers-Harries 2023-10-24 15:18:12 +00:00
Родитель bbff1a3b96
Коммит a26eafe5c3
71 изменённых файлов: 291 добавлений и 3466 удалений

Просмотреть файл

@ -388,8 +388,6 @@ skip-if = ["os == 'win'"] # bug 1391264
["browser_net_reload-button.js"]
["browser_net_reload-markers.js"]
["browser_net_req-resp-bodies.js"]
["browser_net_resend.js"]

Просмотреть файл

@ -1,34 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests if the empty-requests reload button works.
*/
add_task(async function () {
const { monitor } = await initNetMonitor(SIMPLE_URL, { requestCount: 1 });
info("Starting test... ");
const { document } = monitor.panelWin;
const markersDone = waitForTimelineMarkers(monitor);
const button = document.querySelector(".requests-list-reload-notice-button");
button.click();
await waitForNetworkEvents(monitor, 1);
const markers = await markersDone;
ok(true, "Reloading finished");
is(
markers[0].name,
"dom-interactive",
"The first received marker is correct."
);
is(markers[1].name, "dom-complete", "The second received marker is correct.");
return teardown(monitor);
});

Просмотреть файл

@ -28,10 +28,6 @@ with Files("nsAboutRedirector.*"):
with Files("nsIScrollObserver.*"):
BUG_COMPONENT = ("Core", "Panning and Zooming")
DIRS += [
"timeline",
]
XPIDL_SOURCES += [
"nsIContentViewer.idl",
"nsIContentViewerEdit.idl",

Просмотреть файл

@ -30,7 +30,6 @@
#include "mozilla/LoadInfo.h"
#include "mozilla/Logging.h"
#include "mozilla/MediaFeatureChange.h"
#include "mozilla/ObservedDocShell.h"
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/ResultExtensions.h"
@ -70,7 +69,6 @@
#include "mozilla/dom/PerformanceNavigation.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/PopupBlocker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/dom/ScreenOrientation.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ServiceWorkerInterceptController.h"
@ -243,7 +241,6 @@
#include "mozpkix/pkix.h"
#include "NSSErrorsService.h"
#include "timeline/JavascriptTimelineMarker.h"
#include "nsDocShellTelemetryUtils.h"
#ifdef MOZ_PLACES
@ -335,7 +332,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
mLoadType(0),
mFailedLoadType(0),
mJSRunToCompletionDepth(0),
mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
mChannelToDisconnectOnPageHide(0),
mCreatingDocument(false),
@ -388,8 +384,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
}
nsDocShell::~nsDocShell() {
MOZ_ASSERT(!mObserved);
// Avoid notifying observers while we're in the dtor.
mIsBeingDestroyed = true;
@ -2238,49 +2232,6 @@ nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetRecordProfileTimelineMarkers(bool aValue) {
bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
if (currentValue == aValue) {
return NS_OK;
}
if (aValue) {
MOZ_ASSERT(!TimelineConsumers::HasConsumer(this));
TimelineConsumers::AddConsumer(this);
MOZ_ASSERT(TimelineConsumers::HasConsumer(this));
UseEntryScriptProfiling();
} else {
MOZ_ASSERT(TimelineConsumers::HasConsumer(this));
TimelineConsumers::RemoveConsumer(this);
MOZ_ASSERT(!TimelineConsumers::HasConsumer(this));
UnuseEntryScriptProfiling();
}
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue) {
*aValue = !!mObserved;
return NS_OK;
}
nsresult nsDocShell::PopProfileTimelineMarkers(
JSContext* aCx, JS::MutableHandle<JS::Value> aOut) {
nsTArray<dom::ProfileTimelineMarker> store;
SequenceRooter<dom::ProfileTimelineMarker> rooter(aCx, &store);
TimelineConsumers::PopMarkers(this, aCx, store);
if (!ToJSValue(aCx, store, aOut)) {
JS_ClearPendingException(aCx);
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
*aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
return NS_OK;
@ -4527,9 +4478,6 @@ nsDocShell::Destroy() {
// Brak the cycle with the initial client, if present.
mInitialClientSource.reset();
// Make sure we don't record profile timeline markers anymore
SetRecordProfileTimelineMarkers(false);
// Make sure to blow away our mLoadingURI just in case. No loads
// from inside this pagehide.
mLoadingURI = nullptr;
@ -13482,34 +13430,6 @@ bool nsDocShell::IsInvisible() { return mInvisible; }
void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
// The caller owns |aAsyncCause| here.
void nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
const nsAString& aFunctionName,
const nsAString& aFilename,
const uint32_t aLineNumber,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) {
// If first start, mark interval start.
if (mJSRunToCompletionDepth == 0 && TimelineConsumers::HasConsumer(this)) {
TimelineConsumers::AddMarkerForDocShell(
this, mozilla::MakeUnique<JavascriptTimelineMarker>(
aReason, aFunctionName, aFilename, aLineNumber,
MarkerTracingType::START, aAsyncStack, aAsyncCause));
}
mJSRunToCompletionDepth++;
}
void nsDocShell::NotifyJSRunToCompletionStop() {
mJSRunToCompletionDepth--;
// If last stop, mark interval end.
if (mJSRunToCompletionDepth == 0 && TimelineConsumers::HasConsumer(this)) {
TimelineConsumers::AddMarkerForDocShell(this, "Javascript",
MarkerTracingType::END);
}
}
/* static */
void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
const nsString& aKeyword) {

Просмотреть файл

@ -12,7 +12,6 @@
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "mozilla/ScrollbarPreferences.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/BrowsingContext.h"
@ -539,23 +538,6 @@ class nsDocShell final : public nsDocLoader,
friend class mozilla::net::DocumentLoadListener;
friend class nsGlobalWindowOuter;
// It is necessary to allow adding a timeline marker wherever a docshell
// instance is available. This operation happens frequently and needs to
// be very fast, so instead of using a Map or having to search for some
// docshell-specific markers storage, a pointer to an `ObservedDocShell` is
// is stored on docshells directly.
friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell*);
friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell*);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell*, const char*, MarkerTracingType, MarkerStackRequest);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell*, const char*, const TimeStamp&, MarkerTracingType,
MarkerStackRequest);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
friend void mozilla::TimelineConsumers::PopMarkers(
nsDocShell*, JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
nsDocShell(mozilla::dom::BrowsingContext* aBrowsingContext,
uint64_t aContentWindowID);
@ -1202,9 +1184,6 @@ class nsDocShell final : public nsDocLoader,
*/
nsCString mContentTypeHint;
// An observed docshell wrapper is created when recording markers is enabled.
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
// mCurrentURI should be marked immutable on set if possible.
// Change mCurrentURI only through SetCurrentURIInternal method.
nsCOMPtr<nsIURI> mCurrentURI;
@ -1293,10 +1272,6 @@ class nsDocShell final : public nsDocLoader,
uint32_t mLoadType;
uint32_t mFailedLoadType;
// A depth count of how many times NotifyRunToCompletionStart
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;
// Whether or not handling of the <meta name="viewport"> tag is overridden.
// Possible values are defined as constants in nsIDocShell.idl.
MetaViewportOverride mMetaViewportOverride;

Просмотреть файл

@ -478,11 +478,6 @@ interface nsIDocShell : nsIDocShellTreeItem
out int32_t parentCharsetSource,
out nsIPrincipal parentCharsetPrincipal);
/**
* Whether the docShell records profile timeline markers at the moment
*/
[infallible] attribute boolean recordProfileTimelineMarkers;
/**
* Return a DOMHighResTimeStamp representing the number of
* milliseconds from an arbitrary point in time. The reference
@ -491,12 +486,6 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
DOMHighResTimeStamp now();
/**
* Returns and flushes the profile timeline markers gathered by the docShell
*/
[implicit_jscontext]
jsval popProfileTimelineMarkers();
/**
* Add an observer to the list of parties to be notified when this docshell's
* private browsing status is changed. |obs| must support weak references.
@ -622,19 +611,6 @@ interface nsIDocShell : nsIDocShellTreeItem
[noscript,notxpcom,nostdcall] Document getExtantDocument();
/**
* 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(in string aReason,
in AString functionName,
in AString fileName,
in unsigned long lineNumber,
in jsval asyncStack,
in string asyncCause);
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStop();
/**
* This attribute determines whether a document which is not about:blank has
* already be loaded by this docShell.

Просмотреть файл

@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AbstractTimelineMarker.h"
#include "mozilla/TimeStamp.h"
#include "MainThreadUtils.h"
#include "nsAppRunner.h"
namespace mozilla {
AbstractTimelineMarker::AbstractTimelineMarker(const char* aName,
MarkerTracingType aTracingType)
: mName(aName),
mTracingType(aTracingType),
mProcessType(XRE_GetProcessType()),
mIsOffMainThread(!NS_IsMainThread()) {
MOZ_COUNT_CTOR(AbstractTimelineMarker);
SetCurrentTime();
}
AbstractTimelineMarker::AbstractTimelineMarker(const char* aName,
const TimeStamp& aTime,
MarkerTracingType aTracingType)
: mName(aName),
mTracingType(aTracingType),
mProcessType(XRE_GetProcessType()),
mIsOffMainThread(!NS_IsMainThread()) {
MOZ_COUNT_CTOR(AbstractTimelineMarker);
SetCustomTime(aTime);
}
UniquePtr<AbstractTimelineMarker> AbstractTimelineMarker::Clone() {
MOZ_ASSERT(false, "Clone method not yet implemented on this marker type.");
return nullptr;
}
bool AbstractTimelineMarker::Equals(const AbstractTimelineMarker& aOther) {
// Check whether two markers should be considered the same, for the purpose
// of pairing start and end markers. Normally this definition suffices.
return strcmp(mName, aOther.mName) == 0;
}
AbstractTimelineMarker::~AbstractTimelineMarker() {
MOZ_COUNT_DTOR(AbstractTimelineMarker);
}
void AbstractTimelineMarker::SetCurrentTime() {
TimeStamp now = TimeStamp::Now();
SetCustomTime(now);
}
void AbstractTimelineMarker::SetCustomTime(const TimeStamp& aTime) {
mTime = (aTime - TimeStamp::ProcessCreation()).ToMilliseconds();
}
void AbstractTimelineMarker::SetCustomTime(DOMHighResTimeStamp aTime) {
mTime = aTime;
}
void AbstractTimelineMarker::SetProcessType(GeckoProcessType aProcessType) {
mProcessType = aProcessType;
}
void AbstractTimelineMarker::SetOffMainThread(bool aIsOffMainThread) {
mIsOffMainThread = aIsOffMainThread;
}
} // namespace mozilla

Просмотреть файл

@ -1,71 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AbstractTimelineMarker_h_
#define mozilla_AbstractTimelineMarker_h_
#include "TimelineMarkerEnums.h" // for MarkerTracingType
#include "nsDOMNavigationTiming.h" // for DOMHighResTimeStamp
#include "nsXULAppAPI.h" // for GeckoProcessType
#include "mozilla/UniquePtr.h"
struct JSContext;
class JSObject;
namespace mozilla {
class TimeStamp;
namespace dom {
struct ProfileTimelineMarker;
}
class AbstractTimelineMarker {
private:
AbstractTimelineMarker() = delete;
AbstractTimelineMarker(const AbstractTimelineMarker& aOther) = delete;
void operator=(const AbstractTimelineMarker& aOther) = delete;
public:
AbstractTimelineMarker(const char* aName, MarkerTracingType aTracingType);
AbstractTimelineMarker(const char* aName, const TimeStamp& aTime,
MarkerTracingType aTracingType);
virtual ~AbstractTimelineMarker();
virtual UniquePtr<AbstractTimelineMarker> Clone();
virtual bool Equals(const AbstractTimelineMarker& aOther);
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) = 0;
virtual JSObject* GetStack() = 0;
const char* GetName() const { return mName; }
DOMHighResTimeStamp GetTime() const { return mTime; }
MarkerTracingType GetTracingType() const { return mTracingType; }
uint8_t GetProcessType() const { return mProcessType; };
bool IsOffMainThread() const { return mIsOffMainThread; };
private:
const char* mName;
DOMHighResTimeStamp mTime;
MarkerTracingType mTracingType;
uint8_t mProcessType; // @see `enum GeckoProcessType`.
bool mIsOffMainThread;
protected:
void SetCurrentTime();
void SetCustomTime(const TimeStamp& aTime);
void SetCustomTime(DOMHighResTimeStamp aTime);
void SetProcessType(GeckoProcessType aProcessType);
void SetOffMainThread(bool aIsOffMainThread);
};
} // namespace mozilla
#endif /* mozilla_AbstractTimelineMarker_h_ */

Просмотреть файл

@ -1,39 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AutoGlobalTimelineMarker.h"
#include "TimelineConsumers.h"
#include "MainThreadUtils.h"
namespace mozilla {
AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(
const char* aName, MarkerStackRequest aStackRequest /* = STACK */
)
: mName(aName), mStackRequest(aStackRequest) {
MOZ_ASSERT(NS_IsMainThread());
if (TimelineConsumers::IsEmpty()) {
return;
}
TimelineConsumers::AddMarkerForAllObservedDocShells(
mName, MarkerTracingType::START, mStackRequest);
}
AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker() {
MOZ_ASSERT(NS_IsMainThread());
if (TimelineConsumers::IsEmpty()) {
return;
}
TimelineConsumers::AddMarkerForAllObservedDocShells(
mName, MarkerTracingType::END, mStackRequest);
}
} // namespace mozilla

Просмотреть файл

@ -1,48 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AutoGlobalTimelineMarker_h_
#define mozilla_AutoGlobalTimelineMarker_h_
#include "mozilla/Attributes.h"
#include "TimelineMarkerEnums.h"
namespace mozilla {
// # AutoGlobalTimelineMarker
//
// Similar to `AutoTimelineMarker`, but adds its traced marker to all docshells,
// not a single particular one. This is useful for operations that aren't
// associated with any one particular doc shell, or when it isn't clear which
// docshell triggered the operation.
//
// Example usage:
//
// {
// AutoGlobalTimelineMarker marker("Cycle Collection");
// nsCycleCollector* cc = GetCycleCollector();
// cc->Collect();
// ...
// }
class MOZ_RAII AutoGlobalTimelineMarker {
// The name of the marker we are adding.
const char* mName;
// Whether to capture the JS stack or not.
MarkerStackRequest mStackRequest;
public:
explicit AutoGlobalTimelineMarker(
const char* aName,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
~AutoGlobalTimelineMarker();
AutoGlobalTimelineMarker(const AutoGlobalTimelineMarker& aOther) = delete;
void operator=(const AutoGlobalTimelineMarker& aOther) = delete;
};
} // namespace mozilla
#endif /* mozilla_AutoGlobalTimelineMarker_h_ */

Просмотреть файл

@ -1,51 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AutoRestyleTimelineMarker.h"
#include "TimelineConsumers.h"
#include "MainThreadUtils.h"
#include "nsIDocShell.h"
#include "RestyleTimelineMarker.h"
namespace mozilla {
AutoRestyleTimelineMarker::AutoRestyleTimelineMarker(nsIDocShell* aDocShell,
bool aIsAnimationOnly)
: mDocShell(nullptr), mIsAnimationOnly(aIsAnimationOnly) {
MOZ_ASSERT(NS_IsMainThread());
if (!aDocShell) {
return;
}
if (!TimelineConsumers::HasConsumer(aDocShell)) {
return;
}
mDocShell = aDocShell;
TimelineConsumers::AddMarkerForDocShell(
mDocShell, MakeUnique<RestyleTimelineMarker>(mIsAnimationOnly,
MarkerTracingType::START));
}
AutoRestyleTimelineMarker::~AutoRestyleTimelineMarker() {
MOZ_ASSERT(NS_IsMainThread());
if (!mDocShell) {
return;
}
if (!TimelineConsumers::HasConsumer(mDocShell)) {
return;
}
TimelineConsumers::AddMarkerForDocShell(
mDocShell, MakeUnique<RestyleTimelineMarker>(mIsAnimationOnly,
MarkerTracingType::END));
}
} // namespace mozilla

Просмотреть файл

@ -1,30 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AutoRestyleTimelineMarker_h_
#define mozilla_AutoRestyleTimelineMarker_h_
#include "mozilla/RefPtr.h"
class nsIDocShell;
namespace mozilla {
class MOZ_RAII AutoRestyleTimelineMarker {
RefPtr<nsIDocShell> mDocShell;
bool mIsAnimationOnly;
public:
AutoRestyleTimelineMarker(nsIDocShell* aDocShell, bool aIsAnimationOnly);
~AutoRestyleTimelineMarker();
AutoRestyleTimelineMarker(const AutoRestyleTimelineMarker& aOther) = delete;
void operator=(const AutoRestyleTimelineMarker& aOther) = delete;
};
} // namespace mozilla
#endif /* mozilla_AutoRestyleTimelineMarker_h_ */

Просмотреть файл

@ -1,48 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AutoTimelineMarker.h"
#include "nsIDocShell.h"
#include "TimelineConsumers.h"
#include "MainThreadUtils.h"
namespace mozilla {
AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell,
const char* aName)
: mName(aName), mDocShell(nullptr) {
MOZ_ASSERT(NS_IsMainThread());
if (!aDocShell) {
return;
}
if (!TimelineConsumers::HasConsumer(aDocShell)) {
return;
}
mDocShell = aDocShell;
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName,
MarkerTracingType::START);
}
AutoTimelineMarker::~AutoTimelineMarker() {
MOZ_ASSERT(NS_IsMainThread());
if (!mDocShell) {
return;
}
if (!TimelineConsumers::HasConsumer(mDocShell)) {
return;
}
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName,
MarkerTracingType::END);
}
} // namespace mozilla

Просмотреть файл

@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AutoTimelineMarker_h_
#define mozilla_AutoTimelineMarker_h_
#include "mozilla/RefPtr.h"
class nsIDocShell;
namespace mozilla {
// # AutoTimelineMarker
//
// An RAII class to trace some task in the platform by adding a start and end
// timeline marker pair. These markers are then rendered in the devtools'
// performance tool's waterfall graph.
//
// Example usage:
//
// {
// AutoTimelineMarker marker(mDocShell, "Parse CSS");
// nsresult rv = ParseTheCSSFile(mFile);
// ...
// }
class MOZ_RAII AutoTimelineMarker {
// The name of the marker we are adding.
const char* mName;
// The docshell that is associated with this marker.
RefPtr<nsIDocShell> mDocShell;
public:
AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName);
~AutoTimelineMarker();
AutoTimelineMarker(const AutoTimelineMarker& aOther) = delete;
void operator=(const AutoTimelineMarker& aOther) = delete;
};
} // namespace mozilla
#endif /* mozilla_AutoTimelineMarker_h_ */

Просмотреть файл

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_CompositeTimelineMarker_h_
#define mozilla_CompositeTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class CompositeTimelineMarker : public TimelineMarker {
public:
CompositeTimelineMarker(const TimeStamp& aTime,
MarkerTracingType aTracingType)
: TimelineMarker("Composite", aTime, aTracingType) {
// Even though these markers end up being created on the main thread in the
// content or chrome processes, they actually trace down code in the
// compositor parent process. All the information for creating these markers
// is sent along via IPC to an nsView when a composite finishes.
// Mark this as 'off the main thread' to style it differently in frontends.
SetOffMainThread(true);
}
};
} // namespace mozilla
#endif // mozilla_CompositeTimelineMarker_h_

Просмотреть файл

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ConsoleTimelineMarker_h_
#define mozilla_ConsoleTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class ConsoleTimelineMarker : public TimelineMarker {
public:
ConsoleTimelineMarker(const nsAString& aCause, MarkerTracingType aTracingType)
: TimelineMarker("ConsoleTime", aTracingType), mCause(aCause) {
// Stack is captured by default on the "start" marker. Explicitly also
// capture stack on the "end" marker.
if (aTracingType == MarkerTracingType::END) {
CaptureStack();
}
}
virtual bool Equals(const AbstractTimelineMarker& aOther) override {
if (!TimelineMarker::Equals(aOther)) {
return false;
}
// Console markers must have matching causes as well. It is safe to perform
// a static_cast here as the previous equality check ensures that this is
// a console marker instance.
return mCause == static_cast<const ConsoleTimelineMarker*>(&aOther)->mCause;
}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (GetTracingType() == MarkerTracingType::START) {
aMarker.mCauseName.Construct(mCause);
} else {
aMarker.mEndStack = GetStack();
}
}
private:
nsString mCause;
};
} // namespace mozilla
#endif // mozilla_ConsoleTimelineMarker_h_

Просмотреть файл

@ -1,38 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_DocLoadingTimelineMarker_h_
#define mozilla_DocLoadingTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class DocLoadingTimelineMarker : public TimelineMarker {
public:
explicit DocLoadingTimelineMarker(const char* aName)
: TimelineMarker(aName, MarkerTracingType::TIMESTAMP),
mUnixTime(PR_Now()) {}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
aMarker.mUnixTime.Construct(mUnixTime);
}
private:
// Certain consumers might use Date.now() or similar for tracing time.
// However, TimelineMarkers use process creation as an epoch, which provides
// more precision. To allow syncing, attach an additional unix timestamp.
// Using this instead of `AbstractTimelineMarker::GetTime()'s` timestamp
// is strongly discouraged.
PRTime mUnixTime;
};
} // namespace mozilla
#endif // mozilla_DocLoadingTimelineMarker_h_

Просмотреть файл

@ -1,40 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_EventTimelineMarker_h_
#define mozilla_EventTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class EventTimelineMarker : public TimelineMarker {
public:
EventTimelineMarker(const nsAString& aType, uint16_t aPhase,
MarkerTracingType aTracingType)
: TimelineMarker("DOMEvent", aTracingType),
mType(aType),
mPhase(aPhase) {}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (GetTracingType() == MarkerTracingType::START) {
aMarker.mType.Construct(mType);
aMarker.mEventPhase.Construct(mPhase);
}
}
private:
nsString mType;
uint16_t mPhase;
};
} // namespace mozilla
#endif // mozilla_EventTimelineMarker_h_

Просмотреть файл

@ -1,96 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_JavascriptTimelineMarker_h_
#define mozilla_JavascriptTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/ToJSValue.h"
namespace mozilla {
class JavascriptTimelineMarker : public TimelineMarker {
public:
// The caller owns |aAsyncCause| here, so we must copy it into a separate
// string for use later on.
JavascriptTimelineMarker(const char* aReason, const nsAString& aFunctionName,
const nsAString& aFileName, uint32_t aLineNumber,
MarkerTracingType aTracingType,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause)
: TimelineMarker("Javascript", aTracingType,
MarkerStackRequest::NO_STACK),
mCause(NS_ConvertUTF8toUTF16(aReason)),
mFunctionName(aFunctionName),
mFileName(aFileName),
mLineNumber(aLineNumber),
mAsyncCause(aAsyncCause) {
JSContext* ctx = nsContentUtils::GetCurrentJSContext();
if (ctx) {
mAsyncStack.init(ctx, aAsyncStack);
}
}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
aMarker.mCauseName.Construct(mCause);
if (!mFunctionName.IsEmpty() || !mFileName.IsEmpty()) {
dom::RootedDictionary<dom::ProfileTimelineStackFrame> stackFrame(aCx);
stackFrame.mLine.Construct(mLineNumber);
stackFrame.mSource.Construct(mFileName);
stackFrame.mFunctionDisplayName.Construct(mFunctionName);
if (mAsyncStack.isObject() && !mAsyncCause.IsEmpty()) {
JS::Rooted<JSObject*> asyncStack(aCx, &mAsyncStack.toObject());
JS::Rooted<JSObject*> parentFrame(aCx);
JS::Rooted<JSString*> asyncCause(
aCx, JS_NewUCStringCopyN(aCx, mAsyncCause.BeginReading(),
mAsyncCause.Length()));
if (!asyncCause) {
JS_ClearPendingException(aCx);
return;
}
if (JS::IsMaybeWrappedSavedFrame(asyncStack) &&
!JS::CopyAsyncStack(aCx, asyncStack, asyncCause, &parentFrame,
mozilla::Nothing())) {
JS_ClearPendingException(aCx);
} else {
stackFrame.mAsyncParent = parentFrame;
}
}
JS::Rooted<JS::Value> newStack(aCx);
if (ToJSValue(aCx, stackFrame, &newStack)) {
if (newStack.isObject()) {
aMarker.mStack = &newStack.toObject();
}
} else {
JS_ClearPendingException(aCx);
}
}
}
private:
nsString mCause;
nsString mFunctionName;
nsString mFileName;
uint32_t mLineNumber;
JS::PersistentRooted<JS::Value> mAsyncStack;
NS_ConvertUTF8toUTF16 mAsyncCause;
};
} // namespace mozilla
#endif // mozilla_JavascriptTimelineMarker_h_

Просмотреть файл

@ -1,47 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_LayerTimelineMarker_h_
#define mozilla_LayerTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/mozalloc_oom.h"
#include "nsRegion.h"
namespace mozilla {
class LayerTimelineMarker : public TimelineMarker {
public:
explicit LayerTimelineMarker(const nsIntRegion& aRegion)
: TimelineMarker("Layer", MarkerTracingType::HELPER_EVENT),
mRegion(aRegion) {}
void AddLayerRectangles(
dom::Sequence<dom::ProfileTimelineLayerRect>& aRectangles) {
for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
const nsIntRect& iterRect = iter.Get();
dom::ProfileTimelineLayerRect rect;
rect.mX = iterRect.X();
rect.mY = iterRect.Y();
rect.mWidth = iterRect.Width();
rect.mHeight = iterRect.Height();
if (!aRectangles.AppendElement(rect, fallible)) {
// XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
// involve multiple reallocations) and potentially crashing here,
// SetCapacity could be called outside the loop once.
mozalloc_handle_oom(0);
}
}
}
private:
nsIntRegion mRegion;
};
} // namespace mozilla
#endif // mozilla_LayerTimelineMarker_h_

Просмотреть файл

@ -1,40 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_MarkersStorage_h_
#define mozilla_MarkersStorage_h_
#include "TimelineMarkerEnums.h" // for MarkerReleaseRequest
#include "MainThreadUtils.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/LinkedList.h"
#include "nsTArray.h"
namespace mozilla {
class AbstractTimelineMarker;
namespace dom {
struct ProfileTimelineMarker;
}
class MarkersStorage : public LinkedListElement<MarkersStorage> {
public:
MarkersStorage() { MOZ_ASSERT(NS_IsMainThread()); }
virtual ~MarkersStorage() { MOZ_ASSERT(NS_IsMainThread()); }
MarkersStorage(const MarkersStorage& aOther) = delete;
void operator=(const MarkersStorage& aOther) = delete;
virtual void AddMarker(UniquePtr<AbstractTimelineMarker>&& aMarker) = 0;
virtual void AddOTMTMarker(UniquePtr<AbstractTimelineMarker>&& aMarker) = 0;
virtual void ClearMarkers() = 0;
virtual void PopMarkers(JSContext* aCx,
nsTArray<dom::ProfileTimelineMarker>& aStore) = 0;
};
} // namespace mozilla
#endif /* mozilla_MarkersStorage_h_ */

Просмотреть файл

@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_MessagePortTimelineMarker_h_
#define mozilla_MessagePortTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class MessagePortTimelineMarker : public TimelineMarker {
public:
MessagePortTimelineMarker(
dom::ProfileTimelineMessagePortOperationType aOperationType,
MarkerTracingType aTracingType)
: TimelineMarker("MessagePort", aTracingType,
MarkerStackRequest::NO_STACK),
mOperationType(aOperationType) {}
virtual UniquePtr<AbstractTimelineMarker> Clone() override {
MessagePortTimelineMarker* clone =
new MessagePortTimelineMarker(mOperationType, GetTracingType());
clone->SetCustomTime(GetTime());
return UniquePtr<AbstractTimelineMarker>(clone);
}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (GetTracingType() == MarkerTracingType::START) {
aMarker.mMessagePortOperation.Construct(mOperationType);
}
}
private:
dom::ProfileTimelineMessagePortOperationType mOperationType;
};
} // namespace mozilla
#endif /* mozilla_MessagePortTimelineMarker_h_ */

Просмотреть файл

@ -1,171 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ObservedDocShell.h"
#include <utility>
#include "AbstractTimelineMarker.h"
#include "LayerTimelineMarker.h"
#include "MainThreadUtils.h"
#include "mozilla/AutoRestore.h"
#include "nsIDocShell.h"
namespace mozilla {
ObservedDocShell::ObservedDocShell(nsIDocShell* aDocShell)
: mDocShell(aDocShell), mLock("ObservedDocShellMutex") {
MOZ_ASSERT(NS_IsMainThread());
}
void ObservedDocShell::AddMarker(UniquePtr<AbstractTimelineMarker>&& aMarker) {
// Only allow main thread markers to go into this list. No need to lock
// here since `mTimelineMarkers` will only be accessed or modified on the
// main thread only.
MOZ_ASSERT(NS_IsMainThread());
// Don't accept any markers generated by the process of popping
// markers.
if (!mPopping) {
mTimelineMarkers.AppendElement(std::move(aMarker));
}
}
void ObservedDocShell::AddOTMTMarker(
UniquePtr<AbstractTimelineMarker>&& aMarker) {
// Only allow off the main thread markers to go into this list. Since most
// of our markers come from the main thread, be a little more efficient and
// avoid dealing with multithreading scenarios until all the markers are
// actually cleared or popped in `ClearMarkers` or `PopMarkers`.
MOZ_ASSERT(!NS_IsMainThread());
MutexAutoLock lock(mLock); // for `mOffTheMainThreadTimelineMarkers`.
mOffTheMainThreadTimelineMarkers.AppendElement(std::move(aMarker));
}
void ObservedDocShell::ClearMarkers() {
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mLock); // for `mOffTheMainThreadTimelineMarkers`.
mTimelineMarkers.Clear();
mOffTheMainThreadTimelineMarkers.Clear();
}
void ObservedDocShell::PopMarkers(
JSContext* aCx, nsTArray<dom::ProfileTimelineMarker>& aStore) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(!mPopping);
AutoRestore<bool> resetPopping(mPopping);
mPopping = true;
{
MutexAutoLock lock(mLock); // for `mOffTheMainThreadTimelineMarkers`.
// First, move all of our markers into a single array. We'll chose
// the `mTimelineMarkers` store because that's where we expect most of
// our markers to be, and we can access it without holding the lock.
mTimelineMarkers.AppendElements(
std::move(mOffTheMainThreadTimelineMarkers));
}
// If we see an unpaired START, we keep it around for the next call
// to ObservedDocShell::PopMarkers. We store the kept START objects here.
nsTArray<UniquePtr<AbstractTimelineMarker>> keptStartMarkers;
for (uint32_t i = 0; i < mTimelineMarkers.Length(); ++i) {
UniquePtr<AbstractTimelineMarker>& startPayload =
mTimelineMarkers.ElementAt(i);
// If this is a TIMESTAMP marker, there's no corresponding END,
// as it's a single unit of time, not a duration.
if (startPayload->GetTracingType() == MarkerTracingType::TIMESTAMP) {
dom::ProfileTimelineMarker* marker = aStore.AppendElement();
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = startPayload->GetTime();
marker->mStack = startPayload->GetStack();
startPayload->AddDetails(aCx, *marker);
continue;
}
// Whenever a START marker is found, look for the corresponding END
// and build a {name,start,end} JS object.
if (startPayload->GetTracingType() == MarkerTracingType::START) {
bool hasSeenEnd = false;
// "Paint" markers are different because painting is handled at root
// docshell level. The information that a paint was done is stored at
// sub-docshell level, but we can only be sure that a paint did actually
// happen in if a "Layer" marker was recorded too.
bool startIsPaintType = strcmp(startPayload->GetName(), "Paint") == 0;
bool hasSeenLayerType = false;
// If we are processing a "Paint" marker, we append information from
// all the embedded "Layer" markers to this array.
dom::Sequence<dom::ProfileTimelineLayerRect> layerRectangles;
// DOM events can be nested, so we must take care when searching
// for the matching end. It doesn't hurt to apply this logic to
// all event types.
uint32_t markerDepth = 0;
// The assumption is that the devtools timeline flushes markers frequently
// enough for the amount of markers to always be small enough that the
// nested for loop isn't going to be a performance problem.
for (uint32_t j = i + 1; j < mTimelineMarkers.Length(); ++j) {
UniquePtr<AbstractTimelineMarker>& endPayload =
mTimelineMarkers.ElementAt(j);
bool endIsLayerType = strcmp(endPayload->GetName(), "Layer") == 0;
// Look for "Layer" markers to stream out "Paint" markers.
if (startIsPaintType && endIsLayerType) {
AbstractTimelineMarker* raw = endPayload.get();
LayerTimelineMarker* layerPayload =
static_cast<LayerTimelineMarker*>(raw);
layerPayload->AddLayerRectangles(layerRectangles);
hasSeenLayerType = true;
}
if (!startPayload->Equals(*endPayload)) {
continue;
}
if (endPayload->GetTracingType() == MarkerTracingType::START) {
++markerDepth;
continue;
}
if (endPayload->GetTracingType() == MarkerTracingType::END) {
if (markerDepth > 0) {
--markerDepth;
continue;
}
if (!startIsPaintType || (startIsPaintType && hasSeenLayerType)) {
dom::ProfileTimelineMarker* marker = aStore.AppendElement();
marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName());
marker->mStart = startPayload->GetTime();
marker->mEnd = endPayload->GetTime();
marker->mStack = startPayload->GetStack();
if (hasSeenLayerType) {
marker->mRectangles.Construct(layerRectangles);
}
startPayload->AddDetails(aCx, *marker);
endPayload->AddDetails(aCx, *marker);
}
hasSeenEnd = true;
break;
}
}
// If we did not see the corresponding END, keep the START.
if (!hasSeenEnd) {
keptStartMarkers.AppendElement(
std::move(mTimelineMarkers.ElementAt(i)));
mTimelineMarkers.RemoveElementAt(i);
--i;
}
}
}
mTimelineMarkers = std::move(keptStartMarkers);
}
} // namespace mozilla

Просмотреть файл

@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ObservedDocShell_h_
#define mozilla_ObservedDocShell_h_
#include "MarkersStorage.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
#include "nsTArray.h"
class nsIDocShell;
namespace mozilla {
class AbstractTimelineMarker;
namespace dom {
struct ProfileTimelineMarker;
}
// # ObservedDocShell
//
// A wrapper around a docshell for which docshell-specific markers are
// allowed to exist. See TimelineConsumers for register/unregister logic.
class ObservedDocShell : public MarkersStorage {
private:
RefPtr<nsIDocShell> mDocShell;
// Main thread only.
nsTArray<UniquePtr<AbstractTimelineMarker>> mTimelineMarkers;
bool mPopping = false;
// Off the main thread only.
Mutex mLock;
nsTArray<UniquePtr<AbstractTimelineMarker>> mOffTheMainThreadTimelineMarkers
MOZ_GUARDED_BY(mLock);
public:
explicit ObservedDocShell(nsIDocShell* aDocShell);
nsIDocShell* operator*() const { return mDocShell.get(); }
void AddMarker(UniquePtr<AbstractTimelineMarker>&& aMarker) override;
void AddOTMTMarker(UniquePtr<AbstractTimelineMarker>&& aMarker) override;
void ClearMarkers() override;
void PopMarkers(JSContext* aCx,
nsTArray<dom::ProfileTimelineMarker>& aStore) override;
};
} // namespace mozilla
#endif /* mozilla_ObservedDocShell_h_ */

Просмотреть файл

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_RestyleTimelineMarker_h_
#define mozilla_RestyleTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class RestyleTimelineMarker : public TimelineMarker {
public:
RestyleTimelineMarker(bool aIsAnimationOnly, MarkerTracingType aTracingType)
: TimelineMarker("Styles", aTracingType) {
mIsAnimationOnly = aIsAnimationOnly;
}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (GetTracingType() == MarkerTracingType::START) {
aMarker.mIsAnimationOnly.Construct(mIsAnimationOnly);
}
}
private:
bool mIsAnimationOnly;
};
} // namespace mozilla
#endif // mozilla_RestyleTimelineMarker_h_

Просмотреть файл

@ -1,202 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TimelineConsumers.h"
#include "mozilla/ObservedDocShell.h"
#include "mozilla/TimelineMarker.h"
#include "jsapi.h"
#include "nsAppRunner.h" // for XRE_IsContentProcess, XRE_IsParentProcess
#include "nsCRT.h"
#include "nsDocShell.h"
namespace mozilla {
StaticMutex TimelineConsumers::sMutex;
uint32_t TimelineConsumers::sActiveConsumers = 0;
StaticAutoPtr<LinkedList<MarkersStorage>> TimelineConsumers::sMarkersStores;
LinkedList<MarkersStorage>& TimelineConsumers::MarkersStores() {
if (!sMarkersStores) {
sMarkersStores = new LinkedList<MarkersStorage>;
}
return *sMarkersStores;
}
void TimelineConsumers::AddConsumer(nsDocShell* aDocShell) {
MOZ_ASSERT(NS_IsMainThread());
StaticMutexAutoLock lock(
sMutex); // for `sActiveConsumers` and `sMarkersStores`.
UniquePtr<ObservedDocShell>& observed = aDocShell->mObserved;
MOZ_ASSERT(!observed);
if (sActiveConsumers == 0) {
JS::SetProfileTimelineRecordingEnabled(true);
}
sActiveConsumers++;
ObservedDocShell* obsDocShell = new ObservedDocShell(aDocShell);
MarkersStorage* storage = static_cast<MarkersStorage*>(obsDocShell);
observed.reset(obsDocShell);
MarkersStores().insertFront(storage);
}
void TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell) {
MOZ_ASSERT(NS_IsMainThread());
StaticMutexAutoLock lock(
sMutex); // for `sActiveConsumers` and `sMarkersStores`.
UniquePtr<ObservedDocShell>& observed = aDocShell->mObserved;
MOZ_ASSERT(observed);
sActiveConsumers--;
if (sActiveConsumers == 0) {
JS::SetProfileTimelineRecordingEnabled(false);
}
// Clear all markers from the `mTimelineMarkers` store.
observed->ClearMarkers();
// Remove self from the `sMarkersStores` store.
observed->remove();
// Prepare for becoming a consumer later.
observed.reset(nullptr);
}
bool TimelineConsumers::HasConsumer(nsIDocShell* aDocShell) {
MOZ_ASSERT(NS_IsMainThread());
return aDocShell ? aDocShell->GetRecordProfileTimelineMarkers() : false;
}
bool TimelineConsumers::IsEmpty() {
StaticMutexAutoLock lock(sMutex); // for `sActiveConsumers`.
return sActiveConsumers == 0;
}
void TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
const char* aName,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest) {
MOZ_ASSERT(NS_IsMainThread());
if (HasConsumer(aDocShell)) {
aDocShell->mObserved->AddMarker(
MakeUnique<TimelineMarker>(aName, aTracingType, aStackRequest));
}
}
void TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
const char* aName,
const TimeStamp& aTime,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest) {
MOZ_ASSERT(NS_IsMainThread());
if (HasConsumer(aDocShell)) {
aDocShell->mObserved->AddMarker(
MakeUnique<TimelineMarker>(aName, aTime, aTracingType, aStackRequest));
}
}
void TimelineConsumers::AddMarkerForDocShell(
nsDocShell* aDocShell, UniquePtr<AbstractTimelineMarker>&& aMarker) {
MOZ_ASSERT(NS_IsMainThread());
if (HasConsumer(aDocShell)) {
aDocShell->mObserved->AddMarker(std::move(aMarker));
}
}
void TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
const char* aName,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest) {
MOZ_ASSERT(NS_IsMainThread());
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTracingType,
aStackRequest);
}
void TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
const char* aName,
const TimeStamp& aTime,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest) {
MOZ_ASSERT(NS_IsMainThread());
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTime,
aTracingType, aStackRequest);
}
void TimelineConsumers::AddMarkerForDocShell(
nsIDocShell* aDocShell, UniquePtr<AbstractTimelineMarker>&& aMarker) {
MOZ_ASSERT(NS_IsMainThread());
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), std::move(aMarker));
}
void TimelineConsumers::AddMarkerForAllObservedDocShells(
const char* aName, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest /* = STACK */) {
bool isMainThread = NS_IsMainThread();
StaticMutexAutoLock lock(sMutex); // for `sMarkersStores`.
for (MarkersStorage* storage = MarkersStores().getFirst(); storage != nullptr;
storage = storage->getNext()) {
UniquePtr<AbstractTimelineMarker> marker =
MakeUnique<TimelineMarker>(aName, aTracingType, aStackRequest);
if (isMainThread) {
storage->AddMarker(std::move(marker));
} else {
storage->AddOTMTMarker(std::move(marker));
}
}
}
void TimelineConsumers::AddMarkerForAllObservedDocShells(
const char* aName, const TimeStamp& aTime, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest /* = STACK */) {
bool isMainThread = NS_IsMainThread();
StaticMutexAutoLock lock(sMutex); // for `sMarkersStores`.
for (MarkersStorage* storage = MarkersStores().getFirst(); storage != nullptr;
storage = storage->getNext()) {
UniquePtr<AbstractTimelineMarker> marker =
MakeUnique<TimelineMarker>(aName, aTime, aTracingType, aStackRequest);
if (isMainThread) {
storage->AddMarker(std::move(marker));
} else {
storage->AddOTMTMarker(std::move(marker));
}
}
}
void TimelineConsumers::AddMarkerForAllObservedDocShells(
UniquePtr<AbstractTimelineMarker>& aMarker) {
bool isMainThread = NS_IsMainThread();
StaticMutexAutoLock lock(sMutex); // for `sMarkersStores`.
for (MarkersStorage* storage = MarkersStores().getFirst(); storage != nullptr;
storage = storage->getNext()) {
UniquePtr<AbstractTimelineMarker> clone = aMarker->Clone();
if (isMainThread) {
storage->AddMarker(std::move(clone));
} else {
storage->AddOTMTMarker(std::move(clone));
}
}
}
void TimelineConsumers::PopMarkers(
nsDocShell* aDocShell, JSContext* aCx,
nsTArray<dom::ProfileTimelineMarker>& aStore) {
MOZ_ASSERT(NS_IsMainThread());
if (!aDocShell || !aDocShell->mObserved) {
return;
}
aDocShell->mObserved->PopMarkers(aCx, aStore);
}
} // namespace mozilla

Просмотреть файл

@ -1,113 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_TimelineConsumers_h_
#define mozilla_TimelineConsumers_h_
#include "nsIObserver.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/LinkedList.h"
#include "mozilla/StaticMutex.h"
#include "nsTArray.h"
#include "TimelineMarkerEnums.h" // for MarkerTracingType
class nsDocShell;
class nsIDocShell;
struct JSContext;
namespace mozilla {
class TimeStamp;
class MarkersStorage;
class AbstractTimelineMarker;
namespace dom {
struct ProfileTimelineMarker;
}
class TimelineConsumers {
public:
// Methods for registering interested consumers (i.e. "devtools toolboxes").
// Each consumer should be directly focused on a particular docshell, but
// timeline markers don't necessarily have to be tied to that docshell.
// See the public `AddMarker*` methods below.
// Main thread only.
static void AddConsumer(nsDocShell* aDocShell);
static void RemoveConsumer(nsDocShell* aDocShell);
static bool HasConsumer(nsIDocShell* aDocShell);
// Checks if there's any existing interested consumer.
// May be called from any thread.
static bool IsEmpty();
// Methods for adding markers relevant for particular docshells, or generic
// (meaning that they either can't be tied to a particular docshell, or one
// wasn't accessible in the part of the codebase where they're instantiated).
// These will only add markers if at least one docshell is currently being
// observed by a timeline. Markers tied to a particular docshell won't be
// created unless that docshell is specifically being currently observed.
// See nsIDocShell::recordProfileTimelineMarkers
// These methods create a basic TimelineMarker from a name and some metadata,
// relevant for a specific docshell.
// Main thread only.
static void AddMarkerForDocShell(
nsDocShell* aDocShell, const char* aName, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
static void AddMarkerForDocShell(
nsIDocShell* aDocShell, const char* aName, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
static void AddMarkerForDocShell(
nsDocShell* aDocShell, const char* aName, const TimeStamp& aTime,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
static void AddMarkerForDocShell(
nsIDocShell* aDocShell, const char* aName, const TimeStamp& aTime,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
// These methods register and receive ownership of an already created marker,
// relevant for a specific docshell.
// Main thread only.
static void AddMarkerForDocShell(nsDocShell* aDocShell,
UniquePtr<AbstractTimelineMarker>&& aMarker);
static void AddMarkerForDocShell(nsIDocShell* aDocShell,
UniquePtr<AbstractTimelineMarker>&& aMarker);
// These methods create a basic marker from a name and some metadata,
// which doesn't have to be relevant to a specific docshell.
// May be called from any thread.
static void AddMarkerForAllObservedDocShells(
const char* aName, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
static void AddMarkerForAllObservedDocShells(
const char* aName, const TimeStamp& aTime, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
// This method clones and registers an already instantiated marker,
// which doesn't have to be relevant to a specific docshell.
// May be called from any thread.
static void AddMarkerForAllObservedDocShells(
UniquePtr<AbstractTimelineMarker>& aMarker);
static void PopMarkers(nsDocShell* aDocShell, JSContext* aCx,
nsTArray<dom::ProfileTimelineMarker>& aStore);
private:
static StaticMutex sMutex;
static LinkedList<MarkersStorage>& MarkersStores() MOZ_REQUIRES(sMutex);
static uint32_t sActiveConsumers MOZ_GUARDED_BY(sMutex);
static StaticAutoPtr<LinkedList<MarkersStorage>> sMarkersStores
MOZ_GUARDED_BY(sMutex);
};
} // namespace mozilla
#endif /* mozilla_TimelineConsumers_h_ */

Просмотреть файл

@ -1,66 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TimelineMarker.h"
#include "jsapi.h"
#include "js/Exception.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "nsContentUtils.h"
namespace mozilla {
TimelineMarker::TimelineMarker(const char* aName,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest)
: AbstractTimelineMarker(aName, aTracingType) {
CaptureStackIfNecessary(aTracingType, aStackRequest);
}
TimelineMarker::TimelineMarker(const char* aName, const TimeStamp& aTime,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest)
: AbstractTimelineMarker(aName, aTime, aTracingType) {
CaptureStackIfNecessary(aTracingType, aStackRequest);
}
void TimelineMarker::AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) {
if (GetTracingType() == MarkerTracingType::START) {
aMarker.mProcessType.Construct(GetProcessType());
aMarker.mIsOffMainThread.Construct(IsOffMainThread());
}
}
JSObject* TimelineMarker::GetStack() {
if (mStackTrace.initialized()) {
return mStackTrace;
}
return nullptr;
}
void TimelineMarker::CaptureStack() {
JSContext* ctx = nsContentUtils::GetCurrentJSContext();
if (ctx) {
JS::Rooted<JSObject*> stack(ctx);
if (JS::CaptureCurrentStack(ctx, &stack)) {
mStackTrace.init(ctx, stack.get());
} else {
JS_ClearPendingException(ctx);
}
}
}
void TimelineMarker::CaptureStackIfNecessary(MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest) {
if ((aTracingType == MarkerTracingType::START ||
aTracingType == MarkerTracingType::TIMESTAMP) &&
aStackRequest != MarkerStackRequest::NO_STACK) {
CaptureStack();
}
}
} // namespace mozilla

Просмотреть файл

@ -1,47 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_TimelineMarker_h_
#define mozilla_TimelineMarker_h_
#include "AbstractTimelineMarker.h"
#include "js/RootingAPI.h"
namespace mozilla {
// Objects of this type can be added to the timeline if there is an interested
// consumer. The class can also be subclassed to let a given marker creator
// provide custom details.
class TimelineMarker : public AbstractTimelineMarker {
public:
TimelineMarker(const char* aName, MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
TimelineMarker(const char* aName, const TimeStamp& aTime,
MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override;
virtual JSObject* GetStack() override;
protected:
void CaptureStack();
private:
// While normally it is not a good idea to make a persistent root,
// in this case changing nsDocShell to participate in cycle
// collection was deemed too invasive, and the markers are only held
// here temporarily to boot.
JS::PersistentRooted<JSObject*> mStackTrace;
void CaptureStackIfNecessary(MarkerTracingType aTracingType,
MarkerStackRequest aStackRequest);
};
} // namespace mozilla
#endif /* mozilla_TimelineMarker_h_ */

Просмотреть файл

@ -1,18 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_TimelineMarkerEnums_h_
#define mozilla_TimelineMarkerEnums_h_
namespace mozilla {
enum class MarkerTracingType { START, END, TIMESTAMP, HELPER_EVENT };
enum class MarkerStackRequest { STACK, NO_STACK };
} // namespace mozilla
#endif // mozilla_TimelineMarkerEnums_h_

Просмотреть файл

@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_TimestampTimelineMarker_h_
#define mozilla_TimestampTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class TimestampTimelineMarker : public TimelineMarker {
public:
explicit TimestampTimelineMarker(const nsAString& aCause)
: TimelineMarker("TimeStamp", MarkerTracingType::TIMESTAMP),
mCause(aCause) {}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (!mCause.IsEmpty()) {
aMarker.mCauseName.Construct(mCause);
}
}
private:
nsString mCause;
};
} // namespace mozilla
#endif // mozilla_TimestampTimelineMarker_h_

Просмотреть файл

@ -1,44 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_WorkerTimelineMarker_h_
#define mozilla_WorkerTimelineMarker_h_
#include "TimelineMarker.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
namespace mozilla {
class WorkerTimelineMarker : public TimelineMarker {
public:
WorkerTimelineMarker(dom::ProfileTimelineWorkerOperationType aOperationType,
MarkerTracingType aTracingType)
: TimelineMarker("Worker", aTracingType, MarkerStackRequest::NO_STACK),
mOperationType(aOperationType) {}
virtual UniquePtr<AbstractTimelineMarker> Clone() override {
WorkerTimelineMarker* clone =
new WorkerTimelineMarker(mOperationType, GetTracingType());
clone->SetCustomTime(GetTime());
return UniquePtr<AbstractTimelineMarker>(clone);
}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (GetTracingType() == MarkerTracingType::START) {
aMarker.mWorkerOperation.Construct(mOperationType);
}
}
private:
dom::ProfileTimelineWorkerOperationType mOperationType;
};
} // namespace mozilla
#endif /* mozilla_WorkerTimelineMarker_h_ */

Просмотреть файл

@ -1,44 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
with Files("**"):
BUG_COMPONENT = ("DevTools", "Performance Tools (Profiler/Timeline)")
EXPORTS.mozilla += [
"AbstractTimelineMarker.h",
"AutoGlobalTimelineMarker.h",
"AutoRestyleTimelineMarker.h",
"AutoTimelineMarker.h",
"CompositeTimelineMarker.h",
"ConsoleTimelineMarker.h",
"DocLoadingTimelineMarker.h",
"EventTimelineMarker.h",
"JavascriptTimelineMarker.h",
"LayerTimelineMarker.h",
"MarkersStorage.h",
"MessagePortTimelineMarker.h",
"ObservedDocShell.h",
"RestyleTimelineMarker.h",
"TimelineConsumers.h",
"TimelineMarker.h",
"TimelineMarkerEnums.h",
"TimestampTimelineMarker.h",
"WorkerTimelineMarker.h",
]
UNIFIED_SOURCES += [
"AbstractTimelineMarker.cpp",
"AutoGlobalTimelineMarker.cpp",
"AutoRestyleTimelineMarker.cpp",
"AutoTimelineMarker.cpp",
"ObservedDocShell.cpp",
"TimelineConsumers.cpp",
"TimelineMarker.cpp",
]
FINAL_LIBRARY = "xul"
LOCAL_INCLUDES += ["/docshell/base"]

Просмотреть файл

@ -1,97 +0,0 @@
#Timeline
The files in this directory are concerned with providing the backend platform features required for the developer tools interested in tracking down operations done in Gecko. The mechanism we use to define these operations are `markers`.
Examples of traced operations include:
* Style Recalculation
* Layout
* Painting
* JavaScript run-to-completion
* HTML parsing
* etc.
The traced operations are displayed in the DevTools Performance tool's timeline.
This is an overview of how everything works and can be extended.
##MarkersStorage
A `MarkersStorage` is an abstract class defining a place where timeline markers may be held. It defines an interface with pure virtual functions to highlight how this storage can be interacted with:
- `AddMarker`: adding a marker, from the main thread only
- `AddOTMTMarker`: adding a marker off the main thread only
- `ClearMarkers`: clearing all accumulated markers (both from the main thread and off it)
- `PopMarkers`: popping all accumulated markers (both from the main thread and off it).
Note on why we handle on/off the main thread markers separately: since most of our markers will come from the main thread, we can be a little more efficient and avoid dealing with multithreading scenarios until all the markers are actually cleared or popped in `ClearMarkers` or `PopMarkers`. Main thread markers may only be added via `AddMarker`, while off the main thread markers may only be added via `AddOTMTMarker`. Clearing and popping markers will yield until all operations involving off the main thread markers finish. When popping, the markers accumulated off the main thread will be moved over. We expect popping to be fairly infrequent (every few hundred milliseconds, currently we schedule this to happen every 200ms).
##ObservedDocShell
The only implementation of a MarkersStorage we have right now is an `ObservedDocShell`.
Instances of `ObservedDocShell` accumulate markers that are *mostly* about a particular docshell. At a high level, for example, an `ObservedDocshell` would be created when a timeline tool is opened on a page. It is reasonable to assume that most operations which are interesting for that particular page happen on the main thread. However certain operations may happen outside of it, yet are interesting for its developers, for which markers can be created as well (e.g. web audio stuff, service workers etc.). It is also reasonable to assume that a docshell may sometimes not be easily accessible from certain parts of the platform code, but for which markers still need to be created.
Therefore, the following scenarios arise:
- a). creating a marker on the main thread about a particular docshell
- b). creating a marker on the main thread without pinpointing to an affected docshell (unlikely, but allowed; in this case such a marker would have to be stored in all currently existing `ObservedDocShell` instances)
- c). creating a marker off the main thread about a particular docshell (impossible; docshells can't be referenced outside the main thread, in which case some other type of identification mechanism needs to be put in place).
- d). creating a marker off the main thread without pinpointing to a particular docshell (same path as c. here, such a marker would have to be stored in all currently existing `ObservedDocShell` instances).
An observed docshell (in other words, "a docshell for which a timeline tool was opened") can thus receive both main thread and off the main thread markers.
Cross-process markers are unnecessary at the moment, but tracked in bug 1200120.
##TimelineConsumers
A `TimelineConsumer` is a singleton that facilitates access to `ObservedDocShell` instances. This is where a docshell can register/unregister itself as being observed via the `AddConsumer` and `RemoveConsumer` methods.
All markers may only be stored via this singleton. Certain helper methods are available:
* Main thread only
`AddMarkerForDocShell(nsDocShell*, const char*, MarkerTracingType)`
`AddMarkerForDocShell(nsDocShell*, const char*, const TimeStamp&, MarkerTracingType)`
`AddMarkerForDocShell(nsDocShell*, UniquePtr<AbstractTimelineMarker>&&)`
* Any thread
`AddMarkerForAllObservedDocShells(const char*, MarkerTracingType)`
`AddMarkerForAllObservedDocShells(const char*, const TimeStamp&, MarkerTracingType)`
`AddMarkerForAllObservedDocShells(UniquePtr<AbstractTimelineMarker>&)`
The "main thread only" methods deal with point a). described above. The "any thread" methods deal with points b). and d).
##AbstractTimelineMarker
All markers inherit from this abstract class, providing a simple thread-safe extendable blueprint.
Markers are readonly after instantiation, and will always be identified by a name, a timestamp and their tracing type (`START`, `END`, `TIMESTAMP`). It *should not* make sense to modify their data after their creation.
There are only two accessible constructors:
`AbstractTimelineMarker(const char*, MarkerTracingType)`
`AbstractTimelineMarker(const char*, const TimeStamp&, MarkerTracingType)`
which create a marker with a name and a tracing type. If unspecified, the corresponding timestamp will be the current instantiation time. Instantiating a marker *much later* after a particular operation is possible, but be careful providing the correct timestamp.
The `AddDetails` virtual method should be implemented by subclasses when creating WebIDL versions of these markers, which will be sent over to a JavaScript frontend.
##TimelineMarker
A `TimelineMarker` is the main `AbstractTimelineMarker` implementation. They allow attaching a JavaScript stack on `START` and `TIMESTAMP` markers.
These markers will be created when using the `TimelineConsumers` helper methods which take in a string, a tracing type and (optionally) a timestamp. For more complex markers, subclasses are encouraged. See `EventTimelineMarker` or `ConsoleTimelineMarker` for some examples.
##RAII
### mozilla::AutoTimelineMarker
The easiest way to trace Gecko events/tasks with start and end timeline markers is to use the `mozilla::AutoTimelineMarker` RAII class. It automatically adds the start marker on construction, and adds the end marker on destruction. Don't worry too much about potential performance impact! It only actually adds the markers when the given docshell is being observed by a timeline consumer, so essentially nothing will happen if a tool to inspect those markers isn't specifically open.
This class may only be used on the main thread, and pointer to a docshell is necessary. If the docshell is a nullptr, nothing happens and this operation fails silently.
Example: `AutoTimelineMarker marker(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");`
### mozilla::AutoGlobalTimelineMarker`
Similar to the previous RAII class, but doesn't expect a specific docshell, and the marker will be visible in all timeline consumers. This is useful for generic operations that don't involve a particular docshell, or where a docshell isn't accessible. May also only be used on the main thread.
Example: `AutoGlobalTimelineMarker marker("Some global operation");`

Просмотреть файл

@ -49,9 +49,7 @@ support-files = [
"file_onbeforeunload_3.html",
"print_postdata.sjs",
"test-form_sjis.html",
"browser_timelineMarkers-frame-02.js",
"head.js",
"frame-head.js",
"file_data_load_inherit_csp.html",
"file_click_link_within_view_source.html",
"onload_message.html",
@ -311,11 +309,6 @@ skip-if = [
["browser_targetTopLevelLinkClicksToBlank.js"]
["browser_timelineMarkers-01.js"]
["browser_timelineMarkers-02.js"]
skip-if = ["true"] # Bug 1220415
["browser_title_in_session_history.js"]
skip-if = ["!sessionHistoryInParent"]

Просмотреть файл

@ -1,46 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the docShell has the right profile timeline API
const URL = "data:text/html;charset=utf-8,Test page";
add_task(async function () {
await BrowserTestUtils.withNewTab(
{ gBrowser, url: URL },
async function (browser) {
await SpecialPowers.spawn(browser, [], function () {
ok(
"recordProfileTimelineMarkers" in docShell,
"The recordProfileTimelineMarkers attribute exists"
);
ok(
"popProfileTimelineMarkers" in docShell,
"The popProfileTimelineMarkers function exists"
);
ok(
docShell.recordProfileTimelineMarkers === false,
"recordProfileTimelineMarkers is false by default"
);
ok(
docShell.popProfileTimelineMarkers().length === 0,
"There are no markers by default"
);
docShell.recordProfileTimelineMarkers = true;
ok(
docShell.recordProfileTimelineMarkers === true,
"recordProfileTimelineMarkers can be set to true"
);
docShell.recordProfileTimelineMarkers = false;
ok(
docShell.recordProfileTimelineMarkers === false,
"recordProfileTimelineMarkers can be set to false"
);
});
}
);
});

Просмотреть файл

@ -1,16 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var TEST_URL =
"<!DOCTYPE html><style>" +
"body {margin:0; padding: 0;} " +
"div {width:100px;height:100px;background:red;} " +
".resize-change-color {width:50px;height:50px;background:blue;} " +
".change-color {width:50px;height:50px;background:yellow;} " +
".add-class {}" +
"</style><div></div>";
TEST_URL = "data:text/html;charset=utf8," + encodeURIComponent(TEST_URL);
var test = makeTimelineTest("browser_timelineMarkers-frame-02.js", TEST_URL);

Просмотреть файл

@ -1,185 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env mozilla/frame-script */
// This file expects frame-head.js to be loaded in the environment.
/* import-globals-from frame-head.js */
"use strict";
// Test that the docShell profile timeline API returns the right markers when
// restyles, reflows and paints occur
function rectangleContains(rect, x, y, width, height) {
return (
rect.x <= x && rect.y <= y && rect.width >= width && rect.height >= height
);
}
function sanitizeMarkers(list) {
// These markers are currently gathered from all docshells, which may
// interfere with this test.
return list.filter(e => e.name != "Worker" && e.name != "MinorGC");
}
var TESTS = [
{
desc: "Changing the width of the test element",
searchFor: "Paint",
setup(docShell) {
let div = content.document.querySelector("div");
div.setAttribute("class", "resize-change-color");
},
check(markers) {
markers = sanitizeMarkers(markers);
ok(!!markers.length, "markers were returned");
console.log(markers);
info(JSON.stringify(markers.filter(m => m.name == "Paint")));
ok(
markers.some(m => m.name == "Reflow"),
"markers includes Reflow"
);
ok(
markers.some(m => m.name == "Paint"),
"markers includes Paint"
);
for (let marker of markers.filter(m => m.name == "Paint")) {
// This change should generate at least one rectangle.
ok(marker.rectangles.length >= 1, "marker has one rectangle");
// One of the rectangles should contain the div.
ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 100, 100)));
}
ok(
markers.some(m => m.name == "Styles"),
"markers includes Restyle"
);
},
},
{
desc: "Changing the test element's background color",
searchFor: "Paint",
setup(docShell) {
let div = content.document.querySelector("div");
div.setAttribute("class", "change-color");
},
check(markers) {
markers = sanitizeMarkers(markers);
ok(!!markers.length, "markers were returned");
ok(
!markers.some(m => m.name == "Reflow"),
"markers doesn't include Reflow"
);
ok(
markers.some(m => m.name == "Paint"),
"markers includes Paint"
);
for (let marker of markers.filter(m => m.name == "Paint")) {
// This change should generate at least one rectangle.
ok(marker.rectangles.length >= 1, "marker has one rectangle");
// One of the rectangles should contain the div.
ok(marker.rectangles.some(r => rectangleContains(r, 0, 0, 50, 50)));
}
ok(
markers.some(m => m.name == "Styles"),
"markers includes Restyle"
);
},
},
{
desc: "Changing the test element's classname",
searchFor: "Paint",
setup(docShell) {
let div = content.document.querySelector("div");
div.setAttribute("class", "change-color add-class");
},
check(markers) {
markers = sanitizeMarkers(markers);
ok(!!markers.length, "markers were returned");
ok(
!markers.some(m => m.name == "Reflow"),
"markers doesn't include Reflow"
);
ok(
!markers.some(m => m.name == "Paint"),
"markers doesn't include Paint"
);
ok(
markers.some(m => m.name == "Styles"),
"markers includes Restyle"
);
},
},
{
desc: "sync console.time/timeEnd",
searchFor: "ConsoleTime",
setup(docShell) {
content.console.time("FOOBAR");
content.console.timeEnd("FOOBAR");
let markers = docShell.popProfileTimelineMarkers();
is(markers.length, 1, "Got one marker");
is(markers[0].name, "ConsoleTime", "Got ConsoleTime marker");
is(markers[0].causeName, "FOOBAR", "Got ConsoleTime FOOBAR detail");
content.console.time("FOO");
content.setTimeout(() => {
content.console.time("BAR");
content.setTimeout(() => {
content.console.timeEnd("FOO");
content.console.timeEnd("BAR");
}, 100);
}, 100);
},
check(markers) {
markers = sanitizeMarkers(markers);
is(markers.length, 2, "Got 2 markers");
is(markers[0].name, "ConsoleTime", "Got first ConsoleTime marker");
is(markers[0].causeName, "FOO", "Got ConsoleTime FOO detail");
is(markers[1].name, "ConsoleTime", "Got second ConsoleTime marker");
is(markers[1].causeName, "BAR", "Got ConsoleTime BAR detail");
},
},
{
desc: "Timestamps created by console.timeStamp()",
searchFor: "Timestamp",
setup(docShell) {
content.console.timeStamp("rock");
let markers = docShell.popProfileTimelineMarkers();
is(markers.length, 1, "Got one marker");
is(markers[0].name, "TimeStamp", "Got Timestamp marker");
is(markers[0].causeName, "rock", "Got Timestamp label value");
content.console.timeStamp("paper");
content.console.timeStamp("scissors");
content.console.timeStamp();
content.console.timeStamp(undefined);
},
check(markers) {
markers = sanitizeMarkers(markers);
is(markers.length, 4, "Got 4 markers");
is(markers[0].name, "TimeStamp", "Got Timestamp marker");
is(markers[0].causeName, "paper", "Got Timestamp label value");
is(markers[1].name, "TimeStamp", "Got Timestamp marker");
is(markers[1].causeName, "scissors", "Got Timestamp label value");
is(
markers[2].name,
"TimeStamp",
"Got empty Timestamp marker when no argument given"
);
is(markers[2].causeName, void 0, "Got empty Timestamp label value");
is(
markers[3].name,
"TimeStamp",
"Got empty Timestamp marker when argument is undefined"
);
is(markers[3].causeName, void 0, "Got empty Timestamp label value");
markers.forEach(m =>
is(
m.end,
m.start,
"All Timestamp markers should have identical start/end times"
)
);
},
},
];
timelineContentTest(TESTS);

Просмотреть файл

@ -1,114 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env mozilla/frame-script */
// Functions that are automatically loaded as frame scripts for
// timeline tests.
// eslint assumes we inherit browser window stuff, but this
// framescript doesn't.
// eslint-disable-next-line mozilla/no-redeclare-with-import-autofix
const { setTimeout } = ChromeUtils.importESModule(
"resource://gre/modules/Timer.sys.mjs"
);
// Functions that look like mochitest functions but forward to the
// browser process.
this.ok = function (value, message) {
sendAsyncMessage("browser:test:ok", {
value: !!value,
message,
});
};
this.is = function (v1, v2, message) {
ok(v1 == v2, message);
};
this.info = function (message) {
sendAsyncMessage("browser:test:info", { message });
};
this.finish = function () {
sendAsyncMessage("browser:test:finish");
};
/* Start a task that runs some timeline tests in the ordinary way.
*
* @param array tests
* The tests to run. This is an array where each element
* is of the form { desc, searchFor, setup, check }.
*
* desc is the test description, a string.
* searchFor is a string or a function
* If a string, then when a marker with this name is
* found, marker-reading is stopped.
* If a function, then the accumulated marker array is
* passed to it, and marker reading stops when it returns
* true.
* setup is a function that takes the docshell as an argument.
* It should start the test.
* check is a function that takes an array of markers
* as an argument and checks the results of the test.
*/
this.timelineContentTest = function (tests) {
(async function () {
let docShell = content.docShell;
info("Start recording");
docShell.recordProfileTimelineMarkers = true;
for (let { desc, searchFor, setup, check } of tests) {
info("Running test: " + desc);
info("Flushing the previous markers if any");
docShell.popProfileTimelineMarkers();
info("Running the test setup function");
let onMarkers = timelineWaitForMarkers(docShell, searchFor);
setup(docShell);
info("Waiting for new markers on the docShell");
let markers = await onMarkers;
// Cycle collection markers are non-deterministic, and none of these tests
// expect them to show up.
markers = markers.filter(m => !m.name.includes("nsCycleCollector"));
info("Running the test check function");
check(markers);
}
info("Stop recording");
docShell.recordProfileTimelineMarkers = false;
finish();
})();
};
function timelineWaitForMarkers(docshell, searchFor) {
if (typeof searchFor == "string") {
let searchForString = searchFor;
let f = function (markers) {
return markers.some(m => m.name == searchForString);
};
searchFor = f;
}
return new Promise(function (resolve, reject) {
let waitIterationCount = 0;
let maxWaitIterationCount = 10; // Wait for 2sec maximum
let markers = [];
setTimeout(function timeoutHandler() {
let newMarkers = docshell.popProfileTimelineMarkers();
markers = [...markers, ...newMarkers];
if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) {
resolve(markers);
} else {
setTimeout(timeoutHandler, 200);
waitIterationCount++;
}
}, 200);
});
}

Просмотреть файл

@ -1,67 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* Helper function for timeline tests. Returns an async task that is
* suitable for use as a particular timeline test.
* @param string frameScriptName
* Base name of the frame script file.
* @param string url
* URL to load.
*/
function makeTimelineTest(frameScriptName, url) {
info("in timelineTest");
return async function () {
info("in in timelineTest");
waitForExplicitFinish();
await timelineTestOpenUrl(url);
const here = "chrome://mochitests/content/browser/docshell/test/browser/";
let mm = gBrowser.selectedBrowser.messageManager;
mm.loadFrameScript(here + "frame-head.js", false);
mm.loadFrameScript(here + frameScriptName, false);
// Set up some listeners so that timeline tests running in the
// content process can forward their results to the main process.
mm.addMessageListener("browser:test:ok", function (message) {
ok(message.data.value, message.data.message);
});
mm.addMessageListener("browser:test:info", function (message) {
info(message.data.message);
});
mm.addMessageListener("browser:test:finish", function (ignore) {
gBrowser.removeCurrentTab();
finish();
});
};
}
/* Open a URL for a timeline test. */
function timelineTestOpenUrl(url) {
window.focus();
let tabSwitchPromise = new Promise((resolve, reject) => {
window.gBrowser.addEventListener(
"TabSwitchDone",
function () {
resolve();
},
{ once: true }
);
});
let loadPromise = new Promise(function (resolve, reject) {
let browser = window.gBrowser;
let tab = (browser.selectedTab = BrowserTestUtils.addTab(browser, url));
let linkedBrowser = tab.linkedBrowser;
BrowserTestUtils.browserLoaded(linkedBrowser).then(() => resolve(tab));
});
return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab);
}
/**
* Helper function for encoding override tests, loads URL, runs check1,
* forces encoding detection, runs check2.

Просмотреть файл

@ -28,9 +28,6 @@ with Files("browser/*loadDisallowInherit*"):
with Files("browser/*tab_touch_events*"):
BUG_COMPONENT = ("Core", "DOM: Events")
with Files("browser/*timelineMarkers*"):
BUG_COMPONENT = ("DevTools", "Performance Tools (Profiler/Timeline)")
with Files("browser/*ua_emulation*"):
BUG_COMPONENT = ("DevTools", "General")

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -484,15 +484,6 @@ async function waitForAnimationReadyToRestyle(aAnimation) {
}
}
function getDocShellForObservingRestylesForWindow(aWindow) {
const docShell = SpecialPowers.wrap(aWindow).docShell;
docShell.recordProfileTimelineMarkers = true;
docShell.popProfileTimelineMarkers();
return docShell;
}
// Returns the animation restyle markers observed during |frameCount| refresh
// driver ticks in this `window`. This function is typically used to count the
// number of restyles that take place as part of the style update that happens
@ -506,8 +497,6 @@ function observeStyling(frameCount, onFrame) {
// As with observeStyling but applied to target window |aWindow|.
function observeStylingInTargetWindow(aWindow, aFrameCount, aOnFrame) {
const docShell = getDocShellForObservingRestylesForWindow(aWindow);
let priorAnimationTriggeredRestyles =
SpecialPowers.wrap(aWindow).windowUtils.animationTriggeredRestyles;
@ -517,16 +506,7 @@ function observeStylingInTargetWindow(aWindow, aFrameCount, aOnFrame) {
SpecialPowers.wrap(aWindow).windowUtils.animationTriggeredRestyles -
priorAnimationTriggeredRestyles;
const markers = docShell.popProfileTimelineMarkers();
docShell.recordProfileTimelineMarkers = false;
const stylingMarkers = Array.prototype.filter.call(
markers,
(marker, index) => {
return marker.name == "Styles" && marker.isAnimationOnly;
}
);
resolve([stylingMarkers, restyleCount]);
resolve(restyleCount);
});
});
}

Просмотреть файл

@ -40,7 +40,6 @@
#include "mozAutoDocUpdate.h"
#include "mozIDOMWindow.h"
#include "mozIThirdPartyUtil.h"
#include "mozilla/AbstractTimelineMarker.h"
#include "mozilla/AntiTrackingUtils.h"
#include "mozilla/ArrayIterator.h"
#include "mozilla/ArrayUtils.h"
@ -54,7 +53,7 @@
#include "mozilla/ContentPrincipal.h"
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/DocLoadingTimelineMarker.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/AttributeStyles.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/EditorBase.h"
@ -134,7 +133,6 @@
#include "mozilla/TelemetryScalarEnums.h"
#include "mozilla/TextControlElement.h"
#include "mozilla/TextEditor.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/TypedEnumBits.h"
#include "mozilla/URLDecorationStripper.h"
#include "mozilla/URLExtraData.h"
@ -8050,14 +8048,6 @@ void Document::DispatchContentLoadedEvents() {
MaybeResolveReadyForIdle();
}
nsIDocShell* docShell = GetDocShell();
if (TimelineConsumers::HasConsumer(docShell)) {
TimelineConsumers::AddMarkerForDocShell(
docShell,
MakeUnique<DocLoadingTimelineMarker>("document::DOMContentLoaded"));
}
if (mTiming) {
mTiming->NotifyDOMContentLoadedEnd(Document::GetDocumentURI());
}

Просмотреть файл

@ -64,7 +64,6 @@
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/AutoTimelineMarker.h"
#include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/Base64.h"
#include "mozilla/BasePrincipal.h"
@ -5375,8 +5374,6 @@ nsresult nsContentUtils::ParseFragmentHTML(
const nsAString& aSourceBuffer, nsIContent* aTargetNode,
nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
bool aPreventScriptExecution, int32_t aFlags) {
AutoTimelineMarker m(aTargetNode->OwnerDoc()->GetDocShell(), "Parse HTML");
if (nsContentUtils::sFragmentParsingActive) {
MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.");
return NS_ERROR_DOM_INVALID_STATE_ERR;
@ -5450,8 +5447,6 @@ nsresult nsContentUtils::ParseFragmentHTML(
nsresult nsContentUtils::ParseDocumentHTML(
const nsAString& aSourceBuffer, Document* aTargetDocument,
bool aScriptingEnabledForNoscriptParsing) {
AutoTimelineMarker m(aTargetDocument->GetDocShell(), "Parse HTML");
if (nsContentUtils::sFragmentParsingActive) {
MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.");
return NS_ERROR_DOM_INVALID_STATE_ERR;
@ -5474,8 +5469,6 @@ nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
bool aPreventScriptExecution,
int32_t aFlags,
DocumentFragment** aReturn) {
AutoTimelineMarker m(aDocument->GetDocShell(), "Parse XML");
if (nsContentUtils::sFragmentParsingActive) {
MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.");
return NS_ERROR_DOM_INVALID_STATE_ERR;

Просмотреть файл

@ -46,8 +46,6 @@
#include "nsDocShell.h"
#include "nsProxyRelease.h"
#include "nsReadableUtils.h"
#include "mozilla/ConsoleTimelineMarker.h"
#include "mozilla/TimestampTimelineMarker.h"
#include "nsIConsoleAPIStorage.h"
#include "nsIException.h" // for nsIStackFrame
@ -2613,48 +2611,6 @@ bool Console::MonotonicTimer(JSContext* aCx, MethodName aMethodName,
}
*aTimeStamp = performance->Now();
nsDocShell* docShell = static_cast<nsDocShell*>(win->GetDocShell());
bool isTimelineRecording = TimelineConsumers::HasConsumer(docShell);
// The 'timeStamp' recordings do not need an argument; use empty string
// if no arguments passed in.
if (isTimelineRecording && aMethodName == MethodTimeStamp) {
JS::Rooted<JS::Value> value(
aCx, aData.Length() == 0 ? JS_GetEmptyStringValue(aCx) : aData[0]);
JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
if (!jsString) {
return false;
}
nsAutoJSString key;
if (!key.init(aCx, jsString)) {
return false;
}
TimelineConsumers::AddMarkerForDocShell(
docShell, MakeUnique<TimestampTimelineMarker>(key));
}
// For `console.time(foo)` and `console.timeEnd(foo)`.
else if (isTimelineRecording && aData.Length() == 1) {
JS::Rooted<JS::Value> value(aCx, aData[0]);
JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
if (!jsString) {
return false;
}
nsAutoJSString key;
if (!key.init(aCx, jsString)) {
return false;
}
TimelineConsumers::AddMarkerForDocShell(
docShell,
MakeUnique<ConsoleTimelineMarker>(key, aMethodName == MethodTime
? MarkerTracingType::START
: MarkerTracingType::END));
}
return true;
}

Просмотреть файл

@ -2914,29 +2914,6 @@ void BrowserChild::DidComposite(mozilla::layers::TransactionId aTransactionId,
}
}
void BrowserChild::DidRequestComposite(const TimeStamp& aCompositeReqStart,
const TimeStamp& aCompositeReqEnd) {
nsCOMPtr<nsIDocShell> docShellComPtr = do_GetInterface(WebNavigation());
if (!docShellComPtr) {
return;
}
nsDocShell* docShell = static_cast<nsDocShell*>(docShellComPtr.get());
if (TimelineConsumers::HasConsumer(docShell)) {
// Since we're assuming that it's impossible for content JS to directly
// trigger a synchronous paint, we can avoid capturing a stack trace here,
// which means we won't run into JS engine reentrancy issues like bug
// 1310014.
TimelineConsumers::AddMarkerForDocShell(
docShell, "CompositeForwardTransaction", aCompositeReqStart,
MarkerTracingType::START, MarkerStackRequest::NO_STACK);
TimelineConsumers::AddMarkerForDocShell(
docShell, "CompositeForwardTransaction", aCompositeReqEnd,
MarkerTracingType::END, MarkerStackRequest::NO_STACK);
}
}
void BrowserChild::ClearCachedResources() {
MOZ_ASSERT(mPuppetWidget);
RefPtr<WebRenderLayerManager> lm =

Просмотреть файл

@ -482,9 +482,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
const TimeStamp& aCompositeStart,
const TimeStamp& aCompositeEnd);
void DidRequestComposite(const TimeStamp& aCompositeReqStart,
const TimeStamp& aCompositeReqEnd);
void ClearCachedResources();
void SchedulePaint();
void ReinitRendering();

Просмотреть файл

@ -26,10 +26,7 @@
#include "mozilla/dom/RefMessageBodyService.h"
#include "mozilla/dom/SharedMessageBody.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/MessagePortTimelineMarker.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/TimelineMarker.h"
#include "mozilla/Unused.h"
#include "nsContentUtils.h"
#include "nsPresContext.h"
@ -112,27 +109,9 @@ class PostMessageRunnable final : public CancelableRunnable {
IgnoredErrorResult rv;
JS::Rooted<JS::Value> value(cx);
UniquePtr<AbstractTimelineMarker> start;
UniquePtr<AbstractTimelineMarker> end;
bool isTimelineRecording = !TimelineConsumers::IsEmpty();
if (isTimelineRecording) {
start = MakeUnique<MessagePortTimelineMarker>(
ProfileTimelineMessagePortOperationType::DeserializeData,
MarkerTracingType::START);
}
mData->Read(cx, &value, mPort->mRefMessageBodyService,
SharedMessageBody::ReadMethod::StealRefMessageBody, rv);
if (isTimelineRecording) {
end = MakeUnique<MessagePortTimelineMarker>(
ProfileTimelineMessagePortOperationType::DeserializeData,
MarkerTracingType::END);
TimelineConsumers::AddMarkerForAllObservedDocShells(start);
TimelineConsumers::AddMarkerForAllObservedDocShells(end);
}
if (NS_WARN_IF(rv.Failed())) {
JS_ClearPendingException(cx);
mPort->DispatchError();
@ -337,27 +316,9 @@ void MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
RefPtr<SharedMessageBody> data = new SharedMessageBody(
StructuredCloneHolder::TransferringSupported, agentClusterId);
UniquePtr<AbstractTimelineMarker> start;
UniquePtr<AbstractTimelineMarker> end;
bool isTimelineRecording = !TimelineConsumers::IsEmpty();
if (isTimelineRecording) {
start = MakeUnique<MessagePortTimelineMarker>(
ProfileTimelineMessagePortOperationType::SerializeData,
MarkerTracingType::START);
}
data->Write(aCx, aMessage, transferable, mIdentifier->uuid(),
mRefMessageBodyService, aRv);
if (isTimelineRecording) {
end = MakeUnique<MessagePortTimelineMarker>(
ProfileTimelineMessagePortOperationType::SerializeData,
MarkerTracingType::END);
TimelineConsumers::AddMarkerForAllObservedDocShells(start);
TimelineConsumers::AddMarkerForAllObservedDocShells(end);
}
if (NS_WARN_IF(aRv.Failed())) {
return;
}

Просмотреть файл

@ -46,21 +46,8 @@ void AssertIfNotSafeToRunScript() {
}
#endif
static unsigned long gRunToCompletionListeners = 0;
} // namespace
void UseEntryScriptProfiling() {
MOZ_ASSERT(NS_IsMainThread());
++gRunToCompletionListeners;
}
void UnuseEntryScriptProfiling() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gRunToCompletionListeners > 0);
--gRunToCompletionListeners;
}
AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char* aReason, bool aIsMainThread)
: AutoJSAPI(aGlobalObject, aIsMainThread, eEntryScript),
@ -79,9 +66,6 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
#ifdef DEBUG
AssertIfNotSafeToRunScript();
#endif
if (gRunToCompletionListeners > 0) {
mDocShellEntryMonitor.emplace(cx(), aReason);
}
mScriptActivity.emplace(true);
}
}
@ -95,66 +79,4 @@ AutoEntryScript::AutoEntryScript(JSObject* aObject, const char* aReason,
AutoEntryScript::~AutoEntryScript() = default;
AutoEntryScript::DocshellEntryMonitor::DocshellEntryMonitor(JSContext* aCx,
const char* aReason)
: JS::dbg::AutoEntryMonitor(aCx), mReason(aReason) {}
void AutoEntryScript::DocshellEntryMonitor::Entry(
JSContext* aCx, JSFunction* aFunction, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack, const char* aAsyncCause) {
JS::Rooted<JSFunction*> rootedFunction(aCx);
if (aFunction) {
rootedFunction = aFunction;
}
JS::Rooted<JSScript*> rootedScript(aCx);
if (aScript) {
rootedScript = aScript;
}
nsCOMPtr<nsPIDOMWindowInner> window = xpc::CurrentWindowOrNull(aCx);
if (!window || !window->GetDocShell() ||
!window->GetDocShell()->GetRecordProfileTimelineMarkers()) {
return;
}
nsCOMPtr<nsIDocShell> docShellForJSRunToCompletion = window->GetDocShell();
nsAutoJSString functionName;
if (rootedFunction) {
JS::Rooted<JSString*> displayId(aCx,
JS_GetFunctionDisplayId(rootedFunction));
if (displayId) {
if (!functionName.init(aCx, displayId)) {
JS_ClearPendingException(aCx);
return;
}
}
}
nsString filename;
uint32_t lineNumber = 0;
if (!rootedScript) {
rootedScript = JS_GetFunctionScript(aCx, rootedFunction);
}
if (rootedScript) {
CopyUTF8toUTF16(MakeStringSpan(JS_GetScriptFilename(rootedScript)),
filename);
lineNumber = JS_GetScriptBaseLineNumber(aCx, rootedScript);
}
if (!filename.IsEmpty() || !functionName.IsEmpty()) {
docShellForJSRunToCompletion->NotifyJSRunToCompletionStart(
mReason, functionName, filename, lineNumber, aAsyncStack, aAsyncCause);
}
}
void AutoEntryScript::DocshellEntryMonitor::Exit(JSContext* aCx) {
nsCOMPtr<nsPIDOMWindowInner> window = xpc::CurrentWindowOrNull(aCx);
// Not really worth checking GetRecordProfileTimelineMarkers here.
if (window && window->GetDocShell()) {
nsCOMPtr<nsIDocShell> docShellForJSRunToCompletion = window->GetDocShell();
docShellForJSRunToCompletion->NotifyJSRunToCompletionStop();
}
}
} // namespace mozilla::dom

Просмотреть файл

@ -26,16 +26,6 @@ class AutoScriptActivity;
namespace mozilla::dom {
/*
* 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();
/*
* A class that represents a new script entry point.
*
@ -67,37 +57,6 @@ class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI {
}
private:
// A subclass of AutoEntryMonitor that notifies the docshell.
class DocshellEntryMonitor final : public JS::dbg::AutoEntryMonitor {
public:
DocshellEntryMonitor(JSContext* aCx, const char* aReason);
// Please note that |aAsyncCause| here is owned by the caller, and its
// lifetime must outlive the lifetime of the DocshellEntryMonitor object.
// In practice, |aAsyncCause| is identical to |aReason| passed into
// the AutoEntryScript constructor, so the lifetime requirements are
// trivially satisfied by |aReason| being a statically allocated string.
void Entry(JSContext* aCx, JSFunction* aFunction,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) override {
Entry(aCx, aFunction, nullptr, aAsyncStack, aAsyncCause);
}
void Entry(JSContext* aCx, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack,
const char* aAsyncCause) override {
Entry(aCx, nullptr, aScript, aAsyncStack, aAsyncCause);
}
void Exit(JSContext* aCx) override;
private:
void Entry(JSContext* aCx, JSFunction* aFunction, JSScript* aScript,
JS::Handle<JS::Value> aAsyncStack, const char* aAsyncCause);
const char* mReason;
};
// It's safe to make this a weak pointer, since it's the subject principal
// when we go on the stack, so can't go away until after we're gone. In
// particular, this is only used from the CallSetup constructor, and only in
@ -108,7 +67,6 @@ class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI {
nsIPrincipal* MOZ_NON_OWNING_REF mWebIDLCallerPrincipal;
friend nsIPrincipal* GetWebIDLCallerPrincipal();
Maybe<DocshellEntryMonitor> mDocShellEntryMonitor;
Maybe<xpc::AutoScriptActivity> mScriptActivity;
JS::AutoHideScriptedCaller mCallerOverride;
AutoProfilerLabel mAutoProfilerLabel;

Просмотреть файл

@ -1,76 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// For Javascript markers, the |stack| of a ProfileTimelineMarker
// holds an object of this type. It intentionally looks like a
// SavedStack object and is a representation of the frame that is
// about to be constructed at the entry point.
[GenerateConversionToJS]
dictionary ProfileTimelineStackFrame {
long line;
long column = 0;
DOMString source;
DOMString functionDisplayName;
object? parent = null;
object? asyncParent = null;
DOMString asyncCause;
};
dictionary ProfileTimelineLayerRect {
long x = 0;
long y = 0;
long width = 0;
long height = 0;
};
enum ProfileTimelineMessagePortOperationType {
"serializeData",
"deserializeData",
};
enum ProfileTimelineWorkerOperationType {
"serializeDataOffMainThread",
"serializeDataOnMainThread",
"deserializeDataOffMainThread",
"deserializeDataOnMainThread",
};
[GenerateConversionToJS]
dictionary ProfileTimelineMarker {
DOMString name = "";
DOMHighResTimeStamp start = 0;
DOMHighResTimeStamp end = 0;
object? stack = null;
unsigned short processType;
boolean isOffMainThread;
/* For ConsoleTime, Timestamp and Javascript markers. */
DOMString causeName;
/* For ConsoleTime markers. */
object? endStack = null;
/* For DOMEvent markers. */
DOMString type;
unsigned short eventPhase;
/* For document::DOMContentLoaded and document::Load markers. Using this
* instead of the `start` and `end` timestamps is strongly discouraged. */
unsigned long long unixTime; // in microseconds
/* For Paint markers. */
sequence<ProfileTimelineLayerRect> rectangles;
/* For Style markers. */
boolean isAnimationOnly;
/* For MessagePort markers. */
ProfileTimelineMessagePortOperationType messagePortOperation;
/* For Worker markers. */
ProfileTimelineWorkerOperationType workerOperation;
};

Просмотреть файл

@ -268,9 +268,6 @@ with Files("PopStateEvent.webidl*"):
with Files("GeolocationPosition*"):
BUG_COMPONENT = ("Core", "DOM: Geolocation")
with Files("ProfileTimelineMarker.webidl"):
BUG_COMPONENT = ("DevTools", "Performance Tools (Profiler/Timeline)")
with Files("PopoverInvokerElement.webidl"):
BUG_COMPONENT = ("Core", "DOM: Core & HTML")
@ -797,7 +794,6 @@ WEBIDL_FILES = [
"PointerEvent.webidl",
"PopoverInvokerElement.webidl",
"ProcessingInstruction.webidl",
"ProfileTimelineMarker.webidl",
"Promise.webidl",
"PushEvent.webidl",
"PushManager.webidl",

Просмотреть файл

@ -9,8 +9,6 @@
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/WorkerTimelineMarker.h"
#include "nsQueryObject.h"
#include "WorkerScope.h"
@ -47,18 +45,6 @@ bool MessageEventRunnable::DispatchDOMEvent(JSContext* aCx,
JS::Rooted<JS::Value> messageData(aCx);
IgnoredErrorResult rv;
UniquePtr<AbstractTimelineMarker> start;
UniquePtr<AbstractTimelineMarker> end;
bool isTimelineRecording = !TimelineConsumers::IsEmpty();
if (isTimelineRecording) {
start = MakeUnique<WorkerTimelineMarker>(
aIsMainThread
? ProfileTimelineWorkerOperationType::DeserializeDataOnMainThread
: ProfileTimelineWorkerOperationType::DeserializeDataOffMainThread,
MarkerTracingType::START);
}
JS::CloneDataPolicy cloneDataPolicy;
if (parent->GetClientInfo().isSome() &&
parent->GetClientInfo()->AgentClusterId().isSome() &&
@ -73,16 +59,6 @@ bool MessageEventRunnable::DispatchDOMEvent(JSContext* aCx,
Read(parent, aCx, &messageData, cloneDataPolicy, rv);
if (isTimelineRecording) {
end = MakeUnique<WorkerTimelineMarker>(
aIsMainThread
? ProfileTimelineWorkerOperationType::DeserializeDataOnMainThread
: ProfileTimelineWorkerOperationType::DeserializeDataOffMainThread,
MarkerTracingType::END);
TimelineConsumers::AddMarkerForAllObservedDocShells(start);
TimelineConsumers::AddMarkerForAllObservedDocShells(end);
}
if (NS_WARN_IF(rv.Failed())) {
DispatchError(aCx, aTarget);
return false;

Просмотреть файл

@ -10,9 +10,7 @@
#include "mozilla/dom/WorkerBinding.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/Unused.h"
#include "mozilla/WorkerTimelineMarker.h"
#include "nsContentUtils.h"
#include "nsGlobalWindowInner.h"
#include "WorkerPrivate.h"
@ -124,18 +122,6 @@ void Worker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
RefPtr<MessageEventRunnable> runnable = new MessageEventRunnable(
mWorkerPrivate, WorkerRunnable::WorkerThreadModifyBusyCount);
UniquePtr<AbstractTimelineMarker> start;
UniquePtr<AbstractTimelineMarker> end;
bool isTimelineRecording = !TimelineConsumers::IsEmpty();
if (isTimelineRecording) {
start = MakeUnique<WorkerTimelineMarker>(
NS_IsMainThread()
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
MarkerTracingType::START);
}
JS::CloneDataPolicy clonePolicy;
// DedicatedWorkers are always part of the same agent cluster.
clonePolicy.allowIntraClusterClonableSharedObjects();
@ -158,16 +144,6 @@ void Worker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
return;
}
if (isTimelineRecording) {
end = MakeUnique<WorkerTimelineMarker>(
NS_IsMainThread()
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
MarkerTracingType::END);
TimelineConsumers::AddMarkerForAllObservedDocShells(start);
TimelineConsumers::AddMarkerForAllObservedDocShells(end);
}
if (NS_WARN_IF(aRv.Failed())) {
return;
}

Просмотреть файл

@ -67,8 +67,6 @@
#include "mozilla/ThreadEventQueue.h"
#include "mozilla/ThreadSafety.h"
#include "mozilla/ThrottledEventQueue.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/WorkerTimelineMarker.h"
#include "nsCycleCollector.h"
#include "nsGlobalWindowInner.h"
#include "nsIDUtils.h"
@ -4716,18 +4714,6 @@ void WorkerPrivate::PostMessageToParent(
RefPtr<MessageEventRunnable> runnable = new MessageEventRunnable(
this, WorkerRunnable::ParentThreadUnchangedBusyCount);
UniquePtr<AbstractTimelineMarker> start;
UniquePtr<AbstractTimelineMarker> end;
bool isTimelineRecording = !TimelineConsumers::IsEmpty();
if (isTimelineRecording) {
start = MakeUnique<WorkerTimelineMarker>(
NS_IsMainThread()
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
MarkerTracingType::START);
}
JS::CloneDataPolicy clonePolicy;
// Parent and dedicated workers are always part of the same cluster.
@ -4739,16 +4725,6 @@ void WorkerPrivate::PostMessageToParent(
runnable->Write(aCx, aMessage, transferable, clonePolicy, aRv);
if (isTimelineRecording) {
end = MakeUnique<WorkerTimelineMarker>(
NS_IsMainThread()
? ProfileTimelineWorkerOperationType::SerializeDataOnMainThread
: ProfileTimelineWorkerOperationType::SerializeDataOffMainThread,
MarkerTracingType::END);
TimelineConsumers::AddMarkerForAllObservedDocShells(start);
TimelineConsumers::AddMarkerForAllObservedDocShells(end);
}
if (NS_WARN_IF(aRv.Failed())) {
return;
}

Просмотреть файл

@ -58,8 +58,8 @@ async function observe_styling_in_oopif(aFrameCount) {
const observe_styling = function(frameCount) {
// Start in a rAF callback.
waitForAnimationFrames(1).then(() => {
observeStyling(frameCount).then(([markers, counter]) => {
FissionTestHelper.fireEventInEmbedder("OOPIF:StyleCount", [markers.length, counter]);
observeStyling(frameCount).then((counter) => {
FissionTestHelper.fireEventInEmbedder("OOPIF:StyleCount", counter);
});
});
@ -80,9 +80,8 @@ async function test() {
// overflow: hidden style in the out-of-process iframe.
await setup_in_oopif();
let [markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 0,
let restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 0,
"Animation in an out-of-process iframe which is initially clipped out " +
"due to 'overflow: hidden' should be throttled");
@ -96,9 +95,8 @@ async function test() {
// from APZC reaches the iframe process
await observe_styling_in_oopif(1);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 5,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 5,
"Animation in an out-of-process iframe which is no longer clipped out " +
"should NOT be throttled");
@ -112,9 +110,8 @@ async function test() {
// from APZC reaches the iframe process
await observe_styling_in_oopif(1);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 0,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 0,
"Animation in an out-of-process iframe which is clipped out again " +
"should be throttled again");
@ -128,9 +125,8 @@ async function test() {
// helper_fission_scroll_oopif.html
await observe_styling_in_oopif(60);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 5,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 5,
"Animation in an out-of-process iframe which is now visible by " +
"asynchronous scrolling should NOT be throttled");
@ -141,9 +137,8 @@ async function test() {
// Wait for the asyncronous scroll finish.
await observe_styling_in_oopif(60);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 0,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 0,
"Animation in an out-of-process iframe which is scrolled out of view by " +
"asynchronous scrolling should be throttled");
@ -154,9 +149,8 @@ async function test() {
// Wait for the asyncronous scroll finish.
await observe_styling_in_oopif(60);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 5,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 5,
"Animation in an out-of-process iframe appeared by the asynchronous " +
"scrolling should be NOT throttled");
}

Просмотреть файл

@ -55,8 +55,8 @@ async function observe_styling_in_oopif(aFrameCount) {
const observe_styling = function(frameCount) {
// Start in a rAF callback.
waitForAnimationFrames(1).then(() => {
observeStyling(frameCount).then(([markers, counter]) => {
FissionTestHelper.fireEventInEmbedder("OOPIF:StyleCount", [markers.length, counter]);
observeStyling(frameCount).then((counter) => {
FissionTestHelper.fireEventInEmbedder("OOPIF:StyleCount", counter);
});
});
@ -78,9 +78,8 @@ async function test() {
// on the iframe coodinate system.
const [right, bottom] = await setup_in_oopif();
let [markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 0,
let restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 0,
"Animation in an out-of-process iframe which is initially scrolled out " +
"of view should be throttled");
@ -94,9 +93,8 @@ async function test() {
// helper_fission_scroll_oopif.html
await observe_styling_in_oopif(60);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 5,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 5,
"Animation in an out-of-process iframe which is no longer scrolled out " +
"of view should NOT be throttled");
@ -114,9 +112,8 @@ async function test() {
// Wait for the asyncronous scroll finish.
await observe_styling_in_oopif(60);
[markerCount, restyleCounter] = await observe_styling_in_oopif(5);
is(restyleCounter, markerCount, "Restyle counter should match number of markers");
is(markerCount, 0,
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 0,
"Animation in an out-of-process iframe which is scrolled out of view " +
"again should be throttled");
}

Просмотреть файл

@ -74,12 +74,7 @@ add_task(async () => {
);
// Collect restyling markers in 5 frames.
const [markers, counter] = await observeStylingInTargetWindow(
panel.ownerGlobal,
5
);
Assert.equal(markers.length, counter);
const restyleCount = await observeStylingInTargetWindow(panel.ownerGlobal, 5);
// On non WebRender we observe two restyling markers because we get the second
// jank report from the compositor thread before a new pre-rendered result,
@ -90,6 +85,6 @@ add_task(async () => {
// KeyframeEffect::OverflowRegionRefreshInterval (200ms) on very slow
// platforms (e.g. TSAN builds), if it happens we should allow the additional
// restyling here.
Assert.greaterOrEqual(markers.length, 1);
Assert.lessOrEqual(markers.length, 2);
Assert.greaterOrEqual(restyleCount, 1);
Assert.lessOrEqual(restyleCount, 2);
});

Просмотреть файл

@ -9502,15 +9502,6 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
// schedule a similar paint when a frame is deleted.
target->SchedulePaint(nsIFrame::PAINT_DEFAULT, false);
nsDocShell* docShell =
static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
bool isTimelineRecording = TimelineConsumers::HasConsumer(docShell);
if (isTimelineRecording) {
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow",
MarkerTracingType::START);
}
Maybe<uint64_t> innerWindowID;
if (auto* window = mDocument->GetInnerWindow()) {
innerWindowID = Some(window->WindowID());
@ -9711,11 +9702,6 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
tp->Accumulate();
}
if (isTimelineRecording) {
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow",
MarkerTracingType::END);
}
return !interrupted;
}

Просмотреть файл

@ -8,8 +8,6 @@
#include "mozilla/AnimationUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/AutoRestyleTimelineMarker.h"
#include "mozilla/AutoTimelineMarker.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/ComputedStyleInlines.h"
#include "mozilla/DocumentStyleRootIterator.h"
@ -2421,8 +2419,6 @@ void RestyleManager::PostRestyleEventForAnimations(Element* aElement,
mPresContext->TriggeredAnimationRestyle();
AutoRestyleTimelineMarker marker(mPresContext->GetDocShell(),
true /* animation-only */);
Servo_NoteExplicitHints(elementToRestyle, aRestyleHint, nsChangeHint(0));
}
@ -3213,8 +3209,6 @@ void RestyleManager::DoProcessPendingRestyles(ServoTraversalFlags aFlags) {
nsTArray<RefPtr<Element>> anchorsToSuppress;
{
// This marker is not used for testing, so can be removed
AutoRestyleTimelineMarker marker(presContext->GetDocShell(), false);
DocumentStyleRootIterator iter(doc->GetServoRestyleRoot());
while (Element* root = iter.GetNextStyleRoot()) {
nsTArray<nsIFrame*> wrappersToRestyle;
@ -3245,8 +3239,6 @@ void RestyleManager::DoProcessPendingRestyles(ServoTraversalFlags aFlags) {
// processing existing ones. We redirect those into a secondary queue and
// iterate until there's nothing left.
{
AutoTimelineMarker marker(presContext->GetDocShell(),
"StylesApplyChanges");
ReentrantChangeList newChanges;
mReentrantChanges = &newChanges;
while (!currentChanges.IsEmpty()) {

Просмотреть файл

@ -96,8 +96,6 @@
#include "nsIXULRuntime.h"
#include "nsSandboxFlags.h"
#include "mozilla/DocLoadingTimelineMarker.h"
//--------------------------
// Printing Include
//---------------------------
@ -1023,12 +1021,6 @@ nsDocumentViewer::LoadComplete(nsresult aStatus) {
nullptr);
}
// Notify any devtools about the load.
if (TimelineConsumers::HasConsumer(docShell)) {
TimelineConsumers::AddMarkerForDocShell(
docShell, MakeUnique<DocLoadingTimelineMarker>("document::Load"));
}
nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
RefPtr<DocGroup> docGroup = d->GetDocGroup();
// It is possible that the parent document's load event fires earlier than

Просмотреть файл

@ -87,7 +87,6 @@
#include "VsyncSource.h"
#include "mozilla/VsyncDispatcher.h"
#include "mozilla/Unused.h"
#include "mozilla/TimelineConsumers.h"
#include "nsAnimationManager.h"
#include "nsDisplayList.h"
#include "nsDOMNavigationTiming.h"
@ -2138,41 +2137,6 @@ static bool HasPendingAnimations(PresShell* aPresShell) {
return tracker && tracker->HasPendingAnimations();
}
/**
* Return a list of all the child docShells in a given root docShell that are
* visible and are recording markers for the profilingTimeline
*/
static void GetProfileTimelineSubDocShells(nsDocShell* aRootDocShell,
nsTArray<nsDocShell*>& aShells) {
if (!aRootDocShell) {
return;
}
if (TimelineConsumers::IsEmpty()) {
return;
}
RefPtr<BrowsingContext> bc = aRootDocShell->GetBrowsingContext();
if (!bc) {
return;
}
bc->PostOrderWalk([&](BrowsingContext* aContext) {
if (!aContext->IsActive()) {
return;
}
nsDocShell* shell = nsDocShell::Cast(aContext->GetDocShell());
if (!shell || !shell->GetRecordProfileTimelineMarkers()) {
// This process isn't painting OOP iframes so we ignore
// docshells that are OOP.
return;
}
aShells.AppendElement(shell);
});
}
static void TakeFrameRequestCallbacksFrom(
Document* aDocument, nsTArray<DocumentFrameCallbacks>& aTarget) {
aTarget.AppendElement(aDocument);
@ -2793,17 +2757,6 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime,
mCompositionPayloads.Clear();
}
nsTArray<nsDocShell*> profilingDocShells;
GetProfileTimelineSubDocShells(GetDocShell(mPresContext),
profilingDocShells);
for (nsDocShell* docShell : profilingDocShells) {
// For the sake of the profile timeline's simplicity, this is flagged as
// paint even if it includes creating display lists
MOZ_ASSERT(TimelineConsumers::HasConsumer(docShell));
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint",
MarkerTracingType::START);
}
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Starting ProcessPendingUpdates\n");
@ -2827,12 +2780,6 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime,
}
#endif
for (nsDocShell* docShell : profilingDocShells) {
MOZ_ASSERT(TimelineConsumers::HasConsumer(docShell));
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint",
MarkerTracingType::END);
}
dispatchTasksAfterTick = true;
mHasScheduleFlush = false;
} else {

Просмотреть файл

@ -58,7 +58,6 @@
#include "ActiveLayerTracker.h"
#include "AnimationCommon.h"
#include "LayerAnimationInfo.h"
#include "mozilla/TimelineConsumers.h"
#include "AudioChannelService.h"
#include "mozilla/dom/PromiseDebugging.h"

Просмотреть файл

@ -8,7 +8,6 @@
#include "mozilla/ServoStyleSetInlines.h"
#include "gfxPlatformFontList.h"
#include "mozilla/AutoRestyleTimelineMarker.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/AttributeStyles.h"
#include "mozilla/EffectCompositor.h"
@ -103,16 +102,11 @@ class MOZ_RAII AutoSetInServoTraversal {
class MOZ_RAII AutoPrepareTraversal {
public:
explicit AutoPrepareTraversal(ServoStyleSet* aSet)
// For markers for animations, we have already set the markers in
// RestyleManager::PostRestyleEventForAnimations so that we don't need
// to care about animation restyles here.
: mTimelineMarker(aSet->mDocument->GetDocShell(), false),
mSetInServoTraversal(aSet) {
: mSetInServoTraversal(aSet) {
MOZ_ASSERT(!aSet->StylistNeedsUpdate());
}
private:
AutoRestyleTimelineMarker mTimelineMarker;
AutoSetInServoTraversal mSetInServoTraversal;
};

Просмотреть файл

@ -60,25 +60,13 @@ function waitForAnimationFrames(frameCount) {
// frames actually waited because we detected a possibly overflapping SMIL
// time.
function observeStyling(frameCount) {
var Ci = SpecialPowers.Ci;
var docShell = SpecialPowers.wrap(window).docShell;
docShell.recordProfileTimelineMarkers = true;
docShell.popProfileTimelineMarkers();
let priorAnimationTriggeredRestyles = SpecialPowers.DOMWindowUtils.animationTriggeredRestyles;
return new Promise(function(resolve) {
return waitForAnimationFrames(frameCount).then(framesWaited => {
var markers = docShell.popProfileTimelineMarkers();
docShell.recordProfileTimelineMarkers = false;
const restyleCount = SpecialPowers.DOMWindowUtils.animationTriggeredRestyles - priorAnimationTriggeredRestyles;
var stylingMarkers = Array.prototype.filter.call(markers, function(marker, index) {
return marker.name == 'Styles' && marker.isAnimationOnly;
});
is(restyleCount, stylingMarkers.length, "Restyle counter should match number of markers recorded");
resolve({
stylingCount: stylingMarkers.length,
stylingCount: restyleCount,
framesWaited: framesWaited,
});
});

Просмотреть файл

@ -2501,39 +2501,6 @@
}
]
},
{
"flags": [
"getter",
"hasretval"
],
"name": "recordProfileTimelineMarkers",
"params": [
{
"flags": [
"out"
],
"type": {
"tag": "TD_BOOL"
}
}
]
},
{
"flags": [
"setter"
],
"name": "recordProfileTimelineMarkers",
"params": [
{
"flags": [
"in"
],
"type": {
"tag": "TD_BOOL"
}
}
]
},
{
"flags": [
"hasretval"
@ -2550,23 +2517,6 @@
}
]
},
{
"flags": [
"jscontext",
"hasretval"
],
"name": "popProfileTimelineMarkers",
"params": [
{
"flags": [
"out"
],
"type": {
"tag": "TD_JSVAL"
}
}
]
},
{
"flags": [],
"name": "addWeakPrivacyTransitionObserver",
@ -2999,69 +2949,6 @@
}
]
},
{
"flags": [
"hidden"
],
"name": "notifyJSRunToCompletionStart",
"params": [
{
"flags": [
"in"
],
"type": {
"tag": "TD_PSTRING"
}
},
{
"flags": [
"in"
],
"type": {
"tag": "TD_ASTRING"
}
},
{
"flags": [
"in"
],
"type": {
"tag": "TD_ASTRING"
}
},
{
"flags": [
"in"
],
"type": {
"tag": "TD_UINT32"
}
},
{
"flags": [
"in"
],
"type": {
"tag": "TD_JSVAL"
}
},
{
"flags": [
"in"
],
"type": {
"tag": "TD_PSTRING"
}
}
]
},
{
"flags": [
"hidden"
],
"name": "notifyJSRunToCompletionStop",
"params": []
},
{
"flags": [
"getter",

Просмотреть файл

@ -26,8 +26,6 @@
#include "nsContentUtils.h" // for nsAutoScriptBlocker
#include "nsDocShell.h"
#include "nsLayoutUtils.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/CompositeTimelineMarker.h"
#include "mozilla/StartupTimeline.h"
using namespace mozilla;
@ -1102,17 +1100,6 @@ void nsView::DidCompositeWindow(mozilla::layers::TransactionId aTransactionId,
if (aCompositeStart == aCompositeEnd) {
return;
}
nsIDocShell* docShell = context->GetDocShell();
if (TimelineConsumers::HasConsumer(docShell)) {
TimelineConsumers::AddMarkerForDocShell(
docShell, MakeUnique<CompositeTimelineMarker>(
aCompositeStart, MarkerTracingType::START));
TimelineConsumers::AddMarkerForDocShell(
docShell, MakeUnique<CompositeTimelineMarker>(aCompositeEnd,
MarkerTracingType::END));
}
}
void nsView::RequestRepaint() {

Просмотреть файл

@ -22,13 +22,10 @@
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/TimelineMarker.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/FinalizationRegistryBinding.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/dom/PromiseBinding.h"
#include "mozilla/dom/PromiseDebugging.h"
#include "mozilla/dom/PromiseRejectionEvent.h"

Просмотреть файл

@ -80,13 +80,10 @@
#include "mozilla/Sprintf.h"
#include "mozilla/StaticPrefs_javascript.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimelineConsumers.h"
#include "mozilla/TimelineMarker.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/AutoEntryScript.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseBinding.h"
#include "mozilla/dom/PromiseDebugging.h"
@ -1135,44 +1132,6 @@ void CycleCollectedJSRuntime::GCSliceCallback(JSContext* aContext,
}
}
class MinorGCMarker : public TimelineMarker {
private:
JS::GCReason mReason;
public:
MinorGCMarker(MarkerTracingType aTracingType, JS::GCReason aReason)
: TimelineMarker("MinorGC", aTracingType, MarkerStackRequest::NO_STACK),
mReason(aReason) {
MOZ_ASSERT(aTracingType == MarkerTracingType::START ||
aTracingType == MarkerTracingType::END);
}
MinorGCMarker(JS::GCNurseryProgress aProgress, JS::GCReason aReason)
: TimelineMarker(
"MinorGC",
aProgress == JS::GCNurseryProgress::GC_NURSERY_COLLECTION_START
? MarkerTracingType::START
: MarkerTracingType::END,
MarkerStackRequest::NO_STACK),
mReason(aReason) {}
virtual void AddDetails(JSContext* aCx,
dom::ProfileTimelineMarker& aMarker) override {
TimelineMarker::AddDetails(aCx, aMarker);
if (GetTracingType() == MarkerTracingType::START) {
auto reason = JS::ExplainGCReason(mReason);
aMarker.mCauseName.Construct(NS_ConvertUTF8toUTF16(reason));
}
}
virtual UniquePtr<AbstractTimelineMarker> Clone() override {
auto clone = MakeUnique<MinorGCMarker>(GetTracingType(), mReason);
clone->SetCustomTime(GetTime());
return UniquePtr<AbstractTimelineMarker>(std::move(clone));
}
};
/* static */
void CycleCollectedJSRuntime::GCNurseryCollectionCallback(
JSContext* aContext, JS::GCNurseryProgress aProgress, JS::GCReason aReason,
@ -1181,12 +1140,6 @@ void CycleCollectedJSRuntime::GCNurseryCollectionCallback(
MOZ_ASSERT(CycleCollectedJSContext::Get()->Context() == aContext);
MOZ_ASSERT(NS_IsMainThread());
if (!TimelineConsumers::IsEmpty()) {
UniquePtr<AbstractTimelineMarker> abstractMarker(
MakeUnique<MinorGCMarker>(aProgress, aReason));
TimelineConsumers::AddMarkerForAllObservedDocShells(abstractMarker);
}
TimeStamp now = TimeStamp::Now();
if (aProgress == JS::GCNurseryProgress::GC_NURSERY_COLLECTION_START) {
self->mLatestNurseryCollectionStart = now;

Просмотреть файл

@ -167,7 +167,6 @@
#include "js/SliceBudget.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoGlobalTimelineMarker.h"
#include "mozilla/Likely.h"
#include "mozilla/LinkedList.h"
#include "mozilla/MemoryReporting.h"
@ -2689,12 +2688,6 @@ void nsCycleCollector::ForgetSkippable(js::SliceBudget& aBudget,
return;
}
mozilla::Maybe<mozilla::AutoGlobalTimelineMarker> marker;
if (NS_IsMainThread()) {
marker.emplace("nsCycleCollector::ForgetSkippable",
MarkerStackRequest::NO_STACK);
}
// If we remove things from the purple buffer during graph building, we may
// lose track of an object that was mutated during graph building.
MOZ_ASSERT(IsIdle());
@ -3453,11 +3446,6 @@ bool nsCycleCollector::Collect(CCReason aReason, ccIsManual aIsManual,
MOZ_ASSERT(!IsIncrementalGCInProgress());
mozilla::Maybe<mozilla::AutoGlobalTimelineMarker> marker;
if (NS_IsMainThread()) {
marker.emplace("nsCycleCollector::Collect", MarkerStackRequest::NO_STACK);
}
bool startedIdle = IsIdle();
bool collectedAny = false;