// Copyright 2014 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 "src/common/message-template.h"
#include "src/execution/arguments-inl.h"
#include "src/heap/factory.h"
#include "src/heap/heap-inl.h"
#include "src/logging/counters.h"
#include "src/objects/elements.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/objects-inl.h"
#include "src/runtime/runtime-utils.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {

RUNTIME_FUNCTION(Runtime_ArrayBufferDetach) {
  HandleScope scope(isolate);
  DCHECK_EQ(1, args.length());
  Handle<Object> argument = args.at(0);
  // This runtime function is exposed in ClusterFuzz and as such has to
  // support arbitrary arguments.
  if (!argument->IsJSArrayBuffer()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kNotTypedArray));
  }
  Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(argument);
  if (!array_buffer->is_detachable()) {
    return ReadOnlyRoots(isolate).undefined_value();
  }
  if (array_buffer->backing_store() == nullptr) {
    CHECK_EQ(0, array_buffer->byte_length());
    return ReadOnlyRoots(isolate).undefined_value();
  }
  // Shared array buffers should never be detached.
  CHECK(!array_buffer->is_shared());
  DCHECK(!array_buffer->is_external());
  void* backing_store = array_buffer->backing_store();
  size_t byte_length = array_buffer->byte_length();
  array_buffer->set_is_external(true);
  isolate->heap()->UnregisterArrayBuffer(*array_buffer);
  array_buffer->Detach();
  isolate->array_buffer_allocator()->Free(backing_store, byte_length);
  return ReadOnlyRoots(isolate).undefined_value();
}

RUNTIME_FUNCTION(Runtime_TypedArrayCopyElements) {
  HandleScope scope(isolate);
  DCHECK_EQ(3, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target, 0);
  CONVERT_ARG_HANDLE_CHECKED(Object, source, 1);
  CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 2);

  size_t length;
  CHECK(TryNumberToSize(*length_obj, &length));

  ElementsAccessor* accessor = target->GetElementsAccessor();
  return accessor->CopyElements(source, target, length);
}

RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
  HandleScope scope(isolate);
  DCHECK_EQ(1, args.length());
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
  return *holder->GetBuffer();
}


namespace {

template <typename T>
bool CompareNum(T x, T y) {
  if (x < y) {
    return true;
  } else if (x > y) {
    return false;
  } else if (!std::is_integral<T>::value) {
    double _x = x, _y = y;
    if (x == 0 && x == y) {
      /* -0.0 is less than +0.0 */
      return std::signbit(_x) && !std::signbit(_y);
    } else if (!std::isnan(_x) && std::isnan(_y)) {
      /* number is less than NaN */
      return true;
    }
  }
  return false;
}

}  // namespace

RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
  HandleScope scope(isolate);
  DCHECK_EQ(1, args.length());

  // Validation is handled in the Torque builtin.
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, array, 0);
  DCHECK(!array->WasDetached());

  size_t length = array->length();
  if (length <= 1) return *array;

  // In case of a SAB, the data is copied into temporary memory, as
  // std::sort might crash in case the underlying data is concurrently
  // modified while sorting.
  CHECK(array->buffer().IsJSArrayBuffer());
  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(array->buffer()), isolate);
  const bool copy_data = buffer->is_shared();

  Handle<ByteArray> array_copy;
  if (copy_data) {
    const size_t bytes = array->byte_length();
    // TODO(szuend): Re-check this approach once support for larger typed
    //               arrays has landed.
    CHECK_LE(bytes, INT_MAX);
    array_copy = isolate->factory()->NewByteArray(static_cast<int>(bytes));
    std::memcpy(static_cast<void*>(array_copy->GetDataStartAddress()),
                static_cast<void*>(array->DataPtr()), bytes);
  }

  DisallowHeapAllocation no_gc;

  switch (array->type()) {
#define TYPED_ARRAY_SORT(Type, type, TYPE, ctype)                          \
  case kExternal##Type##Array: {                                           \
    ctype* data =                                                          \
        copy_data                                                          \
            ? reinterpret_cast<ctype*>(array_copy->GetDataStartAddress())  \
            : static_cast<ctype*>(array->DataPtr());                       \
    if (kExternal##Type##Array == kExternalFloat64Array ||                 \
        kExternal##Type##Array == kExternalFloat32Array) {                 \
      if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) {        \
        /* TODO(ishell, v8:8875): See UnalignedSlot<T> for details. */     \
        std::sort(UnalignedSlot<ctype>(data),                              \
                  UnalignedSlot<ctype>(data + length), CompareNum<ctype>); \
      } else {                                                             \
        std::sort(data, data + length, CompareNum<ctype>);                 \
      }                                                                    \
    } else {                                                               \
      if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) {        \
        /* TODO(ishell, v8:8875): See UnalignedSlot<T> for details. */     \
        std::sort(UnalignedSlot<ctype>(data),                              \
                  UnalignedSlot<ctype>(data + length));                    \
      } else {                                                             \
        std::sort(data, data + length);                                    \
      }                                                                    \
    }                                                                      \
    break;                                                                 \
  }

    TYPED_ARRAYS(TYPED_ARRAY_SORT)
#undef TYPED_ARRAY_SORT
  }

  if (copy_data) {
    DCHECK(!array_copy.is_null());
    const size_t bytes = array->byte_length();
    std::memcpy(static_cast<void*>(array->DataPtr()),
                static_cast<void*>(array_copy->GetDataStartAddress()), bytes);
  }

  return *array;
}

// 22.2.3.23 %TypedArray%.prototype.set ( overloaded [ , offset ] )
RUNTIME_FUNCTION(Runtime_TypedArraySet) {
  HandleScope scope(isolate);
  Handle<JSTypedArray> target = args.at<JSTypedArray>(0);
  Handle<Object> obj = args.at(1);
  Handle<Smi> offset = args.at<Smi>(2);

  DCHECK(!target->WasDetached());  // Checked in TypedArrayPrototypeSet.
  DCHECK(!obj->IsJSTypedArray());  // Should be handled by CSA.
  DCHECK_LE(0, offset->value());

  const uint32_t uint_offset = static_cast<uint32_t>(offset->value());

  if (obj->IsNumber()) {
    // For number as a first argument, throw TypeError
    // instead of silently ignoring the call, so that
    // users know they did something wrong.
    // (Consistent with Firefox and Blink/WebKit)
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewTypeError(MessageTemplate::kInvalidArgument));
  }

  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj,
                                     Object::ToObject(isolate, obj));

  Handle<Object> len;
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      isolate, len,
      Object::GetProperty(isolate, obj, isolate->factory()->length_string()));
  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len,
                                     Object::ToLength(isolate, len));

  if (uint_offset + len->Number() > target->length()) {
    THROW_NEW_ERROR_RETURN_FAILURE(
        isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
  }

  uint32_t int_l;
  CHECK(DoubleToUint32IfEqualToSelf(len->Number(), &int_l));

  Handle<JSReceiver> source = Handle<JSReceiver>::cast(obj);
  ElementsAccessor* accessor = target->GetElementsAccessor();
  return accessor->CopyElements(source, target, int_l, uint_offset);
}

}  // namespace internal
}  // namespace v8
