diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/runtime/ArrayBuffer.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/runtime/ArrayBuffer.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/ArrayBuffer.h | 232 |
1 files changed, 82 insertions, 150 deletions
diff --git a/Source/JavaScriptCore/runtime/ArrayBuffer.h b/Source/JavaScriptCore/runtime/ArrayBuffer.h index f0d7d2719..46ffdb5ca 100644 --- a/Source/JavaScriptCore/runtime/ArrayBuffer.h +++ b/Source/JavaScriptCore/runtime/ArrayBuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,39 +23,60 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ArrayBuffer_h -#define ArrayBuffer_h +#pragma once +#include "ArrayBufferSharingMode.h" #include "GCIncomingRefCounted.h" #include "Weak.h" -#include <wtf/PassRefPtr.h> +#include <wtf/Function.h> #include <wtf/StdLibExtras.h> -#include <wtf/Vector.h> +#include <wtf/ThreadSafeRefCounted.h> namespace JSC { +class VM; class ArrayBuffer; class ArrayBufferView; class JSArrayBuffer; +typedef Function<void(void*)> ArrayBufferDestructorFunction; + +class SharedArrayBufferContents : public ThreadSafeRefCounted<SharedArrayBufferContents> { +public: + SharedArrayBufferContents(void* data, ArrayBufferDestructorFunction&&); + ~SharedArrayBufferContents(); + + void* data() const { return m_data; } + +private: + void* m_data; + ArrayBufferDestructorFunction m_destructor; +}; + class ArrayBufferContents { WTF_MAKE_NONCOPYABLE(ArrayBufferContents); public: - ArrayBufferContents() - : m_data(0) - , m_sizeInBytes(0) - { } + JS_EXPORT_PRIVATE ArrayBufferContents(); + + JS_EXPORT_PRIVATE ArrayBufferContents(ArrayBufferContents&&); + JS_EXPORT_PRIVATE ArrayBufferContents& operator=(ArrayBufferContents&&); - inline ~ArrayBufferContents(); + JS_EXPORT_PRIVATE ~ArrayBufferContents(); + + JS_EXPORT_PRIVATE void clear(); + + explicit operator bool() { return !!m_data; } - void* data() { return m_data; } - unsigned sizeInBytes() { return m_sizeInBytes; } + void* data() const { return m_data; } + unsigned sizeInBytes() const { return m_sizeInBytes; } + + bool isShared() const { return m_shared; } private: - ArrayBufferContents(void* data, unsigned sizeInBytes) - : m_data(data) - , m_sizeInBytes(sizeInBytes) - { } + ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&&); + + void destroy(); + void reset(); friend class ArrayBuffer; @@ -64,54 +85,55 @@ private: DontInitialize }; - static inline void tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy, 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 copyTo(ArrayBufferContents& other) - { - ASSERT(!other.m_data); - ArrayBufferContents::tryAllocate(m_sizeInBytes, sizeof(char), ArrayBufferContents::DontInitialize, other); - if (!other.m_data) - return; - memcpy(other.m_data, m_data, m_sizeInBytes); - other.m_sizeInBytes = m_sizeInBytes; - } + void tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy); + + void makeShared(); + void transferTo(ArrayBufferContents&); + void copyTo(ArrayBufferContents&); + void shareWith(ArrayBufferContents&); + ArrayBufferDestructorFunction m_destructor; + RefPtr<SharedArrayBufferContents> m_shared; void* m_data; unsigned m_sizeInBytes; }; class ArrayBuffer : public GCIncomingRefCounted<ArrayBuffer> { public: - static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize); - static inline PassRefPtr<ArrayBuffer> create(ArrayBuffer*); - static inline PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength); - static inline PassRefPtr<ArrayBuffer> create(ArrayBufferContents&); - static inline PassRefPtr<ArrayBuffer> createAdopted(const void* data, unsigned byteLength); - - // Only for use by Uint8ClampedArray::createUninitialized. - static inline PassRefPtr<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize); + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize); + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBuffer&); + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, unsigned byteLength); + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBufferContents&&); + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, unsigned byteLength); + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&&); + JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize); + JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(ArrayBuffer&); + JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, unsigned byteLength); + + // Only for use by Uint8ClampedArray::createUninitialized and SharedBuffer::createArrayBuffer. + JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize); + JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(unsigned numElements, unsigned elementByteSize); inline void* data(); inline const void* data() const; inline unsigned byteLength() const; + void makeShared(); + void setSharingMode(ArrayBufferSharingMode); + inline bool isShared() const; + inline ArrayBufferSharingMode sharingMode() const { return isShared() ? ArrayBufferSharingMode::Shared : ArrayBufferSharingMode::Default; } + inline size_t gcSizeEstimateInBytes() const; - inline PassRefPtr<ArrayBuffer> slice(int begin, int end) const; - inline PassRefPtr<ArrayBuffer> slice(int begin) const; + JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(int begin, int end) const; + JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(int begin) const; inline void pin(); inline void unpin(); + inline void pinAndLock(); - JS_EXPORT_PRIVATE bool transfer(ArrayBufferContents&); + JS_EXPORT_PRIVATE bool transferTo(VM&, ArrayBufferContents&); + JS_EXPORT_PRIVATE bool shareWith(ArrayBufferContents&); bool isNeutered() { return !m_contents.m_data; } static ptrdiff_t offsetOfData() { return OBJECT_OFFSETOF(ArrayBuffer, m_contents) + OBJECT_OFFSETOF(ArrayBufferContents, m_data); } @@ -119,15 +141,17 @@ public: ~ArrayBuffer() { } private: - static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); - - inline ArrayBuffer(ArrayBufferContents&); - inline PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const; + static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); + static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, unsigned); + static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); + ArrayBuffer(ArrayBufferContents&&); + RefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const; inline unsigned clampIndex(int index) const; static inline int clampValue(int x, int left, int right); - unsigned m_pinCount; ArrayBufferContents m_contents; + unsigned m_pinCount : 31; + bool m_locked : 1; // m_locked == true means that some API user fetched m_contents directly from a TypedArray object. public: Weak<JSArrayBuffer> m_wrapper; @@ -143,59 +167,6 @@ int ArrayBuffer::clampValue(int x, int left, int right) return x; } -PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize) -{ - return create(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other) -{ - return ArrayBuffer::create(other->data(), other->byteLength()); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength) -{ - ArrayBufferContents contents; - ArrayBufferContents::tryAllocate(byteLength, 1, ArrayBufferContents::ZeroInitialize, contents); - if (!contents.m_data) - return 0; - RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(contents)); - ASSERT(!byteLength || source); - memcpy(buffer->data(), source, byteLength); - return buffer.release(); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents& contents) -{ - return adoptRef(new ArrayBuffer(contents)); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, unsigned byteLength) -{ - ArrayBufferContents contents(const_cast<void*>(data), byteLength); - return create(contents); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::createUninitialized(unsigned numElements, unsigned elementByteSize) -{ - return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy) -{ - ArrayBufferContents contents; - ArrayBufferContents::tryAllocate(numElements, elementByteSize, policy, contents); - if (!contents.m_data) - return 0; - return adoptRef(new ArrayBuffer(contents)); -} - -ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents) - : m_pinCount(0) -{ - contents.transfer(m_contents); -} - void* ArrayBuffer::data() { return m_contents.m_data; @@ -211,25 +182,15 @@ unsigned ArrayBuffer::byteLength() const return m_contents.m_sizeInBytes; } -size_t ArrayBuffer::gcSizeEstimateInBytes() const -{ - return sizeof(ArrayBuffer) + static_cast<size_t>(byteLength()); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const -{ - return sliceImpl(clampIndex(begin), clampIndex(end)); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const +bool ArrayBuffer::isShared() const { - return sliceImpl(clampIndex(begin), byteLength()); + return m_contents.isShared(); } -PassRefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const +size_t ArrayBuffer::gcSizeEstimateInBytes() const { - unsigned size = begin <= end ? end - begin : 0; - return ArrayBuffer::create(static_cast<const char*>(data()) + begin, size); + // FIXME: We probably want to scale this by the shared ref count or something. + return sizeof(ArrayBuffer) + static_cast<size_t>(byteLength()); } unsigned ArrayBuffer::clampIndex(int index) const @@ -250,40 +211,11 @@ void ArrayBuffer::unpin() m_pinCount--; } -void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy, ArrayBufferContents& result) +void ArrayBuffer::pinAndLock() { - // Do not allow 31-bit overflow of the total size. - if (numElements) { - unsigned totalSize = numElements * elementByteSize; - if (totalSize / numElements != elementByteSize - || totalSize > static_cast<unsigned>(std::numeric_limits<int32_t>::max())) { - result.m_data = 0; - return; - } - } - bool allocationSucceeded = false; - if (policy == ZeroInitialize) - allocationSucceeded = WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data); - else { - ASSERT(policy == DontInitialize); - allocationSucceeded = WTF::tryFastMalloc(numElements * elementByteSize).getValue(result.m_data); - } - - if (allocationSucceeded) { - result.m_sizeInBytes = numElements * elementByteSize; - return; - } - result.m_data = 0; -} - -ArrayBufferContents::~ArrayBufferContents() -{ - WTF::fastFree(m_data); + m_locked = true; } } // namespace JSC using JSC::ArrayBuffer; - -#endif // ArrayBuffer_h - |