- Revision
- 258123
- Author
- beid...@apple.com
- Date
- 2020-03-08 17:43:28 -0700 (Sun, 08 Mar 2020)
Log Message
Remember completed subranges during incremental PDF loading.
https://bugs.webkit.org/show_bug.cgi?id=208785
Reviewed by Tim Horton.
Source/_javascript_Core:
Move 'using WTF::Range' from the WTF/Range.h header to these JSC users.
The alternative to making these 3 changes was to make over 20 changes up in the WebCore/WebKits
to resolve the conflict with WebCore::Range.
* b3/B3HeapRange.h:
* b3/air/AirAllocateRegistersAndStackByLinearScan.cpp:
* heap/JITStubRoutineSet.h:
Source/WebKit:
When a range request from a stream loader completes, we will now extend the main resource buffer
to be large enough to hold that range, then we memcpy the data into the main buffer.
We then keep a RangeSet to remember which ranges we've loaded.
Any future range request that comes in we first check against that RangeSet to see if we can handle it from memory.
This is a necessary optimization because PDFKit tends to ask for the same (or overlapping) ranges quite often.
* WebProcess/Plugins/PDF/PDFPlugin.h:
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(WebKit::PDFPlugin::ByteRangeRequest::completeWithAccumulatedData):
(WebKit::PDFPlugin::ByteRangeRequest::maybeComplete):
(WebKit::PDFPlugin::pdfDocumentDidLoad):
(WebKit::PDFPlugin::manualStreamDidReceiveData):
Source/WTF:
* wtf/Range.h: Don't include the typical 'using WTF::Range' as that makes it almost impossible
to use in the stack at WebCore or higher (Because of WebCore::Range)
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (258122 => 258123)
--- trunk/Source/_javascript_Core/ChangeLog 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-03-09 00:43:28 UTC (rev 258123)
@@ -1,3 +1,19 @@
+2020-03-08 Brady Eidson <beid...@apple.com>
+
+ Remember completed subranges during incremental PDF loading.
+ https://bugs.webkit.org/show_bug.cgi?id=208785
+
+ Reviewed by Tim Horton.
+
+ Move 'using WTF::Range' from the WTF/Range.h header to these JSC users.
+
+ The alternative to making these 3 changes was to make over 20 changes up in the WebCore/WebKits
+ to resolve the conflict with WebCore::Range.
+
+ * b3/B3HeapRange.h:
+ * b3/air/AirAllocateRegistersAndStackByLinearScan.cpp:
+ * heap/JITStubRoutineSet.h:
+
2020-03-07 Alexey Shvayka <shvaikal...@gmail.com>
REGRESSION (r258049): Unchecked JS exception in jsc::Stringifier::toJSON
Modified: trunk/Source/_javascript_Core/b3/B3HeapRange.h (258122 => 258123)
--- trunk/Source/_javascript_Core/b3/B3HeapRange.h 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/_javascript_Core/b3/B3HeapRange.h 2020-03-09 00:43:28 UTC (rev 258123)
@@ -29,6 +29,8 @@
#include <wtf/Range.h>
+using WTF::Range;
+
namespace JSC { namespace B3 {
// Alias analysis in B3 is done by checking if two integer ranges overlap. This is powerful enough
Modified: trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersAndStackByLinearScan.cpp (258122 => 258123)
--- trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersAndStackByLinearScan.cpp 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersAndStackByLinearScan.cpp 2020-03-09 00:43:28 UTC (rev 258123)
@@ -44,6 +44,8 @@
#include <wtf/ListDump.h>
#include <wtf/Range.h>
+using WTF::Range;
+
namespace JSC { namespace B3 { namespace Air {
namespace {
Modified: trunk/Source/_javascript_Core/heap/JITStubRoutineSet.h (258122 => 258123)
--- trunk/Source/_javascript_Core/heap/JITStubRoutineSet.h 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/_javascript_Core/heap/JITStubRoutineSet.h 2020-03-09 00:43:28 UTC (rev 258123)
@@ -31,6 +31,8 @@
#include <wtf/Range.h>
#include <wtf/Vector.h>
+using WTF::Range;
+
namespace JSC {
class GCAwareJITStubRoutine;
Modified: trunk/Source/WTF/ChangeLog (258122 => 258123)
--- trunk/Source/WTF/ChangeLog 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/WTF/ChangeLog 2020-03-09 00:43:28 UTC (rev 258123)
@@ -1,3 +1,13 @@
+2020-03-08 Brady Eidson <beid...@apple.com>
+
+ Remember completed subranges during incremental PDF loading.
+ https://bugs.webkit.org/show_bug.cgi?id=208785
+
+ Reviewed by Tim Horton.
+
+ * wtf/Range.h: Don't include the typical 'using WTF::Range' as that makes it almost impossible
+ to use in the stack at WebCore or higher (Because of WebCore::Range)
+
2020-03-08 Per Arne Vollan <pvol...@apple.com>
Unreviewed build fix.
Modified: trunk/Source/WTF/wtf/Range.h (258122 => 258123)
--- trunk/Source/WTF/wtf/Range.h 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/WTF/wtf/Range.h 2020-03-09 00:43:28 UTC (rev 258123)
@@ -138,6 +138,3 @@
};
} // namespace WTF
-
-using WTF::Range;
-
Modified: trunk/Source/WebKit/ChangeLog (258122 => 258123)
--- trunk/Source/WebKit/ChangeLog 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/WebKit/ChangeLog 2020-03-09 00:43:28 UTC (rev 258123)
@@ -1,3 +1,25 @@
+2020-03-08 Brady Eidson <beid...@apple.com>
+
+ Remember completed subranges during incremental PDF loading.
+ https://bugs.webkit.org/show_bug.cgi?id=208785
+
+ Reviewed by Tim Horton.
+
+ When a range request from a stream loader completes, we will now extend the main resource buffer
+ to be large enough to hold that range, then we memcpy the data into the main buffer.
+
+ We then keep a RangeSet to remember which ranges we've loaded.
+ Any future range request that comes in we first check against that RangeSet to see if we can handle it from memory.
+
+ This is a necessary optimization because PDFKit tends to ask for the same (or overlapping) ranges quite often.
+
+ * WebProcess/Plugins/PDF/PDFPlugin.h:
+ * WebProcess/Plugins/PDF/PDFPlugin.mm:
+ (WebKit::PDFPlugin::ByteRangeRequest::completeWithAccumulatedData):
+ (WebKit::PDFPlugin::ByteRangeRequest::maybeComplete):
+ (WebKit::PDFPlugin::pdfDocumentDidLoad):
+ (WebKit::PDFPlugin::manualStreamDidReceiveData):
+
2020-02-28 Jer Noble <jer.no...@apple.com>
[GPUP] Implement Legacy EME API in the GPU Process
Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h (258122 => 258123)
--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h 2020-03-09 00:43:28 UTC (rev 258123)
@@ -38,6 +38,8 @@
#include <WebCore/ScrollableArea.h>
#include <wtf/HashMap.h>
#include <wtf/Identified.h>
+#include <wtf/Range.h>
+#include <wtf/RangeSet.h>
#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
@@ -368,6 +370,7 @@
RefPtr<Thread> m_pdfThread;
HashMap<uint64_t, ByteRangeRequest> m_outstandingByteRangeRequests;
HashMap<RefPtr<WebCore::NetscapePlugInStreamLoader>, uint64_t> m_streamLoaderMap;
+ RangeSet<WTF::Range<uint64_t>> m_completedRanges;
bool m_incrementalPDFLoadingEnabled;
#endif
};
Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm (258122 => 258123)
--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm 2020-03-09 00:34:40 UTC (rev 258122)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm 2020-03-09 00:43:28 UTC (rev 258123)
@@ -828,6 +828,20 @@
if (m_streamLoader)
plugin.forgetLoader(*m_streamLoader);
+
+ // Fold this data into the main data buffer so that if something in its range is requested again (which happens quite often)
+ // we do not need to hit the network layer again.
+
+ auto length = CFDataGetLength(plugin.m_data.get());
+ CFIndex targetSize = m_position + m_accumulatedData.size();
+ auto delta = targetSize - length;
+ if (delta > 0)
+ CFDataIncreaseLength(plugin.m_data.get(), delta);
+
+ if (m_accumulatedData.size()) {
+ memcpy(CFDataGetMutableBytePtr(plugin.m_data.get()) + m_position, m_accumulatedData.data(), m_accumulatedData.size());
+ plugin.m_completedRanges.add({ m_position, m_position + m_accumulatedData.size() - 1});
+ }
}
bool PDFPlugin::ByteRangeRequest::maybeComplete(PDFPlugin& plugin)
@@ -836,6 +850,12 @@
completeWithBytes(CFDataGetBytePtr(plugin.m_data.get()) + m_position, m_count, plugin);
return true;
}
+
+ if (plugin.m_completedRanges.contains({ m_position, m_position + m_count - 1 })) {
+ LOG(PDF, "Completing request %llu with a previously completed range", identifier());
+ completeWithBytes(CFDataGetBytePtr(plugin.m_data.get()) + m_position, m_count, plugin);
+ return true;
+ }
return false;
}
@@ -1287,6 +1307,8 @@
void PDFPlugin::pdfDocumentDidLoad()
{
+ LOG(PDF, "PDF document finished loading with a total of %llu bytes", m_streamedBytes);
+
addArchiveResource();
m_documentFinishedLoading = true;
@@ -1396,6 +1418,10 @@
m_streamedBytes += length;
#if HAVE(INCREMENTAL_PDF_APIS)
+ // Keep our ranges-lookup-table compact by continuously updating its first range
+ // as the entire document streams in from the network.
+ m_completedRanges.add({ 0, m_streamedBytes - 1 });
+
if (m_incrementalPDFLoadingEnabled) {
HashSet<uint64_t> handledRequests;
for (auto& request : m_outstandingByteRangeRequests.values()) {