From 81f365c3682b78d71d304791b248f74f3b15f38f Mon Sep 17 00:00:00 2001
From: Dave Townsend
Date: Mon, 16 May 2011 11:46:55 -0700
Subject: [PATCH 01/15] Bug 623134: Add HTTP logging to track down the
intermittent request timeouts. r=robstrong
---
.../mozapps/extensions/AddonUpdateChecker.jsm | 25 +++++++++++--------
.../test/browser/browser_updatessl.js | 18 +++++++++++++
2 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/toolkit/mozapps/extensions/AddonUpdateChecker.jsm b/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
index cc2e269282f2..ae2e2b71f83d 100644
--- a/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
+++ b/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
@@ -440,16 +440,21 @@ function UpdateParser(aId, aType, aUpdateKey, aUrl, aObserver) {
}
LOG("Requesting " + aUrl);
- this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
- createInstance(Ci.nsIXMLHttpRequest);
- this.request.open("GET", aUrl, true);
- this.request.channel.notificationCallbacks = new BadCertHandler(!requireBuiltIn);
- this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
- this.request.overrideMimeType("text/xml");
- var self = this;
- this.request.onload = function(event) { self.onLoad() };
- this.request.onerror = function(event) { self.onError() };
- this.request.send(null);
+ try {
+ this.request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
+ createInstance(Ci.nsIXMLHttpRequest);
+ this.request.open("GET", aUrl, true);
+ this.request.channel.notificationCallbacks = new BadCertHandler(!requireBuiltIn);
+ this.request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
+ this.request.overrideMimeType("text/xml");
+ var self = this;
+ this.request.onload = function(event) { self.onLoad() };
+ this.request.onerror = function(event) { self.onError() };
+ this.request.send(null);
+ }
+ catch (e) {
+ ERROR("Failed to request update manifest", e);
+ }
}
UpdateParser.prototype = {
diff --git a/toolkit/mozapps/extensions/test/browser/browser_updatessl.js b/toolkit/mozapps/extensions/test/browser/browser_updatessl.js
index eb7899819fbe..9694e5a2c088 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_updatessl.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_updatessl.js
@@ -22,11 +22,29 @@ var gTests = [];
var gStart = 0;
var gLast = 0;
+var HTTPObserver = {
+ observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData,
+ aStringData) {
+ aChannel.QueryInterface(Ci.nsIChannel);
+
+ dump("*** HTTP Activity 0x" + aType.toString(16) + " 0x" + aSubtype.toString(16) +
+ " " + aChannel.URI.spec + "\n");
+ }
+};
+
function test() {
gStart = Date.now();
requestLongerTimeout(4);
waitForExplicitFinish();
+ let observerService = Cc["@mozilla.org/network/http-activity-distributor;1"].
+ getService(Ci.nsIHttpActivityDistributor);
+ observerService.addObserver(HTTPObserver);
+
+ registerCleanupFunction(function() {
+ observerService.removeObserver(HTTPObserver);
+ });
+
run_next_test();
}
From 1d29d4527788976ed3230fb73793d17372a0ef37 Mon Sep 17 00:00:00 2001
From: Taras Glek
Date: Mon, 16 May 2011 16:03:36 -0700
Subject: [PATCH 02/15] Bug 657480: Clean up after TelemetryPing.js r=mak
---
toolkit/components/telemetry/TelemetryPing.js | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js
index 58ad8c35c9ba..d3bfa256ff87 100644
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -235,12 +235,25 @@ TelemetryPing.prototype = {
let idleService = Cc["@mozilla.org/widget/idleservice;1"].
getService(Ci.nsIIdleService);
idleService.addIdleObserver(self, TELEMETRY_INTERVAL);
- Services.obs.addObserver(self, "idle-daily", null);
+ Services.obs.addObserver(self, "idle-daily", false);
+ Services.obs.addObserver(self, "profile-before-change", false);
self.gatherMemory();
+ delete self._timer
}
this._timer.initWithCallback(timerCallback, TELEMETRY_DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
},
+ /**
+ * Remove observers to avoid leaks
+ */
+ uninstall: function uninstall() {
+ let idleService = Cc["@mozilla.org/widget/idleservice;1"].
+ getService(Ci.nsIIdleService);
+ idleService.removeIdleObserver(this, TELEMETRY_INTERVAL);
+ Services.obs.removeObserver(this, "idle-daily");
+ Services.obs.removeObserver(this, "profile-before-change");
+ },
+
/**
* This observer drives telemetry.
*/
@@ -252,6 +265,9 @@ TelemetryPing.prototype = {
case "profile-after-change":
this.setup();
break;
+ case "profile-before-change":
+ this.uninstall();
+ break;
case "idle":
this.gatherMemory();
break;
From 04f1d9f0378c9ef0983821c0442a8301818d859f Mon Sep 17 00:00:00 2001
From: Masayuki Nakano
Date: Tue, 17 May 2011 09:23:23 +0900
Subject: [PATCH 03/15] Bug 605648 Support high resolution scrolling on Windows
r=jimm+smaug
---
content/events/src/nsEventStateManager.cpp | 46 ++-
content/events/src/nsEventStateManager.h | 14 +-
widget/public/nsGUIEvent.h | 36 ++-
widget/public/nsGUIEventIPC.h | 54 +++-
widget/src/windows/nsWindow.cpp | 344 ++++++++++++++-------
widget/src/windows/nsWindow.h | 19 +-
widget/src/windows/nsWindowDefs.h | 4 +
7 files changed, 385 insertions(+), 132 deletions(-)
diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp
index dd06c8244294..b64732025582 100644
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1394,6 +1394,12 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
handler.OnQueryDOMWidgetHittest(static_cast(aEvent));
}
break;
+ case NS_QUERY_SCROLL_TARGET_INFO:
+ {
+ DoQueryScrollTargetInfo(static_cast(aEvent),
+ aTargetFrame);
+ break;
+ }
case NS_SELECTION_SET:
{
nsSelectionEvent *selectionEvent =
@@ -2564,7 +2570,8 @@ nsresult
nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
nsMouseScrollEvent* aMouseEvent,
nsIScrollableFrame::ScrollUnit aScrollQuantity,
- PRBool aAllowScrollSpeedOverride)
+ PRBool aAllowScrollSpeedOverride,
+ nsQueryContentEvent* aQueryEvent)
{
nsIScrollableFrame* frameToScroll = nsnull;
nsIFrame* scrollFrame = aTargetFrame;
@@ -2643,6 +2650,19 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
}
if (!passToParent && frameToScroll) {
+ if (aQueryEvent) {
+ nscoord appUnitsPerDevPixel =
+ aTargetFrame->PresContext()->AppUnitsPerDevPixel();
+ aQueryEvent->mReply.mLineHeight =
+ frameToScroll->GetLineScrollAmount().height / appUnitsPerDevPixel;
+ aQueryEvent->mReply.mPageHeight =
+ frameToScroll->GetPageScrollAmount().height / appUnitsPerDevPixel;
+ aQueryEvent->mReply.mPageWidth =
+ frameToScroll->GetPageScrollAmount().width / appUnitsPerDevPixel;
+ aQueryEvent->mSucceeded = PR_TRUE;
+ return NS_OK;
+ }
+
if (aScrollQuantity == nsIScrollableFrame::LINES) {
numLines =
nsMouseWheelTransaction::AccelerateWheelDelta(numLines, isHorizontal,
@@ -2670,7 +2690,9 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
nsIScrollableFrame::ScrollMode mode;
if (aMouseEvent->scrollFlags & nsMouseScrollEvent::kNoDefer) {
mode = nsIScrollableFrame::INSTANT;
- } else if (aScrollQuantity != nsIScrollableFrame::DEVICE_PIXELS) {
+ } else if (aScrollQuantity != nsIScrollableFrame::DEVICE_PIXELS ||
+ (aMouseEvent->scrollFlags &
+ nsMouseScrollEvent::kAllowSmoothScroll) != 0) {
mode = nsIScrollableFrame::SMOOTH;
} else {
mode = nsIScrollableFrame::NORMAL;
@@ -2688,7 +2710,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
if (newFrame)
return DoScrollText(newFrame, aMouseEvent, aScrollQuantity,
- aAllowScrollSpeedOverride);
+ aAllowScrollSpeedOverride, aQueryEvent);
}
aMouseEvent->scrollOverflow = numLines;
@@ -3051,7 +3073,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
}
if (aEvent->message == NS_MOUSE_PIXEL_SCROLL) {
- if (action == MOUSE_SCROLL_N_LINES ||
+ if (action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
action = MOUSE_SCROLL_PIXELS;
} else {
@@ -3059,7 +3081,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
action = -1;
}
} else if (msEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) {
- if (action == MOUSE_SCROLL_N_LINES ||
+ if (useSysNumLines || action == MOUSE_SCROLL_N_LINES ||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
// Don't scroll lines when a pixel scroll event will follow.
// Also, don't do history scrolling or zooming for momentum scrolls.
@@ -4646,6 +4668,20 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
return NS_OK;
}
+void
+nsEventStateManager::DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
+ nsIFrame* aTargetFrame)
+{
+ nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent;
+ nsIScrollableFrame::ScrollUnit unit;
+ if (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage) {
+ unit = nsIScrollableFrame::PAGES;
+ } else {
+ unit = nsIScrollableFrame::LINES;
+ }
+ DoScrollText(aTargetFrame, msEvent, unit, PR_FALSE, aEvent);
+}
+
void
nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
nsIContent* aContent)
diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h
index 5d64ea9a2680..60efc71c40b1 100644
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -324,10 +324,19 @@ protected:
nsMouseScrollEvent* aEvent,
nsPresContext* aPresContext,
nsEventStatus* aStatus);
+ /**
+ * @param aQueryEvent If you set vailid pointer for this, DoScrollText()
+ * computes the line-height and page size of current
+ * mouse wheel scroll target and sets it to the event.
+ * And then, this method does NOT scroll any scrollable
+ * elements. I.e., you can just query the scroll target
+ * information.
+ */
nsresult DoScrollText(nsIFrame* aTargetFrame,
nsMouseScrollEvent* aMouseEvent,
nsIScrollableFrame::ScrollUnit aScrollQuantity,
- PRBool aAllowScrollSpeedOverride);
+ PRBool aAllowScrollSpeedOverride,
+ nsQueryContentEvent* aQueryEvent = nsnull);
void DoScrollHistory(PRInt32 direction);
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
@@ -397,6 +406,9 @@ protected:
nsresult DoContentCommandEvent(nsContentCommandEvent* aEvent);
nsresult DoContentCommandScrollEvent(nsContentCommandEvent* aEvent);
+ void DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
+ nsIFrame* aTargetFrame);
+
PRBool RemoteQueryContentEvent(nsEvent *aEvent);
mozilla::dom::TabParent *GetCrossProcessTarget();
PRBool IsTargetCrossProcess(nsGUIEvent *aEvent);
diff --git a/widget/public/nsGUIEvent.h b/widget/public/nsGUIEvent.h
index ddea45e1bd0e..3747057b2262 100644
--- a/widget/public/nsGUIEvent.h
+++ b/widget/public/nsGUIEvent.h
@@ -415,6 +415,12 @@ class nsHashKey;
// Query if the DOM element under nsEvent::refPoint belongs to our widget
// or not.
#define NS_QUERY_DOM_WIDGET_HITTEST (NS_QUERY_CONTENT_EVENT_START + 9)
+// Query for some information about mouse wheel event's target
+// XXX This is used only for supporting high resolution mouse scroll on Windows
+// and it's going to be reimplemented with another approach. At that time,
+// this even is going to be removed. Therefore, DON'T use this event for
+// other purpose.
+#define NS_QUERY_SCROLL_TARGET_INFO (NS_QUERY_CONTENT_EVENT_START + 99)
// Video events
#ifdef MOZ_MEDIA
@@ -1188,9 +1194,11 @@ public:
// as needed.
kNoDefer = 1 << 5, // For scrollable views, indicates scroll should not
// occur asynchronously.
- kIsMomentum = 1 << 6 // Marks scroll events that aren't controlled by the
+ kIsMomentum = 1 << 6, // Marks scroll events that aren't controlled by the
// user but fire automatically as the result of a
// "momentum" scroll.
+ kAllowSmoothScroll = 1 << 7 // Allow smooth scroll for the pixel scroll
+ // event.
};
nsMouseScrollEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
@@ -1285,6 +1293,13 @@ public:
refPoint = aPoint;
}
+ void InitForQueryScrollTargetInfo(nsMouseScrollEvent* aEvent)
+ {
+ NS_ASSERTION(message == NS_QUERY_SCROLL_TARGET_INFO,
+ "wrong initializer is called");
+ mInput.mMouseScrollEvent = aEvent;
+ }
+
PRUint32 GetSelectionStart(void) const
{
NS_ASSERTION(message == NS_QUERY_SELECTED_TEXT,
@@ -1304,6 +1319,8 @@ public:
struct {
PRUint32 mOffset;
PRUint32 mLength;
+ // used by NS_QUERY_SCROLL_TARGET_INFO
+ nsMouseScrollEvent* mMouseScrollEvent;
} mInput;
struct {
void* mContentsRoot;
@@ -1317,6 +1334,10 @@ public:
PRPackedBool mWidgetIsHit; // true if DOM element under mouse belongs to widget
// used by NS_QUERY_SELECTION_AS_TRANSFERABLE
nsCOMPtr mTransferable;
+ // used by NS_QUERY_SCROLL_TARGET_INFO
+ PRInt32 mLineHeight;
+ PRInt32 mPageWidth;
+ PRInt32 mPageHeight;
} mReply;
enum {
@@ -1620,15 +1641,7 @@ enum nsDragDropEventStatus {
((evnt)->message == NS_PLUGIN_FOCUS))
#define NS_IS_QUERY_CONTENT_EVENT(evnt) \
- (((evnt)->message == NS_QUERY_SELECTED_TEXT) || \
- ((evnt)->message == NS_QUERY_TEXT_CONTENT) || \
- ((evnt)->message == NS_QUERY_CARET_RECT) || \
- ((evnt)->message == NS_QUERY_TEXT_RECT) || \
- ((evnt)->message == NS_QUERY_EDITOR_RECT) || \
- ((evnt)->message == NS_QUERY_CONTENT_STATE) || \
- ((evnt)->message == NS_QUERY_SELECTION_AS_TRANSFERABLE) || \
- ((evnt)->message == NS_QUERY_CHARACTER_AT_POINT) || \
- ((evnt)->message == NS_QUERY_DOM_WIDGET_HITTEST))
+ ((evnt)->eventStructType == NS_QUERY_CONTENT_EVENT)
#define NS_IS_SELECTION_EVENT(evnt) \
(((evnt)->message == NS_SELECTION_SET))
@@ -1670,7 +1683,8 @@ enum nsDragDropEventStatus {
// cases, you should use NS_IS_IME_RELATED_EVENT instead.
#define NS_IS_IME_RELATED_EVENT(evnt) \
(NS_IS_IME_EVENT(evnt) || \
- NS_IS_QUERY_CONTENT_EVENT(evnt) || \
+ (NS_IS_QUERY_CONTENT_EVENT(evnt) && \
+ evnt->message != NS_QUERY_SCROLL_TARGET_INFO) || \
NS_IS_SELECTION_EVENT(evnt))
/*
diff --git a/widget/public/nsGUIEventIPC.h b/widget/public/nsGUIEventIPC.h
index 9c1cb2be9696..78901256e199 100644
--- a/widget/public/nsGUIEventIPC.h
+++ b/widget/public/nsGUIEventIPC.h
@@ -109,6 +109,50 @@ struct ParamTraits
}
};
+template<>
+struct ParamTraits
+{
+ typedef nsMouseEvent_base paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, static_cast(aParam));
+ WriteParam(aMsg, aParam.button);
+ WriteParam(aMsg, aParam.pressure);
+ WriteParam(aMsg, aParam.inputSource);
+ }
+
+ static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+ {
+ return ReadParam(aMsg, aIter, static_cast(aResult)) &&
+ ReadParam(aMsg, aIter, &aResult->button) &&
+ ReadParam(aMsg, aIter, &aResult->pressure) &&
+ ReadParam(aMsg, aIter, &aResult->inputSource);
+ }
+};
+
+template<>
+struct ParamTraits
+{
+ typedef nsMouseScrollEvent paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, static_cast(aParam));
+ WriteParam(aMsg, aParam.scrollFlags);
+ WriteParam(aMsg, aParam.delta);
+ WriteParam(aMsg, aParam.scrollOverflow);
+ }
+
+ static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+ {
+ return ReadParam(aMsg, aIter, static_cast(aResult)) &&
+ ReadParam(aMsg, aIter, &aResult->scrollFlags) &&
+ ReadParam(aMsg, aIter, &aResult->delta) &&
+ ReadParam(aMsg, aIter, &aResult->scrollOverflow);
+ }
+};
+
template<>
struct ParamTraits
{
@@ -235,12 +279,16 @@ struct ParamTraits
WriteParam(aMsg, aParam.mSucceeded);
WriteParam(aMsg, aParam.mInput.mOffset);
WriteParam(aMsg, aParam.mInput.mLength);
+ WriteParam(aMsg, *aParam.mInput.mMouseScrollEvent);
WriteParam(aMsg, aParam.mReply.mOffset);
WriteParam(aMsg, aParam.mReply.mString);
WriteParam(aMsg, aParam.mReply.mRect);
WriteParam(aMsg, aParam.mReply.mReversed);
WriteParam(aMsg, aParam.mReply.mHasSelection);
WriteParam(aMsg, aParam.mReply.mWidgetIsHit);
+ WriteParam(aMsg, aParam.mReply.mLineHeight);
+ WriteParam(aMsg, aParam.mReply.mPageHeight);
+ WriteParam(aMsg, aParam.mReply.mPageWidth);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
@@ -250,12 +298,16 @@ struct ParamTraits
ReadParam(aMsg, aIter, &aResult->mSucceeded) &&
ReadParam(aMsg, aIter, &aResult->mInput.mOffset) &&
ReadParam(aMsg, aIter, &aResult->mInput.mLength) &&
+ ReadParam(aMsg, aIter, aResult->mInput.mMouseScrollEvent) &&
ReadParam(aMsg, aIter, &aResult->mReply.mOffset) &&
ReadParam(aMsg, aIter, &aResult->mReply.mString) &&
ReadParam(aMsg, aIter, &aResult->mReply.mRect) &&
ReadParam(aMsg, aIter, &aResult->mReply.mReversed) &&
ReadParam(aMsg, aIter, &aResult->mReply.mHasSelection) &&
- ReadParam(aMsg, aIter, &aResult->mReply.mWidgetIsHit);
+ ReadParam(aMsg, aIter, &aResult->mReply.mWidgetIsHit) &&
+ ReadParam(aMsg, aIter, &aResult->mReply.mLineHeight) &&
+ ReadParam(aMsg, aIter, &aResult->mReply.mPageHeight) &&
+ ReadParam(aMsg, aIter, &aResult->mReply.mPageWidth);
}
};
diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp
index 8dd2e2de26e6..79daf8bea828 100644
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -298,6 +298,18 @@ PRUint32 nsWindow::sOOPPPluginFocusEvent =
MSG nsWindow::sRedirectedKeyDown;
+PRBool nsWindow::sNeedsToInitMouseWheelSettings = PR_TRUE;
+ULONG nsWindow::sMouseWheelScrollLines = 0;
+ULONG nsWindow::sMouseWheelScrollChars = 0;
+
+HWND nsWindow::sLastMouseWheelWnd = NULL;
+PRInt32 nsWindow::sRemainingDeltaForScroll = 0;
+PRInt32 nsWindow::sRemainingDeltaForPixel = 0;
+PRBool nsWindow::sLastMouseWheelDeltaIsPositive = PR_FALSE;
+PRBool nsWindow::sLastMouseWheelOrientationIsVertical = PR_FALSE;
+PRBool nsWindow::sLastMouseWheelUnitIsPage = PR_FALSE;
+PRUint32 nsWindow::sLastMouseWheelTime = 0;
+
/**************************************************************
*
* SECTION: globals variables
@@ -4524,8 +4536,6 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
PRBool result = PR_FALSE; // call the default nsWindow proc
*aRetValue = 0;
- static PRBool getWheelInfo = PR_TRUE;
-
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
// Glass hit testing w/custom transparent margins
LRESULT dwmHitResult;
@@ -5187,7 +5197,12 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
break;
case WM_SETTINGCHANGE:
- getWheelInfo = PR_TRUE;
+ switch (wParam) {
+ case SPI_SETWHEELSCROLLLINES:
+ case SPI_SETWHEELSCROLLCHARS:
+ sNeedsToInitMouseWheelSettings = PR_TRUE;
+ break;
+ }
break;
case WM_INPUTLANGCHANGEREQUEST:
@@ -5259,8 +5274,9 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
// If OnMouseWheel returns false, OnMouseWheel processed the event internally.
// 'result' and 'aRetValue' will be set based on what we did with the event, so
// we should fall through.
- if (OnMouseWheel(msg, wParam, lParam, getWheelInfo, result, aRetValue))
+ if (OnMouseWheel(msg, wParam, lParam, result, aRetValue)) {
return result;
+ }
}
break;
@@ -6281,118 +6297,152 @@ PRUint16 nsWindow::GetMouseInputSource()
return inputSource;
}
+/* static */ void
+nsWindow::InitMouseWheelScrollData()
+{
+ if (!sNeedsToInitMouseWheelSettings) {
+ return;
+ }
+ sNeedsToInitMouseWheelSettings = PR_FALSE;
+ ResetRemainingWheelDelta();
+
+ if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
+ &sMouseWheelScrollLines, 0)) {
+ NS_WARNING("Failed to get SPI_GETWHEELSCROLLLINES");
+ sMouseWheelScrollLines = 3;
+ } else if (sMouseWheelScrollLines > WHEEL_DELTA) {
+ // sMouseWheelScrollLines usually equals 3 or 0 (for no scrolling)
+ // However, if sMouseWheelScrollLines > WHEEL_DELTA, we assume that
+ // the mouse driver wants a page scroll. The docs state that
+ // sMouseWheelScrollLines should explicitly equal WHEEL_PAGESCROLL, but
+ // since some mouse drivers use an arbitrary large number instead,
+ // we have to handle that as well.
+ sMouseWheelScrollLines = WHEEL_PAGESCROLL;
+ }
+
+ if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
+ &sMouseWheelScrollChars, 0)) {
+ NS_ASSERTION(!nsUXThemeData::sIsVistaOrLater,
+ "Failed to get SPI_GETWHEELSCROLLCHARS");
+ sMouseWheelScrollChars = 1;
+ } else if (sMouseWheelScrollChars > WHEEL_DELTA) {
+ // See the comments for the case sMouseWheelScrollLines > WHEEL_DELTA.
+ sMouseWheelScrollChars = WHEEL_PAGESCROLL;
+ }
+}
+
+/* static */
+void
+nsWindow::ResetRemainingWheelDelta()
+{
+ sRemainingDeltaForPixel = 0;
+ sRemainingDeltaForScroll = 0;
+ sLastMouseWheelWnd = NULL;
+}
+
+static PRInt32 RoundDelta(double aDelta)
+{
+ return aDelta >= 0 ? (PRInt32)NS_floor(aDelta) : (PRInt32)NS_ceil(aDelta);
+}
+
/*
* OnMouseWheel - mouse wheel event processing. This was originally embedded
* within the message case block. If returning true result should be returned
* immediately (no more processing).
*/
-PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& getWheelInfo, PRBool& result, LRESULT *aRetValue)
+PRBool
+nsWindow::OnMouseWheel(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
+ PRBool& aHandled, LRESULT *aRetValue)
{
- // Handle both flavors of mouse wheel events.
- static int iDeltaPerLine, iDeltaPerChar;
- static ULONG ulScrollLines, ulScrollChars = 1;
- static int currentVDelta, currentHDelta;
- static HWND currentWindow = 0;
+ InitMouseWheelScrollData();
- PRBool isVertical = msg == WM_MOUSEWHEEL;
-
- // Get mouse wheel metrics (but only once).
- if (getWheelInfo) {
- getWheelInfo = PR_FALSE;
-
- SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0);
-
- // ulScrollLines usually equals 3 or 0 (for no scrolling)
- // WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
-
- // However, if ulScrollLines > WHEEL_DELTA, we assume that
- // the mouse driver wants a page scroll. The docs state that
- // ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
- // since some mouse drivers use an arbitrary large number instead,
- // we have to handle that as well.
-
- iDeltaPerLine = 0;
- if (ulScrollLines) {
- if (ulScrollLines <= WHEEL_DELTA) {
- iDeltaPerLine = WHEEL_DELTA / ulScrollLines;
- } else {
- ulScrollLines = WHEEL_PAGESCROLL;
- }
- }
-
- if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
- &ulScrollChars, 0)) {
- // Note that we may always fail to get the value before Win Vista.
- ulScrollChars = 1;
- }
-
- iDeltaPerChar = 0;
- if (ulScrollChars) {
- if (ulScrollChars <= WHEEL_DELTA) {
- iDeltaPerChar = WHEEL_DELTA / ulScrollChars;
- } else {
- ulScrollChars = WHEEL_PAGESCROLL;
- }
- }
+ PRBool isVertical = (aMessage == WM_MOUSEWHEEL);
+ if ((isVertical && sMouseWheelScrollLines == 0) ||
+ (!isVertical && sMouseWheelScrollChars == 0)) {
+ // XXX I think that we should dispatch mouse wheel events even if the
+ // operation will not scroll because the wheel operation really happened
+ // and web application may want to handle the event for non-scroll action.
+ ResetRemainingWheelDelta();
+ *aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
+ aHandled = PR_FALSE;
+ return PR_FALSE;
}
- if ((isVertical && ulScrollLines != WHEEL_PAGESCROLL && !iDeltaPerLine) ||
- (!isVertical && ulScrollChars != WHEEL_PAGESCROLL && !iDeltaPerChar))
- return PR_FALSE; // break
-
// The mousewheel event will be dispatched to the toplevel
// window. We need to give it to the child window.
PRBool quit;
- if (!HandleScrollingPlugins(msg, wParam, lParam, result, aRetValue, quit))
+ if (!HandleScrollingPlugins(aMessage, aWParam, aLParam,
+ aHandled, aRetValue, quit)) {
+ ResetRemainingWheelDelta();
return quit; // return immediately if it's not our window
+ }
- // We should cancel the surplus delta if the current window is not
- // same as previous.
- if (currentWindow != mWnd) {
- currentVDelta = 0;
- currentHDelta = 0;
- currentWindow = mWnd;
- }
-
- nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
- scrollEvent.delta = 0;
- if (isVertical) {
- scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
- if (ulScrollLines == WHEEL_PAGESCROLL) {
- scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
- scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? -1 : 1;
- } else {
- currentVDelta -= (short) HIWORD (wParam);
- if (PR_ABS(currentVDelta) >= iDeltaPerLine) {
- scrollEvent.delta = currentVDelta / iDeltaPerLine;
- currentVDelta %= iDeltaPerLine;
- }
- }
- } else {
- scrollEvent.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
- if (ulScrollChars == WHEEL_PAGESCROLL) {
- scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
- scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? 1 : -1;
- } else {
- currentHDelta += (short) HIWORD (wParam);
- if (PR_ABS(currentHDelta) >= iDeltaPerChar) {
- scrollEvent.delta = currentHDelta / iDeltaPerChar;
- currentHDelta %= iDeltaPerChar;
- }
- }
- }
-
- if (!scrollEvent.delta) {
- // We store the wheel delta, and it will be used next wheel message, so,
- // we consume this message actually. We shouldn't call next wndproc.
- result = PR_TRUE;
- return PR_FALSE; // break
+ PRInt32 nativeDelta = (short)HIWORD(aWParam);
+ if (!nativeDelta) {
+ *aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
+ aHandled = PR_FALSE;
+ ResetRemainingWheelDelta();
+ return PR_FALSE; // We cannot process this message
}
// The event may go to a plug-in which already dispatched this message.
// Then, the event can cause deadlock. We should unlock the sender here.
::ReplyMessage(isVertical ? 0 : TRUE);
+ PRBool isPageScroll =
+ ((isVertical && sMouseWheelScrollLines == WHEEL_PAGESCROLL) ||
+ (!isVertical && sMouseWheelScrollChars == WHEEL_PAGESCROLL));
+
+ // Discard the remaining delta if current wheel message and last one are
+ // received by different window or to scroll different direction or
+ // different unit scroll. Furthermore, if the last event was too old.
+ PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
+ if (sLastMouseWheelWnd &&
+ (sLastMouseWheelWnd != mWnd ||
+ sLastMouseWheelDeltaIsPositive != (nativeDelta > 0) ||
+ sLastMouseWheelOrientationIsVertical != isVertical ||
+ sLastMouseWheelUnitIsPage != isPageScroll ||
+ now - sLastMouseWheelTime > 1500)) {
+ ResetRemainingWheelDelta();
+ }
+ sLastMouseWheelWnd = mWnd;
+ sLastMouseWheelDeltaIsPositive = (nativeDelta > 0);
+ sLastMouseWheelOrientationIsVertical = isVertical;
+ sLastMouseWheelUnitIsPage = isPageScroll;
+ sLastMouseWheelTime = now;
+
+ nsMouseScrollEvent testEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
+ InitEvent(testEvent);
+ testEvent.scrollFlags = isPageScroll ? nsMouseScrollEvent::kIsFullPage : 0;
+ testEvent.scrollFlags |= isVertical ? nsMouseScrollEvent::kIsVertical :
+ nsMouseScrollEvent::kIsHorizontal;
+ testEvent.delta = sLastMouseWheelDeltaIsPositive ? -1 : 1;
+ nsQueryContentEvent queryEvent(PR_TRUE, NS_QUERY_SCROLL_TARGET_INFO, this);
+ InitEvent(queryEvent);
+ queryEvent.InitForQueryScrollTargetInfo(&testEvent);
+ DispatchWindowEvent(&queryEvent);
+ // If the necessary interger isn't larger than 0, we should assume that
+ // the event failed for us.
+ if (queryEvent.mSucceeded) {
+ if (isPageScroll) {
+ if (isVertical) {
+ queryEvent.mSucceeded = (queryEvent.mReply.mPageHeight > 0);
+ } else {
+ queryEvent.mSucceeded = (queryEvent.mReply.mPageWidth > 0);
+ }
+ } else {
+ queryEvent.mSucceeded = (queryEvent.mReply.mLineHeight > 0);
+ }
+ }
+
+ *aRetValue = isVertical ? FALSE : TRUE; // means we process this message
+ nsModifierKeyState modKeyState;
+
+ // Our positive delta value means to bottom or right.
+ // But positive nativeDelta value means to top or right.
+ // Use orienter for computing our delta value.
+ PRInt32 orienter = isVertical ? -1 : 1;
+
// Assume the Control key is down if the Elantech touchpad has sent the
// mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in
// OnKeyUp.)
@@ -6401,25 +6451,97 @@ PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& ge
static_cast(::GetMessageTime()) < mAssumeWheelIsZoomUntil) {
isControl = PR_TRUE;
} else {
- isControl = IS_VK_DOWN(NS_VK_CONTROL);
+ isControl = modKeyState.mIsControlDown;
}
- scrollEvent.isShift = IS_VK_DOWN(NS_VK_SHIFT);
- scrollEvent.isControl = isControl;
- scrollEvent.isMeta = PR_FALSE;
- scrollEvent.isAlt = IS_VK_DOWN(NS_VK_ALT);
+ nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
InitEvent(scrollEvent);
- if (nsnull != mEventCallback) {
- result = DispatchWindowEvent(&scrollEvent);
- }
- // Note that we should return zero if we process WM_MOUSEWHEEL.
- // But if we process WM_MOUSEHWHEEL, we should return non-zero.
+ // If the query event failed, we cannot send pixel events.
+ scrollEvent.scrollFlags =
+ queryEvent.mSucceeded ? nsMouseScrollEvent::kHasPixels : 0;
+ scrollEvent.isShift = modKeyState.mIsShiftDown;
+ scrollEvent.isControl = isControl;
+ scrollEvent.isMeta = PR_FALSE;
+ scrollEvent.isAlt = modKeyState.mIsAltDown;
- if (result)
- *aRetValue = isVertical ? 0 : TRUE;
-
- return PR_FALSE; // break;
-}
+ PRInt32 nativeDeltaForScroll = nativeDelta + sRemainingDeltaForScroll;
+
+ if (isPageScroll) {
+ scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
+ if (isVertical) {
+ scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
+ } else {
+ scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
+ }
+ scrollEvent.delta = nativeDeltaForScroll * orienter / WHEEL_DELTA;
+ PRInt32 recomputedNativeDelta = scrollEvent.delta * orienter / WHEEL_DELTA;
+ sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
+ } else {
+ double deltaPerUnit;
+ if (isVertical) {
+ scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
+ deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollLines;
+ } else {
+ scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
+ deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollChars;
+ }
+ scrollEvent.delta =
+ RoundDelta((double)nativeDeltaForScroll * orienter / deltaPerUnit);
+ PRInt32 recomputedNativeDelta =
+ (PRInt32)(scrollEvent.delta * orienter * deltaPerUnit);
+ sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
+ }
+
+ if (scrollEvent.delta) {
+ aHandled = DispatchWindowEvent(&scrollEvent);
+ if (mOnDestroyCalled) {
+ ResetRemainingWheelDelta();
+ return PR_FALSE;
+ }
+ }
+
+ // If the query event failed, we cannot send pixel events.
+ if (!queryEvent.mSucceeded) {
+ sRemainingDeltaForPixel = 0;
+ return PR_FALSE;
+ }
+
+ nsMouseScrollEvent pixelEvent(PR_TRUE, NS_MOUSE_PIXEL_SCROLL, this);
+ InitEvent(pixelEvent);
+ pixelEvent.scrollFlags = nsMouseScrollEvent::kAllowSmoothScroll |
+ (scrollEvent.scrollFlags & ~nsMouseScrollEvent::kHasPixels);
+ pixelEvent.isShift = modKeyState.mIsShiftDown;
+ pixelEvent.isControl = modKeyState.mIsControlDown;
+ pixelEvent.isMeta = PR_FALSE;
+ pixelEvent.isAlt = modKeyState.mIsAltDown;
+
+ PRInt32 nativeDeltaForPixel = nativeDelta + sRemainingDeltaForPixel;
+
+ double deltaPerPixel;
+ if (isPageScroll) {
+ if (isVertical) {
+ deltaPerPixel = (double)WHEEL_DELTA / queryEvent.mReply.mPageHeight;
+ } else {
+ deltaPerPixel = (double)WHEEL_DELTA / queryEvent.mReply.mPageWidth;
+ }
+ } else {
+ if (isVertical) {
+ deltaPerPixel = (double)WHEEL_DELTA / sMouseWheelScrollLines;
+ } else {
+ deltaPerPixel = (double)WHEEL_DELTA / sMouseWheelScrollChars;
+ }
+ deltaPerPixel /= queryEvent.mReply.mLineHeight;
+ }
+ pixelEvent.delta =
+ RoundDelta((double)nativeDeltaForPixel * orienter / deltaPerPixel);
+ PRInt32 recomputedNativeDelta =
+ (PRInt32)(pixelEvent.delta * orienter * deltaPerPixel);
+ sRemainingDeltaForPixel = nativeDeltaForPixel - recomputedNativeDelta;
+ if (pixelEvent.delta != 0) {
+ aHandled = DispatchWindowEvent(&pixelEvent);
+ }
+ return PR_FALSE;
+}
static PRBool
StringCaseInsensitiveEquals(const PRUnichar* aChars1, const PRUint32 aNumChars1,
diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h
index 75a2b4bb7831..d6d98ca5c63a 100644
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -411,8 +411,8 @@ protected:
BOOL OnInputLangChange(HKL aHKL);
PRBool OnPaint(HDC aDC, PRUint32 aNestingLevel);
void OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
- PRBool OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam,
- PRBool& result, PRBool& getWheelInfo,
+ PRBool OnMouseWheel(UINT aMessage, WPARAM aWParam,
+ LPARAM aLParam, PRBool& aHandled,
LRESULT *aRetValue);
void OnWindowPosChanging(LPWINDOWPOS& info);
@@ -616,6 +616,20 @@ protected:
// was reirected to SendInput() API by OnKeyDown().
static MSG sRedirectedKeyDown;
+ static PRBool sNeedsToInitMouseWheelSettings;
+ static ULONG sMouseWheelScrollLines;
+ static ULONG sMouseWheelScrollChars;
+ static void InitMouseWheelScrollData();
+
+ static HWND sLastMouseWheelWnd;
+ static PRInt32 sRemainingDeltaForScroll;
+ static PRInt32 sRemainingDeltaForPixel;
+ static PRBool sLastMouseWheelDeltaIsPositive;
+ static PRBool sLastMouseWheelOrientationIsVertical;
+ static PRBool sLastMouseWheelUnitIsPage;
+ static PRUint32 sLastMouseWheelTime; // in milliseconds
+ static void ResetRemainingWheelDelta();
+
// If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is
// redirected message, OnKeyDowm() prevents to dispatch NS_KEY_DOWN event
// because it has been dispatched before the message was redirected.
@@ -649,7 +663,6 @@ protected:
nsRefPtr mWindow;
const MSG &mMsg;
};
-
};
/**
diff --git a/widget/src/windows/nsWindowDefs.h b/widget/src/windows/nsWindowDefs.h
index 3bd48bc2eb86..dfb593909c5c 100644
--- a/widget/src/windows/nsWindowDefs.h
+++ b/widget/src/windows/nsWindowDefs.h
@@ -90,6 +90,10 @@
#define SPI_GETWHEELSCROLLCHARS 0x006C
#endif
+#ifndef SPI_SETWHEELSCROLLCHARS
+#define SPI_SETWHEELSCROLLCHARS 0x006D
+#endif
+
#ifndef MAPVK_VSC_TO_VK
#define MAPVK_VK_TO_VSC 0
#define MAPVK_VSC_TO_VK 1
From 0c316873327a2df8ff0ec89a41f956c7676c1013 Mon Sep 17 00:00:00 2001
From: Randell Jesup
Date: Sun, 15 May 2011 05:47:48 -0400
Subject: [PATCH 04/15] Bug 653311 - Switch jprof from hand-rolled stackwalk
code to glibc's backtrace() to work with modern x86 Linuxes, improve jprof
output, update README - r=jim_nance (per bz)
---
tools/jprof/README.html | 133 ++++++++++++++++-------------
tools/jprof/leaky.cpp | 149 ++++++++++++++++++++++++++-------
tools/jprof/leaky.h | 7 +-
tools/jprof/stub/Makefile.in | 3 +
tools/jprof/stub/libmalloc.cpp | 69 ++++++++++++---
tools/jprof/stub/libmalloc.h | 1 +
6 files changed, 262 insertions(+), 100 deletions(-)
diff --git a/tools/jprof/README.html b/tools/jprof/README.html
index 9b910afc8ff6..3d5bc521e12a 100644
--- a/tools/jprof/README.html
+++ b/tools/jprof/README.html
@@ -6,7 +6,8 @@
The Jprof Profiler
-jim_nance@yahoo.com
+jim_nance@yahoo.com
+Recent (4/2011) updates Randell Jesup (see bugzilla for contact info)
@@ -46,12 +47,26 @@ default pull. To do this do:
ac_add_options --enable-jprof
to your .mozconfig
) and
making sure that you do not have the
--enable-strip
configure option set -- jprof needs symbols to
-operate.
+operate. On many architectures with GCC, you'll need to add
+--enable-optimize="-O3 -fno-omit-frame-pointer"
or the
+equivalent to ensure frame pointer generation in the compiler you're using.
Finally, build mozilla with your new configuration. Now you can run jprof.
-
+Options:
+
+ - -s depth : Limit depth looked at from captured stack
+ frames
+ - -v : Output some information about the symbols, memory map, etc.
+ - -t : Group output according to thread. Requires external
+ LD_PRELOAD library to help force sampling of spawned threads; jprof
+ normally captures the main thread only. See gprof-helper;
+ it may need adaption for jprof.
+ - -e exclusion : Allows excluding specific stack frames
+ - -i inclusion : Allows including specific stack frames
+
The behavior of jprof is determined by the value of the JPROF_FLAGS environment
variable. This environment variable can be composed of several substrings
which have the following meanings:
@@ -67,7 +82,8 @@ which have the following meanings:
JP_FIRST=x : Wait x seconds before starting the timer
JP_PERIOD=y : Set timer to interrupt every y seconds. Only
- values of y strictly greater than 0.001 are supported.
+ values of y greater than or equal to 0.001 are supported. Default is
+ 0.050 (50ms).
JP_REALTIME : Do the profiling in intervals of real time rather
than intervals of time used by the mozilla process (and the kernel
@@ -103,10 +119,10 @@ being profiled
setenv JPROF_FLAGS "JP_START JP_FIRST=3 JP_PERIOD=0.025"
- To make the timer start on your signal and fire every 1.5 milliseconds of
+ To make the timer start on your signal and fire every 1 millisecond of
program time use:
- setenv JPROF_FLAGS "JP_DEFER JP_PERIOD=0.0015"
+ setenv JPROF_FLAGS "JP_DEFER JP_PERIOD=0.001"
To make the timer start on your signal and fire every 10 milliseconds of
wall-clock time use:
@@ -189,82 +205,87 @@ corresponding to one function. A typical section looks something like
this:
- 141300 PL_ProcessPendingEvents
- 927 PL_ProcessEventsBeforeID
- 29358 0 142227 PL_HandleEvent
- 92394 nsInputStreamReadyEvent::EventHandler(PLEvent*)
- 49181 HandlePLEvent(ReflowEvent*)
- 481 handleTimerEvent(TimerEventType*)
- 158 nsTransportStatusEvent::HandleEvent(PLEvent*)
- 9 PL_DestroyEvent
-
- 4 __restore_rt
+ index Count Hits Function Name
+ 545 (46.4%) nsBlockFrame::ReflowInlineFrames(nsBlockReflowState&, nsLineList_iterator, int*)
+ 100 (8.5%) nsBlockFrame::ReflowDirtyLines(nsBlockReflowState&)
+ 72870 4 (0.3%) 645 (54.9%) nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, int*, LineReflowStatus*, int)
+ 545 (46.4%) nsBlockFrame::ReflowInlineFrame(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*)
+ 83 (7.1%) nsBlockFrame::PlaceLine(nsBlockReflowState&, nsLineLayout&, nsLineList_iterator, nsFloatManager::SavedState*, nsRect&, int&, int*)
+ 9 (0.8%) nsLineLayout::BeginLineReflow(int, int, int, int, int, int)
+ 1 (0.1%) nsTextFrame::GetType() const
+ 1 (0.1%) nsLineLayout::RelativePositionFrames(nsOverflowAreas&)
+ 1 (0.1%) __i686.get_pc_thunk.bx
+ 1 (0.1%) PL_ArenaAllocate
The information this block tells us is:
-- There were 0 profiler hits in
PL_HandleEvent
- - There were 142227 profiler hits under
PL_HandleEvent
. Of these:
+ - There were 4 profiler hits in
nsBlockFrame::DoReflowInlineFrames
+ - There were 645 profiler hits in or under
nsBlockFrame::DoReflowInlineFrames
. Of these:
- - 92394 were in or under
nsInputStreamReadyEvent::EventHandler
- - 49181 were in or under
HandlePLEvent(ReflowEvent*)
- - 481 were in or under
handleTimerEvent
- - 158 were in or under
nsTransportStatusEvent::HandleEvent
- - 9 were in or under
PL_DestroyEvent
- - 4 were in or under
__restore_rt
+ - 545 were in or under
nsBlockFrame::ReflowInlineFrame
+ - 83 were in or under
nsBlockFrame::PlaceLine
+ - 9 were in or under
nsLineLayout::BeginLineReflow
+ - 1 was in or under
nsTextFrame::GetType
+ - 1 was in or under
nsLineLayout::RelativePositionFrames
+ - 1 was in or under
__i686.get_pc_thunk.bx
+ - 1 was in or under
PL_ArenaAllocate
- - Of these 142227 calls into
PL_HandleEvent
:
+ - Of these 645 calls into
nsBlockFrame::DoReflowInlineFrames
:
- - 141300 came from
PL_ProcessPendingEvents
- - 927 came from
PL_ProcessEventsBeforeID
+ - 545 came from
nsBlockFrame::ReflowInlineFrames
+ - 100 came from
nsBlockFrame::ReflowDirtyLines
The rest of this section explains how to read this information off from the jprof output.
-This block corresponds to the function PL_HandleEvent
, which is
+
This block corresponds to the function nsBlockFrame::DoReflowInlineFrames
, which is
therefore bolded and not a link. The name of this function is preceded by
-three numbers which have the following meaning. The number on the left (29358)
-is the index number, and is not important. The center number (0) is the number
-of times this function was interrupted by the timer. The last number (142227)
-is the number of times this function was in the call stack when the timer went
+five numbers which have the following meaning. The number on the left (72870)
+is the index number, and is not important. The next number (4) and the
+percentage following (0.3%) are the number
+of times this function was interrupted by the timer and the percentage of
+the total hits that is. The last number pair ("645 (54.9%)")
+are the number of times this function was in the call stack when the timer went
off. That is, the timer went off while we were in code that was ultimately
-called from PL_HandleEvent
.
+called from nsBlockFrame::DoReflowInlineFrames
.
For our example we can see that our function was in the call stack for
-142227 interrupt ticks, but we were never the function that was running when
-the interrupt arrived.
+645 interrupt ticks, but we were only the function that was running when
+the interrupt arrived 4 times.
-The functions listed above the line for PL_HandleEvent
are its
+The functions listed above the line for nsBlockFrame::DoReflowInlineFrames
are its
callers. The numbers to the left of these function names are the numbers of
times these functions were in the call stack as callers of
-PL_HandleEvent
. In our example, we were called 927 times by
-PL_ProcessEventsBeforeID
and 141300 times by
-PL_ProcessPendingEvents
.
+nsBlockFrame::DoReflowInlineFrames
. In our example, we were called 545 times by
+nsBlockFrame::ReflowInlineFrames
and 100 times by
+nsBlockFrame::ReflowDirtyLines
.
-The functions listed below the line for PL_HandleEvent
are its
+The functions listed below the line for nsBlockFrame::DoReflowInlineFrames
are its
callees. The numbers to the left of the function names are the numbers of
-times these functions were in the callstack as callees of PL_HandleEvent
. In our example, of the 142227 profiler hits under PL_HandleEvent
92394 were under nsInputStreamReadyEvent::EventHandler
, 49181 were under HandlePLEvent(ReflowEvent*)
, and so forth.
+times these functions were in the callstack as callees of
+nsBlockFrame::DoReflowInlineFrames
and the corresponding percentages. In our example, of the 645 profiler hits under nsBlockFrame::DoReflowInlineFrames
545 were under nsBlockFrame::ReflowInlineFrame
, 83 were under nsBlockFrame::PlaceLine
, and so forth.
+
+NOTE: If there are loops of execution or recursion, the numbers will
+not add up and percentages can exceed 100%. If a function directly calls
+itself "(self)" will be appended to the line, but indirect recursion will
+not be marked.
Bugs
-Jprof has only been tested under Red Hat Linux 6.0, 6.1, and 6.2. It does
-not work under 6.0, though it is possible hack up the source code and make
-it work there. The way I determine the stack trace from inside the
-signal handler is tightly bound to the version of glibc that is running.
-If you know of a more portable way to get this information please let
-me know.
-
-Update
+The current build of Jprof has only been tested under Ubuntu 8.04 LTS, but
+should work under any fairly modern linux distribution using GCC/GLIBC.
+Please update this document with any known compatibilities/incompatibilities.
+
+If you get an error:
Inconsistency detected by ld.so: dl-open.c: 260: dl_open_worker: Assertion `_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT' failed!
+
that means you've hit a timing hole in the version of glibc you're
+running. See Redhat bug 4578.
+