LCOV - code coverage report
Current view: top level - src/builtins - builtins-typed-array.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 101 102 99.0 %
Date: 2019-01-20 Functions: 17 24 70.8 %

          Line data    Source code
       1             : // Copyright 2016 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/builtins/builtins-utils-inl.h"
       6             : #include "src/builtins/builtins.h"
       7             : #include "src/counters.h"
       8             : #include "src/elements.h"
       9             : #include "src/objects-inl.h"
      10             : #include "src/objects/heap-number-inl.h"
      11             : #include "src/objects/js-array-buffer-inl.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : // -----------------------------------------------------------------------------
      17             : // ES6 section 22.2 TypedArray Objects
      18             : 
      19             : // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
      20       71028 : BUILTIN(TypedArrayPrototypeBuffer) {
      21             :   HandleScope scope(isolate);
      22       37701 :   CHECK_RECEIVER(JSTypedArray, typed_array,
      23             :                  "get %TypedArray%.prototype.buffer");
      24       34056 :   return *typed_array->GetBuffer();
      25             : }
      26             : 
      27             : namespace {
      28             : 
      29       10251 : int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) {
      30             :   int64_t relative;
      31       20502 :   if (V8_LIKELY(num->IsSmi())) {
      32        9279 :     relative = Smi::ToInt(*num);
      33             :   } else {
      34             :     DCHECK(num->IsHeapNumber());
      35             :     double fp = HeapNumber::cast(*num)->value();
      36         972 :     if (V8_UNLIKELY(!std::isfinite(fp))) {
      37             :       // +Infinity / -Infinity
      38             :       DCHECK(!std::isnan(fp));
      39         891 :       return fp < 0 ? minimum : maximum;
      40             :     }
      41          81 :     relative = static_cast<int64_t>(fp);
      42             :   }
      43       23580 :   return relative < 0 ? std::max<int64_t>(relative + maximum, minimum)
      44       25650 :                       : std::min<int64_t>(relative, maximum);
      45             : }
      46             : 
      47             : }  // namespace
      48             : 
      49       11664 : BUILTIN(TypedArrayPrototypeCopyWithin) {
      50             :   HandleScope scope(isolate);
      51             : 
      52             :   Handle<JSTypedArray> array;
      53             :   const char* method = "%TypedArray%.prototype.copyWithin";
      54        6237 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      55             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
      56             : 
      57        2511 :   int64_t len = array->length_value();
      58             :   int64_t to = 0;
      59             :   int64_t from = 0;
      60             :   int64_t final = len;
      61             : 
      62        2511 :   if (V8_LIKELY(args.length() > 1)) {
      63             :     Handle<Object> num;
      64        5022 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      65             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(1)));
      66        2511 :     to = CapRelativeIndex(num, 0, len);
      67             : 
      68        2511 :     if (args.length() > 2) {
      69        5004 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      70             :           isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
      71        2502 :       from = CapRelativeIndex(num, 0, len);
      72             : 
      73             :       Handle<Object> end = args.atOrUndefined(isolate, 3);
      74        5004 :       if (!end->IsUndefined(isolate)) {
      75        1764 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num,
      76             :                                            Object::ToInteger(isolate, end));
      77         882 :         final = CapRelativeIndex(num, 0, len);
      78             :       }
      79             :     }
      80             :   }
      81             : 
      82        5022 :   int64_t count = std::min<int64_t>(final - from, len - to);
      83        2997 :   if (count <= 0) return *array;
      84             : 
      85             :   // TypedArray buffer may have been transferred/detached during parameter
      86             :   // processing above. Return early in this case, to prevent potential UAF error
      87             :   // TODO(caitp): throw here, as though the full algorithm were performed (the
      88             :   // throw would have come from ecma262/#sec-integerindexedelementget)
      89             :   // (see )
      90        2034 :   if (V8_UNLIKELY(array->WasDetached())) return *array;
      91             : 
      92             :   // Ensure processed indexes are within array bounds
      93             :   DCHECK_GE(from, 0);
      94             :   DCHECK_LT(from, len);
      95             :   DCHECK_GE(to, 0);
      96             :   DCHECK_LT(to, len);
      97             :   DCHECK_GE(len - count, 0);
      98             : 
      99             :   Handle<FixedTypedArrayBase> elements(
     100        4032 :       FixedTypedArrayBase::cast(array->elements()), isolate);
     101        2016 :   size_t element_size = array->element_size();
     102        2016 :   to = to * element_size;
     103        2016 :   from = from * element_size;
     104        2016 :   count = count * element_size;
     105             : 
     106        4032 :   uint8_t* data = static_cast<uint8_t*>(elements->DataPtr());
     107        2016 :   std::memmove(data + to, data + from, count);
     108             : 
     109        2016 :   return *array;
     110             : }
     111             : 
     112       18324 : BUILTIN(TypedArrayPrototypeFill) {
     113             :   HandleScope scope(isolate);
     114             : 
     115             :   Handle<JSTypedArray> array;
     116             :   const char* method = "%TypedArray%.prototype.fill";
     117        9486 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     118             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     119        4257 :   ElementsKind kind = array->GetElementsKind();
     120             : 
     121        4257 :   Handle<Object> obj_value = args.atOrUndefined(isolate, 1);
     122        4257 :   if (kind == BIGINT64_ELEMENTS || kind == BIGUINT64_ELEMENTS) {
     123         360 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj_value,
     124             :                                        BigInt::FromObject(isolate, obj_value));
     125             :   } else {
     126        8226 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj_value,
     127             :                                        Object::ToNumber(isolate, obj_value));
     128             :   }
     129             : 
     130        4185 :   int64_t len = array->length_value();
     131             :   int64_t start = 0;
     132             :   int64_t end = len;
     133             : 
     134        4185 :   if (args.length() > 2) {
     135             :     Handle<Object> num = args.atOrUndefined(isolate, 2);
     136        2574 :     if (!num->IsUndefined(isolate)) {
     137        2574 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     138             :           isolate, num, Object::ToInteger(isolate, num));
     139        1287 :       start = CapRelativeIndex(num, 0, len);
     140             : 
     141             :       num = args.atOrUndefined(isolate, 3);
     142        2574 :       if (!num->IsUndefined(isolate)) {
     143        1764 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     144             :             isolate, num, Object::ToInteger(isolate, num));
     145         882 :         end = CapRelativeIndex(num, 0, len);
     146             :       }
     147             :     }
     148             :   }
     149             : 
     150        4185 :   int64_t count = end - start;
     151        4590 :   if (count <= 0) return *array;
     152             : 
     153        3780 :   if (V8_UNLIKELY(array->WasDetached())) return *array;
     154             : 
     155             :   // Ensure processed indexes are within array bounds
     156             :   DCHECK_GE(start, 0);
     157             :   DCHECK_LT(start, len);
     158             :   DCHECK_GE(end, 0);
     159             :   DCHECK_LE(end, len);
     160             :   DCHECK_LE(count, len);
     161             : 
     162             :   return ElementsAccessor::ForKind(kind)->Fill(array, obj_value,
     163             :                                                static_cast<uint32_t>(start),
     164        7560 :                                                static_cast<uint32_t>(end));
     165             : }
     166             : 
     167        9756 : BUILTIN(TypedArrayPrototypeIncludes) {
     168             :   HandleScope scope(isolate);
     169             : 
     170             :   Handle<JSTypedArray> array;
     171             :   const char* method = "%TypedArray%.prototype.includes";
     172        4914 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     173             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     174             : 
     175        2493 :   if (args.length() < 2) return ReadOnlyRoots(isolate).false_value();
     176             : 
     177        2313 :   int64_t len = array->length_value();
     178        2556 :   if (len == 0) return ReadOnlyRoots(isolate).false_value();
     179             : 
     180             :   int64_t index = 0;
     181        2070 :   if (args.length() > 2) {
     182             :     Handle<Object> num;
     183        2916 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     184             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
     185        1215 :     index = CapRelativeIndex(num, 0, len);
     186             :   }
     187             : 
     188             :   // TODO(cwhan.tunz): throw. See the above comment in CopyWithin.
     189        1908 :   if (V8_UNLIKELY(array->WasDetached()))
     190           0 :     return ReadOnlyRoots(isolate).false_value();
     191             : 
     192        1908 :   Handle<Object> search_element = args.atOrUndefined(isolate, 1);
     193        1908 :   ElementsAccessor* elements = array->GetElementsAccessor();
     194             :   Maybe<bool> result = elements->IncludesValue(isolate, array, search_element,
     195             :                                                static_cast<uint32_t>(index),
     196        3816 :                                                static_cast<uint32_t>(len));
     197        1908 :   MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
     198        3816 :   return *isolate->factory()->ToBoolean(result.FromJust());
     199             : }
     200             : 
     201        6048 : BUILTIN(TypedArrayPrototypeIndexOf) {
     202             :   HandleScope scope(isolate);
     203             : 
     204             :   Handle<JSTypedArray> array;
     205             :   const char* method = "%TypedArray%.prototype.indexOf";
     206        3186 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     207             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     208             : 
     209        1350 :   int64_t len = array->length_value();
     210        1350 :   if (len == 0) return Smi::FromInt(-1);
     211             : 
     212             :   int64_t index = 0;
     213        1269 :   if (args.length() > 2) {
     214             :     Handle<Object> num;
     215         972 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     216             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
     217         486 :     index = CapRelativeIndex(num, 0, len);
     218             :   }
     219             : 
     220             :   // TODO(cwhan.tunz): throw. See the above comment in CopyWithin.
     221        1269 :   if (V8_UNLIKELY(array->WasDetached())) return Smi::FromInt(-1);
     222             : 
     223        1269 :   Handle<Object> search_element = args.atOrUndefined(isolate, 1);
     224        1269 :   ElementsAccessor* elements = array->GetElementsAccessor();
     225             :   Maybe<int64_t> result = elements->IndexOfValue(isolate, array, search_element,
     226             :                                                  static_cast<uint32_t>(index),
     227        2538 :                                                  static_cast<uint32_t>(len));
     228        1269 :   MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
     229        2538 :   return *isolate->factory()->NewNumberFromInt64(result.FromJust());
     230             : }
     231             : 
     232        5724 : BUILTIN(TypedArrayPrototypeLastIndexOf) {
     233             :   HandleScope scope(isolate);
     234             : 
     235             :   Handle<JSTypedArray> array;
     236             :   const char* method = "%TypedArray%.prototype.lastIndexOf";
     237        3024 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     238             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     239             : 
     240        1269 :   int64_t len = array->length_value();
     241        1269 :   if (len == 0) return Smi::FromInt(-1);
     242             : 
     243        1188 :   int64_t index = len - 1;
     244        1188 :   if (args.length() > 2) {
     245             :     Handle<Object> num;
     246         972 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     247             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
     248             :     // Set a negative value (-1) for returning -1 if num is negative and
     249             :     // len + num is still negative. Upper bound is len - 1.
     250         972 :     index = std::min<int64_t>(CapRelativeIndex(num, -1, len), len - 1);
     251             :   }
     252             : 
     253        1188 :   if (index < 0) return Smi::FromInt(-1);
     254             : 
     255             :   // TODO(cwhan.tunz): throw. See the above comment in CopyWithin.
     256        1107 :   if (V8_UNLIKELY(array->WasDetached())) return Smi::FromInt(-1);
     257             : 
     258        1107 :   Handle<Object> search_element = args.atOrUndefined(isolate, 1);
     259        1107 :   ElementsAccessor* elements = array->GetElementsAccessor();
     260             :   Maybe<int64_t> result = elements->LastIndexOfValue(
     261        2214 :       array, search_element, static_cast<uint32_t>(index));
     262        1107 :   MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
     263        2214 :   return *isolate->factory()->NewNumberFromInt64(result.FromJust());
     264             : }
     265             : 
     266        1584 : BUILTIN(TypedArrayPrototypeReverse) {
     267             :   HandleScope scope(isolate);
     268             : 
     269             :   Handle<JSTypedArray> array;
     270             :   const char* method = "%TypedArray%.prototype.reverse";
     271         954 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     272             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     273             : 
     274         234 :   ElementsAccessor* elements = array->GetElementsAccessor();
     275         468 :   elements->Reverse(*array);
     276         234 :   return *array;
     277             : }
     278             : 
     279             : }  // namespace internal
     280      183867 : }  // namespace v8

Generated by: LCOV version 1.10