LCOV - code coverage report
Current view: top level - src/builtins - builtins-typed-array.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 98 99 99.0 %
Date: 2019-04-17 Functions: 16 23 69.6 %

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

Generated by: LCOV version 1.10