19#define CHECK_SHARED(expected, name, method) \
20 if (name->is_shared() != expected) { \
21 THROW_NEW_ERROR_RETURN_FAILURE( \
23 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
24 isolate->factory()->NewStringFromAsciiChecked(method), \
28#define CHECK_RESIZABLE(expected, name, method) \
29 if (name->is_resizable_by_js() != expected) { \
30 THROW_NEW_ERROR_RETURN_FAILURE( \
32 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
33 isolate->factory()->NewStringFromAsciiChecked(method), \
45std::pair<std::unique_ptr<BackingStore>, std::optional<MessageTemplate>>
46TryAllocateBackingStore(Isolate* isolate,
SharedFlag shared,
48 DirectHandle<Object> max_length,
50 DisallowJavascriptExecution no_js(isolate);
53 size_t max_byte_length = 0;
54 std::unique_ptr<BackingStore> backing_store;
56 size_t max_allocatable =
57 isolate->array_buffer_allocator()->MaxAllocationSize();
61 byte_length > max_allocatable) {
62 return {
nullptr, MessageTemplate::kInvalidArrayBufferLength};
72 max_byte_length > max_allocatable) {
73 return {
nullptr, MessageTemplate::kInvalidArrayBufferMaxLength};
75 if (byte_length > max_byte_length) {
76 return {
nullptr, MessageTemplate::kInvalidArrayBufferMaxLength};
79 size_t page_size, initial_pages, max_pages;
80 const auto maybe_range_error =
82 isolate, byte_length, max_byte_length, &page_size, &initial_pages,
84 if (maybe_range_error.has_value()) {
85 return {
nullptr, maybe_range_error.value()};
88 isolate, byte_length, max_byte_length, page_size, initial_pages,
96 return {
nullptr, MessageTemplate::kArrayBufferAllocationFailed};
98 return {std::move(backing_store), std::nullopt};
102 DirectHandle<JSFunction> target,
104 DirectHandle<Object> length,
105 DirectHandle<Object> max_length,
112 *target != target->native_context()->array_buffer_fun()
119 auto [backing_store, range_error] = TryAllocateBackingStore(
120 isolate, shared, resizable, length, max_length, initialized);
121 DirectHandle<JSObject>
result;
126 const bool backing_store_creation_failed = !backing_store;
127 array_buffer->Setup(shared, resizable, std::move(backing_store), isolate);
128 if (backing_store_creation_failed) {
129 CHECK(range_error.has_value());
132 return *array_buffer;
141 DCHECK(*target == target->native_context()->array_buffer_fun() ||
142 *target == target->native_context()->shared_array_buffer_fun());
143 if (IsUndefined(*
args.new_target(), isolate)) {
146 NewTypeError(MessageTemplate::kConstructorNotFunction,
158 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
167 options, isolate->factory()->max_byte_length_string(), isolate));
169 if (!IsUndefined(*max_length, isolate)) {
170 if (*target == target->native_context()->array_buffer_fun()) {
180 return ConstructBuffer(isolate, target,
new_target, number_length,
187BUILTIN(ArrayBufferConstructor_DoNotInitialize) {
192 return ConstructBuffer(isolate, target, target, length, {},
197 const char* kMethodName,
bool is_shared) {
211 if (!
is_shared && array_buffer->was_detached()) {
213 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
214 isolate->factory()->NewStringFromAsciiChecked(
220 double const len = array_buffer->GetByteLength();
223 double relative_start;
229 double const first = (relative_start < 0)
230 ? std::max(len + relative_start, 0.0)
231 : std::min(relative_start, len);
236 if (IsUndefined(*
end, isolate)) {
245 double const final_ = (relative_end < 0) ? std::max(len + relative_end, 0.0)
246 : std::min(relative_end, len);
249 double const new_len = std::max(final_ - first, 0.0);
255 is_shared ? isolate->shared_array_buffer_fun()
256 : isolate->array_buffer_fun();
266 constexpr int argc = 1;
267 std::array<DirectHandle<Object>, argc> ctor_args = {new_len_obj};
279 if (!IsJSArrayBuffer(*new_)) {
282 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
283 isolate->factory()->NewStringFromAsciiChecked(kMethodName),
296 if (!
is_shared && new_array_buffer->was_detached()) {
298 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
299 isolate->factory()->NewStringFromAsciiChecked(
306 isolate, NewTypeError(MessageTemplate::kArrayBufferSpeciesThis));
312 new_array_buffer->backing_store() == array_buffer->backing_store()) {
314 isolate, NewTypeError(MessageTemplate::kSharedArrayBufferSpeciesThis));
318 size_t new_array_buffer_byte_length = new_array_buffer->GetByteLength();
319 if (new_array_buffer_byte_length < new_len) {
322 NewTypeError(
is_shared ? MessageTemplate::kSharedArrayBufferTooShort
323 : MessageTemplate::kArrayBufferTooShort));
328 if (!
is_shared && array_buffer->was_detached()) {
330 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
331 isolate->factory()->NewStringFromAsciiChecked(
338 size_t first_size = first;
339 size_t new_len_size = new_len;
340 DCHECK(new_array_buffer_byte_length >= new_len_size);
342 if (new_len_size != 0) {
343 size_t from_byte_length = array_buffer->GetByteLength();
347 if (first_size > from_byte_length) {
350 if (new_len_size > from_byte_length - first_size) {
351 new_len_size = from_byte_length - first_size;
354 DCHECK(first_size <= from_byte_length);
355 DCHECK(from_byte_length - first_size >= new_len_size);
357 reinterpret_cast<uint8_t*
>(array_buffer->backing_store()) + first_size;
359 reinterpret_cast<uint8_t*
>(new_array_buffer->backing_store());
365 CopyBytes(to_data, from_data, new_len_size);
374 const char*
const kMethodName =
"SharedArrayBuffer.prototype.slice";
381 const char*
const kMethodName =
"ArrayBuffer.prototype.slice";
386 const char* kMethodName,
bool is_shared) {
405 if (!
is_shared && array_buffer->was_detached()) {
407 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
408 isolate->factory()->NewStringFromAsciiChecked(
417 size_t new_byte_length;
420 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferResizeLength,
421 isolate->factory()->NewStringFromAsciiChecked(
425 if (
is_shared && new_byte_length < array_buffer->GetByteLength()) {
428 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferResizeLength,
429 isolate->factory()->NewStringFromAsciiChecked(
433 if (new_byte_length > array_buffer->max_byte_length()) {
435 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferResizeLength,
436 isolate->factory()->NewStringFromAsciiChecked(
444#ifdef V8_ENABLE_WEBASSEMBLY
445 auto backing_store = array_buffer->GetBackingStore();
446 if (backing_store->is_wasm_memory()) {
447 size_t old_byte_length =
448 backing_store->byte_length(std::memory_order_seq_cst);
451 if (new_byte_length < old_byte_length ||
456 MessageTemplate::kInvalidArrayBufferResizeLength,
457 isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
461 isolate, array_buffer,
462 isolate->factory()->array_buffer_wasm_memory_symbol())
464 CHECK(IsWasmMemoryObject(*memory));
467 uint32_t delta_pages =
468 static_cast<uint32_t
>(new_byte_length - old_byte_length) /
471 delta_pages) == -1) {
473 isolate, NewRangeError(MessageTemplate::kOutOfMemory,
474 isolate->factory()->NewStringFromAsciiChecked(
489 if (array_buffer->GetBackingStore()->ResizeInPlace(isolate,
493 isolate, NewRangeError(MessageTemplate::kOutOfMemory,
494 isolate->factory()->NewStringFromAsciiChecked(
500 if (new_byte_length < array_buffer->byte_length()) {
501 if (Protectors::IsArrayBufferDetachingIntact(isolate)) {
502 Protectors::InvalidateArrayBufferDetaching(isolate);
506 isolate->heap()->ResizeArrayBufferExtension(
507 array_buffer->extension(),
508 static_cast<int64_t
>(new_byte_length) - array_buffer->byte_length());
511 array_buffer->set_byte_length(new_byte_length);
515 array_buffer->GetBackingStore()->GrowInPlace(isolate, new_byte_length);
518 isolate, NewRangeError(MessageTemplate::kOutOfMemory,
519 isolate->factory()->NewStringFromAsciiChecked(
526 MessageTemplate::kInvalidArrayBufferResizeLength,
527 isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
532 CHECK_EQ(0, array_buffer->byte_length_unchecked());
539BUILTIN(SharedArrayBufferPrototypeGetByteLength) {
540 const char*
const kMethodName =
"get SharedArrayBuffer.prototype.byteLength";
548 DCHECK_IMPLIES(!array_buffer->GetBackingStore()->is_wasm_memory(),
549 array_buffer->max_byte_length() ==
550 array_buffer->GetBackingStore()->max_byte_length());
553 size_t byte_length = array_buffer->GetByteLength();
555 return *isolate->factory()->NewNumberFromSize(byte_length);
561 const char*
const kMethodName =
"ArrayBuffer.prototype.resize";
562 constexpr bool kIsShared =
false;
568enum PreserveResizability { kToFixedLength, kPreserveResizability };
571 DirectHandle<JSArrayBuffer> array_buffer,
573 PreserveResizability preserve_resizability,
574 const char* method_name) {
575 size_t max_allocatable =
576 isolate->array_buffer_allocator()->MaxAllocationSize();
582 size_t new_byte_length;
586 new_byte_length = array_buffer->GetByteLength();
590 DirectHandle<Object> number_new_byte_length;
595 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
598 new_byte_length > max_allocatable) {
602 MessageTemplate::kInvalidArrayBufferResizeLength,
603 isolate->factory()->NewStringFromAsciiChecked(method_name)));
608 if (array_buffer->was_detached()) {
610 isolate, NewTypeError(MessageTemplate::kDetachedOperation,
611 isolate->factory()->NewStringFromAsciiChecked(
616 size_t new_max_byte_length;
617 if (preserve_resizability == kPreserveResizability &&
618 array_buffer->is_resizable_by_js()) {
622 new_max_byte_length = array_buffer->max_byte_length();
627 new_max_byte_length = new_byte_length;
634 if (!array_buffer->is_detachable()) {
637 NewTypeError(MessageTemplate::kDataCloneErrorNonDetachableArrayBuffer));
644 if (new_byte_length == 0) {
654 return *isolate->factory()
655 ->NewJSArrayBufferAndBackingStore(
662 auto from_backing_store = array_buffer->GetBackingStore();
663 if (from_backing_store && !from_backing_store->is_resizable_by_js() &&
665 new_byte_length == array_buffer->GetByteLength()) {
677 return *isolate->factory()->NewJSArrayBuffer(std::move(from_backing_store));
682 if (new_byte_length > new_max_byte_length) {
684 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
689 DirectHandle<JSArrayBuffer> new_buffer;
690 MaybeDirectHandle<JSArrayBuffer>
result =
691 isolate->factory()->NewJSArrayBufferAndBackingStore(
694 if (!
result.ToHandle(&new_buffer)) {
696 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
706 reinterpret_cast<uint8_t*
>(array_buffer->backing_store());
709 uint8_t* to_data =
reinterpret_cast<uint8_t*
>(new_buffer->backing_store());
715 size_t from_byte_length = array_buffer->GetByteLength();
716 if (new_byte_length <= from_byte_length) {
717 CopyBytes(to_data, from_data, new_byte_length);
719 CopyBytes(to_data, from_data, from_byte_length);
720 memset(to_data + from_byte_length, 0, new_byte_length - from_byte_length);
735 const char kMethodName[] =
"ArrayBuffer.prototype.transfer";
742 return ArrayBufferTransfer(isolate, array_buffer,
new_length,
743 kPreserveResizability, kMethodName);
748BUILTIN(ArrayBufferPrototypeTransferToFixedLength) {
749 const char kMethodName[] =
"ArrayBuffer.prototype.transferToFixedLength";
756 return ArrayBufferTransfer(isolate, array_buffer,
new_length, kToFixedLength,
763 const char*
const kMethodName =
"SharedArrayBuffer.prototype.grow";
764 constexpr bool kIsShared =
true;
#define CHECK_RESIZABLE(expected, name, method)
#define CHECK_SHARED(expected, name, method)
#define CHECK_RECEIVER(Type, name, method)
@ kGrowableSharedArrayBuffer
static std::unique_ptr< BackingStore > TryAllocateAndPartiallyCommitMemory(Isolate *isolate, size_t byte_length, size_t max_byte_length, size_t page_size, size_t initial_pages, size_t maximum_pages, WasmMemoryFlag wasm_memory, SharedFlag shared, bool has_guard_regions=false)
static std::unique_ptr< BackingStore > Allocate(Isolate *isolate, size_t byte_length, SharedFlag shared, InitializedFlag initialized)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSReceiver > New(Isolate *isolate, DirectHandle< Object > constructor, base::Vector< const DirectHandle< Object > > args)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > Detach(DirectHandle< JSArrayBuffer > buffer, bool force_for_wasm_memory=false, DirectHandle< Object > key={})
static constexpr size_t kMaxByteLength
static std::optional< MessageTemplate > GetResizableBackingStorePageConfigurationImpl(Isolate *isolate, size_t byte_length, size_t max_byte_length, size_t *page_size, size_t *initial_pages, size_t *max_pages)
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< JSObject > New(DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target, DirectHandle< AllocationSite > site, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
static MaybeDirectHandle< Object > ReadFromOptionsBag(DirectHandle< Object > options, DirectHandle< String > option_name, Isolate *isolate)
static constexpr size_t kMaxByteLength
static V8_WARN_UNUSED_RESULT HandleType< Number >::MaybeType ToInteger(Isolate *isolate, HandleType< T > input)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT Maybe< double > IntegerValue(Isolate *isolate, HandleType< T > input)
static V8_EXPORT_PRIVATE bool SameValue(Tagged< Object > obj, Tagged< Object > other)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > SpeciesConstructor(Isolate *isolate, DirectHandle< JSReceiver > recv, DirectHandle< JSFunction > default_ctor)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
static V8_EXPORT_PRIVATE int32_t Grow(Isolate *, DirectHandle< WasmMemoryObject >, uint32_t pages)
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
#define MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
base::Vector< const DirectHandle< Object > > args
DirectHandle< Object > new_target
ZoneVector< RpoNumber > & result
void Relaxed_Memcpy(volatile Atomic8 *dst, volatile const Atomic8 *src, size_t bytes)
constexpr Vector< T > VectorOf(T *start, size_t size)
constexpr size_t kWasmPageSize
void CopyBytes(T *dst, const T *src, size_t num_bytes)
static Tagged< Object > SliceHelper(BuiltinArguments args, Isolate *isolate, const char *kMethodName, bool is_shared)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
JSArrayBuffer::IsDetachableBit is_shared
bool TryNumberToSize(Tagged< Object > number, size_t *result)
static Tagged< Object > ResizeHelper(BuiltinArguments args, Isolate *isolate, const char *kMethodName, bool is_shared)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define DCHECK_IMPLIES(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define V8_UNLIKELY(condition)