Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions deps/v8/include/v8-array-buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,17 @@ class V8_EXPORT ArrayBuffer : public Object {
*/
bool IsImmutable() const;

/**
* Copy up to |bytes_to_copy| bytes from this ArrayBuffer starting at
* position |source_start| to the target ArrayBuffer starting at position
* |target_start|. Nothing is copied if the source or target ArrayBuffer is
* detached.
* Returns the number of bytes actually copied.
*/
size_t CopyArrayBufferBytes(size_t source_start, size_t bytes_to_copy,
Local<ArrayBuffer> target,
size_t target_start) const;

/**
* Detaches this ArrayBuffer and all its views (typed arrays).
* Detaching sets the byte length of the buffer and all typed arrays to zero,
Expand Down Expand Up @@ -605,6 +616,16 @@ class V8_EXPORT SharedArrayBuffer : public Object {
*/
void* Data() const;

/**
* Copy up to |bytes_to_copy| bytes from this SharedArrayBuffer starting at
* position |source_start| to the target SharedArrayBuffer starting at
* position |target_start|.
* Returns the number of bytes actually copied.
*/
size_t CopyArrayBufferBytes(size_t source_start, size_t bytes_to_copy,
Local<SharedArrayBuffer> target,
size_t target_start) const;

V8_INLINE static SharedArrayBuffer* Cast(Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
Expand Down
53 changes: 53 additions & 0 deletions deps/v8/src/api/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4221,6 +4221,44 @@ void* v8::SharedArrayBuffer::Data() const {
return Utils::OpenDirectHandle(this)->backing_store();
}

template <bool is_shared>
static size_t CopyArrayBufferBytesImpl(const void* source_buffer,
size_t source_start,
size_t source_length,
void* target_buffer, size_t target_start,
size_t target_length,
size_t bytes_to_copy) {
source_start = std::min(source_start, source_length);
target_start = std::min(target_start, target_length);
size_t source_size = source_length - source_start;
size_t target_size = target_length - target_start;
bytes_to_copy = std::min({bytes_to_copy, source_size, target_size});
if (bytes_to_copy == 0) return 0;
const char* src = static_cast<const char*>(source_buffer) + source_start;
char* dst = static_cast<char*>(target_buffer) + target_start;
if (is_shared) {
base::Relaxed_Memmove(reinterpret_cast<base::Atomic8*>(dst),
reinterpret_cast<const base::Atomic8*>(src),
bytes_to_copy);
} else {
std::memmove(dst, src, bytes_to_copy);
}
return bytes_to_copy;
}

size_t v8::SharedArrayBuffer::CopyArrayBufferBytes(
size_t source_start, size_t bytes_to_copy, Local<SharedArrayBuffer> target,
size_t target_start) const {
i::DisallowGarbageCollection no_gc;
auto self = Utils::OpenDirectHandle(this);
auto that = Utils::OpenDirectHandle(*target);
DCHECK(!that->is_immutable());
return CopyArrayBufferBytesImpl<true>(self->backing_store(), source_start,
self->GetByteLength(),
that->backing_store(), target_start,
that->GetByteLength(), bytes_to_copy);
}

void v8::ArrayBuffer::CheckCast(Value* that) {
auto obj = *Utils::OpenDirectHandle(that);
Utils::ApiCheck(
Expand Down Expand Up @@ -8907,6 +8945,21 @@ bool v8::ArrayBuffer::IsImmutable() const {
return Utils::OpenDirectHandle(this)->is_immutable();
}

size_t v8::ArrayBuffer::CopyArrayBufferBytes(size_t source_start,
size_t bytes_to_copy,
Local<ArrayBuffer> target,
size_t target_start) const {
i::DisallowGarbageCollection no_gc;
auto self = Utils::OpenDirectHandle(this);
auto that = Utils::OpenDirectHandle(*target);
if (self->was_detached()) return 0;
if (that->was_detached() || that->is_immutable()) return 0;
return CopyArrayBufferBytesImpl<false>(self->backing_store(), source_start,
self->GetByteLength(),
that->backing_store(), target_start,
that->GetByteLength(), bytes_to_copy);
}

namespace {
std::shared_ptr<i::BackingStore> ToInternal(
std::shared_ptr<i::BackingStoreBase> backing_store) {
Expand Down
50 changes: 50 additions & 0 deletions deps/v8/test/cctest/test-api-array-buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1301,3 +1301,53 @@ TEST(ArrayBuffer_ImmutableBackingStore) {

CHECK(ab->IsImmutable());
}

TEST(ArrayBuffer_CopyArrayBufferBytes) {
LocalContext env;
v8::Isolate* isolate = env.isolate();
v8::HandleScope scope(isolate);
auto ab1 = v8::ArrayBuffer::New(isolate, 6);
auto ab2 = v8::ArrayBuffer::New(isolate, 4);
std::memcpy(ab1->Data(), "123456", 6);
std::memcpy(ab2->Data(), "ABCD", 4);
CHECK_EQ(0, ab1->CopyArrayBufferBytes(0, 0, ab2, 0));
CHECK_EQ(0, ab1->CopyArrayBufferBytes(6, 0, ab2, 6));
CHECK_EQ(0, ab1->CopyArrayBufferBytes(0, 4, ab2, 6));
CHECK_EQ(0, std::memcmp(ab2->Data(), "ABCD", 4));
CHECK_EQ(4, ab1->CopyArrayBufferBytes(0, 6, ab2, 0));
CHECK_EQ(0, std::memcmp(ab2->Data(), "1234", 4));
CHECK_EQ(2, ab1->CopyArrayBufferBytes(0, 6, ab2, 2));
CHECK_EQ(0, std::memcmp(ab2->Data(), "1212", 4));
ab2->Detach(v8::Local<v8::Value>()).Check();
CHECK_EQ(0, ab1->CopyArrayBufferBytes(0, 6, ab2, 0));
std::unique_ptr<v8::BackingStore> backing_store =
v8::ArrayBuffer::NewBackingStore(isolate, 6);
CHECK(backing_store);
v8::internal::BackingStore* i_backing_store =
reinterpret_cast<v8::internal::BackingStore*>(backing_store.get());
i_backing_store->set_is_immutable(true);
CHECK(i_backing_store->is_immutable());
std::shared_ptr<v8::BackingStore> shared_backing_store =
std::move(backing_store);
auto ab3 = v8::ArrayBuffer::New(isolate, shared_backing_store);
CHECK(ab3->IsImmutable());
CHECK_EQ(0, ab1->CopyArrayBufferBytes(0, 6, ab3, 0));
}

TEST(SharedArrayBuffer_CopyArrayBufferBytes) {
LocalContext env;
v8::Isolate* isolate = env.isolate();
v8::HandleScope scope(isolate);
auto ab1 = v8::SharedArrayBuffer::New(isolate, 6);
auto ab2 = v8::SharedArrayBuffer::New(isolate, 4);
std::memcpy(ab1->Data(), "123456", 6);
std::memcpy(ab2->Data(), "ABCD", 4);
CHECK_EQ(0, ab1->CopyArrayBufferBytes(0, 0, ab2, 0));
CHECK_EQ(0, ab1->CopyArrayBufferBytes(6, 0, ab2, 6));
CHECK_EQ(0, ab1->CopyArrayBufferBytes(0, 4, ab2, 6));
CHECK_EQ(0, std::memcmp(ab2->Data(), "ABCD", 4));
CHECK_EQ(4, ab1->CopyArrayBufferBytes(0, 6, ab2, 0));
CHECK_EQ(0, std::memcmp(ab2->Data(), "1234", 4));
CHECK_EQ(2, ab1->CopyArrayBufferBytes(0, 6, ab2, 2));
CHECK_EQ(0, std::memcmp(ab2->Data(), "1212", 4));
}
Loading