LCOV - code coverage report
Current view: top level - src/builtins - builtins-typedarray.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 200 203 98.5 %
Date: 2017-10-20 Functions: 23 32 71.9 %

          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.h"
       6             : #include "src/builtins/builtins.h"
       7             : #include "src/counters.h"
       8             : #include "src/elements.h"
       9             : #include "src/objects-inl.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : // -----------------------------------------------------------------------------
      15             : // ES6 section 22.2 TypedArray Objects
      16             : 
      17             : // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
      18       46062 : BUILTIN(TypedArrayPrototypeBuffer) {
      19             :   HandleScope scope(isolate);
      20       17082 :   CHECK_RECEIVER(JSTypedArray, typed_array,
      21             :                  "get %TypedArray%.prototype.buffer");
      22       29556 :   return *typed_array->GetBuffer();
      23             : }
      24             : 
      25             : namespace {
      26             : 
      27       19213 : int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) {
      28             :   int64_t relative;
      29       19213 :   if (V8_LIKELY(num->IsSmi())) {
      30       18241 :     relative = Smi::ToInt(*num);
      31             :   } else {
      32             :     DCHECK(num->IsHeapNumber());
      33             :     double fp = HeapNumber::cast(*num)->value();
      34         972 :     if (V8_UNLIKELY(!std::isfinite(fp))) {
      35             :       // +Infinity / -Infinity
      36             :       DCHECK(!std::isnan(fp));
      37         891 :       return fp < 0 ? minimum : maximum;
      38             :     }
      39          81 :     relative = static_cast<int64_t>(fp);
      40             :   }
      41       43286 :   return relative < 0 ? std::max<int64_t>(relative + maximum, minimum)
      42       51645 :                       : std::min<int64_t>(relative, maximum);
      43             : }
      44             : 
      45        9450 : MaybeHandle<JSTypedArray> TypedArraySpeciesCreateByLength(
      46             :     Isolate* isolate, Handle<JSTypedArray> exemplar, const char* method_name,
      47             :     int64_t length) {
      48             :   const int argc = 1;
      49             :   ScopedVector<Handle<Object>> argv(argc);
      50        9450 :   argv[0] = isolate->factory()->NewNumberFromInt64(length);
      51             :   return JSTypedArray::SpeciesCreate(isolate, exemplar, argc, argv.start(),
      52       18900 :                                      method_name);
      53             : }
      54             : 
      55             : }  // namespace
      56             : 
      57        8532 : BUILTIN(TypedArrayPrototypeCopyWithin) {
      58             :   HandleScope scope(isolate);
      59             : 
      60             :   Handle<JSTypedArray> array;
      61             :   const char* method = "%TypedArray%.prototype.copyWithin";
      62        5688 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      63             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
      64             : 
      65        2439 :   int64_t len = array->length_value();
      66             :   int64_t to = 0;
      67             :   int64_t from = 0;
      68             :   int64_t final = len;
      69             : 
      70        2439 :   if (V8_LIKELY(args.length() > 1)) {
      71             :     Handle<Object> num;
      72        2439 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      73             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(1)));
      74        2439 :     to = CapRelativeIndex(num, 0, len);
      75             : 
      76        2439 :     if (args.length() > 2) {
      77        2430 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
      78             :           isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
      79        2430 :       from = CapRelativeIndex(num, 0, len);
      80             : 
      81             :       Handle<Object> end = args.atOrUndefined(isolate, 3);
      82        2430 :       if (!end->IsUndefined(isolate)) {
      83         810 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num,
      84             :                                            Object::ToInteger(isolate, end));
      85         810 :         final = CapRelativeIndex(num, 0, len);
      86             :       }
      87             :     }
      88             :   }
      89             : 
      90        4878 :   int64_t count = std::min<int64_t>(final - from, len - to);
      91        2925 :   if (count <= 0) return *array;
      92             : 
      93             :   // TypedArray buffer may have been transferred/detached during parameter
      94             :   // processing above. Return early in this case, to prevent potential UAF error
      95             :   // TODO(caitp): throw here, as though the full algorithm were performed (the
      96             :   // throw would have come from ecma262/#sec-integerindexedelementget)
      97             :   // (see )
      98        1953 :   if (V8_UNLIKELY(array->WasNeutered())) return *array;
      99             : 
     100             :   // Ensure processed indexes are within array bounds
     101             :   DCHECK_GE(from, 0);
     102             :   DCHECK_LT(from, len);
     103             :   DCHECK_GE(to, 0);
     104             :   DCHECK_LT(to, len);
     105             :   DCHECK_GE(len - count, 0);
     106             : 
     107             :   Handle<FixedTypedArrayBase> elements(
     108             :       FixedTypedArrayBase::cast(array->elements()));
     109        1944 :   size_t element_size = array->element_size();
     110        1944 :   to = to * element_size;
     111        1944 :   from = from * element_size;
     112        1944 :   count = count * element_size;
     113             : 
     114             :   uint8_t* data = static_cast<uint8_t*>(elements->DataPtr());
     115        1944 :   std::memmove(data + to, data + from, count);
     116             : 
     117        1944 :   return *array;
     118             : }
     119             : 
     120        7950 : BUILTIN(TypedArrayPrototypeFill) {
     121             :   HandleScope scope(isolate);
     122             : 
     123             :   Handle<JSTypedArray> array;
     124             :   const char* method = "%TypedArray%.prototype.fill";
     125        5300 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     126             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     127             : 
     128        2326 :   Handle<Object> obj_value = args.atOrUndefined(isolate, 1);
     129        4652 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     130             :       isolate, obj_value, Object::ToNumber(obj_value));
     131             : 
     132        2326 :   int64_t len = array->length_value();
     133             :   int64_t start = 0;
     134             :   int64_t end = len;
     135             : 
     136        2326 :   if (args.length() > 2) {
     137             :     Handle<Object> num = args.atOrUndefined(isolate, 2);
     138        1215 :     if (!num->IsUndefined(isolate)) {
     139        1215 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     140             :           isolate, num, Object::ToInteger(isolate, num));
     141        1215 :       start = CapRelativeIndex(num, 0, len);
     142             : 
     143             :       num = args.atOrUndefined(isolate, 3);
     144        1215 :       if (!num->IsUndefined(isolate)) {
     145         810 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     146             :             isolate, num, Object::ToInteger(isolate, num));
     147         810 :         end = CapRelativeIndex(num, 0, len);
     148             :       }
     149             :     }
     150             :   }
     151             : 
     152        2326 :   int64_t count = end - start;
     153        2731 :   if (count <= 0) return *array;
     154             : 
     155        1921 :   if (V8_UNLIKELY(array->WasNeutered())) return *array;
     156             : 
     157             :   // Ensure processed indexes are within array bounds
     158             :   DCHECK_GE(start, 0);
     159             :   DCHECK_LT(start, len);
     160             :   DCHECK_GE(end, 0);
     161             :   DCHECK_LE(end, len);
     162             :   DCHECK_LE(count, len);
     163             : 
     164        1921 :   return array->GetElementsAccessor()->Fill(isolate, array, obj_value,
     165             :                                             static_cast<uint32_t>(start),
     166        3842 :                                             static_cast<uint32_t>(end));
     167             : }
     168             : 
     169        6426 : BUILTIN(TypedArrayPrototypeIncludes) {
     170             :   HandleScope scope(isolate);
     171             : 
     172             :   Handle<JSTypedArray> array;
     173             :   const char* method = "%TypedArray%.prototype.includes";
     174        4284 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     175             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     176             : 
     177        2106 :   if (args.length() < 2) return isolate->heap()->false_value();
     178             : 
     179        2025 :   int64_t len = array->length_value();
     180        2025 :   if (len == 0) return isolate->heap()->false_value();
     181             : 
     182             :   int64_t index = 0;
     183        1782 :   if (args.length() > 2) {
     184             :     Handle<Object> num;
     185        1377 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     186             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
     187        1215 :     index = CapRelativeIndex(num, 0, len);
     188             :   }
     189             : 
     190             :   // TODO(cwhan.tunz): throw. See the above comment in CopyWithin.
     191        1620 :   if (V8_UNLIKELY(array->WasNeutered())) return isolate->heap()->false_value();
     192             : 
     193        1620 :   Handle<Object> search_element = args.atOrUndefined(isolate, 1);
     194        1620 :   ElementsAccessor* elements = array->GetElementsAccessor();
     195             :   Maybe<bool> result = elements->IncludesValue(isolate, array, search_element,
     196             :                                                static_cast<uint32_t>(index),
     197        3240 :                                                static_cast<uint32_t>(len));
     198        1620 :   MAYBE_RETURN(result, isolate->heap()->exception());
     199        3240 :   return *isolate->factory()->ToBoolean(result.FromJust());
     200             : }
     201             : 
     202        3645 : BUILTIN(TypedArrayPrototypeIndexOf) {
     203             :   HandleScope scope(isolate);
     204             : 
     205             :   Handle<JSTypedArray> array;
     206             :   const char* method = "%TypedArray%.prototype.indexOf";
     207        2430 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     208             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     209             : 
     210        1053 :   int64_t len = array->length_value();
     211        1053 :   if (len == 0) return Smi::FromInt(-1);
     212             : 
     213             :   int64_t index = 0;
     214         972 :   if (args.length() > 2) {
     215             :     Handle<Object> num;
     216         486 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     217             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
     218         486 :     index = CapRelativeIndex(num, 0, len);
     219             :   }
     220             : 
     221             :   // TODO(cwhan.tunz): throw. See the above comment in CopyWithin.
     222         972 :   if (V8_UNLIKELY(array->WasNeutered())) return Smi::FromInt(-1);
     223             : 
     224         972 :   Handle<Object> search_element = args.atOrUndefined(isolate, 1);
     225         972 :   ElementsAccessor* elements = array->GetElementsAccessor();
     226             :   Maybe<int64_t> result = elements->IndexOfValue(isolate, array, search_element,
     227             :                                                  static_cast<uint32_t>(index),
     228        1944 :                                                  static_cast<uint32_t>(len));
     229         972 :   MAYBE_RETURN(result, isolate->heap()->exception());
     230        1944 :   return *isolate->factory()->NewNumberFromInt64(result.FromJust());
     231             : }
     232             : 
     233        3402 : BUILTIN(TypedArrayPrototypeLastIndexOf) {
     234             :   HandleScope scope(isolate);
     235             : 
     236             :   Handle<JSTypedArray> array;
     237             :   const char* method = "%TypedArray%.prototype.lastIndexOf";
     238        2268 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     239             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     240             : 
     241         972 :   int64_t len = array->length_value();
     242         972 :   if (len == 0) return Smi::FromInt(-1);
     243             : 
     244         891 :   int64_t index = len - 1;
     245         891 :   if (args.length() > 2) {
     246             :     Handle<Object> num;
     247         486 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     248             :         isolate, num, Object::ToInteger(isolate, args.at<Object>(2)));
     249             :     // Set a negative value (-1) for returning -1 if num is negative and
     250             :     // len + num is still negative. Upper bound is len - 1.
     251         972 :     index = std::min<int64_t>(CapRelativeIndex(num, -1, len), len - 1);
     252             :   }
     253             : 
     254         891 :   if (index < 0) return Smi::FromInt(-1);
     255             : 
     256             :   // TODO(cwhan.tunz): throw. See the above comment in CopyWithin.
     257         810 :   if (V8_UNLIKELY(array->WasNeutered())) return Smi::FromInt(-1);
     258             : 
     259         810 :   Handle<Object> search_element = args.atOrUndefined(isolate, 1);
     260         810 :   ElementsAccessor* elements = array->GetElementsAccessor();
     261             :   Maybe<int64_t> result = elements->LastIndexOfValue(
     262        1620 :       isolate, array, search_element, static_cast<uint32_t>(index));
     263         810 :   MAYBE_RETURN(result, isolate->heap()->exception());
     264        1620 :   return *isolate->factory()->NewNumberFromInt64(result.FromJust());
     265             : }
     266             : 
     267         972 : BUILTIN(TypedArrayPrototypeReverse) {
     268             :   HandleScope scope(isolate);
     269             : 
     270             :   Handle<JSTypedArray> array;
     271             :   const char* method = "%TypedArray%.prototype.reverse";
     272         648 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     273             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     274             : 
     275         162 :   ElementsAccessor* elements = array->GetElementsAccessor();
     276         324 :   elements->Reverse(*array);
     277         162 :   return *array;
     278             : }
     279             : 
     280             : namespace {
     281        4954 : Object* TypedArrayCopyElements(Handle<JSTypedArray> target,
     282             :                                Handle<JSReceiver> source, uint32_t length,
     283             :                                uint32_t offset) {
     284        4954 :   ElementsAccessor* accessor = target->GetElementsAccessor();
     285        9908 :   return accessor->CopyElements(source, target, length, offset);
     286             : }
     287             : 
     288             : enum class TypedArraySetResultCodes {
     289             :   // Set from typed array of the same type.
     290             :   // This is processed by TypedArraySetFastCases
     291             :   SAME_TYPE,
     292             :   // Set from typed array of the different type, overlapping in memory.
     293             :   OVERLAPPING,
     294             :   // Set from typed array of the different type, non-overlapping.
     295             :   NONOVERLAPPING,
     296             :   // Set from non-typed array.
     297             :   NON_TYPED_ARRAY
     298             : };
     299             : 
     300         332 : MaybeHandle<Object> TypedArraySetFromOverlapping(Isolate* isolate,
     301             :                                                  Handle<JSTypedArray> target,
     302             :                                                  Handle<JSTypedArray> source,
     303             :                                                  uint32_t offset) {
     304             :   DCHECK_GE(offset, 0);
     305             : 
     306         332 :   size_t sourceElementSize = source->element_size();
     307         332 :   size_t targetElementSize = target->element_size();
     308             : 
     309         332 :   uint32_t source_length = source->length_value();
     310         332 :   if (source_length == 0) return target;
     311             : 
     312             :   // Copy left part.
     313             : 
     314             :   // First un-mutated byte after the next write
     315         323 :   uint32_t target_ptr = 0;
     316         323 :   CHECK(target->byte_offset()->ToUint32(&target_ptr));
     317         323 :   target_ptr += (offset + 1) * targetElementSize;
     318             : 
     319             :   // Next read at sourcePtr. We do not care for memory changing before
     320             :   // sourcePtr - we have already copied it.
     321         323 :   uint32_t source_ptr = 0;
     322         323 :   CHECK(source->byte_offset()->ToUint32(&source_ptr));
     323             : 
     324         323 :   ElementsAccessor* source_accessor = source->GetElementsAccessor();
     325         323 :   ElementsAccessor* target_accessor = target->GetElementsAccessor();
     326             : 
     327             :   uint32_t left_index;
     328         137 :   for (left_index = 0; left_index < source_length && target_ptr <= source_ptr;
     329             :        left_index++) {
     330         274 :     Handle<Object> value = source_accessor->Get(source, left_index);
     331         411 :     target_accessor->Set(target, offset + left_index, *value);
     332             : 
     333         137 :     target_ptr += targetElementSize;
     334         137 :     source_ptr += sourceElementSize;
     335             :   }
     336             : 
     337             :   // Copy right part;
     338             :   // First unmutated byte before the next write
     339         323 :   CHECK(target->byte_offset()->ToUint32(&target_ptr));
     340         323 :   target_ptr += (offset + source_length - 1) * targetElementSize;
     341             : 
     342             :   // Next read before sourcePtr. We do not care for memory changing after
     343             :   // sourcePtr - we have already copied it.
     344         323 :   CHECK(target->byte_offset()->ToUint32(&source_ptr));
     345         323 :   source_ptr += source_length * sourceElementSize;
     346             : 
     347             :   uint32_t right_index;
     348             :   DCHECK_GE(source_length, 1);
     349         541 :   for (right_index = source_length - 1;
     350         356 :        right_index > left_index && target_ptr >= source_ptr; right_index--) {
     351         436 :     Handle<Object> value = source_accessor->Get(source, right_index);
     352         654 :     target_accessor->Set(target, offset + right_index, *value);
     353             : 
     354         218 :     target_ptr -= targetElementSize;
     355         218 :     source_ptr -= sourceElementSize;
     356             :   }
     357             : 
     358         323 :   std::vector<Handle<Object>> temp(right_index + 1 - left_index);
     359             : 
     360         451 :   for (uint32_t i = left_index; i <= right_index; i++) {
     361        1353 :     temp[i - left_index] = source_accessor->Get(source, i);
     362             :   }
     363             : 
     364         451 :   for (uint32_t i = left_index; i <= right_index; i++) {
     365        1353 :     target_accessor->Set(target, offset + i, *temp[i - left_index]);
     366             :   }
     367             : 
     368         323 :   return target;
     369             : }
     370             : 
     371        9645 : MaybeHandle<Smi> TypedArraySetFastCases(Isolate* isolate,
     372             :                                         Handle<JSTypedArray> target,
     373             :                                         Handle<Object> source_obj,
     374             :                                         Handle<Object> offset_obj) {
     375        9645 :   if (!source_obj->IsJSTypedArray()) {
     376             :     return MaybeHandle<Smi>(
     377        4878 :         Smi::FromEnum(TypedArraySetResultCodes::NON_TYPED_ARRAY), isolate);
     378             :   }
     379             : 
     380             :   Handle<JSTypedArray> source = Handle<JSTypedArray>::cast(source_obj);
     381             : 
     382             :   size_t offset = 0;
     383        4767 :   CHECK(TryNumberToSize(*offset_obj, &offset));
     384        4767 :   size_t target_length = target->length_value();
     385        4767 :   size_t source_length = source->length_value();
     386        4767 :   size_t target_byte_length = NumberToSize(target->byte_length());
     387        4767 :   size_t source_byte_length = NumberToSize(source->byte_length());
     388        4767 :   if (offset > target_length || offset + source_length > target_length ||
     389             :       offset + source_length < offset) {  // overflow
     390          74 :     THROW_NEW_ERROR(
     391             :         isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge),
     392             :         Smi);
     393             :   }
     394             : 
     395        4730 :   size_t target_offset = NumberToSize(target->byte_offset());
     396        4730 :   size_t source_offset = NumberToSize(source->byte_offset());
     397             :   uint8_t* target_base =
     398        9460 :       static_cast<uint8_t*>(target->GetBuffer()->backing_store()) +
     399        4730 :       target_offset;
     400             :   uint8_t* source_base =
     401        9460 :       static_cast<uint8_t*>(source->GetBuffer()->backing_store()) +
     402        4730 :       source_offset;
     403             : 
     404             :   // Typed arrays of the same type: use memmove.
     405        9460 :   if (target->type() == source->type()) {
     406        4122 :     memmove(target_base + offset * target->element_size(), source_base,
     407             :             source_byte_length);
     408             :     return MaybeHandle<Smi>(Smi::FromEnum(TypedArraySetResultCodes::SAME_TYPE),
     409        4122 :                             isolate);
     410             :   }
     411             : 
     412             :   // Typed arrays of different types over the same backing store
     413         962 :   if ((source_base <= target_base &&
     414         723 :        source_base + source_byte_length > target_base) ||
     415         263 :       (target_base <= source_base &&
     416         263 :        target_base + target_byte_length > source_base)) {
     417             :     // We do not support overlapping ArrayBuffers
     418             :     DCHECK(target->GetBuffer()->backing_store() ==
     419             :            source->GetBuffer()->backing_store());
     420             :     return MaybeHandle<Smi>(
     421         332 :         Smi::FromEnum(TypedArraySetResultCodes::OVERLAPPING), isolate);
     422             :   } else {  // Non-overlapping typed arrays
     423             :     return MaybeHandle<Smi>(
     424         276 :         Smi::FromEnum(TypedArraySetResultCodes::NONOVERLAPPING), isolate);
     425             :   }
     426             : }
     427             : 
     428             : }  // anonymous namespace
     429             : 
     430             : // 22.2.3.23%TypedArray%.prototype.set ( overloaded [ , offset ] )
     431       29181 : BUILTIN(TypedArrayPrototypeSet) {
     432             :   HandleScope scope(isolate);
     433             : 
     434             :   Handle<Object> target = args.receiver();
     435             :   Handle<Object> obj = args.atOrUndefined(isolate, 1);
     436             :   Handle<Object> offset = args.atOrUndefined(isolate, 2);
     437             :   const char* method = "%TypedArray%.prototype.set";
     438             : 
     439        9727 :   if (!target->IsJSTypedArray()) {
     440         144 :     THROW_NEW_ERROR_RETURN_FAILURE(
     441             :         isolate, NewTypeError(MessageTemplate::kNotTypedArray));
     442             :   }
     443             : 
     444        9655 :   if (offset->IsUndefined(isolate)) {
     445             :     offset = Handle<Object>(Smi::kZero, isolate);
     446             :   } else {
     447        7827 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
     448             :                                        Object::ToInteger(isolate, offset));
     449             :   }
     450             : 
     451        9655 :   if (offset->Number() < 0) {
     452           0 :     THROW_NEW_ERROR_RETURN_FAILURE(
     453             :         isolate, NewRangeError(MessageTemplate::kTypedArraySetNegativeOffset));
     454             :   }
     455             : 
     456        9655 :   if (offset->Number() > Smi::kMaxValue) {
     457          20 :     THROW_NEW_ERROR_RETURN_FAILURE(
     458             :         isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
     459             :   }
     460             : 
     461             :   Handle<JSTypedArray> target_array = Handle<JSTypedArray>::cast(target);
     462        9645 :   if (V8_UNLIKELY(target_array->WasNeutered())) {
     463             :     const MessageTemplate::Template message =
     464             :         MessageTemplate::kDetachedOperation;
     465             :     Handle<String> operation =
     466           0 :         isolate->factory()->NewStringFromAsciiChecked(method);
     467           0 :     THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message, operation));
     468             :   }
     469             : 
     470             :   uint32_t uint_offset;
     471        9645 :   CHECK(offset->ToUint32(&uint_offset));
     472             : 
     473             :   // TODO(cwhan.tunz): Implement CopyElements for overlapping cases, and use
     474             :   // TypedArrayCopyElements for all case instead of this result code based
     475             :   // branches
     476             :   Handle<Smi> result_code;
     477       19290 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     478             :       isolate, result_code,
     479             :       TypedArraySetFastCases(isolate, target_array, obj, offset));
     480             : 
     481        9608 :   switch (static_cast<TypedArraySetResultCodes>(result_code->value())) {
     482             :     case TypedArraySetResultCodes::SAME_TYPE: {
     483             :       break;
     484             :     }
     485             :     case TypedArraySetResultCodes::OVERLAPPING: {
     486         664 :       RETURN_FAILURE_ON_EXCEPTION(
     487             :           isolate, TypedArraySetFromOverlapping(isolate, target_array,
     488             :                                                 Handle<JSTypedArray>::cast(obj),
     489             :                                                 uint_offset));
     490             :       break;
     491             :     }
     492             :     case TypedArraySetResultCodes::NONOVERLAPPING: {
     493             :       return TypedArrayCopyElements(
     494             :           target_array, Handle<JSTypedArray>::cast(obj),
     495         828 :           Handle<JSTypedArray>::cast(obj)->length_value(), uint_offset);
     496             :       break;
     497             :     }
     498             :     case TypedArraySetResultCodes::NON_TYPED_ARRAY: {
     499        4878 :       if (obj->IsNumber()) {
     500             :         // For number as a first argument, throw TypeError
     501             :         // instead of silently ignoring the call, so that
     502             :         // users know they did something wrong.
     503             :         // (Consistent with Firefox and Blink/WebKit)
     504         128 :         THROW_NEW_ERROR_RETURN_FAILURE(
     505             :             isolate, NewTypeError(MessageTemplate::kInvalidArgument));
     506             :       }
     507             : 
     508        9628 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj,
     509             :                                          Object::ToObject(isolate, obj));
     510             : 
     511             :       Handle<Object> len;
     512        9628 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     513             :           isolate, len,
     514             :           Object::GetProperty(obj, isolate->factory()->length_string()));
     515        4814 :       if (len->IsUndefined(isolate)) {
     516             :         break;
     517             :       }
     518        9554 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len,
     519             :                                          Object::ToLength(isolate, len));
     520             : 
     521             :       DCHECK_GE(uint_offset, 0);
     522       14088 :       if (uint_offset + len->Number() > target_array->length_value()) {
     523          36 :         THROW_NEW_ERROR_RETURN_FAILURE(
     524             :             isolate,
     525             :             NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
     526             :       }
     527             :       uint32_t int_l;
     528        4678 :       CHECK(DoubleToUint32IfEqualToSelf(len->Number(), &int_l));
     529             :       return TypedArrayCopyElements(target_array, Handle<JSReceiver>::cast(obj),
     530        4678 :                                     int_l, uint_offset);
     531             :     } break;
     532             :   }
     533             : 
     534             :   return *isolate->factory()->undefined_value();
     535             : }
     536             : 
     537       28836 : BUILTIN(TypedArrayPrototypeSlice) {
     538             :   HandleScope scope(isolate);
     539             : 
     540             :   Handle<JSTypedArray> array;
     541             :   const char* method = "%TypedArray%.prototype.slice";
     542       19224 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     543             :       isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method));
     544             : 
     545        9450 :   int64_t len = array->length_value();
     546             :   int64_t start = 0;
     547             :   int64_t end = len;
     548             :   {
     549             :     Handle<Object> num = args.atOrUndefined(isolate, 1);
     550        9450 :     if (!num->IsUndefined(isolate)) {
     551        5876 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num,
     552             :                                          Object::ToInteger(isolate, num));
     553        5876 :       start = CapRelativeIndex(num, 0, len);
     554             : 
     555             :       num = args.atOrUndefined(isolate, 2);
     556        5876 :       if (!num->IsUndefined(isolate)) {
     557        3446 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num,
     558             :                                            Object::ToInteger(isolate, num));
     559        3446 :         end = CapRelativeIndex(num, 0, len);
     560             :       }
     561             :     }
     562             :   }
     563             : 
     564       18900 :   int64_t count = std::max<int64_t>(end - start, 0);
     565             : 
     566             :   Handle<JSTypedArray> result_array;
     567       18900 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     568             :       isolate, result_array,
     569             :       TypedArraySpeciesCreateByLength(isolate, array, method, count));
     570             : 
     571             :   // TODO(cwhan.tunz): neutering check of the result_array should be done in
     572             :   // TypedArraySpeciesCreate, but currently ValidateTypedArray does not throw
     573             :   // for neutered buffer, so this is a temporary neutering check for the result
     574             :   // array
     575        9207 :   if (V8_UNLIKELY(result_array->WasNeutered())) return *result_array;
     576             : 
     577             :   // TODO(cwhan.tunz): should throw.
     578        9207 :   if (V8_UNLIKELY(array->WasNeutered())) return *result_array;
     579             : 
     580        9207 :   if (count == 0) return *result_array;
     581             : 
     582        6453 :   ElementsAccessor* accessor = array->GetElementsAccessor();
     583             :   return *accessor->Slice(array, static_cast<uint32_t>(start),
     584       25812 :                           static_cast<uint32_t>(end), result_array);
     585             : }
     586             : 
     587             : }  // namespace internal
     588             : }  // namespace v8

Generated by: LCOV version 1.10