Commit 7850270a authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[arraybuffer] Add a check for ArrayBuffer::IsDetached in ArrayBufferView

ArrayBufferView and friends currently cache the buffer start and length.
The cache is cleared on ArrayBuffer::Detach, which requires ArrayBuffer
to keep track of all its ArrayBufferViews in a linked list.

This function adds ArrayBuffer::IsDetached before accessing each cached
value. This will allow us to remove the linked list and simplify the
ownership model and eventually get rid of WTF versions of ArrayBuffer,
ArrayBufferView, and friends.

Bug: chromium:1008840
Change-Id: Ib29d2d4f493ea4abfad0b85314b7934137fa1857
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2091489Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#747741}
parent c2a312dc
......@@ -31,13 +31,13 @@ namespace blink {
ArrayBufferView::ArrayBufferView(scoped_refptr<ArrayBuffer> buffer,
size_t byte_offset)
: byte_offset_(byte_offset),
: raw_byte_offset_(byte_offset),
is_detachable_(true),
buffer_(std::move(buffer)),
prev_view_(nullptr),
next_view_(nullptr) {
base_address_ =
buffer_ ? (static_cast<char*>(buffer_->DataMaybeShared()) + byte_offset_)
raw_base_address_ =
buffer_ ? (static_cast<char*>(buffer_->DataMaybeShared()) + byte_offset)
: nullptr;
if (buffer_)
buffer_->AddView(this);
......@@ -50,8 +50,8 @@ ArrayBufferView::~ArrayBufferView() {
void ArrayBufferView::Detach() {
buffer_ = nullptr;
base_address_ = nullptr;
byte_offset_ = 0;
raw_base_address_ = nullptr;
raw_byte_offset_ = 0;
}
const char* ArrayBufferView::TypeName() {
......
......@@ -60,11 +60,13 @@ class CORE_EXPORT ArrayBufferView : public RefCounted<ArrayBufferView> {
void* BaseAddress() const {
DCHECK(!IsShared());
return base_address_;
return BaseAddressMaybeShared();
}
void* BaseAddressMaybeShared() const {
return !IsDetached() ? raw_base_address_ : nullptr;
}
void* BaseAddressMaybeShared() const { return base_address_; }
size_t ByteOffset() const { return byte_offset_; }
size_t ByteOffset() const { return !IsDetached() ? raw_byte_offset_ : 0; }
virtual size_t ByteLengthAsSizeT() const = 0;
virtual unsigned TypeSize() const = 0;
......@@ -79,14 +81,15 @@ class CORE_EXPORT ArrayBufferView : public RefCounted<ArrayBufferView> {
ArrayBufferView(scoped_refptr<ArrayBuffer>, size_t byte_offset);
virtual void Detach();
bool IsDetached() const { return !buffer_ || buffer_->IsDetached(); }
private:
// The raw_* fields may be stale after Detach. Use getters instead.
// This is the address of the ArrayBuffer's storage, plus the byte offset.
void* base_address_;
size_t byte_offset_;
void* raw_base_address_;
size_t raw_byte_offset_;
bool is_detachable_;
private:
friend class ArrayBuffer;
scoped_refptr<ArrayBuffer> buffer_;
ArrayBufferView* prev_view_;
......
......@@ -51,9 +51,9 @@ class TypedArray : public ArrayBufferView {
return static_cast<T*>(BaseAddressMaybeShared());
}
size_t length() const { return length_; }
size_t length() const { return !IsDetached() ? raw_length_ : 0; }
size_t ByteLengthAsSizeT() const final { return length_ * sizeof(T); }
size_t ByteLengthAsSizeT() const final { return length() * sizeof(T); }
unsigned TypeSize() const final { return sizeof(T); }
......@@ -66,22 +66,22 @@ class TypedArray : public ArrayBufferView {
TypedArray(scoped_refptr<ArrayBuffer> buffer,
size_t byte_offset,
size_t length)
: ArrayBufferView(std::move(buffer), byte_offset), length_(length) {}
: ArrayBufferView(std::move(buffer), byte_offset), raw_length_(length) {}
// Invoked by the indexed getter. Does not perform range checks; caller
// is responsible for doing so and returning undefined as necessary.
T Item(size_t index) const {
SECURITY_DCHECK(index < length_);
SECURITY_DCHECK(index < length());
return Data()[index];
}
private:
void Detach() final {
ArrayBufferView::Detach();
length_ = 0;
raw_length_ = 0;
}
size_t length_;
// It may be stale after Detach. Use length() instead.
size_t raw_length_;
};
template <typename T, bool clamped>
......@@ -134,7 +134,7 @@ scoped_refptr<TypedArray<T, clamped>> TypedArray<T, clamped>::Create(
template <typename T, bool clamped>
inline void TypedArray<T, clamped>::Set(size_t index, double value) {
if (index >= length_)
if (index >= length())
return;
if (std::isnan(value)) // Clamp NaN to 0
value = 0;
......@@ -145,7 +145,7 @@ inline void TypedArray<T, clamped>::Set(size_t index, double value) {
template <>
inline void TypedArray<uint8_t, true>::Set(size_t index, double value) {
if (index >= length_) {
if (index >= length()) {
return;
}
if (std::isnan(value) || value < 0) {
......@@ -159,28 +159,28 @@ inline void TypedArray<uint8_t, true>::Set(size_t index, double value) {
template <>
inline void TypedArray<float, false>::Set(size_t index, double value) {
if (index >= length_)
if (index >= length())
return;
Data()[index] = static_cast<float>(value);
}
template <>
inline void TypedArray<double, false>::Set(size_t index, double value) {
if (index >= length_)
if (index >= length())
return;
Data()[index] = value;
}
template <>
inline void TypedArray<int64_t, false>::Set(size_t index, uint64_t value) {
if (index >= length_)
if (index >= length())
return;
Data()[index] = static_cast<int64_t>(value);
}
template <>
inline void TypedArray<uint64_t, false>::Set(size_t index, uint64_t value) {
if (index >= length_)
if (index >= length())
return;
Data()[index] = value;
}
......
......@@ -24,21 +24,24 @@ class DataView final : public ArrayBufferView {
return base::AdoptRef(new DataView(buffer, byte_offset, byte_length));
}
size_t ByteLengthAsSizeT() const override { return byte_length_; }
size_t ByteLengthAsSizeT() const override {
return !IsDetached() ? raw_byte_length_ : 0;
}
ViewType GetType() const override { return kTypeDataView; }
unsigned TypeSize() const override { return 1; }
protected:
void Detach() override {
ArrayBufferView::Detach();
byte_length_ = 0;
raw_byte_length_ = 0;
}
private:
DataView(ArrayBuffer* buffer, size_t byte_offset, size_t byte_length)
: ArrayBufferView(buffer, byte_offset), byte_length_(byte_length) {}
: ArrayBufferView(buffer, byte_offset), raw_byte_length_(byte_length) {}
size_t byte_length_;
// It may be stale after Detach. Use ByteLengthAsSizeT instead.
size_t raw_byte_length_;
};
} // anonymous namespace
......
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