| Index: Source/wtf/ArrayBufferContents.cpp
|
| diff --git a/Source/wtf/ArrayBufferContents.cpp b/Source/wtf/ArrayBufferContents.cpp
|
| index 71f4bf99e84c63f460579f5417e955bda5fcd73f..7c6177923d6d57be77588decbafa9b37d33ce50f 100644
|
| --- a/Source/wtf/ArrayBufferContents.cpp
|
| +++ b/Source/wtf/ArrayBufferContents.cpp
|
| @@ -34,75 +34,101 @@
|
|
|
| namespace WTF {
|
|
|
| -ArrayBufferContents::ArrayBufferContents()
|
| +
|
| +DataHolder::DataHolder()
|
| : m_data(0)
|
| , m_sizeInBytes(0)
|
| + , m_shared(false) { }
|
| +
|
| +DataHolder::~DataHolder()
|
| +{
|
| + // if (m_data) {
|
| + // printf("Destroy data: %p size: %d shared: %d refs: %d\n", m_data, m_sizeInBytes, m_shared, refCount());
|
| + // }
|
| + partitionFreeGeneric(WTF::Partitions::getBufferPartition(), m_data);
|
| + m_data = 0;
|
| + m_sizeInBytes = 0;
|
| + m_shared = false;
|
| +}
|
| +
|
| +void DataHolder::adopt(void* data, unsigned sizeInBytes, bool shared)
|
| +{
|
| + ASSERT(!m_data);
|
| + m_data = data;
|
| + m_sizeInBytes = sizeInBytes;
|
| + m_shared = shared;
|
| + // printf("Adopt data: %p size: %d shared: %d refs: %d\n", m_data, m_sizeInBytes, m_shared, refCount());
|
| +}
|
| +
|
| +ArrayBufferContents::ArrayBufferContents()
|
| + : m_holder(adoptRef(new DataHolder()))
|
| , m_deallocationObserver(0) { }
|
|
|
| ArrayBufferContents::ArrayBufferContents(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
|
| - : m_data(0)
|
| - , m_sizeInBytes(0)
|
| + : m_holder(adoptRef(new DataHolder()))
|
| , m_deallocationObserver(0)
|
| {
|
| + unsigned totalSize = numElements * elementByteSize;
|
| // Do not allow 32-bit overflow of the total size.
|
| if (numElements) {
|
| - unsigned totalSize = numElements * elementByteSize;
|
| if (totalSize / numElements != elementByteSize) {
|
| - m_data = 0;
|
| return;
|
| }
|
| }
|
| - allocateMemory(numElements * elementByteSize, policy, m_data);
|
| - m_sizeInBytes = numElements * elementByteSize;
|
| + void* data = 0;
|
| + allocateMemory(totalSize, policy, data);
|
| + m_holder->adopt(data, totalSize, false);
|
| }
|
|
|
| ArrayBufferContents::ArrayBufferContents(
|
| - void* data, unsigned sizeInBytes, ArrayBufferDeallocationObserver* observer)
|
| - : m_data(data)
|
| - , m_sizeInBytes(sizeInBytes)
|
| + void* data, unsigned sizeInBytes, bool shared, ArrayBufferDeallocationObserver* observer)
|
| + : m_holder(adoptRef(new DataHolder()))
|
| , m_deallocationObserver(observer)
|
| {
|
| - if (!m_data) {
|
| - ASSERT(!m_sizeInBytes);
|
| - m_sizeInBytes = 0;
|
| + if (!data) {
|
| + ASSERT(!sizeInBytes);
|
| + sizeInBytes = 0;
|
| // Allow null data if size is 0 bytes, make sure m_data is valid pointer.
|
| // (partitionAllocGeneric guarantees valid pointer for size 0)
|
| - allocateMemory(0, ZeroInitialize, m_data);
|
| + allocateMemory(0, ZeroInitialize, data);
|
| }
|
| + m_holder->adopt(data, sizeInBytes, shared);
|
| }
|
|
|
| ArrayBufferContents::~ArrayBufferContents()
|
| {
|
| - freeMemory(m_data, m_sizeInBytes);
|
| + // freeMemory(m_data, m_sizeInBytes);
|
| clear();
|
| }
|
|
|
| void ArrayBufferContents::clear()
|
| {
|
| - if (m_data && m_deallocationObserver)
|
| - m_deallocationObserver->arrayBufferDeallocated(m_sizeInBytes);
|
| - m_data = 0;
|
| - m_sizeInBytes = 0;
|
| + if (m_holder->m_data && m_deallocationObserver)
|
| + m_deallocationObserver->arrayBufferDeallocated(m_holder->m_sizeInBytes);
|
| + m_holder = adoptRef(new DataHolder());
|
| m_deallocationObserver = 0;
|
| }
|
|
|
| void ArrayBufferContents::transfer(ArrayBufferContents& other)
|
| {
|
| - ASSERT(!other.m_data);
|
| - other.m_data = m_data;
|
| - other.m_sizeInBytes = m_sizeInBytes;
|
| - clear();
|
| + ASSERT(!other.m_holder->m_data);
|
| + // TODO mark the memory as allocated in new context?
|
| + other.m_holder = m_holder;
|
| + if (!m_holder->m_shared) {
|
| + clear();
|
| + }
|
| }
|
|
|
| void ArrayBufferContents::copyTo(ArrayBufferContents& other)
|
| {
|
| - ASSERT(!other.m_sizeInBytes);
|
| - other.freeMemory(other.m_data, other.m_sizeInBytes);
|
| - allocateMemory(m_sizeInBytes, DontInitialize, other.m_data);
|
| - if (!other.m_data)
|
| + ASSERT(!other.m_holder->m_sizeInBytes);
|
| + other.m_holder = adoptRef(new DataHolder());
|
| + void* data = 0;
|
| + allocateMemory(m_holder->m_sizeInBytes, DontInitialize, data);
|
| + if (!data)
|
| return;
|
| - memcpy(other.m_data, m_data, m_sizeInBytes);
|
| - other.m_sizeInBytes = m_sizeInBytes;
|
| + memcpy(data, m_holder->m_data, m_holder->m_sizeInBytes);
|
| + other.m_holder->adopt(data, m_holder->m_sizeInBytes, false);
|
| }
|
|
|
| void ArrayBufferContents::allocateMemory(size_t size, InitializationPolicy policy, void*& data)
|
|
|