Title: [99324] trunk/Source/WebCore
Revision
99324
Author
dslo...@google.com
Date
2011-11-04 14:43:56 -0700 (Fri, 04 Nov 2011)

Log Message

Add the ability to transfer ArrayBuffer and "neuter" it.
https://bugs.webkit.org/show_bug.cgi?id=71535

Reviewed by David Levin.

* html/canvas/ArrayBuffer.cpp:
(WebCore::ArrayBuffer::create):
(WebCore::ArrayBuffer::ArrayBuffer):
(WebCore::ArrayBuffer::data):
(WebCore::ArrayBuffer::byteLength):
(WebCore::ArrayBuffer::transfer):
(WebCore::ArrayBufferContents::~ArrayBufferContents):
(WebCore::ArrayBufferContents::tryAllocate):
(WebCore::ArrayBuffer::addView):
(WebCore::ArrayBuffer::removeView):
* html/canvas/ArrayBuffer.h:
(WebCore::ArrayBufferContents::ArrayBufferContents):
(WebCore::ArrayBufferContents::data):
(WebCore::ArrayBufferContents::sizeInBytes):
(WebCore::ArrayBufferContents::release):
(WebCore::ArrayBuffer::~ArrayBuffer):
* html/canvas/ArrayBufferView.cpp:
(WebCore::ArrayBufferView::ArrayBufferView):
(WebCore::ArrayBufferView::~ArrayBufferView):
(WebCore::ArrayBufferView::neuter):
* html/canvas/ArrayBufferView.h:
* html/canvas/DataView.cpp:
(WebCore::DataView::neuter):
(WebCore::DataView::neuterBinding):
* html/canvas/DataView.h:
* html/canvas/TypedArrayBase.h:
(WebCore::TypedArrayBase::neuter):
(WebCore::TypedArrayBase::neuterBinding):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (99323 => 99324)


--- trunk/Source/WebCore/ChangeLog	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/ChangeLog	2011-11-04 21:43:56 UTC (rev 99324)
@@ -1,3 +1,39 @@
+2011-11-04  Dmitry Lomov  <dslo...@google.com>
+
+        Add the ability to transfer ArrayBuffer and "neuter" it.
+        https://bugs.webkit.org/show_bug.cgi?id=71535
+
+        Reviewed by David Levin.
+
+        * html/canvas/ArrayBuffer.cpp:
+        (WebCore::ArrayBuffer::create):
+        (WebCore::ArrayBuffer::ArrayBuffer):
+        (WebCore::ArrayBuffer::data):
+        (WebCore::ArrayBuffer::byteLength):
+        (WebCore::ArrayBuffer::transfer):
+        (WebCore::ArrayBufferContents::~ArrayBufferContents):
+        (WebCore::ArrayBufferContents::tryAllocate):
+        (WebCore::ArrayBuffer::addView):
+        (WebCore::ArrayBuffer::removeView):
+        * html/canvas/ArrayBuffer.h:
+        (WebCore::ArrayBufferContents::ArrayBufferContents):
+        (WebCore::ArrayBufferContents::data):
+        (WebCore::ArrayBufferContents::sizeInBytes):
+        (WebCore::ArrayBufferContents::release):
+        (WebCore::ArrayBuffer::~ArrayBuffer):
+        * html/canvas/ArrayBufferView.cpp:
+        (WebCore::ArrayBufferView::ArrayBufferView):
+        (WebCore::ArrayBufferView::~ArrayBufferView):
+        (WebCore::ArrayBufferView::neuter):
+        * html/canvas/ArrayBufferView.h:
+        * html/canvas/DataView.cpp:
+        (WebCore::DataView::neuter):
+        (WebCore::DataView::neuterBinding):
+        * html/canvas/DataView.h:
+        * html/canvas/TypedArrayBase.h:
+        (WebCore::TypedArrayBase::neuter):
+        (WebCore::TypedArrayBase::neuterBinding):
+
 2011-11-04  Noel Gordon  <noel.gor...@gmail.com>
 
         [Chromium] Implement canvas.toDataURL("image/webp")

Modified: trunk/Source/WebCore/html/canvas/ArrayBuffer.cpp (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/ArrayBuffer.cpp	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBuffer.cpp	2011-11-04 21:43:56 UTC (rev 99324)
@@ -25,6 +25,7 @@
 
 #include "config.h"
 #include "ArrayBuffer.h"
+#include "ArrayBufferView.h"
 
 #include <wtf/RefPtr.h>
 
@@ -42,10 +43,11 @@
 
 PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
 {
-    void* data = "" elementByteSize);
-    if (!data)
+    ArrayBufferContents contents;
+    ArrayBufferContents::tryAllocate(numElements, elementByteSize, contents);
+    if (!contents.m_data)
         return 0;
-    return adoptRef(new ArrayBuffer(data, numElements * elementByteSize));
+    return adoptRef(new ArrayBuffer(contents));
 }
 
 PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
@@ -55,33 +57,39 @@
 
 PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
 {
-    void* data = "" 1);
-    if (!data)
+    ArrayBufferContents contents;
+    ArrayBufferContents::tryAllocate(byteLength, 1, contents);
+    if (!contents.m_data)
         return 0;
-    RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(data, byteLength));
+    RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(contents));
     memcpy(buffer->data(), source, byteLength);
     return buffer.release();
 }
 
-ArrayBuffer::ArrayBuffer(void* data, unsigned sizeInBytes)
-    : m_sizeInBytes(sizeInBytes)
-    , m_data(data)
+PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents& contents)
 {
+    return adoptRef(new ArrayBuffer(contents));
 }
 
+ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents)
+    : m_firstView(0)
+{
+    contents.transfer(m_contents);
+}
+
 void* ArrayBuffer::data()
 {
-    return m_data;
+    return m_contents.m_data;
 }
 
 const void* ArrayBuffer::data() const
 {
-    return m_data;
+    return m_contents.m_data;
 }
 
 unsigned ArrayBuffer::byteLength() const
 {
-    return m_sizeInBytes;
+    return m_contents.m_sizeInBytes;
 }
 
 PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const
@@ -108,26 +116,70 @@
     return clampValue(index, 0, currentLength);
 }
 
-ArrayBuffer::~ArrayBuffer()
+void ArrayBuffer::transfer(ScriptExecutionContext* context, ArrayBufferContents& result, ExceptionCode& ec)
 {
+    RefPtr<ArrayBuffer> keepAlive(this);
+
+    if (!m_contents.m_data) {
+        ec = INVALID_STATE_ERR;
+        result.m_data = 0;
+        return;
+    }
+
+    m_contents.transfer(result);
+
+    while (m_firstView) {
+        ArrayBufferView* current = m_firstView;
+        removeView(current);
+        current->neuter(context);
+    }
+}
+
+ArrayBufferContents::~ArrayBufferContents()
+{
     WTF::fastFree(m_data);
 }
 
-void* ArrayBuffer::tryAllocate(unsigned numElements, unsigned elementByteSize)
+void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents& result)
 {
-    void* result;
     // Do not allow 32-bit overflow of the total size.
     // FIXME: Why not? The tryFastCalloc function already checks its arguments,
     // and will fail if there is any overflow, so why should we include a
     // redudant unnecessarily restrictive check here?
     if (numElements) {
         unsigned totalSize = numElements * elementByteSize;
-        if (totalSize / numElements != elementByteSize)
-            return 0;
+        if (totalSize / numElements != elementByteSize) {
+            result.m_data = 0;
+            return;
+        }
     }
-    if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result))
-        return result;
-    return 0;
+    if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data)) {
+        result.m_sizeInBytes = numElements * elementByteSize;
+        return;
+    }
+    result.m_data = 0;
 }
 
+void ArrayBuffer::addView(ArrayBufferView* view)
+{
+    view->m_buffer = this;
+    view->m_prevView = 0;
+    view->m_nextView = m_firstView;
+    if (m_firstView)
+        m_firstView->m_prevView = view;
+    m_firstView = view;
 }
+
+void ArrayBuffer::removeView(ArrayBufferView* view)
+{
+    ASSERT(this == view->m_buffer);
+    if (view->m_nextView)
+        view->m_nextView->m_prevView = view->m_prevView;
+    if (view->m_prevView)
+        view->m_prevView->m_nextView = view->m_nextView;
+    if (m_firstView == view)
+        m_firstView = view->m_nextView;
+    view->m_prevView = view->m_nextView = 0;
+}
+
+}

Modified: trunk/Source/WebCore/html/canvas/ArrayBuffer.h (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/ArrayBuffer.h	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBuffer.h	2011-11-04 21:43:56 UTC (rev 99324)
@@ -26,16 +26,57 @@
 #ifndef ArrayBuffer_h
 #define ArrayBuffer_h
 
+#include "ExceptionCode.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
 
+class ArrayBuffer;
+class ArrayBufferView;
+class ScriptExecutionContext;
+
+class ArrayBufferContents {
+    WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
+public:
+    ArrayBufferContents() 
+        : m_data(0)
+        , m_sizeInBytes(0)
+    { }
+
+    ~ArrayBufferContents();
+
+    void* data() { return m_data; }
+    unsigned sizeInBytes() { return m_sizeInBytes; }
+
+private:
+    ArrayBufferContents(void* data, unsigned sizeInBytes) 
+        : m_data(data)
+        , m_sizeInBytes(sizeInBytes)
+    { }
+
+    friend class ArrayBuffer;
+
+    static void tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents&);
+    void transfer(ArrayBufferContents& other) 
+    {
+        ASSERT(!other.m_data);
+        other.m_data = m_data;
+        other.m_sizeInBytes = m_sizeInBytes;
+        m_data = 0; 
+        m_sizeInBytes = 0; 
+    }
+
+    void* m_data;
+    unsigned m_sizeInBytes;
+};
+
 class ArrayBuffer : public RefCounted<ArrayBuffer> {
-  public:
+public:
     static PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
     static PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
     static PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
+    static PassRefPtr<ArrayBuffer> create(ArrayBufferContents&);
 
     void* data();
     const void* data() const;
@@ -44,17 +85,20 @@
     PassRefPtr<ArrayBuffer> slice(int begin, int end) const;
     PassRefPtr<ArrayBuffer> slice(int begin) const;
 
-    ~ArrayBuffer();
+    void addView(ArrayBufferView*);
+    void removeView(ArrayBufferView*);
 
-  private:
-    ArrayBuffer(void* data, unsigned sizeInBytes);
-    ArrayBuffer(unsigned numElements, unsigned elementByteSize);
-    static void* tryAllocate(unsigned numElements, unsigned elementByteSize);
+    void transfer(ScriptExecutionContext*, ArrayBufferContents&, ExceptionCode&);
+
+    ~ArrayBuffer() { }
+
+private:
+    ArrayBuffer(ArrayBufferContents&);
     PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
     unsigned clampIndex(int index) const;
 
-    unsigned m_sizeInBytes;
-    void* m_data;
+    ArrayBufferContents m_contents;
+    ArrayBufferView* m_firstView;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/canvas/ArrayBufferView.cpp (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/ArrayBufferView.cpp	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBufferView.cpp	2011-11-04 21:43:56 UTC (rev 99324)
@@ -36,10 +36,14 @@
         , m_buffer(buffer)
 {
     m_baseAddress = m_buffer ? (static_cast<char*>(m_buffer->data()) + m_byteOffset) : 0;
+    if (m_buffer) 
+        m_buffer->addView(this);
 }
 
 ArrayBufferView::~ArrayBufferView()
 {
+    if (m_buffer)
+        m_buffer->removeView(this);
 }
 
 void ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset, ExceptionCode& ec)
@@ -101,4 +105,10 @@
     *length = static_cast<unsigned>(end - start);
 }
 
+void ArrayBufferView::neuter(ScriptExecutionContext*)
+{
+    m_buffer = 0;
+    m_byteOffset = 0;
 }
+
+}

Modified: trunk/Source/WebCore/html/canvas/ArrayBufferView.h (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/ArrayBufferView.h	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/ArrayBufferView.h	2011-11-04 21:43:56 UTC (rev 99324)
@@ -119,13 +119,18 @@
         *numElements = std::min(remainingElements, *numElements);
     }
 
+    virtual void neuter(ScriptExecutionContext*);
+
     // This is the address of the ArrayBuffer's storage, plus the byte offset.
     void* m_baseAddress;
 
     unsigned m_byteOffset;
 
   private:
+    friend class ArrayBuffer;
     RefPtr<ArrayBuffer> m_buffer;
+    ArrayBufferView* m_prevView;
+    ArrayBufferView* m_nextView;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/canvas/DataView.cpp (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/DataView.cpp	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/DataView.cpp	2011-11-04 21:43:56 UTC (rev 99324)
@@ -235,4 +235,16 @@
     setData<double>(byteOffset, value, littleEndian, ec);
 }
 
+void DataView::neuter(ScriptExecutionContext* context)
+{
+    ArrayBufferView::neuter(context);
+    m_byteLength = 0;
+    neuterBinding(context);
 }
+
+void DataView::neuterBinding(ScriptExecutionContext*)
+{
+    // FIXME https://bugs.webkit.org/show_bug.cgi?id=71534 
+}
+
+}

Modified: trunk/Source/WebCore/html/canvas/DataView.h (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/DataView.h	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/DataView.h	2011-11-04 21:43:56 UTC (rev 99324)
@@ -72,6 +72,10 @@
     void setFloat64(unsigned byteOffset, double value, ExceptionCode& ec) { setFloat64(byteOffset, value, false, ec); }
     void setFloat64(unsigned byteOffset, double value, bool littleEndian, ExceptionCode&);
 
+protected:
+    virtual void neuter(ScriptExecutionContext*);
+    virtual void neuterBinding(ScriptExecutionContext*);
+
 private:
     DataView(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength);
 

Modified: trunk/Source/WebCore/html/canvas/TypedArrayBase.h (99323 => 99324)


--- trunk/Source/WebCore/html/canvas/TypedArrayBase.h	2011-11-04 21:42:27 UTC (rev 99323)
+++ trunk/Source/WebCore/html/canvas/TypedArrayBase.h	2011-11-04 21:43:56 UTC (rev 99324)
@@ -112,6 +112,18 @@
         return create<Subclass>(buffer(), offset, length);
     }
 
+    virtual void neuter(ScriptExecutionContext* context)
+    {
+        ArrayBufferView::neuter(context);
+        m_length = 0;
+        neuterBinding(context);
+    }
+
+    virtual void neuterBinding(ScriptExecutionContext*)
+    {
+        // FIXME https://bugs.webkit.org/show_bug.cgi?id=71534
+    }
+
     // We do not want to have to access this via a virtual function in subclasses,
     // which is why it is protected rather than private.
     unsigned m_length;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to