// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits>

#include "src/heap/heap-inl.h"
#include "src/logging/counters.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/objects-inl.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-memory.h"
#include "src/wasm/wasm-module.h"

namespace v8 {
namespace internal {
namespace wasm {

namespace {

constexpr size_t kNegativeGuardSize = 1u << 31;  // 2GiB

void AddAllocationStatusSample(Isolate* isolate,
                               WasmMemoryTracker::AllocationStatus status) {
  isolate->counters()->wasm_memory_allocation_result()->AddSample(
      static_cast<int>(status));
}

bool RunWithGCAndRetry(const std::function<bool()>& fn, Heap* heap,
                       bool* did_retry) {
  // Try up to three times; getting rid of dead JSArrayBuffer allocations might
  // require two GCs because the first GC maybe incremental and may have
  // floating garbage.
  static constexpr int kAllocationRetries = 2;

  for (int trial = 0;; ++trial) {
    if (fn()) return true;
    // {fn} failed. If {kAllocationRetries} is reached, fail.
    *did_retry = true;
    if (trial == kAllocationRetries) return false;
    // Otherwise, collect garbage and retry.
    // TODO(wasm): Since reservation limits are engine-wide, we should do an
    // engine-wide GC here (i.e. trigger a GC in each isolate using the engine,
    // and wait for them all to finish). See https://crbug.com/v8/9405.
    heap->MemoryPressureNotification(MemoryPressureLevel::kCritical, true);
  }
}

void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
                              size_t size, size_t max_size,
                              void** allocation_base,
                              size_t* allocation_length) {
  using AllocationStatus = WasmMemoryTracker::AllocationStatus;
#if V8_TARGET_ARCH_64_BIT
  constexpr bool kRequireFullGuardRegions = true;
#else
  constexpr bool kRequireFullGuardRegions = false;
#endif
  // Let the WasmMemoryTracker know we are going to reserve a bunch of
  // address space.
  size_t reservation_size = std::max(max_size, size);
  bool did_retry = false;

  auto reserve_memory_space = [&] {
    // For guard regions, we always allocate the largest possible offset
    // into the heap, so the addressable memory after the guard page can
    // be made inaccessible.
    //
    // To protect against 32-bit integer overflow issues, we also
    // protect the 2GiB before the valid part of the memory buffer.
    *allocation_length =
        kRequireFullGuardRegions
            ? RoundUp(kWasmMaxHeapOffset + kNegativeGuardSize, CommitPageSize())
            : RoundUp(base::bits::RoundUpToPowerOfTwo(reservation_size),
                      kWasmPageSize);
    DCHECK_GE(*allocation_length, size);
    DCHECK_GE(*allocation_length, kWasmPageSize);

    return memory_tracker->ReserveAddressSpace(*allocation_length);
  };
  if (!RunWithGCAndRetry(reserve_memory_space, heap, &did_retry)) {
    // Reset reservation_size to initial size so that at least the initial size
    // can be allocated if maximum size reservation is not possible.
    reservation_size = size;

    // We are over the address space limit. Fail.
    //
    // When running under the correctness fuzzer (i.e.
    // --correctness-fuzzer-suppressions is preset), we crash
    // instead so it is not incorrectly reported as a correctness
    // violation. See https://crbug.com/828293#c4
    if (FLAG_correctness_fuzzer_suppressions) {
      FATAL("could not allocate wasm memory");
    }
    AddAllocationStatusSample(
        heap->isolate(), AllocationStatus::kAddressSpaceLimitReachedFailure);
    return nullptr;
  }

  // The Reserve makes the whole region inaccessible by default.
  DCHECK_NULL(*allocation_base);
  auto allocate_pages = [&] {
    *allocation_base =
        AllocatePages(GetPlatformPageAllocator(), nullptr, *allocation_length,
                      kWasmPageSize, PageAllocator::kNoAccess);
    return *allocation_base != nullptr;
  };
  if (!RunWithGCAndRetry(allocate_pages, heap, &did_retry)) {
    memory_tracker->ReleaseReservation(*allocation_length);
    AddAllocationStatusSample(heap->isolate(), AllocationStatus::kOtherFailure);
    return nullptr;
  }

  byte* memory = reinterpret_cast<byte*>(*allocation_base);
  if (kRequireFullGuardRegions) {
    memory += kNegativeGuardSize;
  }

  // Make the part we care about accessible.
  auto commit_memory = [&] {
    return size == 0 || SetPermissions(GetPlatformPageAllocator(), memory,
                                       RoundUp(size, kWasmPageSize),
                                       PageAllocator::kReadWrite);
  };
  // SetPermissions commits the extra memory, which may put us over the
  // process memory limit. If so, report this as an OOM.
  if (!RunWithGCAndRetry(commit_memory, heap, &did_retry)) {
    V8::FatalProcessOutOfMemory(nullptr, "TryAllocateBackingStore");
  }

  memory_tracker->RegisterAllocation(heap->isolate(), *allocation_base,
                                     *allocation_length, memory, size);
  AddAllocationStatusSample(heap->isolate(),
                            did_retry ? AllocationStatus::kSuccessAfterRetry
                                      : AllocationStatus::kSuccess);
  return memory;
}

#if V8_TARGET_ARCH_MIPS64
// MIPS64 has a user space of 2^40 bytes on most processors,
// address space limits needs to be smaller.
constexpr size_t kAddressSpaceLimit = 0x8000000000L;  // 512 GiB
#elif V8_TARGET_ARCH_64_BIT
constexpr size_t kAddressSpaceLimit = 0x10100000000L;  // 1 TiB + 4 GiB
#else
constexpr size_t kAddressSpaceLimit = 0xC0000000;  // 3 GiB
#endif

}  // namespace

WasmMemoryTracker::~WasmMemoryTracker() {
  // All reserved address space should be released before the allocation tracker
  // is destroyed.
  DCHECK_EQ(reserved_address_space_, 0u);
  DCHECK_EQ(allocated_address_space_, 0u);
  DCHECK(allocations_.empty());
}

void* WasmMemoryTracker::TryAllocateBackingStoreForTesting(
    Heap* heap, size_t size, void** allocation_base,
    size_t* allocation_length) {
  return TryAllocateBackingStore(this, heap, size, size, allocation_base,
                                 allocation_length);
}

void WasmMemoryTracker::FreeBackingStoreForTesting(base::AddressRegion memory,
                                                   void* buffer_start) {
  base::MutexGuard scope_lock(&mutex_);
  ReleaseAllocation_Locked(nullptr, buffer_start);
  CHECK(FreePages(GetPlatformPageAllocator(),
                  reinterpret_cast<void*>(memory.begin()), memory.size()));
}

bool WasmMemoryTracker::ReserveAddressSpace(size_t num_bytes) {
  size_t reservation_limit = kAddressSpaceLimit;
  while (true) {
    size_t old_count = reserved_address_space_.load();
    if (old_count > reservation_limit) return false;
    if (reservation_limit - old_count < num_bytes) return false;
    if (reserved_address_space_.compare_exchange_weak(old_count,
                                                      old_count + num_bytes)) {
      return true;
    }
  }
}

void WasmMemoryTracker::ReleaseReservation(size_t num_bytes) {
  size_t const old_reserved = reserved_address_space_.fetch_sub(num_bytes);
  USE(old_reserved);
  DCHECK_LE(num_bytes, old_reserved);
}

void WasmMemoryTracker::RegisterAllocation(Isolate* isolate,
                                           void* allocation_base,
                                           size_t allocation_length,
                                           void* buffer_start,
                                           size_t buffer_length) {
  base::MutexGuard scope_lock(&mutex_);

  allocated_address_space_ += allocation_length;
  // Report address space usage in MiB so the full range fits in an int on all
  // platforms.
  isolate->counters()->wasm_address_space_usage_mb()->AddSample(
      static_cast<int>(allocated_address_space_ / MB));

  allocations_.emplace(buffer_start,
                       AllocationData{allocation_base, allocation_length,
                                      buffer_start, buffer_length});
}

WasmMemoryTracker::AllocationData WasmMemoryTracker::ReleaseAllocation_Locked(
    Isolate* isolate, const void* buffer_start) {
  auto find_result = allocations_.find(buffer_start);
  CHECK_NE(find_result, allocations_.end());

  size_t num_bytes = find_result->second.allocation_length;
  DCHECK_LE(num_bytes, reserved_address_space_);
  DCHECK_LE(num_bytes, allocated_address_space_);
  reserved_address_space_ -= num_bytes;
  allocated_address_space_ -= num_bytes;

  AllocationData allocation_data = find_result->second;
  allocations_.erase(find_result);
  return allocation_data;
}

const WasmMemoryTracker::AllocationData* WasmMemoryTracker::FindAllocationData(
    const void* buffer_start) {
  base::MutexGuard scope_lock(&mutex_);
  const auto& result = allocations_.find(buffer_start);
  if (result != allocations_.end()) {
    return &result->second;
  }
  return nullptr;
}

bool WasmMemoryTracker::IsWasmMemory(const void* buffer_start) {
  base::MutexGuard scope_lock(&mutex_);
  return allocations_.find(buffer_start) != allocations_.end();
}

bool WasmMemoryTracker::IsWasmSharedMemory(const void* buffer_start) {
  base::MutexGuard scope_lock(&mutex_);
  const auto& result = allocations_.find(buffer_start);
  // Should be a wasm allocation, and registered as a shared allocation.
  return (result != allocations_.end() && result->second.is_shared);
}

void WasmMemoryTracker::MarkWasmMemoryNotGrowable(
    Handle<JSArrayBuffer> buffer) {
  base::MutexGuard scope_lock(&mutex_);
  const auto& allocation = allocations_.find(buffer->backing_store());
  if (allocation == allocations_.end()) return;
  allocation->second.is_growable = false;
}

bool WasmMemoryTracker::IsWasmMemoryGrowable(Handle<JSArrayBuffer> buffer) {
  base::MutexGuard scope_lock(&mutex_);
  if (buffer->backing_store() == nullptr) return true;
  const auto& allocation = allocations_.find(buffer->backing_store());
  if (allocation == allocations_.end()) return false;
  return allocation->second.is_growable;
}

bool WasmMemoryTracker::FreeWasmMemory(Isolate* isolate,
                                       const void* buffer_start) {
  base::MutexGuard scope_lock(&mutex_);
  const auto& result = allocations_.find(buffer_start);
  if (result == allocations_.end()) return false;
  if (result->second.is_shared) {
    // This is a shared WebAssembly.Memory allocation
    FreeMemoryIfNotShared_Locked(isolate, buffer_start);
    return true;
  }
  // This is a WebAssembly.Memory allocation
  const AllocationData allocation =
      ReleaseAllocation_Locked(isolate, buffer_start);
  CHECK(FreePages(GetPlatformPageAllocator(), allocation.allocation_base,
                  allocation.allocation_length));
  return true;
}

void WasmMemoryTracker::RegisterWasmMemoryAsShared(
    Handle<WasmMemoryObject> object, Isolate* isolate) {
  // Only register with the tracker if shared grow is enabled.
  if (!FLAG_wasm_grow_shared_memory) return;
  const void* backing_store = object->array_buffer().backing_store();
  // TODO(V8:8810): This should be a DCHECK, currently some tests do not
  // use a full WebAssembly.Memory, and fail on registering so return early.
  if (!IsWasmMemory(backing_store)) return;
  {
    base::MutexGuard scope_lock(&mutex_);
    // Register as shared allocation when it is post messaged. This happens only
    // the first time a buffer is shared over Postmessage, and track all the
    // memory objects that are associated with this backing store.
    RegisterSharedWasmMemory_Locked(object, isolate);
    // Add isolate to backing store mapping.
    isolates_per_buffer_[backing_store].emplace(isolate);
  }
}

void WasmMemoryTracker::SetPendingUpdateOnGrow(Handle<JSArrayBuffer> old_buffer,
                                               size_t new_size) {
  base::MutexGuard scope_lock(&mutex_);
  // Keep track of the new size of the buffer associated with each backing
  // store.
  AddBufferToGrowMap_Locked(old_buffer, new_size);
  // Request interrupt to GROW_SHARED_MEMORY to other isolates
  TriggerSharedGrowInterruptOnAllIsolates_Locked(old_buffer);
}

void WasmMemoryTracker::UpdateSharedMemoryInstances(Isolate* isolate) {
  base::MutexGuard scope_lock(&mutex_);
  // For every buffer in the grow_entry_map_, update the size for all the
  // memory objects associated with this isolate.
  for (auto it = grow_update_map_.begin(); it != grow_update_map_.end();) {
    UpdateSharedMemoryStateOnInterrupt_Locked(isolate, it->first, it->second);
    // If all the isolates that share this buffer have hit a stack check, their
    // memory objects are updated, and this grow entry can be erased.
    if (AreAllIsolatesUpdated_Locked(it->first)) {
      it = grow_update_map_.erase(it);
    } else {
      it++;
    }
  }
}

void WasmMemoryTracker::RegisterSharedWasmMemory_Locked(
    Handle<WasmMemoryObject> object, Isolate* isolate) {
  DCHECK(object->array_buffer().is_shared());

  void* backing_store = object->array_buffer().backing_store();
  // The allocation of a WasmMemoryObject should always be registered with the
  // WasmMemoryTracker.
  const auto& result = allocations_.find(backing_store);
  if (result == allocations_.end()) return;

  // Register the allocation as shared, if not alreadt marked as shared.
  if (!result->second.is_shared) result->second.is_shared = true;

  // Create persistent global handles for the memory objects that are shared
  GlobalHandles* global_handles = isolate->global_handles();
  object = global_handles->Create(*object);

  // Add to memory_object_vector to track memory objects, instance objects
  // that will need to be updated on a Grow call
  result->second.memory_object_vector.push_back(
      SharedMemoryObjectState(object, isolate));
}

void WasmMemoryTracker::AddBufferToGrowMap_Locked(
    Handle<JSArrayBuffer> old_buffer, size_t new_size) {
  void* backing_store = old_buffer->backing_store();
  auto entry = grow_update_map_.find(old_buffer->backing_store());
  if (entry == grow_update_map_.end()) {
    // No pending grow for this backing store, add to map.
    grow_update_map_.emplace(backing_store, new_size);
    return;
  }
  // If grow on the same buffer is requested before the update is complete,
  // the new_size should always be greater or equal to the old_size. Equal
  // in the case that grow(0) is called, but new buffer handles are mandated
  // by the Spec.
  CHECK_LE(entry->second, new_size);
  entry->second = new_size;
  // Flush instances_updated everytime a new grow size needs to be updates
  ClearUpdatedInstancesOnPendingGrow_Locked(backing_store);
}

void WasmMemoryTracker::TriggerSharedGrowInterruptOnAllIsolates_Locked(
    Handle<JSArrayBuffer> old_buffer) {
  // Request a GrowShareMemory interrupt on all the isolates that share
  // the backing store.
  const auto& isolates = isolates_per_buffer_.find(old_buffer->backing_store());
  for (const auto& isolate : isolates->second) {
    isolate->stack_guard()->RequestGrowSharedMemory();
  }
}

void WasmMemoryTracker::UpdateSharedMemoryStateOnInterrupt_Locked(
    Isolate* isolate, void* backing_store, size_t new_size) {
  // Update objects only if there are memory objects that share this backing
  // store, and this isolate is marked as one of the isolates that shares this
  // buffer.
  if (MemoryObjectsNeedUpdate_Locked(isolate, backing_store)) {
    UpdateMemoryObjectsForIsolate_Locked(isolate, backing_store, new_size);
    // As the memory objects are updated, add this isolate to a set of isolates
    // that are updated on grow. This state is maintained to track if all the
    // isolates that share the backing store have hit a StackCheck.
    isolates_updated_on_grow_[backing_store].emplace(isolate);
  }
}

bool WasmMemoryTracker::AreAllIsolatesUpdated_Locked(
    const void* backing_store) {
  const auto& buffer_isolates = isolates_per_buffer_.find(backing_store);
  // No isolates share this buffer.
  if (buffer_isolates == isolates_per_buffer_.end()) return true;
  const auto& updated_isolates = isolates_updated_on_grow_.find(backing_store);
  // Some isolates share the buffer, but no isolates have been updated yet.
  if (updated_isolates == isolates_updated_on_grow_.end()) return false;
  if (buffer_isolates->second == updated_isolates->second) {
    // If all the isolates that share this backing_store have hit a stack check,
    // and the memory objects have been updated, remove the entry from the
    // updatemap, and return true.
    isolates_updated_on_grow_.erase(backing_store);
    return true;
  }
  return false;
}

void WasmMemoryTracker::ClearUpdatedInstancesOnPendingGrow_Locked(
    const void* backing_store) {
  // On multiple grows to the same buffer, the entries for that buffer should be
  // flushed. This is done so that any consecutive grows to the same buffer will
  // update all instances that share this buffer.
  const auto& value = isolates_updated_on_grow_.find(backing_store);
  if (value != isolates_updated_on_grow_.end()) {
    value->second.clear();
  }
}

void WasmMemoryTracker::UpdateMemoryObjectsForIsolate_Locked(
    Isolate* isolate, void* backing_store, size_t new_size) {
  const auto& result = allocations_.find(backing_store);
  if (result == allocations_.end() || !result->second.is_shared) return;
  for (const auto& memory_obj_state : result->second.memory_object_vector) {
    DCHECK_NE(memory_obj_state.isolate, nullptr);
    if (isolate == memory_obj_state.isolate) {
      HandleScope scope(isolate);
      Handle<WasmMemoryObject> memory_object = memory_obj_state.memory_object;
      DCHECK(memory_object->IsWasmMemoryObject());
      DCHECK(memory_object->array_buffer().is_shared());
      // Permissions adjusted, but create a new buffer with new size
      // and old attributes. Buffer has already been allocated,
      // just create a new buffer with same backing store.
      bool is_external = memory_object->array_buffer().is_external();
      Handle<JSArrayBuffer> new_buffer = SetupArrayBuffer(
          isolate, backing_store, new_size, is_external, SharedFlag::kShared);
      memory_obj_state.memory_object->update_instances(isolate, new_buffer);
    }
  }
}

bool WasmMemoryTracker::MemoryObjectsNeedUpdate_Locked(
    Isolate* isolate, const void* backing_store) {
  // Return true if this buffer has memory_objects it needs to update.
  const auto& result = allocations_.find(backing_store);
  if (result == allocations_.end() || !result->second.is_shared) return false;
  // Only update if the buffer has memory objects that need to be updated.
  if (result->second.memory_object_vector.empty()) return false;
  const auto& isolate_entry = isolates_per_buffer_.find(backing_store);
  return (isolate_entry != isolates_per_buffer_.end() &&
          isolate_entry->second.count(isolate) != 0);
}

void WasmMemoryTracker::FreeMemoryIfNotShared_Locked(
    Isolate* isolate, const void* backing_store) {
  RemoveSharedBufferState_Locked(isolate, backing_store);
  if (CanFreeSharedMemory_Locked(backing_store)) {
    const AllocationData allocation =
        ReleaseAllocation_Locked(isolate, backing_store);
    CHECK(FreePages(GetPlatformPageAllocator(), allocation.allocation_base,
                    allocation.allocation_length));
  }
}

bool WasmMemoryTracker::CanFreeSharedMemory_Locked(const void* backing_store) {
  const auto& value = isolates_per_buffer_.find(backing_store);
  // If no isolates share this buffer, backing store can be freed.
  // Erase the buffer entry.
  if (value == isolates_per_buffer_.end() || value->second.empty()) return true;
  return false;
}

void WasmMemoryTracker::RemoveSharedBufferState_Locked(
    Isolate* isolate, const void* backing_store) {
  if (isolate != nullptr) {
    DestroyMemoryObjectsAndRemoveIsolateEntry_Locked(isolate, backing_store);
    RemoveIsolateFromBackingStore_Locked(isolate, backing_store);
  } else {
    // This happens for externalized contents cleanup shared memory state
    // associated with this buffer across isolates.
    DestroyMemoryObjectsAndRemoveIsolateEntry_Locked(backing_store);
  }
}

void WasmMemoryTracker::DestroyMemoryObjectsAndRemoveIsolateEntry_Locked(
    const void* backing_store) {
  const auto& result = allocations_.find(backing_store);
  CHECK(result != allocations_.end() && result->second.is_shared);
  auto& object_vector = result->second.memory_object_vector;
  if (object_vector.empty()) return;
  for (const auto& mem_obj_state : object_vector) {
    GlobalHandles::Destroy(mem_obj_state.memory_object.location());
  }
  object_vector.clear();
  // Remove isolate from backing store map.
  isolates_per_buffer_.erase(backing_store);
}

void WasmMemoryTracker::DestroyMemoryObjectsAndRemoveIsolateEntry_Locked(
    Isolate* isolate, const void* backing_store) {
  // This gets called when an internal handle to the ArrayBuffer should be
  // freed, on heap tear down for that isolate, remove the memory objects
  // that are associated with this buffer and isolate.
  const auto& result = allocations_.find(backing_store);
  CHECK(result != allocations_.end() && result->second.is_shared);
  auto& object_vector = result->second.memory_object_vector;
  if (object_vector.empty()) return;
  for (auto it = object_vector.begin(); it != object_vector.end();) {
    if (isolate == it->isolate) {
      GlobalHandles::Destroy(it->memory_object.location());
      it = object_vector.erase(it);
    } else {
      ++it;
    }
  }
}

void WasmMemoryTracker::RemoveIsolateFromBackingStore_Locked(
    Isolate* isolate, const void* backing_store) {
  const auto& isolates = isolates_per_buffer_.find(backing_store);
  if (isolates == isolates_per_buffer_.end() || isolates->second.empty())
    return;
  isolates->second.erase(isolate);
}

void WasmMemoryTracker::DeleteSharedMemoryObjectsOnIsolate(Isolate* isolate) {
  base::MutexGuard scope_lock(&mutex_);
  // This is possible for buffers that are externalized, and their handles have
  // been freed, the backing store wasn't released because externalized contents
  // were using it.
  if (isolates_per_buffer_.empty()) return;
  for (auto& entry : isolates_per_buffer_) {
    if (entry.second.find(isolate) == entry.second.end()) continue;
    const void* backing_store = entry.first;
    entry.second.erase(isolate);
    DestroyMemoryObjectsAndRemoveIsolateEntry_Locked(isolate, backing_store);
  }
  for (auto& buffer_isolates : isolates_updated_on_grow_) {
    auto& isolates = buffer_isolates.second;
    isolates.erase(isolate);
  }
}

Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store,
                                       size_t size, bool is_external,
                                       SharedFlag shared) {
  Handle<JSArrayBuffer> buffer =
      isolate->factory()->NewJSArrayBuffer(shared, AllocationType::kOld);
  constexpr bool is_wasm_memory = true;
  JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store, size,
                       shared, is_wasm_memory);
  buffer->set_is_detachable(false);
  return buffer;
}

MaybeHandle<JSArrayBuffer> AllocateAndSetupArrayBuffer(Isolate* isolate,
                                                       size_t size,
                                                       size_t maximum_size,
                                                       SharedFlag shared) {
  // Enforce flag-limited maximum allocation size.
  if (size > max_mem_bytes()) return {};

  WasmMemoryTracker* memory_tracker = isolate->wasm_engine()->memory_tracker();

  // Set by TryAllocateBackingStore or GetEmptyBackingStore
  void* allocation_base = nullptr;
  size_t allocation_length = 0;

  void* memory = TryAllocateBackingStore(memory_tracker, isolate->heap(), size,
                                         maximum_size, &allocation_base,
                                         &allocation_length);
  if (memory == nullptr) return {};

#if DEBUG
  // Double check the API allocator actually zero-initialized the memory.
  const byte* bytes = reinterpret_cast<const byte*>(memory);
  for (size_t i = 0; i < size; ++i) {
    DCHECK_EQ(0, bytes[i]);
  }
#endif

  reinterpret_cast<v8::Isolate*>(isolate)
      ->AdjustAmountOfExternalAllocatedMemory(size);

  constexpr bool is_external = false;
  return SetupArrayBuffer(isolate, memory, size, is_external, shared);
}

MaybeHandle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) {
  return AllocateAndSetupArrayBuffer(isolate, size, size,
                                     SharedFlag::kNotShared);
}

MaybeHandle<JSArrayBuffer> NewSharedArrayBuffer(Isolate* isolate,
                                                size_t initial_size,
                                                size_t max_size) {
  return AllocateAndSetupArrayBuffer(isolate, initial_size, max_size,
                                     SharedFlag::kShared);
}

void DetachMemoryBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer,
                        bool free_memory) {
  if (buffer->is_shared()) return;  // Detaching shared buffers is impossible.
  DCHECK(!buffer->is_detachable());

  const bool is_external = buffer->is_external();
  DCHECK(!buffer->is_detachable());
  if (!is_external) {
    buffer->set_is_external(true);
    isolate->heap()->UnregisterArrayBuffer(*buffer);
    if (free_memory) {
      // We need to free the memory before detaching the buffer because
      // FreeBackingStore reads buffer->allocation_base(), which is nulled out
      // by Detach. This means there is a dangling pointer until we detach the
      // buffer. Since there is no way for the user to directly call
      // FreeBackingStore, we can ensure this is safe.
      buffer->FreeBackingStoreFromMainThread();
    }
  }

  DCHECK(buffer->is_external());
  buffer->set_is_wasm_memory(false);
  buffer->set_is_detachable(true);
  buffer->Detach();
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8
