LCOV - code coverage report
Current view: top level - src/runtime - runtime-typedarray.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 45 49 91.8 %
Date: 2019-04-17 Functions: 8 17 47.1 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/arguments-inl.h"
       6             : #include "src/counters.h"
       7             : #include "src/elements.h"
       8             : #include "src/heap/factory.h"
       9             : #include "src/heap/heap-inl.h"
      10             : #include "src/message-template.h"
      11             : #include "src/objects-inl.h"
      12             : #include "src/objects/js-array-buffer-inl.h"
      13             : #include "src/runtime/runtime-utils.h"
      14             : #include "src/runtime/runtime.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19        5968 : RUNTIME_FUNCTION(Runtime_ArrayBufferDetach) {
      20             :   HandleScope scope(isolate);
      21             :   DCHECK_EQ(1, args.length());
      22             :   Handle<Object> argument = args.at(0);
      23             :   // This runtime function is exposed in ClusterFuzz and as such has to
      24             :   // support arbitrary arguments.
      25        2984 :   if (!argument->IsJSArrayBuffer()) {
      26           0 :     THROW_NEW_ERROR_RETURN_FAILURE(
      27             :         isolate, NewTypeError(MessageTemplate::kNotTypedArray));
      28             :   }
      29        2984 :   Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(argument);
      30        2984 :   if (!array_buffer->is_detachable()) {
      31             :     return ReadOnlyRoots(isolate).undefined_value();
      32             :   }
      33        2957 :   if (array_buffer->backing_store() == nullptr) {
      34           0 :     CHECK_EQ(0, array_buffer->byte_length());
      35             :     return ReadOnlyRoots(isolate).undefined_value();
      36             :   }
      37             :   // Shared array buffers should never be detached.
      38        2957 :   CHECK(!array_buffer->is_shared());
      39             :   DCHECK(!array_buffer->is_external());
      40             :   void* backing_store = array_buffer->backing_store();
      41             :   size_t byte_length = array_buffer->byte_length();
      42             :   array_buffer->set_is_external(true);
      43        2957 :   isolate->heap()->UnregisterArrayBuffer(*array_buffer);
      44        2957 :   array_buffer->Detach();
      45        2957 :   isolate->array_buffer_allocator()->Free(backing_store, byte_length);
      46             :   return ReadOnlyRoots(isolate).undefined_value();
      47             : }
      48             : 
      49       58636 : RUNTIME_FUNCTION(Runtime_TypedArrayCopyElements) {
      50             :   HandleScope scope(isolate);
      51             :   DCHECK_EQ(3, args.length());
      52       29318 :   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target, 0);
      53             :   CONVERT_ARG_HANDLE_CHECKED(Object, source, 1);
      54       29318 :   CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 2);
      55             : 
      56             :   size_t length;
      57       29318 :   CHECK(TryNumberToSize(*length_obj, &length));
      58             : 
      59       29318 :   ElementsAccessor* accessor = target->GetElementsAccessor();
      60       58636 :   return accessor->CopyElements(source, target, length);
      61             : }
      62             : 
      63           0 : RUNTIME_FUNCTION(Runtime_ArrayBufferViewWasDetached) {
      64             :   HandleScope scope(isolate);
      65             :   DCHECK_EQ(1, args.length());
      66             :   return isolate->heap()->ToBoolean(JSTypedArray::cast(args[0])->WasDetached());
      67             : }
      68             : 
      69        1306 : RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
      70             :   HandleScope scope(isolate);
      71             :   DCHECK_EQ(1, args.length());
      72         653 :   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
      73        1306 :   return *holder->GetBuffer();
      74             : }
      75             : 
      76             : 
      77             : namespace {
      78             : 
      79             : template <typename T>
      80         360 : bool CompareNum(T x, T y) {
      81         360 :   if (x < y) {
      82             :     return true;
      83         270 :   } else if (x > y) {
      84             :     return false;
      85             :   } else if (!std::is_integral<T>::value) {
      86         117 :     double _x = x, _y = y;
      87         234 :     if (x == 0 && x == y) {
      88             :       /* -0.0 is less than +0.0 */
      89         180 :       return std::signbit(_x) && !std::signbit(_y);
      90         126 :     } else if (!std::isnan(_x) && std::isnan(_y)) {
      91             :       /* number is less than NaN */
      92             :       return true;
      93             :     }
      94             :   }
      95          72 :   return false;
      96             : }
      97             : 
      98             : }  // namespace
      99             : 
     100        1008 : RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
     101             :   HandleScope scope(isolate);
     102             :   DCHECK_EQ(1, args.length());
     103             : 
     104             :   CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
     105             : 
     106             :   Handle<JSTypedArray> array;
     107             :   const char* method = "%TypedArray%.prototype.sort";
     108        1008 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     109             :       isolate, array, JSTypedArray::Validate(isolate, target_obj, method));
     110             : 
     111             :   // This line can be removed when JSTypedArray::Validate throws
     112             :   // if array.[[ViewedArrayBuffer]] is detached(v8:4648)
     113         504 :   if (V8_UNLIKELY(array->WasDetached())) return *array;
     114             : 
     115             :   size_t length = array->length();
     116         504 :   if (length <= 1) return *array;
     117             : 
     118             :   Handle<FixedTypedArrayBase> elements(
     119             :       FixedTypedArrayBase::cast(array->elements()), isolate);
     120         342 :   switch (array->type()) {
     121             : #define TYPED_ARRAY_SORT(Type, type, TYPE, ctype)                          \
     122             :   case kExternal##Type##Array: {                                           \
     123             :     ctype* data = static_cast<ctype*>(elements->DataPtr());                \
     124             :     if (kExternal##Type##Array == kExternalFloat64Array ||                 \
     125             :         kExternal##Type##Array == kExternalFloat32Array) {                 \
     126             :       if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) {        \
     127             :         /* TODO(ishell, v8:8875): See UnalignedSlot<T> for details. */     \
     128             :         std::sort(UnalignedSlot<ctype>(data),                              \
     129             :                   UnalignedSlot<ctype>(data + length), CompareNum<ctype>); \
     130             :       } else {                                                             \
     131             :         std::sort(data, data + length, CompareNum<ctype>);                 \
     132             :       }                                                                    \
     133             :     } else {                                                               \
     134             :       if (COMPRESS_POINTERS_BOOL && alignof(ctype) > kTaggedSize) {        \
     135             :         /* TODO(ishell, v8:8875): See UnalignedSlot<T> for details. */     \
     136             :         std::sort(UnalignedSlot<ctype>(data),                              \
     137             :                   UnalignedSlot<ctype>(data + length));                    \
     138             :       } else {                                                             \
     139             :         std::sort(data, data + length);                                    \
     140             :       }                                                                    \
     141             :     }                                                                      \
     142             :     break;                                                                 \
     143             :   }
     144             : 
     145         342 :     TYPED_ARRAYS(TYPED_ARRAY_SORT)
     146             : #undef TYPED_ARRAY_SORT
     147             :   }
     148             : 
     149             :   return *array;
     150             : }
     151             : 
     152           0 : RUNTIME_FUNCTION(Runtime_IsTypedArray) {
     153             :   HandleScope scope(isolate);
     154             :   DCHECK_EQ(1, args.length());
     155             :   return isolate->heap()->ToBoolean(args[0]->IsJSTypedArray());
     156             : }
     157             : 
     158             : // 22.2.3.23 %TypedArray%.prototype.set ( overloaded [ , offset ] )
     159        2754 : RUNTIME_FUNCTION(Runtime_TypedArraySet) {
     160             :   HandleScope scope(isolate);
     161             :   Handle<JSTypedArray> target = args.at<JSTypedArray>(0);
     162             :   Handle<Object> obj = args.at(1);
     163             :   Handle<Smi> offset = args.at<Smi>(2);
     164             : 
     165             :   DCHECK(!target->WasDetached());  // Checked in TypedArrayPrototypeSet.
     166             :   DCHECK(!obj->IsJSTypedArray());  // Should be handled by CSA.
     167             :   DCHECK_LE(0, offset->value());
     168             : 
     169        1377 :   const uint32_t uint_offset = static_cast<uint32_t>(offset->value());
     170             : 
     171        1377 :   if (obj->IsNumber()) {
     172             :     // For number as a first argument, throw TypeError
     173             :     // instead of silently ignoring the call, so that
     174             :     // users know they did something wrong.
     175             :     // (Consistent with Firefox and Blink/WebKit)
     176         126 :     THROW_NEW_ERROR_RETURN_FAILURE(
     177             :         isolate, NewTypeError(MessageTemplate::kInvalidArgument));
     178             :   }
     179             : 
     180        2628 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj,
     181             :                                      Object::ToObject(isolate, obj));
     182             : 
     183             :   Handle<Object> len;
     184        2628 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     185             :       isolate, len,
     186             :       Object::GetProperty(isolate, obj, isolate->factory()->length_string()));
     187        2628 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len,
     188             :                                      Object::ToLength(isolate, len));
     189             : 
     190        3699 :   if (uint_offset + len->Number() > target->length()) {
     191          36 :     THROW_NEW_ERROR_RETURN_FAILURE(
     192             :         isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
     193             :   }
     194             : 
     195             :   uint32_t int_l;
     196        1215 :   CHECK(DoubleToUint32IfEqualToSelf(len->Number(), &int_l));
     197             : 
     198             :   Handle<JSReceiver> source = Handle<JSReceiver>::cast(obj);
     199        1215 :   ElementsAccessor* accessor = target->GetElementsAccessor();
     200        2430 :   return accessor->CopyElements(source, target, int_l, uint_offset);
     201             : }
     202             : 
     203             : }  // namespace internal
     204      122004 : }  // namespace v8

Generated by: LCOV version 1.10