Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: c7bdb5bcd411cab772466fdc79661c41c115095a
https://github.com/WebKit/WebKit/commit/c7bdb5bcd411cab772466fdc79661c41c115095a
Author: Wenson Hsieh <[email protected]>
Date: 2023-06-14 (Wed, 14 Jun 2023)
Changed paths:
M Source/WebCore/Sources.txt
M Source/WebCore/WebCore.xcodeproj/project.pbxproj
M Source/WebCore/dom/ScriptExecutionContext.h
M Source/WebCore/page/DOMTimer.cpp
M Source/WebCore/page/DOMTimer.h
M Source/WebCore/page/LocalFrameView.cpp
A Source/WebCore/page/OpportunisticTaskScheduler.cpp
A Source/WebCore/page/OpportunisticTaskScheduler.h
M Source/WebCore/page/Page.cpp
M Source/WebCore/page/Page.h
M Source/WebCore/platform/RunLoopObserver.h
M Source/WebCore/platform/cf/RunLoopObserverCF.cpp
Log Message:
-----------
Add a mechanism to schedule opportunistic work in between rendering updates
https://bugs.webkit.org/show_bug.cgi?id=258032
rdar://110076652
Reviewed by Ryosuke Niwa.
Add an `OpportunisticTaskScheduler` helper class to be used in a subsequent
patch to dispatch
periodically-scheduled cleanup tasks, such as incremental sweeping, in between
rendering updates
(i.e. after the runloop begins to wait for more work, but before the next
rendering update is
scheduled to start).
This `OpportunisticTaskScheduler` is essentially a wrapper around a
`RunLoopObserver`, which calls
into `Page` to perform scheduled work until a given deadline. The `Page` is the
only entity that
owns the task scheduler, and will tell it to reschedule after every rendering
update. Additionally,
we introduce another mechanism — `OpportunisticTaskDeferralScope` — that
prevents the task scheduler
from firing during certain time intervals where we know that scheduled work is
imminent. For now,
this just includes:
1. Scheduled one-shot timers with a very short duration.
2. Any time prior to first paint, after navigation.
No change in behavior (yet).
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/ScriptExecutionContext.h:
(WebCore::ScriptExecutionContext::addTimeout):
(WebCore::ScriptExecutionContext::takeTimeout):
(WebCore::ScriptExecutionContext::removeTimeout): Deleted.
Change `removeTimeout` to `takeTimeout`, and have it return the removed
`DOMTimer`. This allows us
to (more easily) call `clearOpportunisticTaskDeferralScopeIfPossible()` on the
removed timer below.
* Source/WebCore/page/DOMTimer.cpp:
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::removeById):
(WebCore::DOMTimer::fired):
(WebCore::DOMTimer::didStop):
(WebCore::DOMTimer::makeOpportunisticTaskDeferralScopeIfPossible):
(WebCore::DOMTimer::clearOpportunisticTaskDeferralScopeIfPossible):
Add a opportunistic task deferral scope to prevent us from scheduling
opportunistic tasks in the
case where one-shot zero-delay timers are about to fire.
* Source/WebCore/page/DOMTimer.h:
* Source/WebCore/page/LocalFrameView.cpp:
(WebCore::LocalFrameView::fireLayoutRelatedMilestonesIfNeeded):
Add some plumbing to notify `Page` when we hit first meaningful paint.
* Source/WebCore/page/OpportunisticTaskScheduler.cpp: Added.
(WebCore::OpportunisticTaskDeferralScope::OpportunisticTaskDeferralScope):
(WebCore::OpportunisticTaskDeferralScope::~OpportunisticTaskDeferralScope):
Add a RAII helper class to increment and decrement the deferral count in
`OpportunisticTaskScheduler`, which prevents opportunistically scheduled tasks
from firing; this
RAII pattern hopefully makes it a bit easier to ensure that nothing ends up
with unbalanced calls to
increment or decrement.
(WebCore::OpportunisticTaskScheduler::OpportunisticTaskScheduler):
(WebCore::OpportunisticTaskScheduler::reschedule):
Helper method to reschedule the task scheduler, with a target deadline; called
after completing
rendering updates in `Page`.
(WebCore::OpportunisticTaskScheduler::makeDeferralScope):
Helper method to make a `OpportunisticTaskDeferralScope`, which increments the
deferral count (and
only decrements the count upon detroying the scope).
(WebCore::OpportunisticTaskScheduler::runLoopObserverFired):
Call into page to `performOpportunisticallyScheduledTasks`, once the runloop
observer fires (i.e.,
the runloop has become idle) and only if we still have remaining time until the
next deadline (which
is established when we were most recently rescheduled). This ensures that if
post-rendering-update
tasks take a long time to finish and another rendering update is imminent,
we'll skip this
opportunistic task call entirely, and instead do the work when we're less busy.
(WebCore::OpportunisticTaskScheduler::incrementDeferralCount):
(WebCore::OpportunisticTaskScheduler::decrementDeferralCount):
Private methods to manage the task deferral count; while the count is non-zero,
we avoid calling
into the page to perform opportunistic tasks. When the deferral count is
restored to 0, we then
wait for the runloop to become idle (via `RunLoopObserver`), and then run tasks
if appropriate.
* Source/WebCore/page/OpportunisticTaskScheduler.h: Added.
(WebCore::OpportunisticTaskScheduler::create):
* Source/WebCore/page/Page.cpp:
(WebCore::Page::didCommitLoad):
(WebCore::Page::didFirstMeaningfulPaint):
Hold on to a `OpportunisticTaskDeferralScope` before the page has finished
first paint.
(WebCore::Page::renderingUpdateCompleted):
Reschedule opportunistic tasks (see above for more information).
(WebCore::Page::performOpportunisticallyScheduledTasks):
Leave an empty method stub for now; in the next patch, this will call into a
new `JSC::VM`
entrypoint to perform some pre-scheduled, periodic cleanup tasks, such as
running the incremental
sweeper until the deadline.
* Source/WebCore/page/Page.h:
(WebCore::Page::opportunisticTaskScheduler const):
* Source/WebCore/platform/RunLoopObserver.h:
(WebCore::RunLoopObserver::RunLoopObserver):
(WebCore::RunLoopObserver::isRepeating const):
* Source/WebCore/platform/cf/RunLoopObserverCF.cpp:
(WebCore::RunLoopObserver::schedule):
Add an option to make the `RunLoopObserver` one-shot (as opposed to repeating).
We use this flag
when creating runloop observers in the new `OpportunisticTaskScheduler`, since
we don't want the
runloop observer to continue listening forever.
Canonical link: https://commits.webkit.org/265178@main
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes