Bug 1470260 - Part 2: Make RefreshDriverTimer ref-counted and hold a strong ref on it on the stack when nsRefreshDriver::Tick can be reached.

This commit is contained in:
wolfbeast 2018-09-10 22:22:16 +02:00 committed by Roy Tam
commit f2dad4be1f

View file

@ -143,11 +143,7 @@ public:
{
}
virtual ~RefreshDriverTimer()
{
MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!");
MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!");
}
NS_INLINE_DECL_REFCOUNTING(RefreshDriverTimer)
virtual void AddRefreshDriver(nsRefreshDriver* aDriver)
{
@ -253,6 +249,12 @@ public:
}
protected:
virtual ~RefreshDriverTimer()
{
MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!");
MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!");
}
virtual void StartTimer() = 0;
virtual void StopTimer() = 0;
virtual void ScheduleNextTick(TimeStamp aNowTime) = 0;
@ -335,10 +337,11 @@ protected:
nsTArray<RefPtr<nsRefreshDriver> > mRootRefreshDrivers;
// useful callback for nsITimer-based derived classes, here
// bacause of c++ protected shenanigans
// because of c++ protected shenanigans
static void TimerTick(nsITimer* aTimer, void* aClosure)
{
RefreshDriverTimer *timer = static_cast<RefreshDriverTimer*>(aClosure);
RefPtr<RefreshDriverTimer> timer =
static_cast<RefreshDriverTimer*>(aClosure);
timer->Tick();
}
};
@ -459,9 +462,7 @@ public:
private:
// Since VsyncObservers are refCounted, but the RefreshDriverTimer are
// explicitly shutdown. We create an inner class that has the VsyncObserver
// and is shutdown when the RefreshDriverTimer is deleted. The alternative is
// to (a) make all RefreshDriverTimer RefCounted or (b) use different
// VsyncObserver types.
// and is shutdown when the RefreshDriverTimer is deleted.
class RefreshDriverVsyncObserver final : public VsyncObserver
{
public:
@ -576,7 +577,9 @@ private:
// the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer
// before use.
if (mVsyncRefreshDriverTimer) {
mVsyncRefreshDriverTimer->RunRefreshDrivers(aVsyncTimestamp);
RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer;
timer->RunRefreshDrivers(aVsyncTimestamp);
// Note: mVsyncRefreshDriverTimer might be null now.
}
}
@ -829,7 +832,8 @@ protected:
static void TimerTickOne(nsITimer* aTimer, void* aClosure)
{
InactiveRefreshDriverTimer *timer = static_cast<InactiveRefreshDriverTimer*>(aClosure);
RefPtr<InactiveRefreshDriverTimer> timer =
static_cast<InactiveRefreshDriverTimer*>(aClosure);
timer->TickOne();
}
@ -881,8 +885,8 @@ NS_IMPL_ISUPPORTS(VsyncChildCreateCallback, nsIIPCBackgroundChildCreateCallback)
} // namespace mozilla
static RefreshDriverTimer* sRegularRateTimer;
static InactiveRefreshDriverTimer* sThrottledRateTimer;
static StaticRefPtr<RefreshDriverTimer> sRegularRateTimer;
static StaticRefPtr<InactiveRefreshDriverTimer> sThrottledRateTimer;
#ifdef XP_WIN
static int32_t sHighPrecisionTimerRequests = 0;
@ -964,8 +968,6 @@ GetFirstFrameDelay(imgIRequest* req)
nsRefreshDriver::Shutdown()
{
// clean up our timers
delete sRegularRateTimer;
delete sThrottledRateTimer;
sRegularRateTimer = nullptr;
sThrottledRateTimer = nullptr;
@ -2229,16 +2231,15 @@ nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!XRE_IsParentProcess());
auto* vsyncRefreshDriverTimer =
new VsyncRefreshDriverTimer(aVsyncChild);
RefPtr<RefreshDriverTimer> vsyncRefreshDriverTimer =
new VsyncRefreshDriverTimer(aVsyncChild);
// If we are using software timer, swap current timer to
// VsyncRefreshDriverTimer.
if (sRegularRateTimer) {
sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer);
delete sRegularRateTimer;
}
sRegularRateTimer = vsyncRefreshDriverTimer;
sRegularRateTimer = vsyncRefreshDriverTimer.forget();
}
void