11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-inl.h"
61cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h"
71cb0ef41Sopenharmony_ci#include "src/handles/maybe-handles-inl.h"
81cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"  // For ToBoolean. TODO(jkummerow): Drop.
91cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
101cb0ef41Sopenharmony_ci#include "src/numbers/conversions.h"
111cb0ef41Sopenharmony_ci#include "src/objects/js-array-buffer-inl.h"
121cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8 {
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci#define CHECK_SHARED(expected, name, method)                                \
181cb0ef41Sopenharmony_ci  if (name->is_shared() != expected) {                                      \
191cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(                                         \
201cb0ef41Sopenharmony_ci        isolate,                                                            \
211cb0ef41Sopenharmony_ci        NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,          \
221cb0ef41Sopenharmony_ci                     isolate->factory()->NewStringFromAsciiChecked(method), \
231cb0ef41Sopenharmony_ci                     name));                                                \
241cb0ef41Sopenharmony_ci  }
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci#define CHECK_RESIZABLE(expected, name, method)                             \
271cb0ef41Sopenharmony_ci  if (name->is_resizable() != expected) {                                   \
281cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(                                         \
291cb0ef41Sopenharmony_ci        isolate,                                                            \
301cb0ef41Sopenharmony_ci        NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,          \
311cb0ef41Sopenharmony_ci                     isolate->factory()->NewStringFromAsciiChecked(method), \
321cb0ef41Sopenharmony_ci                     name));                                                \
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
361cb0ef41Sopenharmony_ci// ES#sec-arraybuffer-objects
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cinamespace {
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciObject ConstructBuffer(Isolate* isolate, Handle<JSFunction> target,
411cb0ef41Sopenharmony_ci                       Handle<JSReceiver> new_target, Handle<Object> length,
421cb0ef41Sopenharmony_ci                       Handle<Object> max_length, InitializedFlag initialized) {
431cb0ef41Sopenharmony_ci  SharedFlag shared = *target != target->native_context().array_buffer_fun()
441cb0ef41Sopenharmony_ci                          ? SharedFlag::kShared
451cb0ef41Sopenharmony_ci                          : SharedFlag::kNotShared;
461cb0ef41Sopenharmony_ci  ResizableFlag resizable = max_length.is_null() ? ResizableFlag::kNotResizable
471cb0ef41Sopenharmony_ci                                                 : ResizableFlag::kResizable;
481cb0ef41Sopenharmony_ci  Handle<JSObject> result;
491cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
501cb0ef41Sopenharmony_ci      isolate, result,
511cb0ef41Sopenharmony_ci      JSObject::New(target, new_target, Handle<AllocationSite>::null()));
521cb0ef41Sopenharmony_ci  auto array_buffer = Handle<JSArrayBuffer>::cast(result);
531cb0ef41Sopenharmony_ci  // Ensure that all fields are initialized because BackingStore::Allocate is
541cb0ef41Sopenharmony_ci  // allowed to GC. Note that we cannot move the allocation of the ArrayBuffer
551cb0ef41Sopenharmony_ci  // after BackingStore::Allocate because of the spec.
561cb0ef41Sopenharmony_ci  array_buffer->Setup(shared, resizable, nullptr);
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  size_t byte_length;
591cb0ef41Sopenharmony_ci  size_t max_byte_length = 0;
601cb0ef41Sopenharmony_ci  if (!TryNumberToSize(*length, &byte_length) ||
611cb0ef41Sopenharmony_ci      byte_length > JSArrayBuffer::kMaxByteLength) {
621cb0ef41Sopenharmony_ci    // ToNumber failed.
631cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
641cb0ef41Sopenharmony_ci        isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> backing_store;
681cb0ef41Sopenharmony_ci  if (resizable == ResizableFlag::kNotResizable) {
691cb0ef41Sopenharmony_ci    backing_store =
701cb0ef41Sopenharmony_ci        BackingStore::Allocate(isolate, byte_length, shared, initialized);
711cb0ef41Sopenharmony_ci    max_byte_length = byte_length;
721cb0ef41Sopenharmony_ci  } else {
731cb0ef41Sopenharmony_ci    if (!TryNumberToSize(*max_length, &max_byte_length)) {
741cb0ef41Sopenharmony_ci      THROW_NEW_ERROR_RETURN_FAILURE(
751cb0ef41Sopenharmony_ci          isolate,
761cb0ef41Sopenharmony_ci          NewRangeError(MessageTemplate::kInvalidArrayBufferMaxLength));
771cb0ef41Sopenharmony_ci    }
781cb0ef41Sopenharmony_ci    if (byte_length > max_byte_length) {
791cb0ef41Sopenharmony_ci      THROW_NEW_ERROR_RETURN_FAILURE(
801cb0ef41Sopenharmony_ci          isolate,
811cb0ef41Sopenharmony_ci          NewRangeError(MessageTemplate::kInvalidArrayBufferMaxLength));
821cb0ef41Sopenharmony_ci    }
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci    size_t page_size, initial_pages, max_pages;
851cb0ef41Sopenharmony_ci    MAYBE_RETURN(JSArrayBuffer::GetResizableBackingStorePageConfiguration(
861cb0ef41Sopenharmony_ci                     isolate, byte_length, max_byte_length, kThrowOnError,
871cb0ef41Sopenharmony_ci                     &page_size, &initial_pages, &max_pages),
881cb0ef41Sopenharmony_ci                 ReadOnlyRoots(isolate).exception());
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci    constexpr bool kIsWasmMemory = false;
911cb0ef41Sopenharmony_ci    backing_store = BackingStore::TryAllocateAndPartiallyCommitMemory(
921cb0ef41Sopenharmony_ci        isolate, byte_length, max_byte_length, page_size, initial_pages,
931cb0ef41Sopenharmony_ci        max_pages, kIsWasmMemory, shared);
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci  if (!backing_store) {
961cb0ef41Sopenharmony_ci    // Allocation of backing store failed.
971cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
981cb0ef41Sopenharmony_ci        isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  array_buffer->Attach(std::move(backing_store));
1021cb0ef41Sopenharmony_ci  array_buffer->set_max_byte_length(max_byte_length);
1031cb0ef41Sopenharmony_ci  return *array_buffer;
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci}  // namespace
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci// ES #sec-arraybuffer-constructor
1091cb0ef41Sopenharmony_ciBUILTIN(ArrayBufferConstructor) {
1101cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1111cb0ef41Sopenharmony_ci  Handle<JSFunction> target = args.target();
1121cb0ef41Sopenharmony_ci  DCHECK(*target == target->native_context().array_buffer_fun() ||
1131cb0ef41Sopenharmony_ci         *target == target->native_context().shared_array_buffer_fun());
1141cb0ef41Sopenharmony_ci  if (args.new_target()->IsUndefined(isolate)) {  // [[Call]]
1151cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
1161cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
1171cb0ef41Sopenharmony_ci                              handle(target->shared().Name(), isolate)));
1181cb0ef41Sopenharmony_ci  }
1191cb0ef41Sopenharmony_ci  // [[Construct]]
1201cb0ef41Sopenharmony_ci  Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
1211cb0ef41Sopenharmony_ci  Handle<Object> length = args.atOrUndefined(isolate, 1);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  Handle<Object> number_length;
1241cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
1251cb0ef41Sopenharmony_ci                                     Object::ToInteger(isolate, length));
1261cb0ef41Sopenharmony_ci  if (number_length->Number() < 0.0) {
1271cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
1281cb0ef41Sopenharmony_ci        isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  Handle<Object> number_max_length;
1321cb0ef41Sopenharmony_ci  if (FLAG_harmony_rab_gsab) {
1331cb0ef41Sopenharmony_ci    Handle<Object> max_length;
1341cb0ef41Sopenharmony_ci    Handle<Object> options = args.atOrUndefined(isolate, 2);
1351cb0ef41Sopenharmony_ci    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1361cb0ef41Sopenharmony_ci        isolate, max_length,
1371cb0ef41Sopenharmony_ci        JSObject::ReadFromOptionsBag(
1381cb0ef41Sopenharmony_ci            options, isolate->factory()->max_byte_length_string(), isolate));
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci    if (!max_length->IsUndefined(isolate)) {
1411cb0ef41Sopenharmony_ci      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1421cb0ef41Sopenharmony_ci          isolate, number_max_length, Object::ToInteger(isolate, max_length));
1431cb0ef41Sopenharmony_ci    }
1441cb0ef41Sopenharmony_ci  }
1451cb0ef41Sopenharmony_ci  return ConstructBuffer(isolate, target, new_target, number_length,
1461cb0ef41Sopenharmony_ci                         number_max_length, InitializedFlag::kZeroInitialized);
1471cb0ef41Sopenharmony_ci}
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci// This is a helper to construct an ArrayBuffer with uinitialized memory.
1501cb0ef41Sopenharmony_ci// This means the caller must ensure the buffer is totally initialized in
1511cb0ef41Sopenharmony_ci// all cases, or we will expose uinitialized memory to user code.
1521cb0ef41Sopenharmony_ciBUILTIN(ArrayBufferConstructor_DoNotInitialize) {
1531cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1541cb0ef41Sopenharmony_ci  Handle<JSFunction> target(isolate->native_context()->array_buffer_fun(),
1551cb0ef41Sopenharmony_ci                            isolate);
1561cb0ef41Sopenharmony_ci  Handle<Object> length = args.atOrUndefined(isolate, 1);
1571cb0ef41Sopenharmony_ci  return ConstructBuffer(isolate, target, target, length, Handle<Object>(),
1581cb0ef41Sopenharmony_ci                         InitializedFlag::kUninitialized);
1591cb0ef41Sopenharmony_ci}
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_cistatic Object SliceHelper(BuiltinArguments args, Isolate* isolate,
1621cb0ef41Sopenharmony_ci                          const char* kMethodName, bool is_shared) {
1631cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
1641cb0ef41Sopenharmony_ci  Handle<Object> start = args.at(1);
1651cb0ef41Sopenharmony_ci  Handle<Object> end = args.atOrUndefined(isolate, 2);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  // * If Type(O) is not Object, throw a TypeError exception.
1681cb0ef41Sopenharmony_ci  // * If O does not have an [[ArrayBufferData]] internal slot, throw a
1691cb0ef41Sopenharmony_ci  //   TypeError exception.
1701cb0ef41Sopenharmony_ci  CHECK_RECEIVER(JSArrayBuffer, array_buffer, kMethodName);
1711cb0ef41Sopenharmony_ci  // * [AB] If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
1721cb0ef41Sopenharmony_ci  // * [SAB] If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
1731cb0ef41Sopenharmony_ci  CHECK_SHARED(is_shared, array_buffer, kMethodName);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // * [AB] If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
1761cb0ef41Sopenharmony_ci  if (!is_shared && array_buffer->was_detached()) {
1771cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
1781cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kDetachedOperation,
1791cb0ef41Sopenharmony_ci                              isolate->factory()->NewStringFromAsciiChecked(
1801cb0ef41Sopenharmony_ci                                  kMethodName)));
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  // * [AB] Let len be O.[[ArrayBufferByteLength]].
1841cb0ef41Sopenharmony_ci  // * [SAB] Let len be O.[[ArrayBufferByteLength]].
1851cb0ef41Sopenharmony_ci  double const len = array_buffer->GetByteLength();
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  // * Let relativeStart be ? ToInteger(start).
1881cb0ef41Sopenharmony_ci  Handle<Object> relative_start;
1891cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, relative_start,
1901cb0ef41Sopenharmony_ci                                     Object::ToInteger(isolate, start));
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  // * If relativeStart < 0, let first be max((len + relativeStart), 0); else
1931cb0ef41Sopenharmony_ci  //   let first be min(relativeStart, len).
1941cb0ef41Sopenharmony_ci  double const first = (relative_start->Number() < 0)
1951cb0ef41Sopenharmony_ci                           ? std::max(len + relative_start->Number(), 0.0)
1961cb0ef41Sopenharmony_ci                           : std::min(relative_start->Number(), len);
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  // * If end is undefined, let relativeEnd be len; else let relativeEnd be ?
1991cb0ef41Sopenharmony_ci  //   ToInteger(end).
2001cb0ef41Sopenharmony_ci  double relative_end;
2011cb0ef41Sopenharmony_ci  if (end->IsUndefined(isolate)) {
2021cb0ef41Sopenharmony_ci    relative_end = len;
2031cb0ef41Sopenharmony_ci  } else {
2041cb0ef41Sopenharmony_ci    Handle<Object> relative_end_obj;
2051cb0ef41Sopenharmony_ci    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, relative_end_obj,
2061cb0ef41Sopenharmony_ci                                       Object::ToInteger(isolate, end));
2071cb0ef41Sopenharmony_ci    relative_end = relative_end_obj->Number();
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci  // * If relativeEnd < 0, let final be max((len + relativeEnd), 0); else let
2111cb0ef41Sopenharmony_ci  //   final be min(relativeEnd, len).
2121cb0ef41Sopenharmony_ci  double const final_ = (relative_end < 0) ? std::max(len + relative_end, 0.0)
2131cb0ef41Sopenharmony_ci                                           : std::min(relative_end, len);
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  // * Let newLen be max(final-first, 0).
2161cb0ef41Sopenharmony_ci  double const new_len = std::max(final_ - first, 0.0);
2171cb0ef41Sopenharmony_ci  Handle<Object> new_len_obj = isolate->factory()->NewNumber(new_len);
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  // * [AB] Let ctor be ? SpeciesConstructor(O, %ArrayBuffer%).
2201cb0ef41Sopenharmony_ci  // * [SAB] Let ctor be ? SpeciesConstructor(O, %SharedArrayBuffer%).
2211cb0ef41Sopenharmony_ci  Handle<JSFunction> constructor_fun = is_shared
2221cb0ef41Sopenharmony_ci                                           ? isolate->shared_array_buffer_fun()
2231cb0ef41Sopenharmony_ci                                           : isolate->array_buffer_fun();
2241cb0ef41Sopenharmony_ci  Handle<Object> ctor;
2251cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2261cb0ef41Sopenharmony_ci      isolate, ctor,
2271cb0ef41Sopenharmony_ci      Object::SpeciesConstructor(
2281cb0ef41Sopenharmony_ci          isolate, Handle<JSReceiver>::cast(args.receiver()), constructor_fun));
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  // * Let new be ? Construct(ctor, newLen).
2311cb0ef41Sopenharmony_ci  Handle<JSReceiver> new_;
2321cb0ef41Sopenharmony_ci  {
2331cb0ef41Sopenharmony_ci    const int argc = 1;
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci    base::ScopedVector<Handle<Object>> argv(argc);
2361cb0ef41Sopenharmony_ci    argv[0] = new_len_obj;
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci    Handle<Object> new_obj;
2391cb0ef41Sopenharmony_ci    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2401cb0ef41Sopenharmony_ci        isolate, new_obj, Execution::New(isolate, ctor, argc, argv.begin()));
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci    new_ = Handle<JSReceiver>::cast(new_obj);
2431cb0ef41Sopenharmony_ci  }
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  // * If new does not have an [[ArrayBufferData]] internal slot, throw a
2461cb0ef41Sopenharmony_ci  //   TypeError exception.
2471cb0ef41Sopenharmony_ci  if (!new_->IsJSArrayBuffer()) {
2481cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
2491cb0ef41Sopenharmony_ci        isolate,
2501cb0ef41Sopenharmony_ci        NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
2511cb0ef41Sopenharmony_ci                     isolate->factory()->NewStringFromAsciiChecked(kMethodName),
2521cb0ef41Sopenharmony_ci                     new_));
2531cb0ef41Sopenharmony_ci  }
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  // * [AB] If IsSharedArrayBuffer(new) is true, throw a TypeError exception.
2561cb0ef41Sopenharmony_ci  // * [SAB] If IsSharedArrayBuffer(new) is false, throw a TypeError exception.
2571cb0ef41Sopenharmony_ci  Handle<JSArrayBuffer> new_array_buffer = Handle<JSArrayBuffer>::cast(new_);
2581cb0ef41Sopenharmony_ci  CHECK_SHARED(is_shared, new_array_buffer, kMethodName);
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  // The created ArrayBuffer might or might not be resizable, since the species
2611cb0ef41Sopenharmony_ci  // constructor might return a non-resizable or a resizable buffer.
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  // * [AB] If IsDetachedBuffer(new) is true, throw a TypeError exception.
2641cb0ef41Sopenharmony_ci  if (!is_shared && new_array_buffer->was_detached()) {
2651cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
2661cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kDetachedOperation,
2671cb0ef41Sopenharmony_ci                              isolate->factory()->NewStringFromAsciiChecked(
2681cb0ef41Sopenharmony_ci                                  kMethodName)));
2691cb0ef41Sopenharmony_ci  }
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  // * [AB] If SameValue(new, O) is true, throw a TypeError exception.
2721cb0ef41Sopenharmony_ci  if (!is_shared && new_->SameValue(*args.receiver())) {
2731cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
2741cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kArrayBufferSpeciesThis));
2751cb0ef41Sopenharmony_ci  }
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  // * [SAB] If new.[[ArrayBufferData]] and O.[[ArrayBufferData]] are the same
2781cb0ef41Sopenharmony_ci  //         Shared Data Block values, throw a TypeError exception.
2791cb0ef41Sopenharmony_ci  if (is_shared &&
2801cb0ef41Sopenharmony_ci      new_array_buffer->backing_store() == array_buffer->backing_store()) {
2811cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
2821cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kSharedArrayBufferSpeciesThis));
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  // * If new.[[ArrayBufferByteLength]] < newLen, throw a TypeError exception.
2861cb0ef41Sopenharmony_ci  size_t new_array_buffer_byte_length = new_array_buffer->GetByteLength();
2871cb0ef41Sopenharmony_ci  if (new_array_buffer_byte_length < new_len) {
2881cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
2891cb0ef41Sopenharmony_ci        isolate,
2901cb0ef41Sopenharmony_ci        NewTypeError(is_shared ? MessageTemplate::kSharedArrayBufferTooShort
2911cb0ef41Sopenharmony_ci                               : MessageTemplate::kArrayBufferTooShort));
2921cb0ef41Sopenharmony_ci  }
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci  // * [AB] NOTE: Side-effects of the above steps may have detached O.
2951cb0ef41Sopenharmony_ci  // * [AB] If IsDetachedBuffer(O) is true, throw a TypeError exception.
2961cb0ef41Sopenharmony_ci  if (!is_shared && array_buffer->was_detached()) {
2971cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
2981cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kDetachedOperation,
2991cb0ef41Sopenharmony_ci                              isolate->factory()->NewStringFromAsciiChecked(
3001cb0ef41Sopenharmony_ci                                  kMethodName)));
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  // * Let fromBuf be O.[[ArrayBufferData]].
3041cb0ef41Sopenharmony_ci  // * Let toBuf be new.[[ArrayBufferData]].
3051cb0ef41Sopenharmony_ci  // * Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen).
3061cb0ef41Sopenharmony_ci  size_t first_size = first;
3071cb0ef41Sopenharmony_ci  size_t new_len_size = new_len;
3081cb0ef41Sopenharmony_ci  DCHECK(new_array_buffer_byte_length >= new_len_size);
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci  if (new_len_size != 0) {
3111cb0ef41Sopenharmony_ci    size_t from_byte_length = array_buffer->GetByteLength();
3121cb0ef41Sopenharmony_ci    if (V8_UNLIKELY(!is_shared && array_buffer->is_resizable())) {
3131cb0ef41Sopenharmony_ci      // The above steps might have resized the underlying buffer. In that case,
3141cb0ef41Sopenharmony_ci      // only copy the still-accessible portion of the underlying data.
3151cb0ef41Sopenharmony_ci      if (first_size > from_byte_length) {
3161cb0ef41Sopenharmony_ci        return *new_;  // Nothing to copy.
3171cb0ef41Sopenharmony_ci      }
3181cb0ef41Sopenharmony_ci      if (new_len_size > from_byte_length - first_size) {
3191cb0ef41Sopenharmony_ci        new_len_size = from_byte_length - first_size;
3201cb0ef41Sopenharmony_ci      }
3211cb0ef41Sopenharmony_ci    }
3221cb0ef41Sopenharmony_ci    DCHECK(first_size <= from_byte_length);
3231cb0ef41Sopenharmony_ci    DCHECK(from_byte_length - first_size >= new_len_size);
3241cb0ef41Sopenharmony_ci    uint8_t* from_data =
3251cb0ef41Sopenharmony_ci        reinterpret_cast<uint8_t*>(array_buffer->backing_store()) + first_size;
3261cb0ef41Sopenharmony_ci    uint8_t* to_data =
3271cb0ef41Sopenharmony_ci        reinterpret_cast<uint8_t*>(new_array_buffer->backing_store());
3281cb0ef41Sopenharmony_ci    if (is_shared) {
3291cb0ef41Sopenharmony_ci      base::Relaxed_Memcpy(reinterpret_cast<base::Atomic8*>(to_data),
3301cb0ef41Sopenharmony_ci                           reinterpret_cast<base::Atomic8*>(from_data),
3311cb0ef41Sopenharmony_ci                           new_len_size);
3321cb0ef41Sopenharmony_ci    } else {
3331cb0ef41Sopenharmony_ci      CopyBytes(to_data, from_data, new_len_size);
3341cb0ef41Sopenharmony_ci    }
3351cb0ef41Sopenharmony_ci  }
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  return *new_;
3381cb0ef41Sopenharmony_ci}
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci// ES #sec-sharedarraybuffer.prototype.slice
3411cb0ef41Sopenharmony_ciBUILTIN(SharedArrayBufferPrototypeSlice) {
3421cb0ef41Sopenharmony_ci  const char* const kMethodName = "SharedArrayBuffer.prototype.slice";
3431cb0ef41Sopenharmony_ci  return SliceHelper(args, isolate, kMethodName, true);
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci// ES #sec-arraybuffer.prototype.slice
3471cb0ef41Sopenharmony_ci// ArrayBuffer.prototype.slice ( start, end )
3481cb0ef41Sopenharmony_ciBUILTIN(ArrayBufferPrototypeSlice) {
3491cb0ef41Sopenharmony_ci  const char* const kMethodName = "ArrayBuffer.prototype.slice";
3501cb0ef41Sopenharmony_ci  return SliceHelper(args, isolate, kMethodName, false);
3511cb0ef41Sopenharmony_ci}
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_cistatic Object ResizeHelper(BuiltinArguments args, Isolate* isolate,
3541cb0ef41Sopenharmony_ci                           const char* kMethodName, bool is_shared) {
3551cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci  // 1 Let O be the this value.
3581cb0ef41Sopenharmony_ci  // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
3591cb0ef41Sopenharmony_ci  CHECK_RECEIVER(JSArrayBuffer, array_buffer, kMethodName);
3601cb0ef41Sopenharmony_ci  CHECK_RESIZABLE(true, array_buffer, kMethodName);
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  // [RAB] 3. If IsSharedArrayBuffer(O) is true, throw a *TypeError* exception
3631cb0ef41Sopenharmony_ci  // [GSAB] 3. If IsSharedArrayBuffer(O) is false, throw a *TypeError* exception
3641cb0ef41Sopenharmony_ci  CHECK_SHARED(is_shared, array_buffer, kMethodName);
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  // Let newByteLength to ? ToIntegerOrInfinity(newLength).
3671cb0ef41Sopenharmony_ci  Handle<Object> new_length = args.at(1);
3681cb0ef41Sopenharmony_ci  Handle<Object> number_new_byte_length;
3691cb0ef41Sopenharmony_ci  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_new_byte_length,
3701cb0ef41Sopenharmony_ci                                     Object::ToInteger(isolate, new_length));
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci  // [RAB] If IsDetachedBuffer(O) is true, throw a TypeError exception.
3731cb0ef41Sopenharmony_ci  if (!is_shared && array_buffer->was_detached()) {
3741cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
3751cb0ef41Sopenharmony_ci        isolate, NewTypeError(MessageTemplate::kDetachedOperation,
3761cb0ef41Sopenharmony_ci                              isolate->factory()->NewStringFromAsciiChecked(
3771cb0ef41Sopenharmony_ci                                  kMethodName)));
3781cb0ef41Sopenharmony_ci  }
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci  // [RAB] If newByteLength < 0 or newByteLength >
3811cb0ef41Sopenharmony_ci  // O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci  // [GSAB] If newByteLength < currentByteLength or newByteLength >
3841cb0ef41Sopenharmony_ci  // O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
3851cb0ef41Sopenharmony_ci  size_t new_byte_length;
3861cb0ef41Sopenharmony_ci  if (!TryNumberToSize(*number_new_byte_length, &new_byte_length)) {
3871cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
3881cb0ef41Sopenharmony_ci        isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferResizeLength,
3891cb0ef41Sopenharmony_ci                               isolate->factory()->NewStringFromAsciiChecked(
3901cb0ef41Sopenharmony_ci                                   kMethodName)));
3911cb0ef41Sopenharmony_ci  }
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci  if (is_shared && new_byte_length < array_buffer->byte_length()) {
3941cb0ef41Sopenharmony_ci    // GrowableSharedArrayBuffer is only allowed to grow.
3951cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
3961cb0ef41Sopenharmony_ci        isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferResizeLength,
3971cb0ef41Sopenharmony_ci                               isolate->factory()->NewStringFromAsciiChecked(
3981cb0ef41Sopenharmony_ci                                   kMethodName)));
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci  if (new_byte_length > array_buffer->max_byte_length()) {
4021cb0ef41Sopenharmony_ci    THROW_NEW_ERROR_RETURN_FAILURE(
4031cb0ef41Sopenharmony_ci        isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferResizeLength,
4041cb0ef41Sopenharmony_ci                               isolate->factory()->NewStringFromAsciiChecked(
4051cb0ef41Sopenharmony_ci                                   kMethodName)));
4061cb0ef41Sopenharmony_ci  }
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  size_t page_size = AllocatePageSize();
4091cb0ef41Sopenharmony_ci  size_t new_committed_pages;
4101cb0ef41Sopenharmony_ci  bool round_return_value =
4111cb0ef41Sopenharmony_ci      RoundUpToPageSize(new_byte_length, page_size,
4121cb0ef41Sopenharmony_ci                        JSArrayBuffer::kMaxByteLength, &new_committed_pages);
4131cb0ef41Sopenharmony_ci  CHECK(round_return_value);
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci  // [RAB] Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
4161cb0ef41Sopenharmony_ci  // [GSAB] Let hostHandled be ? HostGrowArrayBuffer(O, newByteLength).
4171cb0ef41Sopenharmony_ci  // If hostHandled is handled, return undefined.
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci  // TODO(v8:11111, v8:12746): Wasm integration.
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci  if (!is_shared) {
4221cb0ef41Sopenharmony_ci    // [RAB] Let oldBlock be O.[[ArrayBufferData]].
4231cb0ef41Sopenharmony_ci    // [RAB] Let newBlock be ? CreateByteDataBlock(newByteLength).
4241cb0ef41Sopenharmony_ci    // [RAB] Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
4251cb0ef41Sopenharmony_ci    // [RAB] Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
4261cb0ef41Sopenharmony_ci    // [RAB] NOTE: Neither creation of the new Data Block nor copying from the
4271cb0ef41Sopenharmony_ci    // old Data Block are observable. Implementations reserve the right to
4281cb0ef41Sopenharmony_ci    // implement this method as in-place growth or shrinkage.
4291cb0ef41Sopenharmony_ci    if (array_buffer->GetBackingStore()->ResizeInPlace(
4301cb0ef41Sopenharmony_ci            isolate, new_byte_length, new_committed_pages * page_size) !=
4311cb0ef41Sopenharmony_ci        BackingStore::ResizeOrGrowResult::kSuccess) {
4321cb0ef41Sopenharmony_ci      THROW_NEW_ERROR_RETURN_FAILURE(
4331cb0ef41Sopenharmony_ci          isolate, NewRangeError(MessageTemplate::kOutOfMemory,
4341cb0ef41Sopenharmony_ci                                 isolate->factory()->NewStringFromAsciiChecked(
4351cb0ef41Sopenharmony_ci                                     kMethodName)));
4361cb0ef41Sopenharmony_ci    }
4371cb0ef41Sopenharmony_ci    // [RAB] Set O.[[ArrayBufferByteLength]] to newLength.
4381cb0ef41Sopenharmony_ci    array_buffer->set_byte_length(new_byte_length);
4391cb0ef41Sopenharmony_ci  } else {
4401cb0ef41Sopenharmony_ci    // [GSAB] (Detailed description of the algorithm omitted.)
4411cb0ef41Sopenharmony_ci    auto result = array_buffer->GetBackingStore()->GrowInPlace(
4421cb0ef41Sopenharmony_ci        isolate, new_byte_length, new_committed_pages * page_size);
4431cb0ef41Sopenharmony_ci    if (result == BackingStore::ResizeOrGrowResult::kFailure) {
4441cb0ef41Sopenharmony_ci      THROW_NEW_ERROR_RETURN_FAILURE(
4451cb0ef41Sopenharmony_ci          isolate, NewRangeError(MessageTemplate::kOutOfMemory,
4461cb0ef41Sopenharmony_ci                                 isolate->factory()->NewStringFromAsciiChecked(
4471cb0ef41Sopenharmony_ci                                     kMethodName)));
4481cb0ef41Sopenharmony_ci    }
4491cb0ef41Sopenharmony_ci    if (result == BackingStore::ResizeOrGrowResult::kRace) {
4501cb0ef41Sopenharmony_ci      THROW_NEW_ERROR_RETURN_FAILURE(
4511cb0ef41Sopenharmony_ci          isolate,
4521cb0ef41Sopenharmony_ci          NewRangeError(
4531cb0ef41Sopenharmony_ci              MessageTemplate::kInvalidArrayBufferResizeLength,
4541cb0ef41Sopenharmony_ci              isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
4551cb0ef41Sopenharmony_ci    }
4561cb0ef41Sopenharmony_ci    // Invariant: byte_length for a GSAB is 0 (it needs to be read from the
4571cb0ef41Sopenharmony_ci    // BackingStore).
4581cb0ef41Sopenharmony_ci    CHECK_EQ(0, array_buffer->byte_length());
4591cb0ef41Sopenharmony_ci  }
4601cb0ef41Sopenharmony_ci  return ReadOnlyRoots(isolate).undefined_value();
4611cb0ef41Sopenharmony_ci}
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci// ES #sec-get-sharedarraybuffer.prototype.bytelength
4641cb0ef41Sopenharmony_ci// get SharedArrayBuffer.prototype.byteLength
4651cb0ef41Sopenharmony_ciBUILTIN(SharedArrayBufferPrototypeGetByteLength) {
4661cb0ef41Sopenharmony_ci  const char* const kMethodName = "get SharedArrayBuffer.prototype.byteLength";
4671cb0ef41Sopenharmony_ci  HandleScope scope(isolate);
4681cb0ef41Sopenharmony_ci  // 1. Let O be the this value.
4691cb0ef41Sopenharmony_ci  // 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
4701cb0ef41Sopenharmony_ci  CHECK_RECEIVER(JSArrayBuffer, array_buffer, kMethodName);
4711cb0ef41Sopenharmony_ci  // 3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
4721cb0ef41Sopenharmony_ci  CHECK_SHARED(true, array_buffer, kMethodName);
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci  DCHECK_EQ(array_buffer->max_byte_length(),
4751cb0ef41Sopenharmony_ci            array_buffer->GetBackingStore()->max_byte_length());
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  // 4. Let length be ArrayBufferByteLength(O, SeqCst).
4781cb0ef41Sopenharmony_ci  size_t byte_length = array_buffer->GetByteLength();
4791cb0ef41Sopenharmony_ci  // 5. Return F(length).
4801cb0ef41Sopenharmony_ci  return *isolate->factory()->NewNumberFromSize(byte_length);
4811cb0ef41Sopenharmony_ci}
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci// ES #sec-arraybuffer.prototype.resize
4841cb0ef41Sopenharmony_ci// ArrayBuffer.prototype.resize(new_size))
4851cb0ef41Sopenharmony_ciBUILTIN(ArrayBufferPrototypeResize) {
4861cb0ef41Sopenharmony_ci  const char* const kMethodName = "ArrayBuffer.prototype.resize";
4871cb0ef41Sopenharmony_ci  constexpr bool kIsShared = false;
4881cb0ef41Sopenharmony_ci  return ResizeHelper(args, isolate, kMethodName, kIsShared);
4891cb0ef41Sopenharmony_ci}
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci// ES #sec-sharedarraybuffer.prototype.grow
4921cb0ef41Sopenharmony_ci// SharedArrayBuffer.prototype.grow(new_size))
4931cb0ef41Sopenharmony_ciBUILTIN(SharedArrayBufferPrototypeGrow) {
4941cb0ef41Sopenharmony_ci  const char* const kMethodName = "SharedArrayBuffer.prototype.grow";
4951cb0ef41Sopenharmony_ci  constexpr bool kIsShared = true;
4961cb0ef41Sopenharmony_ci  return ResizeHelper(args, isolate, kMethodName, kIsShared);
4971cb0ef41Sopenharmony_ci}
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci}  // namespace internal
5001cb0ef41Sopenharmony_ci}  // namespace v8
501