Unreviewed, rolling out r215608.
authormcatanzaro@igalia.com <mcatanzaro@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 22 Apr 2017 02:23:45 +0000 (02:23 +0000)
committermcatanzaro@igalia.com <mcatanzaro@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 22 Apr 2017 02:23:45 +0000 (02:23 +0000)
Hundreds of test failures on GTK bot

Reverted changeset:

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

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215661 268f45cc-cd09-0410-ab3c-d52691b4dbfc

51 files changed:
Source/WebCore/ChangeLog
Source/WebCore/editing/cocoa/EditorCocoa.mm
Source/WebCore/editing/ios/EditorIOS.mm
Source/WebCore/editing/mac/EditorMac.mm
Source/WebCore/loader/TextTrackLoader.cpp
Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp
Source/WebCore/loader/cache/CachedResource.cpp
Source/WebCore/loader/cocoa/DiskCacheMonitorCocoa.mm
Source/WebCore/platform/SharedBuffer.cpp
Source/WebCore/platform/SharedBuffer.h
Source/WebCore/platform/SharedBufferChunkReader.cpp
Source/WebCore/platform/SharedBufferChunkReader.h
Source/WebCore/platform/URLParser.cpp
Source/WebCore/platform/cf/KeyedEncoderCF.cpp
Source/WebCore/platform/cf/SharedBufferCF.cpp
Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm
Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm
Source/WebCore/platform/cocoa/SharedBufferCocoa.mm
Source/WebCore/platform/graphics/avfoundation/objc/WebCoreAVFResourceLoader.mm
Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
Source/WebCore/platform/graphics/mac/ImageMac.mm
Source/WebCore/platform/image-decoders/ImageDecoder.cpp
Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
Source/WebCore/platform/ios/PlatformPasteboardIOS.mm
Source/WebCore/platform/mac/PasteboardMac.mm
Source/WebCore/platform/mac/PlatformPasteboardMac.mm
Source/WebCore/platform/network/BlobResourceHandle.cpp
Source/WebCore/platform/network/MIMEHeader.cpp
Source/WebCore/platform/network/MIMEHeader.h
Source/WebCore/platform/network/cf/ResourceHandleCFURLConnectionDelegateWithOperationQueue.cpp
Source/WebCore/platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm
Source/WebCore/platform/network/mac/WebCoreResourceHandleAsOperationQueueDelegate.mm
Source/WebCore/platform/soup/SharedBufferSoup.cpp
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebView/WebArchive.mm
Source/WebKit/mac/WebView/WebFrame.mm
Source/WebKit/mac/WebView/WebResource.mm
Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm
Source/WebKit2/Platform/IPC/DataReference.cpp
Source/WebKit2/Shared/ShareableResource.cpp
Source/WebKit2/UIProcess/API/Cocoa/WKURLSchemeHandlerTask.mm
Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm
Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.mm
Source/WebKit2/WebProcess/Plugins/PluginView.cpp
Source/WebKit2/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm
Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebCore/cocoa/SharedBuffer.mm

index 02c6b88..0924575 100644 (file)
@@ -1,3 +1,15 @@
+2017-04-21  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        Unreviewed, rolling out r215608.
+
+        Hundreds of test failures on GTK bot
+
+        Reverted changeset:
+
+        "Reduce copies and allocations in SharedBuffer::append"
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+        http://trac.webkit.org/changeset/215608
+
 2017-04-21  Zalan Bujtas  <zalan@apple.com>
 
         REGRESSION(r205374): <li> content inside <ul> should mid-word wrap when word-break: break-word is present.
index 05dc8a8..05c8908 100644 (file)
@@ -157,7 +157,7 @@ static RefPtr<SharedBuffer> archivedDataForAttributedString(NSAttributedString *
     if (!attributedString.length)
         return nullptr;
 
-    return SharedBuffer::create([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
+    return SharedBuffer::wrapNSData([NSKeyedArchiver archivedDataWithRootObject:attributedString]);
 }
 
 void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
@@ -205,7 +205,7 @@ RefPtr<SharedBuffer> Editor::selectionInWebArchiveFormat()
     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(&m_frame);
     if (!archive)
         return nullptr;
-    return SharedBuffer::create(archive->rawDataRepresentation().get());
+    return SharedBuffer::wrapCFData(archive->rawDataRepresentation().get());
 }
 
 // FIXME: Makes no sense that selectedTextForDataTransfer always includes alt text, but stringSelectionForPasteboard does not.
@@ -276,7 +276,7 @@ RefPtr<SharedBuffer> Editor::dataInRTFDFormat(NSAttributedString *string)
         return nullptr;
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    return SharedBuffer::create([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
+    return SharedBuffer::wrapNSData([string RTFDFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
     END_BLOCK_OBJC_EXCEPTIONS;
 
     return nullptr;
@@ -289,7 +289,7 @@ RefPtr<SharedBuffer> Editor::dataInRTFFormat(NSAttributedString *string)
         return nullptr;
 
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    return SharedBuffer::create([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
+    return SharedBuffer::wrapNSData([string RTFFromRange:NSMakeRange(0, length) documentAttributes:@{ }]);
     END_BLOCK_OBJC_EXCEPTIONS;
 
     return nullptr;
index 805898a..ef15cb5 100644 (file)
@@ -339,10 +339,10 @@ bool Editor::WebContentReader::readURL(const URL& url, const String&)
         RetainPtr<NSString> fileType = adoptNS((NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[localPath pathExtension], NULL));
         NSData *data = [NSData dataWithContentsOfFile:localPath];
         if (UTTypeConformsTo((CFStringRef)fileType.get(), kUTTypePNG)) {
-            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::create([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.png"), @"image/png", emptyString(), emptyString())));
+            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::wrapNSData([[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::create([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.jpg"), @"image/jpg", emptyString(), emptyString())));
+            addFragment(frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(SharedBuffer::wrapNSData([[data copy] autorelease]), URL::fakeURLWithRelativePart("image.jpg"), @"image/jpg", emptyString(), emptyString())));
             return fragment;
         }
     } else {
index 63bc3d8..60efef7 100644 (file)
@@ -204,7 +204,7 @@ RefPtr<SharedBuffer> Editor::imageInWebArchiveFormat(Element& imageElement)
     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(imageElement);
     if (!archive)
         return nullptr;
-    return SharedBuffer::create(archive->rawDataRepresentation().get());
+    return SharedBuffer::wrapCFData(archive->rawDataRepresentation().get());
 }
 
 RefPtr<SharedBuffer> Editor::dataSelectionForPasteboard(const String& pasteboardType)
index 728fe33..62cbdca 100644 (file)
@@ -91,15 +91,12 @@ void TextTrackLoader::processNewCueData(CachedResource& resource)
     if (!m_cueParser)
         m_cueParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), m_scriptExecutionContext);
 
-    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();
+    const char* data;
+    unsigned length;
+
+    while ((length = buffer->getSomeData(data, m_parseOffset))) {
+        m_cueParser->parseBytes(data, length);
+        m_parseOffset += length;
     }
 }
 
index ba98a3e..097482f 100644 (file)
@@ -221,7 +221,7 @@ RefPtr<ArchiveResource> LegacyWebArchive::createResource(CFDictionaryRef diction
         response = createResourceResponseFromPropertyListData(resourceResponseData, resourceResponseVersion);
     }
 
-    return ArchiveResource::create(SharedBuffer::create(resourceData), URL(URL(), url), mimeType, textEncoding, frameName, response);
+    return ArchiveResource::create(SharedBuffer::wrapCFData(resourceData), URL(URL(), url), mimeType, textEncoding, frameName, response);
 }
 
 Ref<LegacyWebArchive> LegacyWebArchive::create()
index 25c0dfa..eee2033 100644 (file)
@@ -850,9 +850,8 @@ void CachedResource::tryReplaceEncodedData(SharedBuffer& newBuffer)
     if (m_data->size() != newBuffer.size() || memcmp(m_data->data(), newBuffer.data(), m_data->size()))
         return;
 
-    m_data->clear();
-    m_data->append(newBuffer);
-    didReplaceSharedBufferContents();
+    if (m_data->tryReplaceContentsWithPlatformBuffer(newBuffer))
+        didReplaceSharedBufferContents();
 }
 
 #endif
index 4825bd0..6ac45a1 100644 (file)
@@ -48,7 +48,7 @@ RefPtr<SharedBuffer> DiskCacheMonitor::tryGetFileBackedSharedBufferFromCFURLCach
     if (!data)
         return nullptr;
 
-    return SharedBuffer::create(data);
+    return SharedBuffer::wrapCFData(data);
 }
 
 void DiskCacheMonitor::monitorFileBackingStoreCreation(const ResourceRequest& request, SessionID sessionID, CFCachedURLResponseRef cachedResponse)
index b80772e..8161f63 100644 (file)
 #include <algorithm>
 #include <wtf/unicode/UTF8.h>
 
-#if USE(SOUP)
-#include "GUniquePtrSoup.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);
+}
+
 #endif
 
-namespace WebCore {
+SharedBuffer::SharedBuffer()
+    : m_buffer(adoptRef(*new DataBuffer))
+{
+}
 
-SharedBuffer::SharedBuffer(const char* data, size_t size)
+SharedBuffer::SharedBuffer(const char* data, unsigned size)
+    : m_buffer(adoptRef(*new DataBuffer))
 {
     append(data, size);
 }
 
-SharedBuffer::SharedBuffer(const unsigned char* data, size_t size)
+SharedBuffer::SharedBuffer(const unsigned char* data, unsigned size)
+    : m_buffer(adoptRef(*new DataBuffer))
 {
     append(reinterpret_cast<const char*>(data), size);
 }
 
 SharedBuffer::SharedBuffer(MappedFileData&& fileData)
-    : m_size(fileData.size())
+    : m_buffer(adoptRef(*new DataBuffer))
+    , m_fileData(WTFMove(fileData))
 {
-    m_segments.append(DataSegment::create(WTFMove(fileData)));
 }
 
-SharedBuffer::SharedBuffer(Vector<char>&& data)
+SharedBuffer::~SharedBuffer()
 {
-    append(WTFMove(data));
+    clear();
 }
 
 RefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePath)
@@ -71,30 +102,37 @@ RefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePa
 
 Ref<SharedBuffer> SharedBuffer::create(Vector<char>&& vector)
 {
-    return adoptRef(*new SharedBuffer(WTFMove(vector)));
+    auto buffer = create();
+    buffer->m_buffer->data = WTFMove(vector);
+    buffer->m_size = buffer->m_buffer->data.size();
+    return buffer;
 }
 
-void SharedBuffer::combineToOneSegment() const
+unsigned SharedBuffer::size() const
 {
-    if (m_segments.size() <= 1)
-        return;
+    if (hasPlatformData())
+        return platformDataSize();
+    
+    if (m_fileData)
+        return m_fileData.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);
+    return m_size;
 }
 
 const char* SharedBuffer::data() const
 {
-    if (!m_segments.size())
-        return nullptr;
-    combineToOneSegment();
-    return m_segments[0]->data();
+    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();
 }
 
 RefPtr<ArrayBuffer> SharedBuffer::createArrayBuffer() const
@@ -105,67 +143,169 @@ RefPtr<ArrayBuffer> SharedBuffer::createArrayBuffer() const
         return nullptr;
     }
 
-    size_t position = 0;
-    for (const auto& segment : m_segments) {
-        memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment->data(), segment->size());
-        position += segment->size();
+    const char* segment = 0;
+    unsigned position = 0;
+    while (unsigned segmentSize = getSomeData(segment, position)) {
+        memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment, segmentSize);
+        position += segmentSize;
+    }
+
+    if (position != arrayBuffer->byteLength()) {
+        ASSERT_NOT_REACHED();
+        // Don't return the incomplete ArrayBuffer.
+        return nullptr;
     }
 
-    ASSERT(position == m_size);
     return arrayBuffer;
 }
 
-void SharedBuffer::append(const SharedBuffer& data)
+void SharedBuffer::append(SharedBuffer& data)
 {
-    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());
+    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;
+    }
 }
 
-void SharedBuffer::append(const char* data, size_t length)
+void SharedBuffer::append(const char* data, unsigned 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;
-    Vector<char> vector;
-    vector.append(data, length);
-    m_segments.append(DataSegment::create(WTFMove(vector)));
+    if (m_buffer->data.isEmpty())
+        m_buffer->data.reserveInitialCapacity(length);
+    appendToDataBuffer(data, length);
+#endif
 }
 
 void SharedBuffer::append(Vector<char>&& data)
 {
-    m_size += data.size();
-    m_segments.append(DataSegment::create(WTFMove(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());
 }
 
 void SharedBuffer::clear()
 {
-    m_size = 0;
+    m_fileData = { };
+
+    clearPlatformData();
+    
+#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
+    for (char* segment : m_segments)
+        freeSegment(segment);
     m_segments.clear();
+#else
+    m_dataArray.clear();
+#endif
+
+    m_size = 0;
+    clearDataBuffer();
 }
 
 Ref<SharedBuffer> SharedBuffer::copy() const
 {
-    Ref<SharedBuffer> clone = adoptRef(*new SharedBuffer);
+    Ref<SharedBuffer> clone { adoptRef(*new SharedBuffer) };
+
+    if (hasPlatformData() || m_fileData) {
+        clone->append(data(), size());
+        return clone;
+    }
+
     clone->m_size = m_size;
-    clone->m_segments.reserveInitialCapacity(m_segments.size());
-    for (const auto& segment : m_segments)
-        clone->m_segments.uncheckedAppend(segment.copyRef());
+    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());
+
     return clone;
 }
 
-const char* SharedBuffer::DataSegment::data() const
+void SharedBuffer::duplicateDataBufferIfNecessary() const
 {
-    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);
+    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->data;
+    m_buffer = WTFMove(newBuffer);
+}
+
+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)
@@ -174,21 +314,111 @@ void SharedBuffer::hintMemoryNotNeededSoon()
 }
 #endif
 
-size_t SharedBuffer::DataSegment::size() const
+#if !USE(NETWORK_CFDATA_ARRAY_CALLBACK)
+
+void SharedBuffer::copyBufferAndClear(char* destination, unsigned bytesToCopy) const
 {
-    auto visitor = WTF::makeVisitor(
-        [](const Vector<char>& data) { return data.size(); },
-#if USE(CF)
-        [](const RetainPtr<CFDataRef>& data) { return CFDataGetLength(data.get()); },
+    for (char* segment : m_segments) {
+        unsigned effectiveBytesToCopy = std::min(bytesToCopy, segmentSize);
+        memcpy(destination, segment, effectiveBytesToCopy);
+        destination += effectiveBytesToCopy;
+        bytesToCopy -= effectiveBytesToCopy;
+        freeSegment(segment);
+    }
+    m_segments.clear();
+}
+
 #endif
-#if USE(SOUP)
-        [](const GUniquePtr<SoupBuffer>& data) { return static_cast<size_t>(data->length); },
+
+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);
 #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.
index 9ea6ce9..88580c6 100644 (file)
@@ -31,7 +31,6 @@
 #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>
 
@@ -50,24 +49,27 @@ OBJC_CLASS NSData;
 
 namespace WebCore {
     
-class WEBCORE_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
+class SharedBuffer : public RefCounted<SharedBuffer> {
 public:
     static Ref<SharedBuffer> create() { return adoptRef(*new SharedBuffer); }
-    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);
+    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(Vector<char>&&);
+    WEBCORE_EXPORT static RefPtr<SharedBuffer> createWithContentsOfFile(const String& filePath);
+
+    WEBCORE_EXPORT static Ref<SharedBuffer> create(Vector<char>&&);
+    
+    WEBCORE_EXPORT ~SharedBuffer();
     
 #if USE(FOUNDATION)
-    RetainPtr<NSData> createNSData();
-    RetainPtr<NSArray> createNSDataArray() const;
-    static Ref<SharedBuffer> create(NSData *);
+    WEBCORE_EXPORT RetainPtr<NSData> createNSData();
+    WEBCORE_EXPORT RetainPtr<NSArray> createNSDataArray() const;
+    WEBCORE_EXPORT static Ref<SharedBuffer> wrapNSData(NSData *);
 #endif
 #if USE(CF)
-    RetainPtr<CFDataRef> createCFData();
-    static Ref<SharedBuffer> create(CFDataRef);
-    void append(CFDataRef);
+    WEBCORE_EXPORT RetainPtr<CFDataRef> createCFData();
+    WEBCORE_EXPORT static Ref<SharedBuffer> wrapCFData(CFDataRef);
+    WEBCORE_EXPORT void append(CFDataRef);
 #endif
 
 #if USE(SOUP)
@@ -75,93 +77,101 @@ public:
     static Ref<SharedBuffer> wrapSoupBuffer(SoupBuffer*);
 #endif
 
-    // 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;
-
+    // 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;
     // Creates an ArrayBuffer and copies this SharedBuffer's contents to that
     // ArrayBuffer without merging segmented buffers into a flat buffer.
-    RefPtr<ArrayBuffer> createArrayBuffer() const;
+    WEBCORE_EXPORT RefPtr<ArrayBuffer> createArrayBuffer() const;
 
-    // FIXME: This should return a size_t.
-    unsigned size() const { return m_size; }
+    WEBCORE_EXPORT unsigned size() const;
 
     bool isEmpty() const { return !size(); }
 
-    void append(const SharedBuffer&);
-    void append(const char*, size_t);
-    void append(Vector<char>&&);
+    WEBCORE_EXPORT void append(SharedBuffer&);
+    WEBCORE_EXPORT void append(const char*, unsigned);
+    WEBCORE_EXPORT void append(Vector<char>&&);
 
-    void clear();
+    WEBCORE_EXPORT void clear();
 
-    Ref<SharedBuffer> copy() const;
+    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;
+
+    bool tryReplaceContentsWithPlatformBuffer(SharedBuffer&);
+    WEBCORE_EXPORT bool hasPlatformData() const;
+
+    struct DataBuffer : public ThreadSafeRefCounted<DataBuffer> {
+        Vector<char> data;
+    };
 
-    // 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;
+    void hintMemoryNotNeededSoon();
 
-        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:
+    WEBCORE_EXPORT SharedBuffer();
+    WEBCORE_EXPORT SharedBuffer(const char*, unsigned);
+    WEBCORE_EXPORT SharedBuffer(const unsigned char*, unsigned);
+    explicit SharedBuffer(MappedFileData&&);
 
-    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)) { }
+    static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
 
-        Variant<Vector<char>,
-#if USE(CF)
-            RetainPtr<CFDataRef>,
-#endif
-#if USE(SOUP)
-            GUniquePtr<SoupBuffer>,
-#endif
-            MappedFileData> m_immutableData;
-        friend class SharedBuffer;
-    };
+    // 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;
 
-    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 clearPlatformData();
+    void maybeTransferPlatformData();
+    bool maybeAppendPlatformData(SharedBuffer&);
 
-    void hintMemoryNotNeededSoon();
+    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;
 
-private:
-    SharedBuffer() = default;
-    SharedBuffer(const char*, size_t);
-    SharedBuffer(const unsigned char*, size_t);
-    SharedBuffer(Vector<char>&&);
-    SharedBuffer(MappedFileData&&);
 #if USE(CF)
-    SharedBuffer(CFDataRef);
+    explicit SharedBuffer(CFDataRef);
+    RetainPtr<CFDataRef> m_cfData;
+    CFDataRef existingCFData();
 #endif
+
 #if USE(SOUP)
-    SharedBuffer(SoupBuffer*);
+    explicit SharedBuffer(SoupBuffer*);
+    GUniquePtr<SoupBuffer> m_soupBuffer;
 #endif
 
-    void combineToOneSegment() const;
-    
-    static RefPtr<SharedBuffer> createFromReadingFile(const String& filePath);
-
-    size_t m_size { 0 };
-    mutable Vector<Ref<const DataSegment>> m_segments;
+    MappedFileData m_fileData;
 };
 
 RefPtr<SharedBuffer> utf8Buffer(const String&);
index a203fee..6a13fe6 100644 (file)
 #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 {
@@ -105,10 +100,7 @@ bool SharedBufferChunkReader::nextChunk(Vector<char>& chunk, bool includeSeparat
         // Read the next segment.
         m_segmentIndex = 0;
         m_bufferPosition += m_segmentLength;
-        // 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;
+        m_segmentLength = m_buffer->getSomeData(m_segment, m_bufferPosition);
         if (!m_segmentLength) {
             m_reachedEndOfFile = true;
             if (m_separatorIndex > 0)
@@ -142,14 +134,12 @@ size_t SharedBufferChunkReader::peek(Vector<char>& data, size_t requestedSize)
 
     size_t bufferPosition = m_bufferPosition + m_segmentLength;
     const char* segment = 0;
-
-    // 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;
+    while (size_t segmentLength = m_buffer->getSomeData(segment, bufferPosition)) {
+        if (requestedSize <= readBytesCount + segmentLength) {
+            data.append(segment, requestedSize - readBytesCount);
+            readBytesCount += (requestedSize - readBytesCount);
+            break;
+        }
         data.append(segment, segmentLength);
         readBytesCount += segmentLength;
         bufferPosition += segmentLength;
@@ -158,5 +148,3 @@ size_t SharedBufferChunkReader::peek(Vector<char>& data, size_t requestedSize)
 }
 
 }
-
-#endif
index 756eee2..568ec3c 100644 (file)
@@ -28,9 +28,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#pragma once
-
-#if ENABLE(MHTML)
+#ifndef SharedBufferChunkReader_h
+#define SharedBufferChunkReader_h
 
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
index 54cae45..9d130ee 100644 (file)
@@ -1149,8 +1149,6 @@ ALWAYS_INLINE size_t URLParser::currentPosition(const CodePointIterator<Characte
 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;
index d0f0c9e..619a2c0 100644 (file)
@@ -145,7 +145,7 @@ RefPtr<SharedBuffer> KeyedEncoderCF::finishEncoding()
     auto data = adoptCF(CFPropertyListCreateData(kCFAllocatorDefault, m_rootDictionary.get(), kCFPropertyListBinaryFormat_v1_0, 0, nullptr));
     if (!data)
         return nullptr;
-    return SharedBuffer::create(data.get());
+    return SharedBuffer::wrapCFData(data.get());
 }
 
 } // namespace WebCore
index 4995904..f4024b4 100644 (file)
 
 namespace WebCore {
 
-SharedBuffer::SharedBuffer(CFDataRef data)
+SharedBuffer::SharedBuffer(CFDataRef cfData)
+    : m_buffer(adoptRef(*new DataBuffer))
+    , m_cfData(cfData)
 {
-    append(data);
 }
 
 // Using Foundation allows for an even more efficient implementation of this function,
@@ -43,34 +44,144 @@ SharedBuffer::SharedBuffer(CFDataRef data)
 #if !USE(FOUNDATION)
 RetainPtr<CFDataRef> SharedBuffer::createCFData()
 {
-    if (m_segments.size() == 1) {
-        if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(m_segments[0]->m_immutableData))
-            return *data;
-    }
-    return adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(data()), size()));
+    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()));
 }
 #endif
 
-Ref<SharedBuffer> SharedBuffer::create(CFDataRef data)
+Ref<SharedBuffer> SharedBuffer::wrapCFData(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()
 {
-    for (const auto& segment : m_segments) {
-        if (segment->hasOneRef()) {
-            if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(segment->m_immutableData))
-                OSAllocator::hintMemoryNotNeededSoon(const_cast<UInt8*>(CFDataGetBytePtr(data->get())), CFDataGetLength(data->get()));
-        }
-    }
+    if (!hasPlatformData())
+        return;
+    OSAllocator::hintMemoryNotNeededSoon(const_cast<char*>(platformData()), platformDataSize());
+}
+
+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
+
 }
index ceeb62e..aac8787 100644 (file)
@@ -197,7 +197,7 @@ void NetworkExtensionContentFilter::finishedAddingData()
 Ref<SharedBuffer> NetworkExtensionContentFilter::replacementData() const
 {
     ASSERT(didBlockData());
-    return SharedBuffer::create(m_replacementData.get());
+    return SharedBuffer::wrapNSData(m_replacementData.get());
 }
 
 #if ENABLE(CONTENT_FILTERING)
index 95e911f..e7c1ee2 100644 (file)
@@ -93,7 +93,7 @@ void ParentalControlsContentFilter::finishedAddingData()
 Ref<SharedBuffer> ParentalControlsContentFilter::replacementData() const
 {
     ASSERT(didBlockData());
-    return SharedBuffer::create(m_replacementData.get());
+    return SharedBuffer::wrapNSData(m_replacementData.get());
 }
 
 #if ENABLE(CONTENT_FILTERING)
index f19777e..70be9e3 100644 (file)
@@ -35,10 +35,10 @@ using namespace WebCore;
 
 @interface WebCoreSharedBufferData : NSData
 {
-    RefPtr<const SharedBuffer::DataSegment> sharedBufferDataSegment;
+    RefPtr<SharedBuffer::DataBuffer> sharedBufferDataBuffer;
 }
 
-- (id)initWithSharedBufferDataSegment:(const SharedBuffer::DataSegment&)dataSegment;
+- (id)initWithSharedBufferDataBuffer:(SharedBuffer::DataBuffer*)dataBuffer;
 @end
 
 @implementation WebCoreSharedBufferData
@@ -59,31 +59,31 @@ using namespace WebCore;
     [super dealloc];
 }
 
-- (id)initWithSharedBufferDataSegment:(const SharedBuffer::DataSegment&)dataSegment
+- (id)initWithSharedBufferDataBuffer:(SharedBuffer::DataBuffer*)dataBuffer
 {
     self = [super init];
     
     if (self)
-        sharedBufferDataSegment = &dataSegment;
+        sharedBufferDataBuffer = dataBuffer;
 
     return self;
 }
 
 - (NSUInteger)length
 {
-    return sharedBufferDataSegment->size();
+    return sharedBufferDataBuffer->data.size();
 }
 
 - (const void *)bytes
 {
-    return sharedBufferDataSegment->data();
+    return sharedBufferDataBuffer->data.data();
 }
 
 @end
 
 namespace WebCore {
 
-Ref<SharedBuffer> SharedBuffer::create(NSData *nsData)
+Ref<SharedBuffer> SharedBuffer::wrapNSData(NSData *nsData)
 {
     return adoptRef(*new SharedBuffer((CFDataRef)nsData));
 }
@@ -93,28 +93,57 @@ RetainPtr<NSData> SharedBuffer::createNSData()
     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()
 {
-    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());
+    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());
 }
 
 RefPtr<SharedBuffer> SharedBuffer::createFromReadingFile(const String& filePath)
 {
     NSData *resourceData = [NSData dataWithContentsOfFile:filePath];
     if (resourceData) 
-        return SharedBuffer::create(resourceData);
+        return SharedBuffer::wrapNSData(resourceData);
     return nullptr;
 }
 
 RetainPtr<NSArray> SharedBuffer::createNSDataArray() const
 {
-    auto dataArray = adoptNS([[NSMutableArray alloc] initWithCapacity:m_segments.size()]);
-    for (const auto& segment : m_segments)
-        [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:segment]).get()];
+    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
+
     return WTFMove(dataArray);
 }
 
index b5c4135..08de639 100644 (file)
@@ -173,38 +173,27 @@ void WebCoreAVFResourceLoader::fulfillRequestWithResource(CachedResource& resour
         responseOffset = static_cast<NSUInteger>(contentRange.firstBytePosition());
 
     // Check for possible unsigned overflow.
-    ASSERT(dataRequest.currentOffset >= dataRequest.requestedOffset);
-    ASSERT(dataRequest.requestedLength >= (dataRequest.currentOffset - dataRequest.requestedOffset));
-
-    NSUInteger remainingLength = dataRequest.requestedLength - static_cast<NSUInteger>(dataRequest.currentOffset - dataRequest.requestedOffset);
-
-    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;
-    }
+    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;
+
+        const char* someData;
+        NSUInteger receivedLength = data->getSomeData(someData, static_cast<unsigned>([dataRequest currentOffset] - responseOffset));
+
+        // 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();
     }
index bd8567c..1cfd3eb 100644 (file)
@@ -201,7 +201,7 @@ RetainPtr<CFTypeRef> FontPlatformData::objectForEqualityCheck() const
 RefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
 {
     if (RetainPtr<CFDataRef> data = adoptCF(CTFontCopyTable(font(), table, kCTFontTableOptionNoOptions)))
-        return SharedBuffer::create(data.get());
+        return SharedBuffer::wrapCFData(data.get());
     
     return nullptr;
 }
index fb8fa05..4eeac73 100644 (file)
@@ -1163,8 +1163,13 @@ void ResourceHandleStreamingClient::didReceiveData(ResourceHandle*, const char*
 
 void ResourceHandleStreamingClient::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffer, int /* encodedLength */)
 {
-    for (const auto& segment : buffer.get())
-        handleDataReceived(segment->data(), segment->size());
+    // 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;
+    }
 }
 
 void ResourceHandleStreamingClient::didFinishLoading(ResourceHandle*)
index f5fa697..2dba80a 100644 (file)
@@ -63,7 +63,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char *name)
     NSData *namedImageData = [NSData dataWithContentsOfFile:imagePath];
     if (namedImageData) {
         auto image = BitmapImage::create();
-        image->setData(SharedBuffer::create(namedImageData), true);
+        image->setData(SharedBuffer::wrapNSData(namedImageData), true);
         return WTFMove(image);
     }
 
index 663f6d8..baf9e46 100644 (file)
@@ -42,19 +42,17 @@ namespace WebCore {
 
 namespace {
 
-static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer)
+unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset)
 {
     unsigned bytesExtracted = 0;
-    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;
+    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)
             break;
-        }
+        offset += bytesToCopy;
     }
     return bytesExtracted;
 }
@@ -102,7 +100,7 @@ RefPtr<ImageDecoder> ImageDecoder::create(const SharedBuffer& data, AlphaOption
 {
     static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
     char contents[lengthOfLongestSignature];
-    unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data);
+    unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
     if (length < lengthOfLongestSignature)
         return nullptr;
 
index 0d548cc..9604a50 100644 (file)
@@ -157,10 +157,11 @@ public:
         if (setjmp(JMPBUF(m_png)))
             return decoder->setFailed();
 
-        for (const auto& segment : data) {
-            m_readOffset += segment->size();
+        const char* segment;
+        while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) {
+            m_readOffset += segmentLength;
             m_currentBufferSize = m_readOffset;
-            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment->data())), segment->size());
+            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength);
             // 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.
index 3178c4f..2b223d9 100644 (file)
@@ -308,7 +308,7 @@ RefPtr<SharedBuffer> PlatformPasteboard::readBuffer(int index, const String& typ
 
     if (![pasteboardItem count])
         return nullptr;
-    return SharedBuffer::create([pasteboardItem.get() objectAtIndex:0]);
+    return SharedBuffer::wrapNSData([pasteboardItem.get() objectAtIndex:0]);
 }
 
 String PlatformPasteboard::readString(int index, const String& type)
index 8ad4758..a90ec3d 100644 (file)
@@ -261,7 +261,7 @@ static void writeFileWrapperAsRTFDAttachment(NSFileWrapper *wrapper, const Strin
     if (!RTFDData)
         return;
 
-    newChangeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::create(RTFDData).ptr(), NSRTFDPboardType, pasteboardName);
+    newChangeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapNSData(RTFDData).ptr(), NSRTFDPboardType, pasteboardName);
 }
 
 void Pasteboard::write(const PasteboardImage& pasteboardImage)
@@ -278,7 +278,7 @@ void Pasteboard::write(const PasteboardImage& pasteboardImage)
         types.append(WebArchivePboardType);
 
     m_changeCount = writeURLForTypes(types, m_pasteboardName, pasteboardImage.url);
-    m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::create(imageData).ptr(), NSTIFFPboardType, m_pasteboardName);
+    m_changeCount = platformStrategies()->pasteboardStrategy()->setBufferForType(SharedBuffer::wrapCFData(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);
index 16a248c..daff4fc 100644 (file)
@@ -50,7 +50,7 @@ RefPtr<SharedBuffer> PlatformPasteboard::bufferForType(const String& pasteboardT
     NSData *data = [m_pasteboard.get() dataForType:pasteboardType];
     if (!data)
         return nullptr;
-    return SharedBuffer::create([[data copy] autorelease]);
+    return SharedBuffer::wrapNSData([[data copy] autorelease]);
 }
 
 int PlatformPasteboard::numberOfFiles()
index 9cff893..8e574c1 100644 (file)
@@ -604,7 +604,7 @@ void BlobResourceHandle::notifyResponseOnError()
 void BlobResourceHandle::notifyReceiveData(const char* data, int bytesRead)
 {
     if (client())
-        client()->didReceiveBuffer(this, SharedBuffer::create(reinterpret_cast<const uint8_t*>(data), bytesRead), bytesRead);
+        client()->didReceiveBuffer(this, SharedBuffer::create(data, bytesRead), bytesRead);
 }
 
 void BlobResourceHandle::notifyFail(Error errorCode)
index 251693e..267b597 100644 (file)
@@ -31,8 +31,6 @@
 #include "config.h"
 #include "MIMEHeader.h"
 
-#if ENABLE(MHTML)
-
 #include "ParsedContentType.h"
 #include "SharedBufferChunkReader.h"
 #include <wtf/HashMap.h>
@@ -135,5 +133,3 @@ MIMEHeader::MIMEHeader()
 }
 
 }
-
-#endif
index 008aec2..4df3e28 100644 (file)
@@ -28,9 +28,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#pragma once
-
-#if ENABLE(MHTML)
+#ifndef MIMEHeader_h
+#define MIMEHeader_h
 
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
index 1d39f68..de29de2 100644 (file)
@@ -177,7 +177,7 @@ void ResourceHandleCFURLConnectionDelegateWithOperationQueue::didReceiveData(CFD
         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::create(data), originalLength);
+            m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
         }
 
         CFRelease(data);
index bfc557a..d1cd8e5 100644 (file)
@@ -184,7 +184,7 @@ void SynchronousResourceHandleCFURLConnectionDelegate::didReceiveData(CFDataRef
     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::create(data), originalLength);
+        client->didReceiveBuffer(m_handle, SharedBuffer::wrapCFData(data), originalLength);
 }
 
 void SynchronousResourceHandleCFURLConnectionDelegate::didFinishLoading()
index f025cfb..c825a29 100644 (file)
@@ -174,7 +174,7 @@ using namespace WebCore;
     // 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::create(data), -1);
+    m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
 }
 
 - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
index d7a34f0..631f4be 100644 (file)
@@ -223,7 +223,7 @@ using namespace WebCore;
         // 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::create(data), -1);
+        m_handle->client()->didReceiveBuffer(m_handle, SharedBuffer::wrapNSData(data), -1);
     });
 }
 
index 9c0bf79..3b4b61a 100644 (file)
 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,6 +40,11 @@ Ref<SharedBuffer> SharedBuffer::wrapSoupBuffer(SoupBuffer* soupBuffer)
 
 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();
@@ -47,6 +52,57 @@ GUniquePtr<SoupBuffer> SharedBuffer::createSoupBuffer(unsigned offset, unsigned
     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
index d7484b7..566c45c 100644 (file)
@@ -1,3 +1,15 @@
+2017-04-21  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        Unreviewed, rolling out r215608.
+
+        Hundreds of test failures on GTK bot
+
+        Reverted changeset:
+
+        "Reduce copies and allocations in SharedBuffer::append"
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+        http://trac.webkit.org/changeset/215608
+
 2017-04-21  Alex Christensen  <achristensen@webkit.org>
 
         Reduce copies and allocations in SharedBuffer::append
index d1044e1..ff7546d 100644 (file)
@@ -200,7 +200,7 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 #endif
 
     _private = [[WebArchivePrivate alloc] init];
-    auto coreArchive = LegacyWebArchive::create(SharedBuffer::create(data));
+    auto coreArchive = LegacyWebArchive::create(SharedBuffer::wrapNSData(data));
     if (!coreArchive) {
         [self release];
         return nil;
index 6da930a..b2c27b5 100644 (file)
@@ -2493,7 +2493,7 @@ static NSURL *createUniqueWebDataURL()
     ResourceRequest request(baseURL);
 
     ResourceResponse response(responseURL, MIMEType, [data length], encodingName);
-    SubstituteData substituteData(WebCore::SharedBuffer::create(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
+    SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
 
     _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
 }
index 3977b44..b3bb75b 100644 (file)
@@ -149,7 +149,7 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
         return nil;
     }
 
-    auto coreResource = ArchiveResource::create(SharedBuffer::create(data), url, mimeType, textEncoding, frameName, response);
+    auto coreResource = ArchiveResource::create(SharedBuffer::wrapNSData(data), url, mimeType, textEncoding, frameName, response);
     if (!coreResource) {
         [self release];
         return nil;
@@ -301,7 +301,7 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
         return nil;
     }
 
-    auto coreResource = ArchiveResource::create(SharedBuffer::create(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response);
+    auto coreResource = ArchiveResource::create(SharedBuffer::wrapNSData(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response);
     if (!coreResource) {
         [self release];
         return nil;
index b8a761e..6042bec 100644 (file)
@@ -1,3 +1,15 @@
+2017-04-21  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        Unreviewed, rolling out r215608.
+
+        Hundreds of test failures on GTK bot
+
+        Reverted changeset:
+
+        "Reduce copies and allocations in SharedBuffer::append"
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+        http://trac.webkit.org/changeset/215608
+
 2017-04-21  Andy Estes  <aestes@apple.com>
 
         [macOS] Enable media selection button on AVTouchBarScrubber
index d135afe..f0c5c3c 100644 (file)
@@ -386,7 +386,7 @@ static WebCore::NetworkLoadPriority toNetworkLoadPriority(float priority)
 
     auto storedCredentials = _withCredentials ? WebCore::StoredCredentials::AllowStoredCredentials : WebCore::StoredCredentials::DoNotAllowStoredCredentials;
     if (auto* networkDataTask = _session->dataTaskForIdentifier(dataTask.taskIdentifier, storedCredentials))
-        networkDataTask->didReceiveData(WebCore::SharedBuffer::create(data));
+        networkDataTask->didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
 }
 
 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
index 7da38d6..9bdec4f 100644 (file)
@@ -47,8 +47,13 @@ void SharedBufferDataReference::encode(Encoder& encoder) const
     encoder.reserve(bufferSize + sizeof(uint64_t));
     encoder << bufferSize;
 
-    for (const auto& segment : *m_buffer)
-        encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(segment->data()), segment->size(), 1);
+    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;
+    }
 }
 
 } // namespace IPC
index d147d80..9e2eb00 100644 (file)
@@ -87,7 +87,7 @@ RefPtr<SharedBuffer> ShareableResource::wrapInSharedBuffer()
 #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::create(cfData.get());
+    return SharedBuffer::wrapCFData(cfData.get());
 #elif USE(SOUP)
     return SharedBuffer::wrapSoupBuffer(soup_buffer_new_with_owner(data(), size(), this, [](void* data) { static_cast<ShareableResource*>(data)->deref(); }));
 #else
index 952f131..d0e868b 100644 (file)
@@ -70,7 +70,7 @@ static void raiseExceptionIfNecessary(WebKit::WebURLSchemeHandlerTask::Exception
 
 - (void)didReceiveData:(NSData *)data
 {
-    auto result = _urlSchemeHandlerTask->task().didReceiveData(WebCore::SharedBuffer::create(data));
+    auto result = _urlSchemeHandlerTask->task().didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
     raiseExceptionIfNecessary(result);
 }
 
index 486fcfd..72bae5c 100644 (file)
@@ -646,7 +646,7 @@ static inline WKEditorInsertAction toWK(EditorInsertAction action)
             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::create(dataByType[type]));
+                pasteboardData.append(SharedBuffer::wrapNSData(dataByType[type]));
             };
         }
 
index 02d84a1..130bf05 100644 (file)
@@ -916,7 +916,7 @@ void PDFPlugin::addArchiveResource()
     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::create(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
+    RefPtr<ArchiveResource> resource = ArchiveResource::create(SharedBuffer::wrapCFData(m_data.get()), m_sourceURL, "application/pdf", String(), String(), synthesizedResponse);
     pluginView()->frame()->document()->loader()->addArchiveResource(resource.releaseNonNull());
 }
 
@@ -1756,7 +1756,7 @@ RefPtr<SharedBuffer> PDFPlugin::liveResourceData() const
     if (!pdfData)
         return nullptr;
 
-    return SharedBuffer::create(pdfData);
+    return SharedBuffer::wrapNSData(pdfData);
 }
 
 bool PDFPlugin::pluginHandlesContentOffsetForAccessibilityHitTest() const
@@ -1827,7 +1827,7 @@ void PDFPlugin::writeItemsToPasteboard(NSString *pasteboardName, NSArray *items,
             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::create(data);
+            RefPtr<SharedBuffer> buffer = SharedBuffer::wrapNSData(data);
 
             if (!buffer)
                 continue;
index 8c04351..f383281 100644 (file)
@@ -1311,8 +1311,14 @@ void PluginView::redeliverManualStream()
 
     // Deliver the data.
     if (m_manualStreamData) {
-        for (const auto& segment : *m_manualStreamData)
-            manualLoadDidReceiveData(segment->data(), segment->size());
+        const char* data;
+        unsigned position = 0;
+
+        while (unsigned length = m_manualStreamData->getSomeData(data, position)) {
+            manualLoadDidReceiveData(data, length);
+            position += length;
+        }
+
         m_manualStreamData = nullptr;
     }
 
index 5f45654..57144af 100644 (file)
@@ -165,7 +165,7 @@ void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Eleme
     SharedMemory::Handle archiveHandle;
     size_t archiveSize = 0;
     if (data) {
-        RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::create((NSData *)data.get());
+        RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::wrapNSData((NSData *)data.get());
         RefPtr<SharedMemory> archiveSharedMemoryBuffer = SharedMemory::allocate(archiveBuffer->size());
         if (!archiveSharedMemoryBuffer)
             return;
index f8fb041..4519d23 100644 (file)
@@ -709,7 +709,7 @@ String WebPage::cachedResponseMIMETypeForURL(const URL& url)
 
 RefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const URL& url)
 {
-    return SharedBuffer::create([cachedResponseForURL(this, url) data]);
+    return SharedBuffer::wrapNSData([cachedResponseForURL(this, url) data]);
 }
 
 bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request)
index bc12f1e..ddff0f7 100644 (file)
@@ -1,3 +1,15 @@
+2017-04-21  Michael Catanzaro  <mcatanzaro@igalia.com>
+
+        Unreviewed, rolling out r215608.
+
+        Hundreds of test failures on GTK bot
+
+        Reverted changeset:
+
+        "Reduce copies and allocations in SharedBuffer::append"
+        https://bugs.webkit.org/show_bug.cgi?id=170956
+        http://trac.webkit.org/changeset/215608
+
 2017-04-21  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [WK2] Add delegate hooks for overriding unhanded data interaction operations
index 399b95c..2646766 100644 (file)
@@ -59,8 +59,8 @@ TEST_F(SharedBufferTest, createNSDataArray)
         buffer->append((CFDataRef)worldData);
         expectDataArraysEqual(@[ helloData, worldData ], buffer->createNSDataArray().get());
 
-        expectDataArraysEqual(@[ helloData ], SharedBuffer::create(helloData)->createNSDataArray().get());
-        expectDataArraysEqual(@[ worldData ], SharedBuffer::create((CFDataRef)worldData)->createNSDataArray().get());
+        expectDataArraysEqual(@[ helloData ], SharedBuffer::wrapNSData(helloData)->createNSDataArray().get());
+        expectDataArraysEqual(@[ worldData ], SharedBuffer::wrapCFData((CFDataRef)worldData)->createNSDataArray().get());
 
         expectDataArraysEqual(@[ [NSData dataWithContentsOfFile:tempFilePath()] ], SharedBuffer::createWithContentsOfFile(tempFilePath())->createNSDataArray().get());
     }