Commit 7fc06d62 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[arraybuffer] Merge ArrayBuffer into DOMArrayBufferBase

With this CL the ArrayBuffer class gets finally removed and completely
merged into DOMArrayBufferBase. This required the following changes:

* Move the internal fields of ArrayBuffer to DOMArrayBufferBase:
  array_buffer_contents_ and is_detached_.
* Change DOMArrayBufferBase to be based on ArrayBufferContents instead of
  ArrayBuffer now.
* Change the constructors of DOMArrayBuffer and SharedDOMArrayBuffer.
* Move the implementation of ArrayBuffer::Transfer to DOMArrayBuffer.
* Make ArrayBufferContents copyable. As ArrayBufferContents is just a
  wrapper around an std::shared_ptr, this is fine.
* Add a Detach function to DOMArrayBufferBase which allows to set the
  is_detached_ flag.

R=haraken@chromium.org, ulan@chromium.org

Bug: chromium:1008840
Change-Id: I2355ce0a38cf0453af2960b03e7a984dc002d1c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2106058Reviewed-by: default avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750945}
parent 7ea3734d
include_rules = [ include_rules = [
"+base/allocator/partition_allocator/partition_alloc.h", "+base/allocator/partition_allocator/partition_alloc.h",
"+base/allocator/partition_allocator/oom.h",
"+base/auto_reset.h", "+base/auto_reset.h",
"+base/bind.h", "+base/bind.h",
"+base/bind_helpers.h", "+base/bind_helpers.h",
......
...@@ -147,7 +147,7 @@ DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() { ...@@ -147,7 +147,7 @@ DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() {
SafeCast<size_t>(bytes_loaded_)); SafeCast<size_t>(bytes_loaded_));
} }
array_buffer_result_ = DOMArrayBuffer::Create(raw_data_); array_buffer_result_ = DOMArrayBuffer::Create(std::move(raw_data_));
DCHECK_EQ(raw_data_.DataLength(), 0u); DCHECK_EQ(raw_data_.DataLength(), 0u);
raw_data_.Reset(); raw_data_.Reset();
return array_buffer_result_; return array_buffer_result_;
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h" #include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h"
......
...@@ -6,8 +6,6 @@ import("//third_party/blink/renderer/core/core.gni") ...@@ -6,8 +6,6 @@ import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("typed_arrays") { blink_core_sources("typed_arrays") {
sources = [ sources = [
"array_buffer/array_buffer.cc",
"array_buffer/array_buffer.h",
"array_buffer/array_buffer_contents.cc", "array_buffer/array_buffer_contents.cc",
"array_buffer/array_buffer_contents.h", "array_buffer/array_buffer_contents.h",
"array_buffer_view_helpers.h", "array_buffer_view_helpers.h",
......
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer.h"
#include "base/memory/scoped_refptr.h"
namespace blink {
bool ArrayBuffer::Transfer(ArrayBufferContents& result) {
DCHECK(!IsShared());
scoped_refptr<ArrayBuffer> keep_alive(this);
if (is_detached_) {
result.Detach();
return false;
}
if (!contents_.Data()) {
// We transfer an empty ArrayBuffer, we can just allocate an empty content.
result = ArrayBufferContents(contents_.BackingStore());
return true;
}
contents_.Transfer(result);
is_detached_ = true;
return true;
}
bool ArrayBuffer::ShareContentsWith(ArrayBufferContents& result) {
DCHECK(IsShared());
scoped_refptr<ArrayBuffer> keep_alive(this);
if (!contents_.BackingStore()) {
result.Detach();
return false;
}
contents_.ShareWith(result);
return true;
}
bool ArrayBuffer::ShareNonSharedForInternalUse(ArrayBufferContents& result) {
DCHECK(!IsShared());
scoped_refptr<ArrayBuffer> keep_alive(this);
if (!contents_.BackingStore()) {
result.Detach();
return false;
}
contents_.ShareNonSharedForInternalUse(result);
return true;
}
} // namespace blink
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_ARRAY_BUFFER_ARRAY_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_ARRAY_BUFFER_ARRAY_BUFFER_H_
#include "base/allocator/partition_allocator/oom.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
class ArrayBuffer;
class ArrayBufferView;
class CORE_EXPORT ArrayBuffer : public RefCounted<ArrayBuffer> {
USING_FAST_MALLOC(ArrayBuffer);
public:
static inline scoped_refptr<ArrayBuffer> Create(size_t num_elements,
size_t element_byte_size);
static inline scoped_refptr<ArrayBuffer> Create(ArrayBuffer*);
static inline scoped_refptr<ArrayBuffer> Create(const void* source,
size_t byte_length);
static inline scoped_refptr<ArrayBuffer> Create(ArrayBufferContents&);
static inline scoped_refptr<ArrayBuffer> CreateOrNull(
size_t num_elements,
size_t element_byte_size);
// Only for use by DOMArrayBuffer::CreateUninitializedOrNull().
static inline scoped_refptr<ArrayBuffer> CreateUninitializedOrNull(
size_t num_elements,
size_t element_byte_size);
static inline scoped_refptr<ArrayBuffer> CreateShared(
size_t num_elements,
size_t element_byte_size);
static inline scoped_refptr<ArrayBuffer> CreateShared(const void* source,
size_t byte_length);
inline void* Data();
inline const void* Data() const;
inline void* DataShared();
inline const void* DataShared() const;
inline void* DataMaybeShared();
inline const void* DataMaybeShared() const;
inline size_t ByteLengthAsSizeT() const;
void AddView(ArrayBufferView*);
void RemoveView(ArrayBufferView*);
bool Transfer(ArrayBufferContents&);
bool ShareContentsWith(ArrayBufferContents&);
// Documentation see DOMArrayBuffer.
bool ShareNonSharedForInternalUse(ArrayBufferContents&);
bool IsDetached() const { return is_detached_; }
bool IsShared() const { return contents_.IsShared(); }
ArrayBufferContents* Content() { return &contents_; }
~ArrayBuffer() = default;
protected:
inline explicit ArrayBuffer(ArrayBufferContents&);
private:
static inline scoped_refptr<ArrayBuffer> Create(
size_t num_elements,
size_t element_byte_size,
ArrayBufferContents::InitializationPolicy);
static inline scoped_refptr<ArrayBuffer> CreateOrNull(
size_t num_elements,
size_t element_byte_size,
ArrayBufferContents::InitializationPolicy);
static inline scoped_refptr<ArrayBuffer> CreateShared(
size_t num_elements,
size_t element_byte_size,
ArrayBufferContents::InitializationPolicy);
ArrayBufferContents contents_;
bool is_detached_;
};
scoped_refptr<ArrayBuffer> ArrayBuffer::Create(size_t num_elements,
size_t element_byte_size) {
return Create(num_elements, element_byte_size,
ArrayBufferContents::kZeroInitialize);
}
scoped_refptr<ArrayBuffer> ArrayBuffer::Create(ArrayBuffer* other) {
// TODO(binji): support creating a SharedArrayBuffer by copying another
// ArrayBuffer?
DCHECK(!other->IsShared());
return ArrayBuffer::Create(other->Data(), other->ByteLengthAsSizeT());
}
scoped_refptr<ArrayBuffer> ArrayBuffer::Create(const void* source,
size_t byte_length) {
ArrayBufferContents contents(byte_length, 1, ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
if (UNLIKELY(!contents.Data()))
OOM_CRASH(byte_length);
scoped_refptr<ArrayBuffer> buffer = base::AdoptRef(new ArrayBuffer(contents));
memcpy(buffer->Data(), source, byte_length);
return buffer;
}
scoped_refptr<ArrayBuffer> ArrayBuffer::Create(ArrayBufferContents& contents) {
CHECK(contents.DataLength() == 0 || contents.DataMaybeShared());
return base::AdoptRef(new ArrayBuffer(contents));
}
scoped_refptr<ArrayBuffer> ArrayBuffer::CreateOrNull(size_t num_elements,
size_t element_byte_size) {
return CreateOrNull(num_elements, element_byte_size,
ArrayBufferContents::kZeroInitialize);
}
scoped_refptr<ArrayBuffer> ArrayBuffer::CreateUninitializedOrNull(
size_t num_elements,
size_t element_byte_size) {
return CreateOrNull(num_elements, element_byte_size,
ArrayBufferContents::kDontInitialize);
}
scoped_refptr<ArrayBuffer> ArrayBuffer::Create(
size_t num_elements,
size_t element_byte_size,
ArrayBufferContents::InitializationPolicy policy) {
ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBufferContents::kNotShared, policy);
if (UNLIKELY(!contents.Data()))
OOM_CRASH(num_elements * element_byte_size);
return base::AdoptRef(new ArrayBuffer(contents));
}
scoped_refptr<ArrayBuffer> ArrayBuffer::CreateOrNull(
size_t num_elements,
size_t element_byte_size,
ArrayBufferContents::InitializationPolicy policy) {
ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBufferContents::kNotShared, policy);
if (!contents.Data())
return nullptr;
return base::AdoptRef(new ArrayBuffer(contents));
}
scoped_refptr<ArrayBuffer> ArrayBuffer::CreateShared(size_t num_elements,
size_t element_byte_size) {
return CreateShared(num_elements, element_byte_size,
ArrayBufferContents::kZeroInitialize);
}
scoped_refptr<ArrayBuffer> ArrayBuffer::CreateShared(const void* source,
size_t byte_length) {
ArrayBufferContents contents(byte_length, 1, ArrayBufferContents::kShared,
ArrayBufferContents::kDontInitialize);
CHECK(contents.DataShared());
scoped_refptr<ArrayBuffer> buffer = base::AdoptRef(new ArrayBuffer(contents));
memcpy(buffer->DataShared(), source, byte_length);
return buffer;
}
scoped_refptr<ArrayBuffer> ArrayBuffer::CreateShared(
size_t num_elements,
size_t element_byte_size,
ArrayBufferContents::InitializationPolicy policy) {
ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBufferContents::kShared, policy);
CHECK(contents.DataShared());
return base::AdoptRef(new ArrayBuffer(contents));
}
ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents) : is_detached_(false) {
if (contents.IsShared())
contents.ShareWith(contents_);
else
contents.Transfer(contents_);
}
void* ArrayBuffer::Data() {
return contents_.Data();
}
const void* ArrayBuffer::Data() const {
return contents_.Data();
}
void* ArrayBuffer::DataShared() {
return contents_.DataShared();
}
const void* ArrayBuffer::DataShared() const {
return contents_.DataShared();
}
void* ArrayBuffer::DataMaybeShared() {
return contents_.DataMaybeShared();
}
const void* ArrayBuffer::DataMaybeShared() const {
return contents_.DataMaybeShared();
}
size_t ArrayBuffer::ByteLengthAsSizeT() const {
return contents_.DataLength();
}
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_ARRAY_BUFFER_ARRAY_BUFFER_H_
...@@ -65,11 +65,13 @@ class CORE_EXPORT ArrayBufferContents { ...@@ -65,11 +65,13 @@ class CORE_EXPORT ArrayBufferContents {
InitializationPolicy); InitializationPolicy);
ArrayBufferContents(void* data, size_t length, DataDeleter deleter); ArrayBufferContents(void* data, size_t length, DataDeleter deleter);
ArrayBufferContents(ArrayBufferContents&&) = default; ArrayBufferContents(ArrayBufferContents&&) = default;
ArrayBufferContents(const ArrayBufferContents&) = default;
explicit ArrayBufferContents(std::shared_ptr<v8::BackingStore> backing_store) explicit ArrayBufferContents(std::shared_ptr<v8::BackingStore> backing_store)
: backing_store_(std::move(backing_store)) {} : backing_store_(std::move(backing_store)) {}
~ArrayBufferContents(); ~ArrayBufferContents();
ArrayBufferContents& operator=(const ArrayBufferContents&) = default;
ArrayBufferContents& operator=(ArrayBufferContents&&) = default; ArrayBufferContents& operator=(ArrayBufferContents&&) = default;
void Detach(); void Detach();
...@@ -112,8 +114,6 @@ class CORE_EXPORT ArrayBufferContents { ...@@ -112,8 +114,6 @@ class CORE_EXPORT ArrayBufferContents {
static void* AllocateMemoryWithFlags(size_t, InitializationPolicy, int); static void* AllocateMemoryWithFlags(size_t, InitializationPolicy, int);
std::shared_ptr<v8::BackingStore> backing_store_; std::shared_ptr<v8::BackingStore> backing_store_;
DISALLOW_COPY_AND_ASSIGN(ArrayBufferContents);
}; };
} // namespace blink } // namespace blink
......
...@@ -44,11 +44,21 @@ bool DOMArrayBuffer::Transfer(v8::Isolate* isolate, ...@@ -44,11 +44,21 @@ bool DOMArrayBuffer::Transfer(v8::Isolate* isolate,
DOMArrayBuffer* to_transfer = this; DOMArrayBuffer* to_transfer = this;
if (!IsDetachable(isolate)) { if (!IsDetachable(isolate)) {
to_transfer = to_transfer =
DOMArrayBuffer::Create(Buffer()->Data(), Buffer()->ByteLengthAsSizeT()); DOMArrayBuffer::Create(Content()->Data(), ByteLengthAsSizeT());
} }
if (!to_transfer->Buffer()->Transfer(result)) if (IsDetached()) {
result.Detach();
return false; return false;
}
if (!Content()->Data()) {
// We transfer an empty ArrayBuffer, we can just allocate an empty content.
result = ArrayBufferContents(Content()->BackingStore());
} else {
Content()->Transfer(result);
Detach();
}
Vector<v8::Local<v8::ArrayBuffer>, 4> buffer_handles; Vector<v8::Local<v8::ArrayBuffer>, 4> buffer_handles;
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
...@@ -62,21 +72,25 @@ bool DOMArrayBuffer::Transfer(v8::Isolate* isolate, ...@@ -62,21 +72,25 @@ bool DOMArrayBuffer::Transfer(v8::Isolate* isolate,
DOMArrayBuffer* DOMArrayBuffer::CreateOrNull(size_t num_elements, DOMArrayBuffer* DOMArrayBuffer::CreateOrNull(size_t num_elements,
size_t element_byte_size) { size_t element_byte_size) {
scoped_refptr<ArrayBuffer> buffer = ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBuffer::CreateOrNull(num_elements, element_byte_size); ArrayBufferContents::kNotShared,
if (!buffer) ArrayBufferContents::kZeroInitialize);
if (!contents.Data()) {
return nullptr; return nullptr;
return Create(std::move(buffer)); }
return Create(std::move(contents));
} }
DOMArrayBuffer* DOMArrayBuffer::CreateUninitializedOrNull( DOMArrayBuffer* DOMArrayBuffer::CreateUninitializedOrNull(
size_t num_elements, size_t num_elements,
size_t element_byte_size) { size_t element_byte_size) {
scoped_refptr<ArrayBuffer> buffer = ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBuffer::CreateUninitializedOrNull(num_elements, element_byte_size); ArrayBufferContents::kNotShared,
if (!buffer) ArrayBufferContents::kDontInitialize);
if (!contents.Data()) {
return nullptr; return nullptr;
return Create(std::move(buffer)); }
return Create(std::move(contents));
} }
v8::Local<v8::Value> DOMArrayBuffer::Wrap( v8::Local<v8::Value> DOMArrayBuffer::Wrap(
...@@ -89,10 +103,9 @@ v8::Local<v8::Value> DOMArrayBuffer::Wrap( ...@@ -89,10 +103,9 @@ v8::Local<v8::Value> DOMArrayBuffer::Wrap(
v8::Local<v8::ArrayBuffer> wrapper; v8::Local<v8::ArrayBuffer> wrapper;
{ {
v8::Context::Scope context_scope(creation_context->CreationContext()); v8::Context::Scope context_scope(creation_context->CreationContext());
wrapper = wrapper = v8::ArrayBuffer::New(isolate, Content()->BackingStore());
v8::ArrayBuffer::New(isolate, Buffer()->Content()->BackingStore());
wrapper->Externalize(Buffer()->Content()->BackingStore()); wrapper->Externalize(Content()->BackingStore());
} }
return AssociateWithWrapper(isolate, wrapper_type_info, wrapper); return AssociateWithWrapper(isolate, wrapper_type_info, wrapper);
...@@ -112,7 +125,7 @@ DOMArrayBuffer* DOMArrayBuffer::Create( ...@@ -112,7 +125,7 @@ DOMArrayBuffer* DOMArrayBuffer::Create(
data += span.size(); data += span.size();
} }
return Create(ArrayBuffer::Create(contents)); return Create(std::move(contents));
} }
DOMArrayBuffer* DOMArrayBuffer::Create( DOMArrayBuffer* DOMArrayBuffer::Create(
...@@ -132,7 +145,7 @@ DOMArrayBuffer* DOMArrayBuffer::Create( ...@@ -132,7 +145,7 @@ DOMArrayBuffer* DOMArrayBuffer::Create(
ptr += span.size(); ptr += span.size();
} }
return Create(ArrayBuffer::Create(contents)); return Create(std::move(contents));
} }
DOMArrayBuffer* DOMArrayBuffer::Slice(size_t begin, size_t end) const { DOMArrayBuffer* DOMArrayBuffer::Slice(size_t begin, size_t end) const {
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_ARRAY_BUFFER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_ARRAY_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_ARRAY_BUFFER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_ARRAY_BUFFER_H_
#include "base/allocator/partition_allocator/oom.h"
#include "base/containers/span.h" #include "base/containers/span.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h"
#include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
...@@ -17,18 +18,29 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase { ...@@ -17,18 +18,29 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
static DOMArrayBuffer* Create(scoped_refptr<ArrayBuffer> buffer) { static DOMArrayBuffer* Create(ArrayBufferContents contents) {
return MakeGarbageCollected<DOMArrayBuffer>(std::move(buffer)); return MakeGarbageCollected<DOMArrayBuffer>(std::move(contents));
} }
static DOMArrayBuffer* Create(size_t num_elements, size_t element_byte_size) { static DOMArrayBuffer* Create(size_t num_elements, size_t element_byte_size) {
return Create(ArrayBuffer::Create(num_elements, element_byte_size)); ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kZeroInitialize);
if (UNLIKELY(!contents.Data())) {
OOM_CRASH(num_elements * element_byte_size);
}
return Create(std::move(contents));
} }
static DOMArrayBuffer* Create(const void* source, size_t byte_length) { static DOMArrayBuffer* Create(const void* source, size_t byte_length) {
return Create(ArrayBuffer::Create(source, byte_length)); ArrayBufferContents contents(byte_length, 1,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
if (UNLIKELY(!contents.Data())) {
OOM_CRASH(byte_length);
} }
static DOMArrayBuffer* Create(ArrayBufferContents& contents) { memcpy(contents.Data(), source, byte_length);
return Create(ArrayBuffer::Create(contents)); return Create(std::move(contents));
} }
static DOMArrayBuffer* Create(scoped_refptr<SharedBuffer>); static DOMArrayBuffer* Create(scoped_refptr<SharedBuffer>);
static DOMArrayBuffer* Create(const Vector<base::span<const char>>&); static DOMArrayBuffer* Create(const Vector<base::span<const char>>&);
...@@ -41,8 +53,8 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase { ...@@ -41,8 +53,8 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase {
static DOMArrayBuffer* CreateUninitializedOrNull(size_t num_elements, static DOMArrayBuffer* CreateUninitializedOrNull(size_t num_elements,
size_t element_byte_size); size_t element_byte_size);
explicit DOMArrayBuffer(scoped_refptr<ArrayBuffer> buffer) explicit DOMArrayBuffer(ArrayBufferContents contents)
: DOMArrayBufferBase(std::move(buffer)) {} : DOMArrayBufferBase(std::move(contents)) {}
DOMArrayBuffer* Slice(size_t begin, size_t end) const; DOMArrayBuffer* Slice(size_t begin, size_t end) const;
...@@ -56,7 +68,12 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase { ...@@ -56,7 +68,12 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase {
// for e.g. WebAudio which uses a separate thread for processing the // for e.g. WebAudio which uses a separate thread for processing the
// ArrayBuffer while at the same time exposing a NonShared Float32Array. // ArrayBuffer while at the same time exposing a NonShared Float32Array.
bool ShareNonSharedForInternalUse(ArrayBufferContents& result) { bool ShareNonSharedForInternalUse(ArrayBufferContents& result) {
return Buffer()->ShareNonSharedForInternalUse(result); if (!Content()->BackingStore()) {
result.Detach();
return false;
}
Content()->ShareNonSharedForInternalUse(result);
return true;
} }
v8::Local<v8::Value> Wrap(v8::Isolate*, v8::Local<v8::Value> Wrap(v8::Isolate*,
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_ARRAY_BUFFER_BASE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_ARRAY_BUFFER_BASE_H_
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
...@@ -16,27 +16,28 @@ class CORE_EXPORT DOMArrayBufferBase : public ScriptWrappable { ...@@ -16,27 +16,28 @@ class CORE_EXPORT DOMArrayBufferBase : public ScriptWrappable {
public: public:
~DOMArrayBufferBase() override = default; ~DOMArrayBufferBase() override = default;
const ArrayBuffer* Buffer() const { return buffer_.get(); } const ArrayBufferContents* Content() const { return &contents_; }
ArrayBuffer* Buffer() { return buffer_.get(); } ArrayBufferContents* Content() { return &contents_; }
const void* Data() const { return Buffer()->Data(); } const void* Data() const { return contents_.Data(); }
void* Data() { return Buffer()->Data(); } void* Data() { return contents_.Data(); }
const void* DataMaybeShared() const { return Buffer()->DataMaybeShared(); } const void* DataMaybeShared() const { return contents_.DataMaybeShared(); }
void* DataMaybeShared() { return Buffer()->DataMaybeShared(); } void* DataMaybeShared() { return contents_.DataMaybeShared(); }
size_t ByteLengthAsSizeT() const { return Buffer()->ByteLengthAsSizeT(); } size_t ByteLengthAsSizeT() const { return contents_.DataLength(); }
// This function is deprecated and should not be used. Use {ByteLengthAsSizeT} // This function is deprecated and should not be used. Use {ByteLengthAsSizeT}
// instead. // instead.
unsigned DeprecatedByteLengthAsUnsigned() const { unsigned DeprecatedByteLengthAsUnsigned() const {
size_t size = ByteLengthAsSizeT(); return base::checked_cast<unsigned>(contents_.DataLength());
CHECK_LE(size, static_cast<size_t>(std::numeric_limits<unsigned>::max()));
return static_cast<unsigned>(size);
} }
bool IsDetached() const { return Buffer()->IsDetached(); } bool IsDetached() const { return is_detached_; }
bool IsShared() const { return Buffer()->IsShared(); }
void Detach() { is_detached_ = true; }
bool IsShared() const { return contents_.IsShared(); }
v8::Local<v8::Value> Wrap(v8::Isolate*, v8::Local<v8::Value> Wrap(v8::Isolate*,
v8::Local<v8::Object> creation_context) override { v8::Local<v8::Object> creation_context) override {
...@@ -45,12 +46,11 @@ class CORE_EXPORT DOMArrayBufferBase : public ScriptWrappable { ...@@ -45,12 +46,11 @@ class CORE_EXPORT DOMArrayBufferBase : public ScriptWrappable {
} }
protected: protected:
explicit DOMArrayBufferBase(scoped_refptr<ArrayBuffer> buffer) explicit DOMArrayBufferBase(ArrayBufferContents contents)
: buffer_(std::move(buffer)) { : contents_(std::move(contents)) {}
DCHECK(buffer_);
}
scoped_refptr<ArrayBuffer> buffer_; ArrayBufferContents contents_;
bool is_detached_ = false;
}; };
} // namespace blink } // namespace blink
......
...@@ -15,8 +15,8 @@ v8::Local<v8::Value> DOMSharedArrayBuffer::Wrap( ...@@ -15,8 +15,8 @@ v8::Local<v8::Value> DOMSharedArrayBuffer::Wrap(
const WrapperTypeInfo* wrapper_type_info = this->GetWrapperTypeInfo(); const WrapperTypeInfo* wrapper_type_info = this->GetWrapperTypeInfo();
v8::Local<v8::SharedArrayBuffer> wrapper = v8::Local<v8::SharedArrayBuffer> wrapper =
v8::SharedArrayBuffer::New(isolate, Buffer()->Content()->BackingStore()); v8::SharedArrayBuffer::New(isolate, Content()->BackingStore());
wrapper->Externalize(Buffer()->Content()->BackingStore()); wrapper->Externalize(Content()->BackingStore());
return AssociateWithWrapper(isolate, wrapper_type_info, wrapper); return AssociateWithWrapper(isolate, wrapper_type_info, wrapper);
} }
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_SHARED_ARRAY_BUFFER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_SHARED_ARRAY_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_SHARED_ARRAY_BUFFER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_TYPED_ARRAYS_DOM_SHARED_ARRAY_BUFFER_H_
#include "base/allocator/partition_allocator/oom.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_base.h"
namespace blink { namespace blink {
...@@ -15,28 +16,43 @@ class CORE_EXPORT DOMSharedArrayBuffer final : public DOMArrayBufferBase { ...@@ -15,28 +16,43 @@ class CORE_EXPORT DOMSharedArrayBuffer final : public DOMArrayBufferBase {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
public: public:
static DOMSharedArrayBuffer* Create(scoped_refptr<ArrayBuffer> buffer) { static DOMSharedArrayBuffer* Create(ArrayBufferContents contents) {
DCHECK(buffer->IsShared()); DCHECK(contents.IsShared());
return MakeGarbageCollected<DOMSharedArrayBuffer>(std::move(buffer)); return MakeGarbageCollected<DOMSharedArrayBuffer>(std::move(contents));
} }
static DOMSharedArrayBuffer* Create(unsigned num_elements, static DOMSharedArrayBuffer* Create(unsigned num_elements,
unsigned element_byte_size) { unsigned element_byte_size) {
return Create(ArrayBuffer::CreateShared(num_elements, element_byte_size)); ArrayBufferContents contents(num_elements, element_byte_size,
ArrayBufferContents::kShared,
ArrayBufferContents::kZeroInitialize);
if (UNLIKELY(!contents.DataShared())) {
OOM_CRASH(num_elements * element_byte_size);
}
return Create(std::move(contents));
} }
static DOMSharedArrayBuffer* Create(const void* source, static DOMSharedArrayBuffer* Create(const void* source,
unsigned byte_length) { unsigned byte_length) {
return Create(ArrayBuffer::CreateShared(source, byte_length)); ArrayBufferContents contents(byte_length, 1, ArrayBufferContents::kShared,
ArrayBufferContents::kDontInitialize);
if (UNLIKELY(!contents.DataShared())) {
OOM_CRASH(byte_length);
} }
static DOMSharedArrayBuffer* Create(ArrayBufferContents& contents) { memcpy(contents.DataShared(), source, byte_length);
DCHECK(contents.IsShared()); return Create(std::move(contents));
return Create(ArrayBuffer::Create(contents));
} }
explicit DOMSharedArrayBuffer(scoped_refptr<ArrayBuffer> buffer) explicit DOMSharedArrayBuffer(ArrayBufferContents contents)
: DOMArrayBufferBase(std::move(buffer)) {} : DOMArrayBufferBase(std::move(contents)) {}
bool ShareContentsWith(ArrayBufferContents& result) { bool ShareContentsWith(ArrayBufferContents& result) {
return Buffer()->ShareContentsWith(result); if (!Content()->BackingStore()) {
result.Detach();
return false;
}
Content()->ShareWith(result);
return true;
} }
v8::Local<v8::Value> Wrap(v8::Isolate*, v8::Local<v8::Value> Wrap(v8::Isolate*,
......
...@@ -1665,7 +1665,7 @@ ImageData* BaseRenderingContext2D::getImageData( ...@@ -1665,7 +1665,7 @@ ImageData* BaseRenderingContext2D::getImageData(
"Buffer size exceeds maximum heap object size."); "Buffer size exceeds maximum heap object size.");
return nullptr; return nullptr;
} }
DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(std::move(contents));
ImageData* imageData = ImageData::Create( ImageData* imageData = ImageData::Create(
image_data_rect.Size(), image_data_rect.Size(),
......
...@@ -450,7 +450,6 @@ void PresentationConnection::send(const String& message, ...@@ -450,7 +450,6 @@ void PresentationConnection::send(const String& message,
void PresentationConnection::send(DOMArrayBuffer* array_buffer, void PresentationConnection::send(DOMArrayBuffer* array_buffer,
ExceptionState& exception_state) { ExceptionState& exception_state) {
DCHECK(array_buffer); DCHECK(array_buffer);
DCHECK(array_buffer->Buffer());
if (!CanSendMessage(exception_state)) if (!CanSendMessage(exception_state))
return; return;
if (!base::CheckedNumeric<wtf_size_t>(array_buffer->ByteLengthAsSizeT()) if (!base::CheckedNumeric<wtf_size_t>(array_buffer->ByteLengthAsSizeT())
...@@ -643,7 +642,6 @@ void PresentationConnection::DidFinishLoadingBlob(DOMArrayBuffer* buffer) { ...@@ -643,7 +642,6 @@ void PresentationConnection::DidFinishLoadingBlob(DOMArrayBuffer* buffer) {
DCHECK(!messages_.IsEmpty()); DCHECK(!messages_.IsEmpty());
DCHECK_EQ(messages_.front()->type, kMessageTypeBlob); DCHECK_EQ(messages_.front()->type, kMessageTypeBlob);
DCHECK(buffer); DCHECK(buffer);
DCHECK(buffer->Buffer());
if (!base::CheckedNumeric<wtf_size_t>(buffer->ByteLengthAsSizeT()) if (!base::CheckedNumeric<wtf_size_t>(buffer->ByteLengthAsSizeT())
.IsValid()) { .IsValid()) {
// TODO(crbug.com/1036565): generate error message? The problem is that the // TODO(crbug.com/1036565): generate error message? The problem is that the
......
...@@ -348,7 +348,6 @@ void DOMWebSocket::send(DOMArrayBuffer* binary_data, ...@@ -348,7 +348,6 @@ void DOMWebSocket::send(DOMArrayBuffer* binary_data,
NETWORK_DVLOG(1) << "WebSocket " << this << " send() Sending ArrayBuffer " NETWORK_DVLOG(1) << "WebSocket " << this << " send() Sending ArrayBuffer "
<< binary_data; << binary_data;
DCHECK(binary_data); DCHECK(binary_data);
DCHECK(binary_data->Buffer());
if (common_.GetState() == kConnecting) { if (common_.GetState() == kConnecting) {
SetInvalidStateErrorForSendMethod(exception_state); SetInvalidStateErrorForSendMethod(exception_state);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment