Source/WebCore/ChangeLog

 12021-07-23 Myles C. Maxfield <mmaxfield@apple.com>
 2
 3 [GPU Process] Add resource use counter infrastructure to RemoteResourceCache
 4 https://bugs.webkit.org/show_bug.cgi?id=228222
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This is part 2 of https://bugs.webkit.org/show_bug.cgi?id=228216.
 9
 10 No new tests because there is no behavior change yet. This patch is just adding infrastructure. For now, all these
 11 use counts sent by the web process are 0 - I'll implement that part in 3 follow-up patches.
 12
 13 * platform/graphics/displaylists/DisplayListReplayer.h:
 14 (WebCore::DisplayList::Replayer::Delegate::recordResourceUse):
 15
1162021-07-23 Andres Gonzalez <andresg_22@apple.com>
217
318 Add a method to WebAccessibilityObjectWrapper so that clients can retrieve the text of each line and their corresponding bounding rectangles.

Source/WebKit/ChangeLog

 12021-07-23 Myles C. Maxfield <mmaxfield@apple.com>
 2
 3 [GPU Process] Add resource use counter infrastructure to RemoteResourceCache
 4 https://bugs.webkit.org/show_bug.cgi?id=228222
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This patch adds the infrastructure for associating a counter with each resource in the RemoteResourceCache.
 9 As the web process uses a resource during display list recording, it increments a counter, and as the GPU
 10 process uses a resource, it increments a counter in the RemoteResourceCache. When the web process is done
 11 with a resource, it sends a release message to the GPU process which crucially includes the web process's
 12 counter. The GPU process has to then wait to actually delete the resource until its own use counter matches
 13 the one it received from the web process. This patch implements this deferred deletion infrastructure
 14 in the GPU process.
 15
 16 * GPUProcess/graphics/RemoteRenderingBackend.cpp:
 17 (WebKit::RemoteRenderingBackend::ReplayerDelegate::recordResourceUse):
 18 (WebKit::RemoteRenderingBackend::releaseRemoteResource): Pass the use count to the RemoteResourceCache.
 19 * GPUProcess/graphics/RemoteRenderingBackend.h: Add the use count field.
 20 * GPUProcess/graphics/RemoteRenderingBackend.messages.in: Ditto.
 21 * GPUProcess/graphics/RemoteResourceCache.cpp:
 22 (WebKit::RemoteResourceCache::cacheImageBuffer): It's actually okay if there's already an resource cached.
 23 That just means that the web process started using a resource again before the GPU process consumed all
 24 commands that used it the first time. All we need to do is increment the open count.
 25 (WebKit::RemoteResourceCache::cacheNativeImage): Ditto.
 26 (WebKit::RemoteResourceCache::cacheFont): Ditto.
 27 (WebKit::RemoteResourceCache::ensureResourceUseCounter):
 28 (WebKit::RemoteResourceCache::maybeRemoveResource): This is called whenever it's possible for us to be in
 29 situation where we should be removing a resource (aka whenever the use count increments). It checks to see
 30 if we can remove the resource, and if it can, does so.
 31 (WebKit::RemoteResourceCache::recordResourceUse): The callback that runs for each resource use during
 32 replaying. It can't actually delete any resources, so instead it just records which resources had their
 33 use counts incremented, and waits for prune() to actually call maybeRemoveResource().
 34 (WebKit::RemoteResourceCache::prune): After the replay is complete, call maybeRemoveResource() on all the
 35 resources which had their use counters touched.
 36 (WebKit::RemoteResourceCache::releaseRemoteResource): Put the relevant resource into the state where we
 37 are waiting for the use counters to match before we can delete the resource. Also, call maybeRemoveResource()
 38 so it can be deleted immediately if the counters already match.
 39 * GPUProcess/graphics/RemoteResourceCache.h: Add a new data structure to hold the use counters. There's
 40 a big comment in here that describes what these fields mean.
 41 * WebProcess/GPU/graphics/RemoteImageBufferProxy.h:
 42 (WebKit::RemoteImageBufferProxy::~RemoteImageBufferProxy): Send a dummy use count for now. This will be
 43 implemented in a follow-up patch.
 44 * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
 45 (WebKit::RemoteRenderingBackendProxy::releaseRemoteResource): Add the useCount parameter.
 46 * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h: Ditto.
 47 * WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp:
 48 (WebKit::RemoteResourceCacheProxy::releaseNativeImage): Send a dummy use count for now. This will be
 49 implemented in a follow-up patch.
 50 (WebKit::RemoteResourceCacheProxy::clearFontMap): Ditto.
 51 (WebKit::RemoteResourceCacheProxy::finalizeRenderingUpdateForFonts): Ditto.
 52
1532021-07-23 Alex Christensen <achristensen@webkit.org>
254
355 Make WKContentRuleListStore respond to same selectors as _WKUserContentExtensionStore

Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h

@@public:
6868 virtual bool apply(ItemHandle, GraphicsContext&) { return false; }
6969 virtual void didCreateMaskImageBuffer(WebCore::ImageBuffer&) { }
7070 virtual void didResetMaskImageBuffer() { }
 71 virtual void recordResourceUse(RenderingResourceIdentifier) { }
7172 };
7273
7374private:

Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp

@@void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, Ren
184184 wakeUpAndApplyDisplayList(std::exchange(m_pendingWakeupInfo, std::nullopt)->arguments);
185185}
186186
187 RemoteRenderingBackend::ReplayerDelegate::ReplayerDelegate(WebCore::ImageBuffer& destination, RemoteRenderingBackend& remoteRenderingBackend, GPUConnectionToWebProcess& gpuConnectionToWebProcess)
 187RemoteRenderingBackend::ReplayerDelegate::ReplayerDelegate(WebCore::ImageBuffer& destination, RemoteRenderingBackend& remoteRenderingBackend)
188188 : m_destination(destination)
189189 , m_remoteRenderingBackend(remoteRenderingBackend)
190  , m_gpuConnectionToWebProcess(gpuConnectionToWebProcess)
191190{
192191}
193192
194193bool RemoteRenderingBackend::ReplayerDelegate::apply(WebCore::DisplayList::ItemHandle item, WebCore::GraphicsContext& graphicsContext)
195194{
196  // FIXME: Inspect the item and record resource use here.
197 
198195 auto apply = [&](auto&& destination) {
199196 return destination.apply(item, graphicsContext);
200197 };

@@void RemoteRenderingBackend::ReplayerDelegate::didResetMaskImageBuffer()
214211 m_remoteRenderingBackend.didResetMaskImageBuffer();
215212}
216213
 214void RemoteRenderingBackend::ReplayerDelegate::recordResourceUse(RenderingResourceIdentifier renderingResourceIdentifier)
 215{
 216 m_remoteRenderingBackend.remoteResourceCache().recordResourceUse(renderingResourceIdentifier);
 217}
 218
217219DisplayList::ReplayResult RemoteRenderingBackend::submit(const DisplayList::DisplayList& displayList, ImageBuffer& destination)
218220{
219221 if (displayList.isEmpty())
220222 return { };
221223
222  ReplayerDelegate replayerDelegate(destination, *this, m_gpuConnectionToWebProcess);
 224 ReplayerDelegate replayerDelegate(destination, *this);
223225
224226 return WebCore::DisplayList::Replayer {
225227 destination.context(),

@@void RemoteRenderingBackend::deleteAllFonts()
509511 m_remoteResourceCache.deleteAllFonts();
510512}
511513
512 void RemoteRenderingBackend::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier)
 514void RemoteRenderingBackend::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier, uint64_t useCount)
513515{
514516 ASSERT(!RunLoop::isMain());
515  m_remoteResourceCache.releaseRemoteResource(renderingResourceIdentifier);
 517 auto success = m_remoteResourceCache.releaseRemoteResource(renderingResourceIdentifier, useCount);
 518 MESSAGE_CHECK(success, "Resource is being released before being cached.");
516519 updateRenderingResourceRequest();
517520}
518521

Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h

@@private:
144144 void cacheNativeImage(const ShareableBitmap::Handle&, WebCore::RenderingResourceIdentifier);
145145 void cacheFont(Ref<WebCore::Font>&&);
146146 void deleteAllFonts();
147  void releaseRemoteResource(WebCore::RenderingResourceIdentifier);
 147 void releaseRemoteResource(WebCore::RenderingResourceIdentifier, uint64_t useCount);
148148 void didCreateSharedDisplayListHandle(WebCore::DisplayList::ItemBufferIdentifier, const SharedMemory::IPCHandle&, WebCore::RenderingResourceIdentifier destinationBufferIdentifier);
149149
150150 class ReplayerDelegate : public WebCore::DisplayList::Replayer::Delegate {
151151 public:
152  ReplayerDelegate(WebCore::ImageBuffer&, RemoteRenderingBackend&, GPUConnectionToWebProcess&);
 152 ReplayerDelegate(WebCore::ImageBuffer&, RemoteRenderingBackend&);
153153
154154 private:
155155 bool apply(WebCore::DisplayList::ItemHandle, WebCore::GraphicsContext&) final;
156156 void didCreateMaskImageBuffer(WebCore::ImageBuffer&) final;
157157 void didResetMaskImageBuffer() final;
 158 void recordResourceUse(WebCore::RenderingResourceIdentifier) final;
158159
159160 WebCore::ImageBuffer& m_destination;
160161 RemoteRenderingBackend& m_remoteRenderingBackend;
161  Ref<GPUConnectionToWebProcess> m_gpuConnectionToWebProcess;
162162 };
163163
164164 struct PendingWakeupInformation {

Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in

@@messages -> RemoteRenderingBackend {
3636 CacheFont(IPC::FontReference font)
3737 DeleteAllFonts()
3838 DidCreateSharedDisplayListHandle(WebCore::DisplayList::ItemBufferIdentifier identifier, WebKit::SharedMemory::IPCHandle handle, WebCore::RenderingResourceIdentifier destinationBufferIdentifier)
39  ReleaseRemoteResource(WebCore::RenderingResourceIdentifier renderingResourceIdentifier)
 39 ReleaseRemoteResource(WebCore::RenderingResourceIdentifier renderingResourceIdentifier, uint64_t useCount)
4040}
4141
4242#endif // ENABLE(GPU_PROCESS)

Source/WebKit/GPUProcess/graphics/RemoteResourceCache.cpp

@@using namespace WebCore;
3333
3434void RemoteResourceCache::cacheImageBuffer(Ref<ImageBuffer>&& imageBuffer)
3535{
36  auto addResult = m_imageBuffers.add(imageBuffer->renderingResourceIdentifier(), WTFMove(imageBuffer));
37  ASSERT_UNUSED(addResult, addResult.isNewEntry);
 36 auto renderingResourceIdentifier = imageBuffer->renderingResourceIdentifier();
 37 m_imageBuffers.add(renderingResourceIdentifier, WTFMove(imageBuffer));
 38
 39 ensureResourceUseCounter(renderingResourceIdentifier);
3840}
3941
4042ImageBuffer* RemoteResourceCache::cachedImageBuffer(RenderingResourceIdentifier renderingResourceIdentifier)

@@ImageBuffer* RemoteResourceCache::cachedImageBuffer(RenderingResourceIdentifier
4446
4547void RemoteResourceCache::cacheNativeImage(Ref<NativeImage>&& image)
4648{
47  auto addResult = m_nativeImages.add(image->renderingResourceIdentifier(), WTFMove(image));
48  ASSERT_UNUSED(addResult, addResult.isNewEntry);
 49 auto renderingResourceIdentifier = image->renderingResourceIdentifier();
 50 m_nativeImages.add(renderingResourceIdentifier, WTFMove(image));
 51
 52 ensureResourceUseCounter(renderingResourceIdentifier);
4953}
5054
5155void RemoteResourceCache::cacheFont(Ref<Font>&& font)
5256{
53  auto addResult = m_fonts.add(font->renderingResourceIdentifier(), WTFMove(font));
54  ASSERT_UNUSED(addResult, addResult.isNewEntry);
 57 auto renderingResourceIdentifier = font->renderingResourceIdentifier();
 58 m_fonts.add(renderingResourceIdentifier, WTFMove(font));
 59
 60 ensureResourceUseCounter(renderingResourceIdentifier);
 61}
 62
 63void RemoteResourceCache::ensureResourceUseCounter(RenderingResourceIdentifier renderingResourceIdentifier)
 64{
 65 auto result = m_resourceUseCounters.add(renderingResourceIdentifier, ResourceUseCounter { });
 66 if (!result.isNewEntry) {
 67 auto& state = result.iterator->value.state;
 68 RELEASE_ASSERT(state == ResourceState::ToBeDeleted);
 69 state = ResourceState::Alive;
 70 }
5571}
5672
5773void RemoteResourceCache::deleteAllFonts()

@@void RemoteResourceCache::deleteAllFonts()
5975 m_fonts.clear();
6076}
6177
62 void RemoteResourceCache::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier)
 78bool RemoteResourceCache::maybeRemoveResource(RenderingResourceIdentifier renderingResourceIdentifier, ResourceUseCountersMap::iterator& iterator)
6379{
 80 // It's actually okay if useCount > 0.
 81 // It just means that there's a cache message pending, and we've eagerly used a previously-cached resource.
 82 // Which is fine.
 83 // FIXME: Maybe we shouldn't actually remove the resource in this situation?
 84 // We may actually be able to get a head start on some display list items if they're ready for us and we have the resources they depend on.
 85
 86 auto& value = iterator->value;
 87 if (value.state == ResourceState::Alive || value.useOrPendingCount < 0)
 88 return true;
 89
 90 if (!value.useOrPendingCount)
 91 m_resourceUseCounters.remove(iterator);
 92
6493 if (m_imageBuffers.remove(renderingResourceIdentifier))
65  return;
 94 return true;
6695 if (m_nativeImages.remove(renderingResourceIdentifier))
67  return;
 96 return true;
6897 if (m_fonts.remove(renderingResourceIdentifier))
69  return;
 98 return true;
 99
70100 // Caching the remote resource should have happened before releasing it.
71  ASSERT_NOT_REACHED();
 101 return false;
 102}
 103
 104void RemoteResourceCache::recordResourceUse(RenderingResourceIdentifier renderingResourceIdentifier)
 105{
 106 auto iterator = m_resourceUseCounters.find(renderingResourceIdentifier);
 107
 108 ASSERT(iterator != m_resourceUseCounters.end());
 109
 110 ResourceUseCounter& useCounter = iterator->value;
 111 ++useCounter.useOrPendingCount;
 112
 113 maybeRemoveResource(renderingResourceIdentifier, iterator);
 114}
 115
 116bool RemoteResourceCache::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier, uint64_t useCount)
 117{
 118 auto iterator = m_resourceUseCounters.find(renderingResourceIdentifier);
 119 if (iterator == m_resourceUseCounters.end())
 120 return false;
 121 ResourceUseCounter& useCounter = iterator->value;
 122 useCounter.state = ResourceState::ToBeDeleted;
 123 useCounter.useOrPendingCount -= useCount;
 124 return maybeRemoveResource(renderingResourceIdentifier, iterator);
72125}
73126
74127} // namespace WebKit

Source/WebKit/GPUProcess/graphics/RemoteResourceCache.h

@@public:
4646 void cacheNativeImage(Ref<WebCore::NativeImage>&&);
4747 void cacheFont(Ref<WebCore::Font>&&);
4848 void deleteAllFonts();
49  void releaseRemoteResource(WebCore::RenderingResourceIdentifier);
 49 bool releaseRemoteResource(WebCore::RenderingResourceIdentifier, uint64_t useCount);
 50 void recordResourceUse(WebCore::RenderingResourceIdentifier);
5051
5152 const WebCore::ImageBufferHashMap& imageBuffers() const { return m_imageBuffers; }
5253 const WebCore::NativeImageHashMap& nativeImages() const { return m_nativeImages; }
5354 const WebCore::FontRenderingResourceMap& fonts() const { return m_fonts; }
5455
5556private:
 57 // Because the cache/release messages are sent asynchronously from the display list items which
 58 // reference the resources, it's totally possible that we see a release message before we've
 59 // executed all the display list items which reference the resource. The web process tells us
 60 // how many display list items will reference this resource, and we defer deletion of the resource
 61 // until we execute that many display list items. It's actually a bit worse than this, though,
 62 // because we may actually see a *new* cache message during the time when deletion is deferred.
 63 //
 64 // We can only safely delete a resource when:
 65 // 1. All the cache messages have an accompanying release message, and
 66 // 2. We've processed as many display list items that reference a particular resource as the web
 67 // process has encoded.
 68 enum class ResourceState {
 69 Alive,
 70 ToBeDeleted
 71 };
 72 struct ResourceUseCounter {
 73 ResourceState state { ResourceState::Alive };
 74 int64_t useOrPendingCount { 0 };
 75 };
 76 using ResourceUseCountersMap = HashMap<WebCore::RenderingResourceIdentifier, ResourceUseCounter>;
 77
 78 bool maybeRemoveResource(WebCore::RenderingResourceIdentifier, ResourceUseCountersMap::iterator&);
 79 void ensureResourceUseCounter(WebCore::RenderingResourceIdentifier);
 80
5681 WebCore::ImageBufferHashMap m_imageBuffers;
5782 WebCore::NativeImageHashMap m_nativeImages;
5883 WebCore::FontRenderingResourceMap m_fonts;
 84
 85 ResourceUseCountersMap m_resourceUseCounters;
5986};
6087
6188} // namespace WebKit

Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h

@@public:
7272
7373 flushDrawingContext();
7474 m_remoteRenderingBackendProxy->remoteResourceCacheProxy().releaseImageBuffer(m_renderingResourceIdentifier);
75  m_remoteRenderingBackendProxy->releaseRemoteResource(m_renderingResourceIdentifier);
 75 m_remoteRenderingBackendProxy->releaseRemoteResource(m_renderingResourceIdentifier, 0); // FIXME: Pass the real use count here.
7676 }
7777
7878 ImageBufferBackendHandle createImageBufferBackendHandle()

Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp

@@void RemoteRenderingBackendProxy::deleteAllFonts()
249249 send(Messages::RemoteRenderingBackend::DeleteAllFonts(), renderingBackendIdentifier(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
250250}
251251
252 void RemoteRenderingBackendProxy::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier)
 252void RemoteRenderingBackendProxy::releaseRemoteResource(RenderingResourceIdentifier renderingResourceIdentifier, uint64_t useCount)
253253{
254254 if (renderingResourceIdentifier == m_currentDestinationImageBufferIdentifier)
255255 m_currentDestinationImageBufferIdentifier = std::nullopt;
256256
257  send(Messages::RemoteRenderingBackend::ReleaseRemoteResource(renderingResourceIdentifier), renderingBackendIdentifier(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
 257 send(Messages::RemoteRenderingBackend::ReleaseRemoteResource(renderingResourceIdentifier, useCount), renderingBackendIdentifier(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
258258}
259259
260260void RemoteRenderingBackendProxy::didCreateImageBufferBackend(ImageBufferBackendHandle handle, RenderingResourceIdentifier renderingResourceIdentifier)

Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h

@@public:
104104 void cacheNativeImage(const ShareableBitmap::Handle&, WebCore::RenderingResourceIdentifier);
105105 void cacheFont(Ref<WebCore::Font>&&);
106106 void deleteAllFonts();
107  void releaseRemoteResource(WebCore::RenderingResourceIdentifier);
 107 void releaseRemoteResource(WebCore::RenderingResourceIdentifier, uint64_t useCount);
108108
109109 enum class DidReceiveBackendCreationResult : bool {
110110 ReceivedAnyResponse,

Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.cpp

@@void RemoteResourceCacheProxy::releaseNativeImage(RenderingResourceIdentifier re
121121 if (!m_nativeImages.remove(renderingResourceIdentifier))
122122 return;
123123
124  // Tell the GPU process to remove this resource.
125  m_remoteRenderingBackendProxy.releaseRemoteResource(renderingResourceIdentifier);
 124 m_remoteRenderingBackendProxy.releaseRemoteResource(renderingResourceIdentifier, 0); // FIXME: Pass the real use count here.
126125}
127126
128127void RemoteResourceCacheProxy::prepareForNextRenderingUpdate()

@@void RemoteResourceCacheProxy::prepareForNextRenderingUpdate()
134133void RemoteResourceCacheProxy::clearFontMap()
135134{
136135 for (auto& item : m_fontIdentifierToLastRenderingUpdateVersionMap)
137  m_remoteRenderingBackendProxy.releaseRemoteResource(item.key);
 136 m_remoteRenderingBackendProxy.releaseRemoteResource(item.key, 0); // FIXME: Pass the real use count here.
138137 m_fontIdentifierToLastRenderingUpdateVersionMap.clear();
139138 m_numberOfFontsUsedInCurrentRenderingUpdate = 0;
140139}

@@void RemoteResourceCacheProxy::finalizeRenderingUpdateForFonts()
152151 for (auto& item : m_fontIdentifierToLastRenderingUpdateVersionMap) {
153152 if (m_currentRenderingUpdateVersion - item.value >= minimumRenderingUpdateCountToKeepFontAlive) {
154153 toRemove.add(item.key);
155  m_remoteRenderingBackendProxy.releaseRemoteResource(item.key);
 154 m_remoteRenderingBackendProxy.releaseRemoteResource(item.key, 0); // FIXME: Pass the real use count here.
156155 }
157156 }
158157