Title: [215608] trunk
Revision
215608
Author
[email protected]
Date
2017-04-21 07:21:46 -0700 (Fri, 21 Apr 2017)

Log Message

Reduce copies and allocations in SharedBuffer::append
https://bugs.webkit.org/show_bug.cgi?id=170956

Reviewed by Andreas Kling.

Source/WebCore:

SharedBuffer was a mess of different data structures added over the years.
SharedBuffer::append would allocate large Vector<char>s and call memcpy, and that
is inefficient and causes crashes when large allocations fail, and the allocations
and copies aren't even necessary.  There were also const correctness problems in
ResourceLoader::addDataOrBuffer, and iterating a SharedBuffer was strange because
sometimes we don't want to add unnecessary copies.

These problems are solved by making SharedBuffer a Vector of read-only data segments,
which can be contained in various ways but we don't care because all we want to do is
read them.  Appending SharedBuffers is now const correct because we just add to a
Vector<Ref<DataSegment>> and neither SharedBuffer can write to the data.  Sometimes,
though, we want all the data to be in continuous memory, and if there are multiple
segments then the data needs to be copied once to a new segment.  We should audit the
call sites of SharedBuffer::data and see if this is really necessary.

No change in functional behavior.  Fewer copies of the data are made when buffering
data in the NetworkProcess.  No extra memory is allocated for bytes we think we might
need to append in the future.  Data is now only copied into one buffer lazily as needed,
which could slightly change when small delays from memcpy happen, but it's an overall
improvement.  We could have a performance hit if we were to call append() then data()
then append() then data() etc. but that doesn't happen in WebKit because we call append
repeatedly when buffering the data then call data() once when reading the data.

* editing/cocoa/EditorCocoa.mm:
(WebCore::archivedDataForAttributedString):
(WebCore::Editor::selectionInWebArchiveFormat):
(WebCore::Editor::dataInRTFDFormat):
(WebCore::Editor::dataInRTFFormat):
* editing/ios/EditorIOS.mm:
(WebCore::Editor::WebContentReader::readURL):
* editing/mac/EditorMac.mm:
(WebCore::Editor::imageInWebArchiveFormat):
* loader/TextTrackLoader.cpp:
(WebCore::TextTrackLoader::processNewCueData):
* loader/archive/cf/LegacyWebArchive.cpp:
(WebCore::LegacyWebArchive::createResource):
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::tryReplaceEncodedData):
* loader/cocoa/DiskCacheMonitorCocoa.mm:
(WebCore::DiskCacheMonitor::tryGetFileBackedSharedBufferFromCFURLCachedResponse):
* platform/SharedBuffer.cpp:
(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::create):
(WebCore::SharedBuffer::combineToOneSegment):
(WebCore::SharedBuffer::data):
(WebCore::SharedBuffer::createArrayBuffer):
(WebCore::SharedBuffer::append):
(WebCore::SharedBuffer::clear):
(WebCore::SharedBuffer::copy):
(WebCore::SharedBuffer::DataSegment::data):
(WebCore::SharedBuffer::DataSegment::size):
(WebCore::segmentIndex): Deleted.
(WebCore::offsetInSegment): Deleted.
(WebCore::allocateSegment): Deleted.
(WebCore::freeSegment): Deleted.
(WebCore::SharedBuffer::~SharedBuffer): Deleted.
(WebCore::SharedBuffer::size): Deleted.
(WebCore::SharedBuffer::duplicateDataBufferIfNecessary): Deleted.
(WebCore::SharedBuffer::appendToDataBuffer): Deleted.
(WebCore::SharedBuffer::clearDataBuffer): Deleted.
(WebCore::SharedBuffer::copyBufferAndClear): Deleted.
(WebCore::SharedBuffer::buffer): Deleted.
(WebCore::SharedBuffer::getSomeData): Deleted.
(WebCore::SharedBuffer::maybeTransferMappedFileData): Deleted.
(WebCore::SharedBuffer::clearPlatformData): Deleted.
(WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
(WebCore::SharedBuffer::hasPlatformData): Deleted.
(WebCore::SharedBuffer::platformData): Deleted.
(WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
* platform/SharedBuffer.h:
(WebCore::SharedBuffer::create): Deleted.
(WebCore::SharedBuffer::isEmpty): Deleted.
* platform/SharedBufferChunkReader.cpp:
(WebCore::SharedBufferChunkReader::nextChunk):
(WebCore::SharedBufferChunkReader::peek):
* platform/SharedBufferChunkReader.h:
* platform/URLParser.cpp:
(WebCore::URLParser::URLParser):
* platform/cf/KeyedEncoderCF.cpp:
(WebCore::KeyedEncoderCF::finishEncoding):
* platform/cf/SharedBufferCF.cpp:
(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::createCFData):
(WebCore::SharedBuffer::create):
(WebCore::SharedBuffer::hintMemoryNotNeededSoon):
(WebCore::SharedBuffer::append):
(WebCore::SharedBuffer::wrapCFData): Deleted.
(WebCore::SharedBuffer::hasPlatformData): Deleted.
(WebCore::SharedBuffer::platformData): Deleted.
(WebCore::SharedBuffer::platformDataSize): Deleted.
(WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
(WebCore::SharedBuffer::clearPlatformData): Deleted.
(WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
(WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
(WebCore::SharedBuffer::copyBufferAndClear): Deleted.
(WebCore::SharedBuffer::copySomeDataFromDataArray): Deleted.
(WebCore::SharedBuffer::singleDataArrayBuffer): Deleted.
(WebCore::SharedBuffer::maybeAppendDataArray): Deleted.
* platform/cocoa/NetworkExtensionContentFilter.mm:
(WebCore::NetworkExtensionContentFilter::replacementData):
* platform/cocoa/ParentalControlsContentFilter.mm:
(WebCore::ParentalControlsContentFilter::replacementData):
* platform/cocoa/SharedBufferCocoa.mm:
(-[WebCoreSharedBufferData initWithSharedBufferDataSegment:]):
(-[WebCoreSharedBufferData length]):
(-[WebCoreSharedBufferData bytes]):
(WebCore::SharedBuffer::create):
(WebCore::SharedBuffer::createCFData):
(WebCore::SharedBuffer::createFromReadingFile):
(WebCore::SharedBuffer::createNSDataArray):
(-[WebCoreSharedBufferData initWithSharedBufferDataBuffer:]): Deleted.
(WebCore::SharedBuffer::wrapNSData): Deleted.
(WebCore::SharedBuffer::existingCFData): Deleted.
* platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
(WebCore::WebCoreAVFResourceLoader::fulfillRequestWithResource):
* platform/graphics/cocoa/FontPlatformDataCocoa.mm:
(WebCore::FontPlatformData::openTypeTable):
* platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
(ResourceHandleStreamingClient::didReceiveBuffer):
* platform/graphics/mac/ImageMac.mm:
(WebCore::Image::loadPlatformResource):
* platform/image-decoders/ImageDecoder.cpp:
(WebCore::ImageDecoder::create):
* platform/image-decoders/png/PNGImageDecoder.cpp:
(WebCore::PNGImageReader::decode):
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::readBuffer):
* platform/mac/PasteboardMac.mm:
(WebCore::writeFileWrapperAsRTFDAttachment):
(WebCore::Pasteboard::write):
* platform/mac/PlatformPasteboardMac.mm:
(WebCore::PlatformPasteboard::bufferForType):
* platform/network/BlobResourceHandle.cpp:
(WebCore::BlobResourceHandle::notifyReceiveData):
* platform/network/MIMEHeader.cpp:
* platform/network/MIMEHeader.h:
* platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp:
(WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData):
* platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
(WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData):
* platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
(-[WebCoreResourceHandleAsDelegate connection:didReceiveData:lengthReceived:]):
* platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm:
(-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveData:lengthReceived:]):
* platform/soup/SharedBufferSoup.cpp:
(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::createSoupBuffer):
(WebCore::SharedBuffer::clearPlatformData): Deleted.
(WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
(WebCore::SharedBuffer::hasPlatformData): Deleted.
(WebCore::SharedBuffer::platformData): Deleted.
(WebCore::SharedBuffer::platformDataSize): Deleted.
(WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
(WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.

Source/WebKit/mac:

* WebView/WebArchive.mm:
(-[WebArchive initWithData:]):
* WebView/WebFrame.mm:
(-[WebFrame _loadData:MIMEType:textEncodingName:baseURL:unreachableURL:]):
* WebView/WebResource.mm:
(-[WebResource initWithCoder:]):
(-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):

Source/WebKit2:

* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
* Platform/IPC/DataReference.cpp:
(IPC::SharedBufferDataReference::encode):
* Shared/ShareableResource.cpp:
(WebKit::ShareableResource::wrapInSharedBuffer):
* UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm:
(-[WKURLSchemeHandlerTaskImpl didReceiveData:]):
* WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
(-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(WebKit::PDFPlugin::addArchiveResource):
(WebKit::PDFPlugin::liveResourceData):
(WebKit::PDFPlugin::writeItemsToPasteboard):
* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::redeliverManualStream):
* WebProcess/WebCoreSupport/mac/WebDragClientMac.mm:
(WebKit::WebDragClient::declareAndWriteDragImage):
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::cachedResponseDataForURL):

Tools:

* TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm:
(TestWebKitAPI::TEST_F):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (215607 => 215608)


--- trunk/Source/WebCore/ChangeLog	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/ChangeLog	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1,3 +1,165 @@
+2017-04-21  Alex Christensen  <[email protected]>
+
+        Reduce copies and allocations in SharedBuffer::append
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+
+        Reviewed by Andreas Kling.
+
+        SharedBuffer was a mess of different data structures added over the years.
+        SharedBuffer::append would allocate large Vector<char>s and call memcpy, and that
+        is inefficient and causes crashes when large allocations fail, and the allocations
+        and copies aren't even necessary.  There were also const correctness problems in
+        ResourceLoader::addDataOrBuffer, and iterating a SharedBuffer was strange because
+        sometimes we don't want to add unnecessary copies.
+
+        These problems are solved by making SharedBuffer a Vector of read-only data segments,
+        which can be contained in various ways but we don't care because all we want to do is
+        read them.  Appending SharedBuffers is now const correct because we just add to a
+        Vector<Ref<DataSegment>> and neither SharedBuffer can write to the data.  Sometimes,
+        though, we want all the data to be in continuous memory, and if there are multiple
+        segments then the data needs to be copied once to a new segment.  We should audit the
+        call sites of SharedBuffer::data and see if this is really necessary.
+
+        No change in functional behavior.  Fewer copies of the data are made when buffering
+        data in the NetworkProcess.  No extra memory is allocated for bytes we think we might
+        need to append in the future.  Data is now only copied into one buffer lazily as needed,
+        which could slightly change when small delays from memcpy happen, but it's an overall
+        improvement.  We could have a performance hit if we were to call append() then data()
+        then append() then data() etc. but that doesn't happen in WebKit because we call append
+        repeatedly when buffering the data then call data() once when reading the data.
+
+        * editing/cocoa/EditorCocoa.mm:
+        (WebCore::archivedDataForAttributedString):
+        (WebCore::Editor::selectionInWebArchiveFormat):
+        (WebCore::Editor::dataInRTFDFormat):
+        (WebCore::Editor::dataInRTFFormat):
+        * editing/ios/EditorIOS.mm:
+        (WebCore::Editor::WebContentReader::readURL):
+        * editing/mac/EditorMac.mm:
+        (WebCore::Editor::imageInWebArchiveFormat):
+        * loader/TextTrackLoader.cpp:
+        (WebCore::TextTrackLoader::processNewCueData):
+        * loader/archive/cf/LegacyWebArchive.cpp:
+        (WebCore::LegacyWebArchive::createResource):
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::tryReplaceEncodedData):
+        * loader/cocoa/DiskCacheMonitorCocoa.mm:
+        (WebCore::DiskCacheMonitor::tryGetFileBackedSharedBufferFromCFURLCachedResponse):
+        * platform/SharedBuffer.cpp:
+        (WebCore::SharedBuffer::SharedBuffer):
+        (WebCore::SharedBuffer::create):
+        (WebCore::SharedBuffer::combineToOneSegment):
+        (WebCore::SharedBuffer::data):
+        (WebCore::SharedBuffer::createArrayBuffer):
+        (WebCore::SharedBuffer::append):
+        (WebCore::SharedBuffer::clear):
+        (WebCore::SharedBuffer::copy):
+        (WebCore::SharedBuffer::DataSegment::data):
+        (WebCore::SharedBuffer::DataSegment::size):
+        (WebCore::segmentIndex): Deleted.
+        (WebCore::offsetInSegment): Deleted.
+        (WebCore::allocateSegment): Deleted.
+        (WebCore::freeSegment): Deleted.
+        (WebCore::SharedBuffer::~SharedBuffer): Deleted.
+        (WebCore::SharedBuffer::size): Deleted.
+        (WebCore::SharedBuffer::duplicateDataBufferIfNecessary): Deleted.
+        (WebCore::SharedBuffer::appendToDataBuffer): Deleted.
+        (WebCore::SharedBuffer::clearDataBuffer): Deleted.
+        (WebCore::SharedBuffer::copyBufferAndClear): Deleted.
+        (WebCore::SharedBuffer::buffer): Deleted.
+        (WebCore::SharedBuffer::getSomeData): Deleted.
+        (WebCore::SharedBuffer::maybeTransferMappedFileData): Deleted.
+        (WebCore::SharedBuffer::clearPlatformData): Deleted.
+        (WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
+        (WebCore::SharedBuffer::hasPlatformData): Deleted.
+        (WebCore::SharedBuffer::platformData): Deleted.
+        (WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
+        * platform/SharedBuffer.h:
+        (WebCore::SharedBuffer::create): Deleted.
+        (WebCore::SharedBuffer::isEmpty): Deleted.
+        * platform/SharedBufferChunkReader.cpp:
+        (WebCore::SharedBufferChunkReader::nextChunk):
+        (WebCore::SharedBufferChunkReader::peek):
+        * platform/SharedBufferChunkReader.h:
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::URLParser):
+        * platform/cf/KeyedEncoderCF.cpp:
+        (WebCore::KeyedEncoderCF::finishEncoding):
+        * platform/cf/SharedBufferCF.cpp:
+        (WebCore::SharedBuffer::SharedBuffer):
+        (WebCore::SharedBuffer::createCFData):
+        (WebCore::SharedBuffer::create):
+        (WebCore::SharedBuffer::hintMemoryNotNeededSoon):
+        (WebCore::SharedBuffer::append):
+        (WebCore::SharedBuffer::wrapCFData): Deleted.
+        (WebCore::SharedBuffer::hasPlatformData): Deleted.
+        (WebCore::SharedBuffer::platformData): Deleted.
+        (WebCore::SharedBuffer::platformDataSize): Deleted.
+        (WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
+        (WebCore::SharedBuffer::clearPlatformData): Deleted.
+        (WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
+        (WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
+        (WebCore::SharedBuffer::copyBufferAndClear): Deleted.
+        (WebCore::SharedBuffer::copySomeDataFromDataArray): Deleted.
+        (WebCore::SharedBuffer::singleDataArrayBuffer): Deleted.
+        (WebCore::SharedBuffer::maybeAppendDataArray): Deleted.
+        * platform/cocoa/NetworkExtensionContentFilter.mm:
+        (WebCore::NetworkExtensionContentFilter::replacementData):
+        * platform/cocoa/ParentalControlsContentFilter.mm:
+        (WebCore::ParentalControlsContentFilter::replacementData):
+        * platform/cocoa/SharedBufferCocoa.mm:
+        (-[WebCoreSharedBufferData initWithSharedBufferDataSegment:]):
+        (-[WebCoreSharedBufferData length]):
+        (-[WebCoreSharedBufferData bytes]):
+        (WebCore::SharedBuffer::create):
+        (WebCore::SharedBuffer::createCFData):
+        (WebCore::SharedBuffer::createFromReadingFile):
+        (WebCore::SharedBuffer::createNSDataArray):
+        (-[WebCoreSharedBufferData initWithSharedBufferDataBuffer:]): Deleted.
+        (WebCore::SharedBuffer::wrapNSData): Deleted.
+        (WebCore::SharedBuffer::existingCFData): Deleted.
+        * platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm:
+        (WebCore::WebCoreAVFResourceLoader::fulfillRequestWithResource):
+        * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
+        (WebCore::FontPlatformData::openTypeTable):
+        * platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:
+        (ResourceHandleStreamingClient::didReceiveBuffer):
+        * platform/graphics/mac/ImageMac.mm:
+        (WebCore::Image::loadPlatformResource):
+        * platform/image-decoders/ImageDecoder.cpp:
+        (WebCore::ImageDecoder::create):
+        * platform/image-decoders/png/PNGImageDecoder.cpp:
+        (WebCore::PNGImageReader::decode):
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::PlatformPasteboard::readBuffer):
+        * platform/mac/PasteboardMac.mm:
+        (WebCore::writeFileWrapperAsRTFDAttachment):
+        (WebCore::Pasteboard::write):
+        * platform/mac/PlatformPasteboardMac.mm:
+        (WebCore::PlatformPasteboard::bufferForType):
+        * platform/network/BlobResourceHandle.cpp:
+        (WebCore::BlobResourceHandle::notifyReceiveData):
+        * platform/network/MIMEHeader.cpp:
+        * platform/network/MIMEHeader.h:
+        * platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp:
+        (WebCore::ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData):
+        * platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
+        (WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData):
+        * platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
+        (-[WebCoreResourceHandleAsDelegate connection:didReceiveData:lengthReceived:]):
+        * platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm:
+        (-[WebCoreResourceHandleAsOperationQueueDelegate connection:didReceiveData:lengthReceived:]):
+        * platform/soup/SharedBufferSoup.cpp:
+        (WebCore::SharedBuffer::SharedBuffer):
+        (WebCore::SharedBuffer::createSoupBuffer):
+        (WebCore::SharedBuffer::clearPlatformData): Deleted.
+        (WebCore::SharedBuffer::maybeTransferPlatformData): Deleted.
+        (WebCore::SharedBuffer::hasPlatformData): Deleted.
+        (WebCore::SharedBuffer::platformData): Deleted.
+        (WebCore::SharedBuffer::platformDataSize): Deleted.
+        (WebCore::SharedBuffer::maybeAppendPlatformData): Deleted.
+        (WebCore::SharedBuffer::tryReplaceContentsWithPlatformBuffer): Deleted.
+
 2017-04-21  Timothy Horton  <[email protected]>
 
         Expose obscured insets to web content (as "safe area insets")

Modified: trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm (215607 => 215608)


--- trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/editing/cocoa/EditorCocoa.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -157,7 +157,7 @@
     if (!attributedString.length)
         return nullptr;
 
-    return SharedBuffer::wrapNSData([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
+    return SharedBuffer::create([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
 }
 
 void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
@@ -205,7 +205,7 @@
     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(&m_frame);
     if (!archive)
         return nullptr;
-    return SharedBuffer::wrapCFData(archive->rawDataRepresentation().get());
+    return SharedBuffer::create(archive->rawDataRepresentation().get());
 }
 
 // FIXME: Makes no sense that selectedTextForDataTransfer always includes alt text, but stringSelectionForPasteboard does not.
@@ -276,7 +276,7 @@
         return nullptr;
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    return SharedBuffer::wrapNSData([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
+    return SharedBuffer::create([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
     END_BLOCK_OBJC_EXCEPTIONS;
 
     return nullptr;
@@ -289,7 +289,7 @@
         return nullptr;
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    return SharedBuffer::wrapNSData([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
+    return SharedBuffer::create([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
     END_BLOCK_OBJC_EXCEPTIONS;
 
     return nullptr;

Modified: trunk/Source/WebCore/editing/ios/EditorIOS.mm (215607 => 215608)


--- trunk/Source/WebCore/editing/ios/EditorIOS.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/editing/ios/EditorIOS.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -339,10 +339,10 @@
         RetainPtr<NSString> fileType = adoptNS((NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[localPath pathExtension], NULL));
         NSData *data = "" dataWithContentsOfFile:localPath];
         if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypePNG)) {
-            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.png"), @"image/png", emptyString(), emptyString())));
+            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::create([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.png"), @"image/png", emptyString(), emptyString())));
             return fragment;
         } else if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypeJPEG)) {
-            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.jpg"), @"image/jpg", emptyString(), emptyString())));
+            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::create([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.jpg"), @"image/jpg", emptyString(), emptyString())));
             return fragment;
         }
     } else {

Modified: trunk/Source/WebCore/editing/mac/EditorMac.mm (215607 => 215608)


--- trunk/Source/WebCore/editing/mac/EditorMac.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/editing/mac/EditorMac.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -204,7 +204,7 @@
     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(imageElement);
     if (!archive)
         return nullptr;
-    return SharedBuffer::wrapCFData(archive->rawDataRepresentation().get());
+    return SharedBuffer::create(archive->rawDataRepresentation().get());
 }
 
 RefPtr<SharedBuffer> Editor::dataSelectionForPasteboard(const String& pasteboardType)

Modified: trunk/Source/WebCore/loader/TextTrackLoader.cpp (215607 => 215608)


--- trunk/Source/WebCore/loader/TextTrackLoader.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/loader/TextTrackLoader.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -91,12 +91,15 @@
     if (!m_cueParser)
         m_cueParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), m_scriptExecutionContext);
 
-    const char* data;
-    unsigned length;
-
-    while ((length = buffer->getSomeData(data, m_parseOffset))) {
-        m_cueParser->parseBytes(data, length);
-        m_parseOffset += length;
+    auto bytesToSkip = m_parseOffset;
+    for (const auto& segment : *buffer) {
+        if (bytesToSkip > segment->size()) {
+            bytesToSkip -= segment->size();
+            continue;
+        }
+        m_cueParser->parseBytes(segment->data() + bytesToSkip, segment->size() - bytesToSkip);
+        bytesToSkip = 0;
+        m_parseOffset += segment->size();
     }
 }
 

Modified: trunk/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp (215607 => 215608)


--- trunk/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -221,7 +221,7 @@
         response = createResourceResponseFromPropertyListData(resourceResponseData, resourceResponseVersion);
     }
 
-    return ArchiveResource::create(SharedBuffer::wrapCFData(resourceData), URL(URL(), url), mimeType, textEncoding, frameName, response);
+    return ArchiveResource::create(SharedBuffer::create(resourceData), URL(URL(), url), mimeType, textEncoding, frameName, response);
 }
 
 Ref<LegacyWebArchive> LegacyWebArchive::create()

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (215607 => 215608)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -850,8 +850,9 @@
     if (m_data->size() != newBuffer.size() || memcmp(m_data->data(), newBuffer.data(), m_data->size()))
         return;
 
-    if (m_data->tryReplaceContentsWithPlatformBuffer(newBuffer))
-        didReplaceSharedBufferContents();
+    m_data->clear();
+    m_data->append(newBuffer);
+    didReplaceSharedBufferContents();
 }
 
 #endif

Modified: trunk/Source/WebCore/loader/cocoa/DiskCacheMonitorCocoa.mm (215607 => 215608)


--- trunk/Source/WebCore/loader/cocoa/DiskCacheMonitorCocoa.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/loader/cocoa/DiskCacheMonitorCocoa.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -48,7 +48,7 @@
     if (!data)
         return nullptr;
 
-    return SharedBuffer::wrapCFData(data);
+    return SharedBuffer::create(data);
 }
 
 void DiskCacheMonitor::monitorFileBackingStoreCreation(const ResourceRequest& request, SessionID sessionID, CFCachedURLResponseRef cachedResponse)

Modified: trunk/Source/WebCore/platform/SharedBuffer.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/SharedBuffer.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/SharedBuffer.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -31,62 +31,31 @@
 #include <algorithm>
 #include <wtf/unicode/UTF8.h>
 
-namespace WebCore {
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-
-static const unsigned segmentSize = 0x1000;
-static const unsigned segmentPositionMask = 0x0FFF;
-
-static inline unsigned segmentIndex(unsigned position)
-{
-    return position / segmentSize;
-}
-
-static inline unsigned offsetInSegment(unsigned position)
-{
-    return position & segmentPositionMask;
-}
-
-static inline char* allocateSegment() WARN_UNUSED_RETURN;
-static inline char* allocateSegment()
-{
-    return static_cast<char*>(fastMalloc(segmentSize));
-}
-
-static inline void freeSegment(char* p)
-{
-    fastFree(p);
-}
-
+#if USE(SOUP)
+#include "GUniquePtrSoup.h"
 #endif
 
-SharedBuffer::SharedBuffer()
-    : m_buffer(adoptRef(*new DataBuffer))
-{
-}
+namespace WebCore {
 
-SharedBuffer::SharedBuffer(const char* data, unsigned size)
-    : m_buffer(adoptRef(*new DataBuffer))
+SharedBuffer::SharedBuffer(const char* data, size_t size)
 {
     append(data, size);
 }
 
-SharedBuffer::SharedBuffer(const unsigned char* data, unsigned size)
-    : m_buffer(adoptRef(*new DataBuffer))
+SharedBuffer::SharedBuffer(const unsigned char* data, size_t size)
 {
     append(reinterpret_cast<const char*>(data), size);
 }
 
 SharedBuffer::SharedBuffer(MappedFileData&& fileData)
-    : m_buffer(adoptRef(*new DataBuffer))
-    , m_fileData(WTFMove(fileData))
+    : m_size(fileData.size())
 {
+    m_segments.append(DataSegment::create(WTFMove(fileData)));
 }
 
-SharedBuffer::~SharedBuffer()
+SharedBuffer::SharedBuffer(Vector<char>&& data)
 {
-    clear();
+    append(WTFMove(data));
 }
 
 RefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePath)
@@ -102,37 +71,30 @@
 
 Ref<SharedBuffer> SharedBuffer::create(Vector<char>&& vector)
 {
-    auto buffer = create();
-    buffer->m_buffer->data = ""
-    buffer->m_size = buffer->m_buffer->data.size();
-    return buffer;
+    return adoptRef(*new SharedBuffer(WTFMove(vector)));
 }
 
-unsigned SharedBuffer::size() const
+void SharedBuffer::combineToOneSegment() const
 {
-    if (hasPlatformData())
-        return platformDataSize();
-    
-    if (m_fileData)
-        return m_fileData.size();
+    if (m_segments.size() <= 1)
+        return;
 
-    return m_size;
+    Vector<char> combinedData;
+    combinedData.reserveInitialCapacity(m_size);
+    for (const auto& segment : m_segments)
+        combinedData.append(segment->data(), segment->size());
+    ASSERT(combinedData.size() == m_size);
+    m_segments.clear();
+    m_segments.append(DataSegment::create(WTFMove(combinedData)));
+    ASSERT(m_segments.size() == 1);
 }
 
 const char* SharedBuffer::data() const
 {
-    if (hasPlatformData())
-        return platformData();
-
-    if (m_fileData)
-        return static_cast<const char*>(m_fileData.data());
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    if (const char* buffer = singleDataArrayBuffer())
-        return buffer;
-#endif
-
-    return this->buffer().data();
+    if (!m_segments.size())
+        return nullptr;
+    combineToOneSegment();
+    return m_segments[0]->data();
 }
 
 RefPtr<ArrayBuffer> SharedBuffer::createArrayBuffer() const
@@ -143,171 +105,69 @@
         return nullptr;
     }
 
-    const char* segment = 0;
-    unsigned position = 0;
-    while (unsigned segmentSize = getSomeData(segment, position)) {
-        memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment, segmentSize);
-        position += segmentSize;
+    size_t position = 0;
+    for (const auto& segment : m_segments) {
+        memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment->data(), segment->size());
+        position += segment->size();
     }
 
-    if (position != arrayBuffer->byteLength()) {
-        ASSERT_NOT_REACHED();
-        // Don't return the incomplete ArrayBuffer.
-        return nullptr;
-    }
-
+    ASSERT(position == m_size);
     return arrayBuffer;
 }
 
-void SharedBuffer::append(SharedBuffer& data)
+void SharedBuffer::append(const SharedBuffer& data)
 {
-    if (maybeAppendPlatformData(data))
-        return;
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    if (maybeAppendDataArray(data))
-        return;
-#endif
-
-    const char* segment;
-    size_t position = 0;
-    while (size_t length = data.getSomeData(segment, position)) {
-        append(segment, length);
-        position += length;
-    }
+    m_size += data.m_size;
+    m_segments.reserveCapacity(m_segments.size() + data.m_segments.size());
+    for (const auto& segment : data.m_segments)
+        m_segments.uncheckedAppend(segment.copyRef());
 }
 
-void SharedBuffer::append(const char* data, unsigned length)
+void SharedBuffer::append(const char* data, size_t length)
 {
-    if (!length)
-        return;
-
-    maybeTransferMappedFileData();
-    maybeTransferPlatformData();
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    unsigned positionInSegment = offsetInSegment(m_size - m_buffer->data.size());
     m_size += length;
-
-    if (m_size <= segmentSize) {
-        // No need to use segments for small resource data
-        if (m_buffer->data.isEmpty())
-            m_buffer->data.reserveInitialCapacity(length);
-        appendToDataBuffer(data, length);
-        return;
-    }
-
-    char* segment;
-    if (!positionInSegment) {
-        segment = allocateSegment();
-        m_segments.append(segment);
-    } else
-        segment = m_segments.last() + positionInSegment;
-
-    unsigned segmentFreeSpace = segmentSize - positionInSegment;
-    unsigned bytesToCopy = std::min(length, segmentFreeSpace);
-
-    for (;;) {
-        memcpy(segment, data, bytesToCopy);
-        if (static_cast<unsigned>(length) == bytesToCopy)
-            break;
-
-        length -= bytesToCopy;
-        data += bytesToCopy;
-        segment = allocateSegment();
-        m_segments.append(segment);
-        bytesToCopy = std::min(length, segmentSize);
-    }
-#else
-    m_size += length;
-    if (m_buffer->data.isEmpty())
-        m_buffer->data.reserveInitialCapacity(length);
-    appendToDataBuffer(data, length);
-#endif
+    Vector<char> vector;
+    vector.append(data, length);
+    m_segments.append(DataSegment::create(WTFMove(vector)));
 }
 
 void SharedBuffer::append(Vector<char>&& data)
 {
-    // This takes its argument as a rvalue reference because we intend to have a future
-    // version take ownership of the vector rather than copying.
-    append(data.data(), data.size());
+    m_size += data.size();
+    m_segments.append(DataSegment::create(WTFMove(data)));
 }
 
 void SharedBuffer::clear()
 {
-    m_fileData = { };
-
-    clearPlatformData();
-    
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    for (char* segment : m_segments)
-        freeSegment(segment);
+    m_size = 0;
     m_segments.clear();
-#else
-    m_dataArray.clear();
-#endif
-
-    m_size = 0;
-    clearDataBuffer();
 }
 
 Ref<SharedBuffer> SharedBuffer::copy() const
 {
-    Ref<SharedBuffer> clone { adoptRef(*new SharedBuffer) };
-
-    if (hasPlatformData() || m_fileData) {
-        clone->append(data(), size());
-        return clone;
-    }
-
+    Ref<SharedBuffer> clone = adoptRef(*new SharedBuffer);
     clone->m_size = m_size;
-    clone->m_buffer->data.reserveCapacity(m_size);
-    clone->m_buffer->data.append(m_buffer->data.data(), m_buffer->data.size());
-
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    if (!m_segments.isEmpty()) {
-        unsigned lastIndex = m_segments.size() - 1;
-        for (unsigned i = 0; i < lastIndex; ++i)
-            clone->m_buffer->data.append(m_segments[i], segmentSize);
-
-        unsigned sizeOfLastSegment = m_size - m_buffer->data.size() - lastIndex * segmentSize;
-        clone->m_buffer->data.append(m_segments.last(), sizeOfLastSegment);
-    }
-#else
-    for (auto& data : m_dataArray)
-        clone->m_dataArray.append(data.get());
-#endif
-    ASSERT(clone->size() == size());
-
+    clone->m_segments.reserveInitialCapacity(m_segments.size());
+    for (const auto& segment : m_segments)
+        clone->m_segments.uncheckedAppend(segment.copyRef());
     return clone;
 }
 
-void SharedBuffer::duplicateDataBufferIfNecessary() const
+const char* SharedBuffer::DataSegment::data() const
 {
-    size_t currentCapacity = m_buffer->data.capacity();
-    if (m_buffer->hasOneRef() || m_size <= currentCapacity)
-        return;
-
-    size_t newCapacity = std::max(static_cast<size_t>(m_size), currentCapacity * 2);
-    auto newBuffer = adoptRef(*new DataBuffer);
-    newBuffer->data.reserveInitialCapacity(newCapacity);
-    newBuffer->data = ""
-    m_buffer = WTFMove(newBuffer);
+    auto visitor = WTF::makeVisitor(
+        [](const Vector<char>& data) { return data.data(); },
+#if USE(CF)
+        [](const RetainPtr<CFDataRef>& data) { return reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())); },
+#endif
+#if USE(SOUP)
+        [](const GUniquePtr<SoupBuffer>& data) { return data->data; },
+#endif
+        [](const MappedFileData& data) { return reinterpret_cast<const char*>(data.data()); }
+    );
+    return WTF::visit(visitor, m_immutableData);
 }
 
-void SharedBuffer::appendToDataBuffer(const char *data, unsigned length) const
-{
-    duplicateDataBufferIfNecessary();
-    m_buffer->data.append(data, length);
-}
-
-void SharedBuffer::clearDataBuffer()
-{
-    if (!m_buffer->hasOneRef())
-        m_buffer = adoptRef(*new DataBuffer);
-    else
-        m_buffer->data.clear();
-}
-
 #if !USE(CF)
 void SharedBuffer::hintMemoryNotNeededSoon()
 {
@@ -314,111 +174,21 @@
 }
 #endif
 
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-
-void SharedBuffer::copyBufferAndClear(char* destination, unsigned bytesToCopy) const
+size_t SharedBuffer::DataSegment::size() const
 {
-    for (char* segment : m_segments) {
-        unsigned effectiveBytesToCopy = std::min(bytesToCopy, segmentSize);
-        memcpy(destination, segment, effectiveBytesToCopy);
-        destination += effectiveBytesToCopy;
-        bytesToCopy -= effectiveBytesToCopy;
-        freeSegment(segment);
-    }
-    m_segments.clear();
-}
-
+    auto visitor = WTF::makeVisitor(
+        [](const Vector<char>& data) { return data.size(); },
+#if USE(CF)
+        [](const RetainPtr<CFDataRef>& data) { return CFDataGetLength(data.get()); },
 #endif
-
-const Vector<char>& SharedBuffer::buffer() const
-{
-    unsigned bufferSize = m_buffer->data.size();
-    if (m_size > bufferSize) {
-        duplicateDataBufferIfNecessary();
-        m_buffer->data.resize(m_size);
-        copyBufferAndClear(m_buffer->data.data() + bufferSize, m_size - bufferSize);
-    }
-    return m_buffer->data;
-}
-
-unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const
-{
-    unsigned totalSize = size();
-    if (position >= totalSize) {
-        someData = 0;
-        return 0;
-    }
-
-    if (hasPlatformData() || m_fileData) {
-        ASSERT_WITH_SECURITY_IMPLICATION(position < size());
-        someData = data() + position;
-        return totalSize - position;
-    }
-
-    ASSERT_WITH_SECURITY_IMPLICATION(position < m_size);
-    unsigned consecutiveSize = m_buffer->data.size();
-    if (position < consecutiveSize) {
-        someData = m_buffer->data.data() + position;
-        return consecutiveSize - position;
-    }
- 
-    position -= consecutiveSize;
-#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    unsigned segments = m_segments.size();
-    unsigned maxSegmentedSize = segments * segmentSize;
-    unsigned segment = segmentIndex(position);
-    if (segment < segments) {
-        unsigned bytesLeft = totalSize - consecutiveSize;
-        unsigned segmentedSize = std::min(maxSegmentedSize, bytesLeft);
-
-        unsigned positionInSegment = offsetInSegment(position);
-        someData = m_segments[segment] + positionInSegment;
-        return segment == segments - 1 ? segmentedSize - position : segmentSize - positionInSegment;
-    }
-    ASSERT_NOT_REACHED();
-    return 0;
-#else
-    return copySomeDataFromDataArray(someData, position);
+#if USE(SOUP)
+        [](const GUniquePtr<SoupBuffer>& data) { return static_cast<size_t>(data->length); },
 #endif
+        [](const MappedFileData& data) { return data.size(); }
+    );
+    return WTF::visit(visitor, m_immutableData);
 }
 
-void SharedBuffer::maybeTransferMappedFileData()
-{
-    if (m_fileData) {
-        auto fileData = WTFMove(m_fileData);
-        append(static_cast<const char*>(fileData.data()), fileData.size());
-    }
-}
-
-#if !USE(CF) && !USE(SOUP)
-
-inline void SharedBuffer::clearPlatformData()
-{
-}
-
-inline void SharedBuffer::maybeTransferPlatformData()
-{
-}
-
-inline bool SharedBuffer::hasPlatformData() const
-{
-    return false;
-}
-
-inline const char* SharedBuffer::platformData() const
-{
-    ASSERT_NOT_REACHED();
-
-    return nullptr;
-}
-
-inline bool SharedBuffer::maybeAppendPlatformData(SharedBuffer&)
-{
-    return false;
-}
-
-#endif
-
 RefPtr<SharedBuffer> utf8Buffer(const String& string)
 {
     // Allocate a buffer big enough to hold all the characters.

Modified: trunk/Source/WebCore/platform/SharedBuffer.h (215607 => 215608)


--- trunk/Source/WebCore/platform/SharedBuffer.h	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/SharedBuffer.h	2017-04-21 14:21:46 UTC (rev 215608)
@@ -31,6 +31,7 @@
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
 #include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Variant.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
@@ -49,27 +50,24 @@
 
 namespace WebCore {
     
-class SharedBuffer : public RefCounted<SharedBuffer> {
+class WEBCORE_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
 public:
     static Ref<SharedBuffer> create() { return adoptRef(*new SharedBuffer); }
-    static Ref<SharedBuffer> create(const char* c, unsigned i) { return adoptRef(*new SharedBuffer(c, i)); }
-    static Ref<SharedBuffer> create(const unsigned char* data, unsigned size) { return adoptRef(*new SharedBuffer(data, size)); }
+    static Ref<SharedBuffer> create(const char* data, size_t size) { return adoptRef(*new SharedBuffer(data, size)); }
+    static Ref<SharedBuffer> create(const unsigned char* data, size_t size) { return adoptRef(*new SharedBuffer(data, size)); }
+    static RefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
 
-    WEBCORE_EXPORT static RefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
-
-    WEBCORE_EXPORT static Ref<SharedBuffer> create(Vector<char>&&);
+    static Ref<SharedBuffer> create(Vector<char>&&);
     
-    WEBCORE_EXPORT ~SharedBuffer();
-    
 #if USE(FOUNDATION)
-    WEBCORE_EXPORT RetainPtr<NSData> createNSData();
-    WEBCORE_EXPORT RetainPtr<NSArray> createNSDataArray() const;
-    WEBCORE_EXPORT static Ref<SharedBuffer> wrapNSData(NSData *);
+    RetainPtr<NSData> createNSData();
+    RetainPtr<NSArray> createNSDataArray() const;
+    static Ref<SharedBuffer> create(NSData *);
 #endif
 #if USE(CF)
-    WEBCORE_EXPORT RetainPtr<CFDataRef> createCFData();
-    WEBCORE_EXPORT static Ref<SharedBuffer> wrapCFData(CFDataRef);
-    WEBCORE_EXPORT void append(CFDataRef);
+    RetainPtr<CFDataRef> createCFData();
+    static Ref<SharedBuffer> create(CFDataRef);
+    void append(CFDataRef);
 #endif
 
 #if USE(SOUP)
@@ -77,101 +75,93 @@
     static Ref<SharedBuffer> wrapSoupBuffer(SoupBuffer*);
 #endif
 
-    // Calling this function will force internal segmented buffers
-    // to be merged into a flat buffer. Use getSomeData() whenever possible
-    // for better performance.
-    WEBCORE_EXPORT const char* data() const;
+    // Calling data() causes all the data segments to be copied into one segment if they are not already.
+    // Iterate the segments using begin() and end() instead.
+    // FIXME: Audit the call sites of this function and replace them with iteration if possible.
+    const char* data() const;
+
     // Creates an ArrayBuffer and copies this SharedBuffer's contents to that
     // ArrayBuffer without merging segmented buffers into a flat buffer.
-    WEBCORE_EXPORT RefPtr<ArrayBuffer> createArrayBuffer() const;
+    RefPtr<ArrayBuffer> createArrayBuffer() const;
 
-    WEBCORE_EXPORT unsigned size() const;
+    // FIXME: This should return a size_t.
+    unsigned size() const { return m_size; }
 
     bool isEmpty() const { return !size(); }
 
-    WEBCORE_EXPORT void append(SharedBuffer&);
-    WEBCORE_EXPORT void append(const char*, unsigned);
-    WEBCORE_EXPORT void append(Vector<char>&&);
+    void append(const SharedBuffer&);
+    void append(const char*, size_t);
+    void append(Vector<char>&&);
 
-    WEBCORE_EXPORT void clear();
+    void clear();
 
-    WEBCORE_EXPORT Ref<SharedBuffer> copy() const;
-    
-    // Return the number of consecutive bytes after "position". "data"
-    // points to the first byte.
-    // Return 0 when no more data left.
-    // When extracting all data with getSomeData(), the caller should
-    // repeat calling it until it returns 0.
-    // Usage:
-    //      const char* segment;
-    //      unsigned pos = 0;
-    //      while (unsigned length = sharedBuffer->getSomeData(segment, pos)) {
-    //          // Use the data. for example: decoder->decode(segment, length);
-    //          pos += length;
-    //      }
-    WEBCORE_EXPORT unsigned getSomeData(const char*& data, unsigned position = 0) const;
+    Ref<SharedBuffer> copy() const;
 
-    bool tryReplaceContentsWithPlatformBuffer(SharedBuffer&);
-    WEBCORE_EXPORT bool hasPlatformData() const;
+    // Data wrapped by a DataSegment should be immutable because it can be referenced by other objects.
+    // To modify or combine the data, allocate a new DataSegment.
+    class DataSegment : public ThreadSafeRefCounted<DataSegment> {
+    public:
+        const char* data() const;
+        size_t size() const;
 
-    struct DataBuffer : public ThreadSafeRefCounted<DataBuffer> {
-        Vector<char> data;
+        static Ref<DataSegment> create(Vector<char>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+#if USE(CF)
+        static Ref<DataSegment> create(RetainPtr<CFDataRef>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+#endif
+#if USE(SOUP)
+        static Ref<DataSegment> create(GUniquePtr<SoupBuffer>&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+#endif
+        static Ref<DataSegment> create(MappedFileData&& data) { return adoptRef(*new DataSegment(WTFMove(data))); }
+
+    private:
+        DataSegment(Vector<char>&& data)
+            : m_immutableData(WTFMove(data)) { }
+#if USE(CF)
+        DataSegment(RetainPtr<CFDataRef>&& data)
+            : m_immutableData(WTFMove(data)) { }
+#endif
+#if USE(SOUP)
+        DataSegment(GUniquePtr<SoupBuffer>&& data)
+            : m_immutableData(WTFMove(data)) { }
+#endif
+        DataSegment(MappedFileData&& data)
+            : m_immutableData(WTFMove(data)) { }
+
+        Variant<Vector<char>,
+#if USE(CF)
+            RetainPtr<CFDataRef>,
+#endif
+#if USE(SOUP)
+            GUniquePtr<SoupBuffer>,
+#endif
+            MappedFileData> m_immutableData;
+        friend class SharedBuffer;
     };
 
+    Vector<Ref<const DataSegment>>::const_iterator begin() const { return m_segments.begin(); }
+    Vector<Ref<const DataSegment>>::const_iterator end() const { return m_segments.end(); }
+
     void hintMemoryNotNeededSoon();
 
 private:
-    WEBCORE_EXPORT SharedBuffer();
-    WEBCORE_EXPORT SharedBuffer(const char*, unsigned);
-    WEBCORE_EXPORT SharedBuffer(const unsigned char*, unsigned);
-    explicit SharedBuffer(MappedFileData&&);
-
-    static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
-
-    // Calling this function will force internal segmented buffers
-    // to be merged into a flat buffer. Use getSomeData() whenever possible
-    // for better performance.
-    const Vector<char>& buffer() const;
-
-    void clearPlatformData();
-    void maybeTransferPlatformData();
-    bool maybeAppendPlatformData(SharedBuffer&);
-
-    void maybeTransferMappedFileData();
-
-    void copyBufferAndClear(char* destination, unsigned bytesToCopy) const;
-
-    void appendToDataBuffer(const char *, unsigned) const;
-    void duplicateDataBufferIfNecessary() const;
-    void clearDataBuffer();
-
-    unsigned m_size { 0 };
-    mutable Ref<DataBuffer> m_buffer;
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    mutable Vector<RetainPtr<CFDataRef>> m_dataArray;
-    unsigned copySomeDataFromDataArray(const char*& someData, unsigned position) const;
-    const char *singleDataArrayBuffer() const;
-    bool maybeAppendDataArray(SharedBuffer&);
-#else
-    mutable Vector<char*> m_segments;
-#endif
-
-    unsigned platformDataSize() const;
-    const char* platformData() const;
-
+    SharedBuffer() = default;
+    SharedBuffer(const char*, size_t);
+    SharedBuffer(const unsigned char*, size_t);
+    SharedBuffer(Vector<char>&&);
+    SharedBuffer(MappedFileData&&);
 #if USE(CF)
-    explicit SharedBuffer(CFDataRef);
-    RetainPtr<CFDataRef> m_cfData;
-    CFDataRef existingCFData();
+    SharedBuffer(CFDataRef);
 #endif
-
 #if USE(SOUP)
-    explicit SharedBuffer(SoupBuffer*);
-    GUniquePtr<SoupBuffer> m_soupBuffer;
+    SharedBuffer(SoupBuffer*);
 #endif
 
-    MappedFileData m_fileData;
+    void combineToOneSegment() const;
+    
+    static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
+
+    size_t m_size { 0 };
+    mutable Vector<Ref<const DataSegment>> m_segments;
 };
 
 RefPtr<SharedBuffer> utf8Buffer(const String&);

Modified: trunk/Source/WebCore/platform/SharedBufferChunkReader.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/SharedBufferChunkReader.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/SharedBufferChunkReader.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -31,6 +31,11 @@
 #include "config.h"
 #include "SharedBufferChunkReader.h"
 
+#if ENABLE(MHTML)
+
+// FIXME: This class is overkill. Remove this class and just iterate the segments of a SharedBuffer
+// using the cool new SharedBuffer::begin() and SharedBuffer::end() instead of using this class.
+
 #include "SharedBuffer.h"
 
 namespace WebCore {
@@ -100,7 +105,10 @@
         // Read the next segment.
         m_segmentIndex = 0;
         m_bufferPosition += m_segmentLength;
-        m_segmentLength = m_buffer->getSomeData(m_segment, m_bufferPosition);
+        // Let's pretend all the data is in one block.
+        // FIXME: This class should be removed in favor of just iterating the segments of the SharedBuffer.
+        m_segment = m_buffer->data() + m_bufferPosition;
+        m_segmentLength = m_buffer->size() - m_bufferPosition;
         if (!m_segmentLength) {
             m_reachedEndOfFile = true;
             if (m_separatorIndex > 0)
@@ -134,12 +142,14 @@
 
     size_t bufferPosition = m_bufferPosition + m_segmentLength;
     const char* segment = 0;
-    while (size_t segmentLength = m_buffer->getSomeData(segment, bufferPosition)) {
-        if (requestedSize <= readBytesCount + segmentLength) {
-            data.append(segment, requestedSize - readBytesCount);
-            readBytesCount += (requestedSize - readBytesCount);
-            break;
-        }
+
+    // Let's pretend all the data is in one block.
+    // FIXME: This class should be removed in favor of just iterating the segments of the SharedBuffer.
+    if (bufferPosition != m_buffer->size()) {
+        segment = m_buffer->data() + bufferPosition;
+        size_t segmentLength = m_buffer->size() - bufferPosition;
+        if (segmentLength > requestedSize)
+            segmentLength = requestedSize;
         data.append(segment, segmentLength);
         readBytesCount += segmentLength;
         bufferPosition += segmentLength;
@@ -148,3 +158,5 @@
 }
 
 }
+
+#endif

Modified: trunk/Source/WebCore/platform/SharedBufferChunkReader.h (215607 => 215608)


--- trunk/Source/WebCore/platform/SharedBufferChunkReader.h	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/SharedBufferChunkReader.h	2017-04-21 14:21:46 UTC (rev 215608)
@@ -28,9 +28,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SharedBufferChunkReader_h
-#define SharedBufferChunkReader_h
+#pragma once
 
+#if ENABLE(MHTML)
+
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 

Modified: trunk/Source/WebCore/platform/URLParser.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/URLParser.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/URLParser.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1149,6 +1149,8 @@
 URLParser::URLParser(const String& input, const URL& base, const TextEncoding& encoding)
     : m_inputString(input)
 {
+    if (input == "file:///Users/alexchristensen/webkit/LayoutTests/webarchive/archive-empty-frame-source.html")
+        WTFLogAlways("HIT");
     if (input.isNull()) {
         if (base.isValid() && !base.m_cannotBeABaseURL) {
             m_url = base;

Modified: trunk/Source/WebCore/platform/cf/KeyedEncoderCF.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/cf/KeyedEncoderCF.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/cf/KeyedEncoderCF.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -145,7 +145,7 @@
     auto data = "" m_rootDictionary.get(), kCFPropertyListBinaryFormat_v1_0, 0, nullptr));
     if (!data)
         return nullptr;
-    return SharedBuffer::wrapCFData(data.get());
+    return SharedBuffer::create(data.get());
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -33,10 +33,9 @@
 
 namespace WebCore {
 
-SharedBuffer::SharedBuffer(CFDataRef cfData)
-    : m_buffer(adoptRef(*new DataBuffer))
-    , m_cfData(cfData)
+SharedBuffer::SharedBuffer(CFDataRef data)
 {
+    append(data);
 }
 
 // Using Foundation allows for an even more efficient implementation of this function,
@@ -44,144 +43,34 @@
 #if !USE(FOUNDATION)
 RetainPtr<CFDataRef> SharedBuffer::createCFData()
 {
-    if (m_cfData)
-        return m_cfData;
-
-    // Internal data in SharedBuffer can be segmented. We need to get the contiguous buffer.
-    const Vector<char>& contiguousBuffer = buffer();
-    return adoptCF(CFDataCreate(0, reinterpret_cast<const UInt8*>(contiguousBuffer.data()), contiguousBuffer.size()));
+    if (m_segments.size() == 1) {
+        if (auto data = ""
+            return *data;
+    }
+    return adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(data()), size()));
 }
 #endif
 
-Ref<SharedBuffer> SharedBuffer::wrapCFData(CFDataRef data)
+Ref<SharedBuffer> SharedBuffer::create(CFDataRef data)
 {
     return adoptRef(*new SharedBuffer(data));
 }
 
-bool SharedBuffer::hasPlatformData() const
-{
-    return m_cfData;
-}
-
-const char* SharedBuffer::platformData() const
-{
-    return reinterpret_cast<const char*>(CFDataGetBytePtr(m_cfData.get()));
-}
-
-unsigned SharedBuffer::platformDataSize() const
-{
-    return CFDataGetLength(m_cfData.get());
-}
-
 void SharedBuffer::hintMemoryNotNeededSoon()
 {
-    if (!hasPlatformData())
-        return;
-    OSAllocator::hintMemoryNotNeededSoon(const_cast<char*>(platformData()), platformDataSize());
+    for (const auto& segment : m_segments) {
+        if (segment->hasOneRef()) {
+            if (auto data = ""
+                OSAllocator::hintMemoryNotNeededSoon(const_cast<UInt8*>(CFDataGetBytePtr(data->get())), CFDataGetLength(data->get()));
+        }
+    }
 }
 
-void SharedBuffer::maybeTransferPlatformData()
-{
-    if (!m_cfData)
-        return;
-    
-    ASSERT(!m_size);
-    
-    // Hang on to the m_cfData pointer in a local pointer as append() will re-enter maybeTransferPlatformData()
-    // and we need to make sure to early return when it does.
-    RetainPtr<CFDataRef> cfData = adoptCF(m_cfData.leakRef());
-
-    append(reinterpret_cast<const char*>(CFDataGetBytePtr(cfData.get())), CFDataGetLength(cfData.get()));
-}
-
-void SharedBuffer::clearPlatformData()
-{
-    m_cfData = 0;
-}
-
-bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
-{
-    if (!newContents.m_cfData)
-        return false;
-
-    clear();
-    m_cfData = newContents.m_cfData;
-    return true;
-}
-
-bool SharedBuffer::maybeAppendPlatformData(SharedBuffer& newContents)
-{
-    if (size() || !newContents.m_cfData)
-        return false;
-    m_cfData = newContents.m_cfData;
-    return true;
-}
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
 void SharedBuffer::append(CFDataRef data)
 {
     ASSERT(data);
-    m_dataArray.append(data);
     m_size += CFDataGetLength(data);
+    m_segments.append(DataSegment::create(data));
 }
 
-void SharedBuffer::copyBufferAndClear(char* destination, unsigned bytesToCopy) const
-{
-    if (m_dataArray.isEmpty())
-        return;
-
-    CFIndex bytesLeft = bytesToCopy;
-    for (auto& cfData : m_dataArray) {
-        CFIndex dataLen = CFDataGetLength(cfData.get());
-        ASSERT(bytesLeft >= dataLen);
-        memcpy(destination, CFDataGetBytePtr(cfData.get()), dataLen);
-        destination += dataLen;
-        bytesLeft -= dataLen;
-    }
-    m_dataArray.clear();
 }
-
-unsigned SharedBuffer::copySomeDataFromDataArray(const char*& someData, unsigned position) const
-{
-    unsigned totalOffset = 0;
-    for (auto& cfData : m_dataArray) {
-        unsigned dataLen = static_cast<unsigned>(CFDataGetLength(cfData.get()));
-        ASSERT(totalOffset <= position);
-        unsigned localOffset = position - totalOffset;
-        if (localOffset < dataLen) {
-            someData = reinterpret_cast<const char *>(CFDataGetBytePtr(cfData.get())) + localOffset;
-            return dataLen - localOffset;
-        }
-        totalOffset += dataLen;
-    }
-    return 0;
-}
-
-const char *SharedBuffer::singleDataArrayBuffer() const
-{
-    // If we had previously copied data into m_buffer in copyDataArrayAndClear() or some other
-    // function, then we can't return a pointer to the CFDataRef buffer.
-    if (m_buffer->data.size())
-        return 0;
-
-    if (m_dataArray.size() != 1)
-        return 0;
-
-    return reinterpret_cast<const char*>(CFDataGetBytePtr(m_dataArray.at(0).get()));
-}
-
-bool SharedBuffer::maybeAppendDataArray(SharedBuffer& data)
-{
-    if (m_buffer->data.size() || m_cfData || !data.m_dataArray.size())
-        return false;
-#if !ASSERT_DISABLED
-    unsigned originalSize = size();
-#endif
-    for (auto& cfData : data.m_dataArray)
-        append(cfData.get());
-    ASSERT(size() == originalSize + data.size());
-    return true;
-}
-#endif
-
-}

Modified: trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -197,7 +197,7 @@
 Ref<SharedBuffer> NetworkExtensionContentFilter::replacementData() const
 {
     ASSERT(didBlockData());
-    return SharedBuffer::wrapNSData(m_replacementData.get());
+    return SharedBuffer::create(m_replacementData.get());
 }
 
 #if ENABLE(CONTENT_FILTERING)

Modified: trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -93,7 +93,7 @@
 Ref<SharedBuffer> ParentalControlsContentFilter::replacementData() const
 {
     ASSERT(didBlockData());
-    return SharedBuffer::wrapNSData(m_replacementData.get());
+    return SharedBuffer::create(m_replacementData.get());
 }
 
 #if ENABLE(CONTENT_FILTERING)

Modified: trunk/Source/WebCore/platform/cocoa/SharedBufferCocoa.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/cocoa/SharedBufferCocoa.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/cocoa/SharedBufferCocoa.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -35,10 +35,10 @@
 
 @interface WebCoreSharedBufferData : NSData
 {
-    RefPtr<SharedBuffer::DataBuffer> sharedBufferDataBuffer;
+    RefPtr<const SharedBuffer::DataSegment> sharedBufferDataSegment;
 }
 
-- (id)initWithSharedBufferDataBuffer:(SharedBuffer::DataBuffer*)dataBuffer;
+- (id)initWithSharedBufferDataSegment:(const SharedBuffer::DataSegment&)dataSegment;
 @end
 
 @implementation WebCoreSharedBufferData
@@ -59,12 +59,12 @@
     [super dealloc];
 }
 
-- (id)initWithSharedBufferDataBuffer:(SharedBuffer::DataBuffer*)dataBuffer
+- (id)initWithSharedBufferDataSegment:(const SharedBuffer::DataSegment&)dataSegment
 {
     self = [super init];
     
     if (self)
-        sharedBufferDataBuffer = dataBuffer;
+        sharedBufferDataSegment = &dataSegment;
 
     return self;
 }
@@ -71,12 +71,12 @@
 
 - (NSUInteger)length
 {
-    return sharedBufferDataBuffer->data.size();
+    return sharedBufferDataSegment->size();
 }
 
 - (const void *)bytes
 {
-    return sharedBufferDataBuffer->data.data();
+    return sharedBufferDataSegment->data();
 }
 
 @end
@@ -83,7 +83,7 @@
 
 namespace WebCore {
 
-Ref<SharedBuffer> SharedBuffer::wrapNSData(NSData *nsData)
+Ref<SharedBuffer> SharedBuffer::create(NSData *nsData)
 {
     return adoptRef(*new SharedBuffer((CFDataRef)nsData));
 }
@@ -93,26 +93,13 @@
     return adoptNS((NSData *)createCFData().leakRef());
 }
 
-CFDataRef SharedBuffer::existingCFData()
-{
-    if (m_cfData)
-        return m_cfData.get();
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    if (m_dataArray.size() == 1)
-        return m_dataArray.at(0).get();
-#endif
-
-    return nullptr;
-}
-
 RetainPtr<CFDataRef> SharedBuffer::createCFData()
 {
-    if (CFDataRef cfData = existingCFData())
-        return cfData;
-
-    data(); // Force data into m_buffer from segments or data array.
-    return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:m_buffer.ptr()]).leakRef());
+    combineToOneSegment();
+    if (!m_segments.size())
+        return adoptCF(CFDataCreate(nullptr, nullptr, 0));
+    ASSERT(m_segments.size() == 1);
+    return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:m_segments[0]]).leakRef());
 }
 
 RefPtr<SharedBuffer> SharedBuffer::createFromReadingFile(const String& filePath)
@@ -119,31 +106,15 @@
 {
     NSData *resourceData = [NSData dataWithContentsOfFile:filePath];
     if (resourceData) 
-        return SharedBuffer::wrapNSData(resourceData);
+        return SharedBuffer::create(resourceData);
     return nullptr;
 }
 
 RetainPtr<NSArray> SharedBuffer::createNSDataArray() const
 {
-    if (auto platformData = (NSData *)m_cfData.get())
-        return @[ platformData ];
-
-    if (m_fileData)
-        return @[ [NSData dataWithBytes:m_fileData.data() length:m_fileData.size()] ];
-
-    auto dataArray = adoptNS([[NSMutableArray alloc] init]);
-    if (m_buffer->data.size())
-        [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:m_buffer.ptr()]).get()];
-
-#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
-    for (auto& data : m_dataArray)
-        [dataArray addObject:(NSData *)data.get()];
-#else
-    // Cocoa platforms all currently USE(NETWORK_CFDATA_ARRAY_CALLBACK), so implementing a code path for copying segments would be dead code.
-    // If this ever changes, the following static_assert will detect it.
-    static_assert(false, "FIXME: Copy the segments into an array of NSData objects.");
-#endif
-
+    auto dataArray = adoptNS([[NSMutableArray alloc] initWithCapacity:m_segments.size()]);
+    for (const auto& segment : m_segments)
+        [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:segment]).get()];
     return WTFMove(dataArray);
 }
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -173,27 +173,38 @@
         responseOffset = static_cast<NSUInteger>(contentRange.firstBytePosition());
 
     // Check for possible unsigned overflow.
-    ASSERT([dataRequest currentOffset] >= [dataRequest requestedOffset]);
-    ASSERT([dataRequest requestedLength] >= ([dataRequest currentOffset] - [dataRequest requestedOffset]));
+    ASSERT(dataRequest.currentOffset >= dataRequest.requestedOffset);
+    ASSERT(dataRequest.requestedLength >= (dataRequest.currentOffset - dataRequest.requestedOffset));
 
-    NSUInteger remainingLength = [dataRequest requestedLength] - static_cast<NSUInteger>([dataRequest currentOffset] - [dataRequest requestedOffset]);
-    do {
-        // Check to see if there is any data available in the buffer to fulfill the data request.
-        if (data->size() <= [dataRequest currentOffset] - responseOffset)
-            return;
+    NSUInteger remainingLength = dataRequest.requestedLength - static_cast<NSUInteger>(dataRequest.currentOffset - dataRequest.requestedOffset);
 
-        const char* someData;
-        NSUInteger receivedLength = data->getSomeData(someData, static_cast<unsigned>([dataRequest currentOffset] - responseOffset));
+    auto bytesToSkip = dataRequest.currentOffset - responseOffset;
+    RetainPtr<NSArray> array = data->createNSDataArray();
+    for (size_t i = 0; i < [array count]; ++i) {
+        NSData *segment = [array objectAtIndex:i];
+        if (bytesToSkip) {
+            if (bytesToSkip > segment.length) {
+                bytesToSkip -= segment.length;
+                continue;
+            }
+            auto bytesToUse = segment.length - bytesToSkip;
+            [dataRequest respondWithData:[segment subdataWithRange:NSMakeRange(static_cast<NSUInteger>(bytesToSkip), static_cast<NSUInteger>(segment.length - bytesToSkip))]];
+            bytesToSkip = 0;
+            remainingLength -= bytesToUse;
+            continue;
+        }
+        if (segment.length <= remainingLength) {
+            [dataRequest respondWithData:segment];
+            remainingLength -= segment.length;
+            continue;
+        }
+        [dataRequest respondWithData:[segment subdataWithRange:NSMakeRange(0, remainingLength)]];
+        remainingLength = 0;
+        if (!remainingLength)
+            break;
+    }
 
-        // Create an NSData with only as much of the received data as necessary to fulfill the request.
-        NSUInteger length = MIN(receivedLength, remainingLength);
-        RetainPtr<NSData> nsData = adoptNS([[NSData alloc] initWithBytes:someData length:length]);
-
-        [dataRequest respondWithData:nsData.get()];
-        remainingLength -= length;
-    } while (remainingLength);
-
-    if ([dataRequest currentOffset] + [dataRequest requestedLength] >= [dataRequest requestedOffset]) {
+    if (dataRequest.currentOffset + dataRequest.requestedLength >= dataRequest.requestedOffset) {
         [m_avRequest.get() finishLoading];
         stopLoading();
     }

Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -201,7 +201,7 @@
 RefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
 {
     if (RetainPtr<CFDataRef> data = "" table, kCTFontTableOptionNoOptions)))
-        return SharedBuffer::wrapCFData(data.get());
+        return SharedBuffer::create(data.get());
     
     return nullptr;
 }

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1163,13 +1163,8 @@
 
 void ResourceHandleStreamingClient::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffer, int /* encodedLength */)
 {
-    // This pattern is suggested by SharedBuffer.h.
-    const char* segment;
-    unsigned position = 0;
-    while (unsigned length = buffer->getSomeData(segment, position)) {
-        handleDataReceived(segment, length);
-        position += length;
-    }
+    for (const auto& segment : buffer.get())
+        handleDataReceived(segment->data(), segment->size());
 }
 
 void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*)

Modified: trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -63,7 +63,7 @@
     NSData *namedImageData = [NSData dataWithContentsOfFile:imagePath];
     if (namedImageData) {
         auto image = BitmapImage::create();
-        image->setData(SharedBuffer::wrapNSData(namedImageData), true);
+        image->setData(SharedBuffer::create(namedImageData), true);
         return WTFMove(image);
     }
 

Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -42,17 +42,19 @@
 
 namespace {
 
-unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
+static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer)
 {
     unsigned bytesExtracted = 0;
-    const char* moreData;
-    while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) {
-        unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength);
-        memcpy(buffer + bytesExtracted, moreData, bytesToCopy);
-        bytesExtracted += bytesToCopy;
-        if (bytesExtracted == bufferLength)
+    for (const auto& segment : sharedBuffer) {
+        if (bytesExtracted + segment->size() <= bufferLength) {
+            memcpy(buffer + bytesExtracted, segment->data(), segment->size());
+            bytesExtracted += segment->size();
+        } else {
+            ASSERT(bufferLength - bytesExtracted < segment->size());
+            memcpy(buffer + bytesExtracted, segment->data(), bufferLength - bytesExtracted);
+            bytesExtracted = bufferLength;
             break;
-        offset += bytesToCopy;
+        }
     }
     return bytesExtracted;
 }
@@ -100,7 +102,7 @@
 {
     static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
     char contents[lengthOfLongestSignature];
-    unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
+    unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data);
     if (length < lengthOfLongestSignature)
         return nullptr;
 

Modified: trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -157,11 +157,10 @@
         if (setjmp(JMPBUF(m_png)))
             return decoder->setFailed();
 
-        const char* segment;
-        while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) {
-            m_readOffset += segmentLength;
+        for (const auto& segment : data) {
+            m_readOffset += segment->size();
             m_currentBufferSize = m_readOffset;
-            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength);
+            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment->data())), segment->size());
             // We explicitly specify the superclass encodedDataStatus() because we
             // merely want to check if we've managed to set the size, not
             // (recursively) trigger additional decoding if we haven't.

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -308,7 +308,7 @@
 
     if (![pasteboardItem count])
         return nullptr;
-    return SharedBuffer::wrapNSData([pasteboardItem.get() objectAtIndex:0]);
+    return SharedBuffer::create([pasteboardItem.get() objectAtIndex:0]);
 }
 
 String PlatformPasteboard::readString(int index, const String& type)

Modified: trunk/Source/WebCore/platform/mac/PasteboardMac.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/mac/PasteboardMac.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -261,7 +261,7 @@
     if (!RTFDData)
         return;
 
-    newChangeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(RTFDData).ptr(), NSRTFDPboardType, pasteboardName);
+    newChangeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::create(RTFDData).ptr(), NSRTFDPboardType, pasteboardName);
 }
 
 void Pasteboard::write(const PasteboardImage& pasteboardImage)
@@ -278,7 +278,7 @@
         types.append(WebArchivePboardType);
 
     m_changeCount = writeURLForTypes(types, m_pasteboardName, pasteboardImage.url);
-    m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapCFData(imageData).ptr(), NSTIFFPboardType, m_pasteboardName);
+    m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::create(imageData).ptr(), NSTIFFPboardType, m_pasteboardName);
     if (pasteboardImage.dataInWebArchiveFormat)
         m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(pasteboardImage.dataInWebArchiveFormat.get(), WebArchivePboardType, m_pasteboardName);
     writeFileWrapperAsRTFDAttachment(fileWrapper(pasteboardImage), m_pasteboardName, m_changeCount);

Modified: trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -50,7 +50,7 @@
     NSData *data = "" dataForType:pasteboardType];
     if (!data)
         return nullptr;
-    return SharedBuffer::wrapNSData([[data copy] autorelease]);
+    return SharedBuffer::create([[data copy] autorelease]);
 }
 
 int PlatformPasteboard::numberOfFiles()

Modified: trunk/Source/WebCore/platform/network/BlobResourceHandle.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/network/BlobResourceHandle.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/BlobResourceHandle.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -604,7 +604,7 @@
 void BlobResourceHandle::notifyReceiveData(const char* data, int bytesRead)
 {
     if (client())
-        client()->didReceiveBuffer(this, SharedBuffer::create(data, bytesRead), bytesRead);
+        client()->didReceiveBuffer(this, SharedBuffer::create(reinterpret_cast<const uint8_t*>(data), bytesRead), bytesRead);
 }
 
 void BlobResourceHandle::notifyFail(Error errorCode)

Modified: trunk/Source/WebCore/platform/network/MIMEHeader.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/network/MIMEHeader.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/MIMEHeader.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -31,6 +31,8 @@
 #include "config.h"
 #include "MIMEHeader.h"
 
+#if ENABLE(MHTML)
+
 #include "ParsedContentType.h"
 #include "SharedBufferChunkReader.h"
 #include <wtf/HashMap.h>
@@ -133,3 +135,5 @@
 }
 
 }
+
+#endif

Modified: trunk/Source/WebCore/platform/network/MIMEHeader.h (215607 => 215608)


--- trunk/Source/WebCore/platform/network/MIMEHeader.h	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/MIMEHeader.h	2017-04-21 14:21:46 UTC (rev 215608)
@@ -28,9 +28,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef MIMEHeader_h
-#define MIMEHeader_h
+#pragma once
 
+#if ENABLE(MHTML)
+
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>

Modified: trunk/Source/WebCore/platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -177,7 +177,7 @@
         if (protectedThis->hasHandle() && m_handle->client()) {
             LOG(Network, "CFNet - ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData(handle=%p) (%s)", m_handle, m_handle->firstRequest().url().string().utf8().data());
 
-            m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
+            m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data), originalLength);
         }
 
         CFRelease(data);

Modified: trunk/Source/WebCore/platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -184,7 +184,7 @@
     LOG(Network, "CFNet - SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData(handle=%p, bytes=%ld) (%s)", m_handle, CFDataGetLength(data), m_handle->firstRequest().url().string().utf8().data());
 
     if (ResourceHandleClient* client = m_handle->client())
-        client->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
+        client->didReceiveBuffer(m_handle, SharedBuffer::create(data), originalLength);
 }
 
 void SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading()

Modified: trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -174,7 +174,7 @@
     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
     // -1 means we do not provide any data about transfer size to inspector so it would use
     // Content-Length headers or content size to show transfer size.
-    m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
+    m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data), -1);
 }
 
 - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite

Modified: trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm (215607 => 215608)


--- trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -223,7 +223,7 @@
         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793
         // -1 means we do not provide any data about transfer size to inspector so it would use
         // Content-Length headers or content size to show transfer size.
-        m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
+        m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::create(data), -1);
     });
 }
 

Modified: trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp (215607 => 215608)


--- trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -27,10 +27,10 @@
 namespace WebCore {
 
 SharedBuffer::SharedBuffer(SoupBuffer* soupBuffer)
-    : m_buffer(*new DataBuffer)
-    , m_soupBuffer(soupBuffer)
 {
     ASSERT(soupBuffer);
+    m_size = soupBuffer->length;
+    m_segments.append(DataSegment::create(GUniquePtr<SoupBuffer>(soupBuffer)));
 }
 
 Ref<SharedBuffer> SharedBuffer::wrapSoupBuffer(SoupBuffer* soupBuffer)
@@ -40,11 +40,6 @@
 
 GUniquePtr<SoupBuffer> SharedBuffer::createSoupBuffer(unsigned offset, unsigned size)
 {
-    if (m_soupBuffer && !offset && !size) {
-        GUniquePtr<SoupBuffer> buffer(soup_buffer_copy(m_soupBuffer.get()));
-        return buffer;
-    }
-
     ref();
     GUniquePtr<SoupBuffer> buffer(soup_buffer_new_with_owner(data() + offset, size ? size : this->size(), this, [](void* data) {
         static_cast<SharedBuffer*>(data)->deref();
@@ -52,57 +47,6 @@
     return buffer;
 }
 
-void SharedBuffer::clearPlatformData()
-{
-    m_soupBuffer.reset();
-}
-
-void SharedBuffer::maybeTransferPlatformData()
-{
-    if (!m_soupBuffer)
-        return;
-
-    ASSERT(!m_size);
-
-    // Hang on to the m_soupBuffer pointer in a local pointer as append() will re-enter maybeTransferPlatformData()
-    // and we need to make sure to early return when it does.
-    GUniquePtr<SoupBuffer> soupBuffer;
-    soupBuffer.swap(m_soupBuffer);
-
-    append(soupBuffer->data, soupBuffer->length);
-}
-
-bool SharedBuffer::hasPlatformData() const
-{
-    return m_soupBuffer.get();
-}
-
-const char* SharedBuffer::platformData() const
-{
-    return m_soupBuffer->data;
-}
-
-unsigned SharedBuffer::platformDataSize() const
-{
-    return m_soupBuffer->length;
-}
-
-bool SharedBuffer::maybeAppendPlatformData(SharedBuffer&)
-{
-    return false;
-}
-
-bool SharedBuffer::tryReplaceContentsWithPlatformBuffer(SharedBuffer& newContents)
-{
-    if (!newContents.hasPlatformData())
-        return false;
-
-    clear();
-    // FIXME: Use GRefPtr instead of GUniquePtr for the SoupBuffer.
-    m_soupBuffer.swap(newContents.m_soupBuffer);
-    return true;
-}
-
 } // namespace WebCore
 
 #endif

Modified: trunk/Source/WebKit/mac/ChangeLog (215607 => 215608)


--- trunk/Source/WebKit/mac/ChangeLog	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit/mac/ChangeLog	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1,3 +1,18 @@
+2017-04-21  Alex Christensen  <[email protected]>
+
+        Reduce copies and allocations in SharedBuffer::append
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+
+        Reviewed by Andreas Kling.
+
+        * WebView/WebArchive.mm:
+        (-[WebArchive initWithData:]):
+        * WebView/WebFrame.mm:
+        (-[WebFrame _loadData:MIMEType:textEncodingName:baseURL:unreachableURL:]):
+        * WebView/WebResource.mm:
+        (-[WebResource initWithCoder:]):
+        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
+
 2017-04-20  Dewei Zhu  <[email protected]>
 
         Build fix to start using C++14.

Modified: trunk/Source/WebKit/mac/WebView/WebArchive.mm (215607 => 215608)


--- trunk/Source/WebKit/mac/WebView/WebArchive.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit/mac/WebView/WebArchive.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -200,7 +200,7 @@
 #endif
 
     _private = [[WebArchivePrivate alloc] init];
-    auto coreArchive = LegacyWebArchive::create(SharedBuffer::wrapNSData(data));
+    auto coreArchive = LegacyWebArchive::create(SharedBuffer::create(data));
     if (!coreArchive) {
         [self release];
         return nil;

Modified: trunk/Source/WebKit/mac/WebView/WebFrame.mm (215607 => 215608)


--- trunk/Source/WebKit/mac/WebView/WebFrame.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit/mac/WebView/WebFrame.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -2493,7 +2493,7 @@
     ResourceRequest request(baseURL);
 
     ResourceResponse response(responseURL, MIMEType, [data length], encodingName);
-    SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
+    SubstituteData substituteData(WebCore::SharedBuffer::create(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
 
     _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
 }

Modified: trunk/Source/WebKit/mac/WebView/WebResource.mm (215607 => 215608)


--- trunk/Source/WebKit/mac/WebView/WebResource.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit/mac/WebView/WebResource.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -149,7 +149,7 @@
         return nil;
     }
 
-    auto coreResource = ArchiveResource::create(SharedBuffer::wrapNSData(data), url, mimeType, textEncoding, frameName, response);
+    auto coreResource = ArchiveResource::create(SharedBuffer::create(data), url, mimeType, textEncoding, frameName, response);
     if (!coreResource) {
         [self release];
         return nil;
@@ -301,7 +301,7 @@
         return nil;
     }
 
-    auto coreResource = ArchiveResource::create(SharedBuffer::wrapNSData(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response);
+    auto coreResource = ArchiveResource::create(SharedBuffer::create(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response);
     if (!coreResource) {
         [self release];
         return nil;

Modified: trunk/Source/WebKit2/ChangeLog (215607 => 215608)


--- trunk/Source/WebKit2/ChangeLog	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/ChangeLog	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1,3 +1,31 @@
+2017-04-21  Alex Christensen  <[email protected]>
+
+        Reduce copies and allocations in SharedBuffer::append
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+
+        Reviewed by Andreas Kling.
+
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
+        * Platform/IPC/DataReference.cpp:
+        (IPC::SharedBufferDataReference::encode):
+        * Shared/ShareableResource.cpp:
+        (WebKit::ShareableResource::wrapInSharedBuffer):
+        * UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm:
+        (-[WKURLSchemeHandlerTaskImpl didReceiveData:]):
+        * WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
+        (-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
+        * WebProcess/Plugins/PDF/PDFPlugin.mm:
+        (WebKit::PDFPlugin::addArchiveResource):
+        (WebKit::PDFPlugin::liveResourceData):
+        (WebKit::PDFPlugin::writeItemsToPasteboard):
+        * WebProcess/Plugins/PluginView.cpp:
+        (WebKit::PluginView::redeliverManualStream):
+        * WebProcess/WebCoreSupport/mac/WebDragClientMac.mm:
+        (WebKit::WebDragClient::declareAndWriteDragImage):
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::cachedResponseDataForURL):
+
 2017-04-20  Konstantin Tokarev  <[email protected]>
 
         [cmake] Define FORWARDING_HEADERS_DIR in WebKitFS and use it everywhere

Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm (215607 => 215608)


--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -386,7 +386,7 @@
 
     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
     if (auto* networkDataTask = _session->dataTaskForIdentifier(dataTask.taskIdentifier, storedCredentials))
-        networkDataTask->didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
+        networkDataTask->didReceiveData(WebCore::SharedBuffer::create(data));
 }
 
 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

Modified: trunk/Source/WebKit2/Platform/IPC/DataReference.cpp (215607 => 215608)


--- trunk/Source/WebKit2/Platform/IPC/DataReference.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/Platform/IPC/DataReference.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -47,13 +47,8 @@
     encoder.reserve(bufferSize + sizeof(uint64_t));
     encoder << bufferSize;
 
-    const char* partialData;
-    unsigned position = 0;
-    while (position < bufferSize) {
-        unsigned bytesToWrite = m_buffer->getSomeData(partialData, position);
-        encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(partialData), bytesToWrite, 1);
-        position += bytesToWrite;
-    }
+    for (const auto& segment : *m_buffer)
+        encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(segment->data()), segment->size(), 1);
 }
 
 } // namespace IPC

Modified: trunk/Source/WebKit2/Shared/ShareableResource.cpp (215607 => 215608)


--- trunk/Source/WebKit2/Shared/ShareableResource.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/Shared/ShareableResource.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -87,7 +87,7 @@
 #if USE(CF)
     RetainPtr<CFAllocatorRef> deallocator = adoptCF(createShareableResourceDeallocator(this));
     RetainPtr<CFDataRef> cfData = adoptCF(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data()), static_cast<CFIndex>(size()), deallocator.get()));
-    return SharedBuffer::wrapCFData(cfData.get());
+    return SharedBuffer::create(cfData.get());
 #elif USE(SOUP)
     return SharedBuffer::wrapSoupBuffer(soup_buffer_new_with_owner(data(), size(), this, [](void* data) { static_cast<ShareableResource*>(data)->deref(); }));
 #else

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm (215607 => 215608)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -70,7 +70,7 @@
 
 - (void)didReceiveData:(NSData *)data
 {
-    auto result = _urlSchemeHandlerTask->task().didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
+    auto result = _urlSchemeHandlerTask->task().didReceiveData(WebCore::SharedBuffer::create(data));
     raiseExceptionIfNecessary(result);
 }
 

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm (215607 => 215608)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -646,7 +646,7 @@
             auto dataByType = [m_controller->_editingDelegate.get() _webProcessPlugInBrowserContextController:m_controller pasteboardDataForRange:wrapper(*InjectedBundleRangeHandle::getOrCreate(range).get())];
             for (NSString *type in dataByType) {
                 pasteboardTypes.append(type);
-                pasteboardData.append(SharedBuffer::wrapNSData(dataByType[type]));
+                pasteboardData.append(SharedBuffer::create(dataByType[type]));
             };
         }
 

Modified: trunk/Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.mm (215607 => 215608)


--- trunk/Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -916,7 +916,7 @@
     RetainPtr<NSURLResponse> response = adoptNS([[NSHTTPURLResponse alloc] initWithURL:m_sourceURL statusCode:200 HTTPVersion:(NSString*)kCFHTTPVersion1_1 headerFields:headers]);
     ResourceResponse synthesizedResponse(response.get());
 
-    RefPtr<ArchiveResource> resource = ArchiveResource::create(SharedBuffer::wrapCFData(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
+    RefPtr<ArchiveResource> resource = ArchiveResource::create(SharedBuffer::create(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
     pluginView()->frame()->document()->loader()->addArchiveResource(resource.releaseNonNull());
 }
 
@@ -1756,7 +1756,7 @@
     if (!pdfData)
         return nullptr;
 
-    return SharedBuffer::wrapNSData(pdfData);
+    return SharedBuffer::create(pdfData);
 }
 
 bool PDFPlugin::pluginHandlesContentOffsetForAccessibilityHitTest() const
@@ -1827,7 +1827,7 @@
             RetainPtr<NSString> plainTextString = adoptNS([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
             webProcess.parentProcessConnection()->sendSync(Messages::WebPasteboardProxy::SetPasteboardStringForType(pasteboardName, type, plainTextString.get()), Messages::WebPasteboardProxy::SetPasteboardStringForType::Reply(newChangeCount), 0);
         } else {
-            RefPtr<SharedBuffer> buffer = SharedBuffer::wrapNSData(data);
+            RefPtr<SharedBuffer> buffer = SharedBuffer::create(data);
 
             if (!buffer)
                 continue;

Modified: trunk/Source/WebKit2/WebProcess/Plugins/PluginView.cpp (215607 => 215608)


--- trunk/Source/WebKit2/WebProcess/Plugins/PluginView.cpp	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/WebProcess/Plugins/PluginView.cpp	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1311,14 +1311,8 @@
 
     // Deliver the data.
     if (m_manualStreamData) {
-        const char* data;
-        unsigned position = 0;
-
-        while (unsigned length = m_manualStreamData->getSomeData(data, position)) {
-            manualLoadDidReceiveData(data, length);
-            position += length;
-        }
-
+        for (const auto& segment : *m_manualStreamData)
+            manualLoadDidReceiveData(segment->data(), segment->size());
         m_manualStreamData = nullptr;
     }
 

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm (215607 => 215608)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -165,7 +165,7 @@
     SharedMemory::Handle archiveHandle;
     size_t archiveSize = 0;
     if (data) {
-        RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::wrapNSData((NSData *)data.get());
+        RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::create((NSData *)data.get());
         RefPtr<SharedMemory> archiveSharedMemoryBuffer = SharedMemory::allocate(archiveBuffer->size());
         if (!archiveSharedMemoryBuffer)
             return;

Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm (215607 => 215608)


--- trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -709,7 +709,7 @@
 
 RefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const URL& url)
 {
-    return SharedBuffer::wrapNSData([cachedResponseForURL(this, url) data]);
+    return SharedBuffer::create([cachedResponseForURL(this, url) data]);
 }
 
 bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request)

Modified: trunk/Tools/ChangeLog (215607 => 215608)


--- trunk/Tools/ChangeLog	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Tools/ChangeLog	2017-04-21 14:21:46 UTC (rev 215608)
@@ -1,3 +1,13 @@
+2017-04-21  Alex Christensen  <[email protected]>
+
+        Reduce copies and allocations in SharedBuffer::append
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+
+        Reviewed by Andreas Kling.
+
+        * TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm:
+        (TestWebKitAPI::TEST_F):
+
 2017-04-20  Konstantin Tokarev  <[email protected]>
 
         [cmake] Define FORWARDING_HEADERS_DIR in WebKitFS and use it everywhere

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm (215607 => 215608)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm	2017-04-21 07:34:18 UTC (rev 215607)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm	2017-04-21 14:21:46 UTC (rev 215608)
@@ -59,8 +59,8 @@
         buffer->append((CFDataRef)worldData);
         expectDataArraysEqual(@[ helloData, worldData ], buffer->createNSDataArray().get());
 
-        expectDataArraysEqual(@[ helloData ], SharedBuffer::wrapNSData(helloData)->createNSDataArray().get());
-        expectDataArraysEqual(@[ worldData ], SharedBuffer::wrapCFData((CFDataRef)worldData)->createNSDataArray().get());
+        expectDataArraysEqual(@[ helloData ], SharedBuffer::create(helloData)->createNSDataArray().get());
+        expectDataArraysEqual(@[ worldData ], SharedBuffer::create((CFDataRef)worldData)->createNSDataArray().get());
 
         expectDataArraysEqual(@[ [NSData dataWithContentsOfFile:tempFilePath()] ], SharedBuffer::createWithContentsOfFile(tempFilePath())->createNSDataArray().get());
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to