LCOV - code coverage report
Current view: top level - src/runtime - runtime-typedarray.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 87 116 75.0 %
Date: 2017-04-26 Functions: 11 32 34.4 %

          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/runtime/runtime-utils.h"
       6             : 
       7             : #include "src/arguments.h"
       8             : #include "src/elements.h"
       9             : #include "src/factory.h"
      10             : #include "src/messages.h"
      11             : #include "src/objects-inl.h"
      12             : #include "src/runtime/runtime.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17           0 : RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
      18             :   SealHandleScope shs(isolate);
      19             :   DCHECK_EQ(1, args.length());
      20           0 :   CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
      21           0 :   return holder->byte_length();
      22             : }
      23             : 
      24             : 
      25        8460 : RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
      26        2825 :   HandleScope scope(isolate);
      27             :   DCHECK_EQ(1, args.length());
      28        2825 :   Handle<Object> argument = args.at(0);
      29             :   // This runtime function is exposed in ClusterFuzz and as such has to
      30             :   // support arbitrary arguments.
      31        2825 :   if (!argument->IsJSArrayBuffer()) {
      32           0 :     THROW_NEW_ERROR_RETURN_FAILURE(
      33             :         isolate, NewTypeError(MessageTemplate::kNotTypedArray));
      34             :   }
      35        2825 :   Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(argument);
      36             : 
      37        2825 :   if (array_buffer->backing_store() == NULL) {
      38          15 :     CHECK(Smi::kZero == array_buffer->byte_length());
      39          15 :     return isolate->heap()->undefined_value();
      40             :   }
      41             :   // Shared array buffers should never be neutered.
      42        2810 :   CHECK(!array_buffer->is_shared());
      43             :   DCHECK(!array_buffer->is_external());
      44             :   void* backing_store = array_buffer->backing_store();
      45        2810 :   size_t byte_length = NumberToSize(array_buffer->byte_length());
      46        2810 :   array_buffer->set_is_external(true);
      47        2810 :   isolate->heap()->UnregisterArrayBuffer(*array_buffer);
      48        2810 :   array_buffer->Neuter();
      49        2810 :   isolate->array_buffer_allocator()->Free(backing_store, byte_length);
      50        2810 :   return isolate->heap()->undefined_value();
      51             : }
      52             : 
      53       70196 : RUNTIME_FUNCTION(Runtime_TypedArrayCopyElements) {
      54       35098 :   HandleScope scope(isolate);
      55             :   DCHECK_EQ(3, args.length());
      56       70196 :   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, destination, 0);
      57       70196 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, source, 1);
      58       70196 :   CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 2);
      59             : 
      60             :   size_t length;
      61       35098 :   CHECK(TryNumberToSize(*length_obj, &length));
      62             : 
      63       35098 :   Handle<JSTypedArray> destination_ta = Handle<JSTypedArray>::cast(destination);
      64             : 
      65       35098 :   ElementsAccessor* accessor = destination_ta->GetElementsAccessor();
      66       70196 :   return accessor->CopyElements(source, destination, length);
      67             : }
      68             : 
      69             : #define BUFFER_VIEW_GETTER(Type, getter, accessor)   \
      70             :   RUNTIME_FUNCTION(Runtime_##Type##Get##getter) {    \
      71             :     HandleScope scope(isolate);                      \
      72             :     DCHECK_EQ(1, args.length());                     \
      73             :     CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0); \
      74             :     return holder->accessor();                       \
      75             :   }
      76             : 
      77       10208 : BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length)
      78       57604 : BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset)
      79      206608 : BUFFER_VIEW_GETTER(TypedArray, Length, length)
      80             : 
      81             : #undef BUFFER_VIEW_GETTER
      82             : 
      83       82536 : RUNTIME_FUNCTION(Runtime_ArrayBufferViewWasNeutered) {
      84       41268 :   HandleScope scope(isolate);
      85             :   DCHECK_EQ(1, args.length());
      86       41268 :   return isolate->heap()->ToBoolean(JSTypedArray::cast(args[0])->WasNeutered());
      87             : }
      88             : 
      89       33438 : RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
      90       16719 :   HandleScope scope(isolate);
      91             :   DCHECK_EQ(1, args.length());
      92       33438 :   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
      93       33438 :   return *holder->GetBuffer();
      94             : }
      95             : 
      96             : 
      97             : // Return codes for Runtime_TypedArraySetFastCases.
      98             : // Should be synchronized with typedarray.js natives.
      99             : enum TypedArraySetResultCodes {
     100             :   // Set from typed array of the same type.
     101             :   // This is processed by TypedArraySetFastCases
     102             :   TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
     103             :   // Set from typed array of the different type, overlapping in memory.
     104             :   TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
     105             :   // Set from typed array of the different type, non-overlapping.
     106             :   TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
     107             :   // Set from non-typed array.
     108             :   TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
     109             : };
     110             : 
     111             : 
     112       28156 : RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
     113       14078 :   HandleScope scope(isolate);
     114             :   DCHECK_EQ(3, args.length());
     115       28156 :   if (!args[0]->IsJSTypedArray()) {
     116         168 :     THROW_NEW_ERROR_RETURN_FAILURE(
     117             :         isolate, NewTypeError(MessageTemplate::kNotTypedArray));
     118             :   }
     119             : 
     120       27988 :   if (!args[1]->IsJSTypedArray()) {
     121        7124 :     return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
     122             :   }
     123             : 
     124       13740 :   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0);
     125       13740 :   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1);
     126       13740 :   CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2);
     127             : 
     128             :   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
     129             :   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
     130        6870 :   size_t offset = 0;
     131        6870 :   CHECK(TryNumberToSize(*offset_obj, &offset));
     132        6870 :   size_t target_length = target->length_value();
     133        6870 :   size_t source_length = source->length_value();
     134        6870 :   size_t target_byte_length = NumberToSize(target->byte_length());
     135        6870 :   size_t source_byte_length = NumberToSize(source->byte_length());
     136        6870 :   if (offset > target_length || offset + source_length > target_length ||
     137             :       offset + source_length < offset) {  // overflow
     138         114 :     THROW_NEW_ERROR_RETURN_FAILURE(
     139             :         isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
     140             :   }
     141             : 
     142        6813 :   size_t target_offset = NumberToSize(target->byte_offset());
     143        6813 :   size_t source_offset = NumberToSize(source->byte_offset());
     144             :   uint8_t* target_base =
     145       20439 :       static_cast<uint8_t*>(target->GetBuffer()->backing_store()) +
     146        6813 :       target_offset;
     147             :   uint8_t* source_base =
     148       20439 :       static_cast<uint8_t*>(source->GetBuffer()->backing_store()) +
     149        6813 :       source_offset;
     150             : 
     151             :   // Typed arrays of the same type: use memmove.
     152       13626 :   if (target->type() == source->type()) {
     153       12004 :     memmove(target_base + offset * target->element_size(), source_base,
     154        6002 :             source_byte_length);
     155        6002 :     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
     156             :   }
     157             : 
     158             :   // Typed arrays of different types over the same backing store
     159        1352 :   if ((source_base <= target_base &&
     160         998 :        source_base + source_byte_length > target_base) ||
     161         270 :       (target_base <= source_base &&
     162         270 :        target_base + target_byte_length > source_base)) {
     163             :     // We do not support overlapping ArrayBuffers
     164             :     DCHECK(target->GetBuffer()->backing_store() ==
     165             :            source->GetBuffer()->backing_store());
     166         468 :     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
     167             :   } else {  // Non-overlapping typed arrays
     168         343 :     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
     169       14078 :   }
     170             : }
     171             : 
     172             : namespace {
     173             : 
     174             : template <typename T>
     175         560 : bool CompareNum(T x, T y) {
     176         560 :   if (x < y) {
     177             :     return true;
     178         420 :   } else if (x > y) {
     179             :     return false;
     180             :   } else if (!std::is_integral<T>::value) {
     181         182 :     double _x = x, _y = y;
     182         364 :     if (x == 0 && x == y) {
     183             :       /* -0.0 is less than +0.0 */
     184         280 :       return std::signbit(_x) && !std::signbit(_y);
     185         196 :     } else if (!std::isnan(_x) && std::isnan(_y)) {
     186             :       /* number is less than NaN */
     187             :       return true;
     188             :     }
     189             :   }
     190         112 :   return false;
     191             : }
     192             : 
     193             : }  // namespace
     194             : 
     195         842 : RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
     196         421 :   HandleScope scope(isolate);
     197             :   DCHECK_EQ(1, args.length());
     198             : 
     199         421 :   CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
     200             : 
     201             :   Handle<JSTypedArray> array;
     202             :   const char* method = "%TypedArray%.prototype.sort";
     203         842 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     204             :       isolate, array, JSTypedArray::Validate(isolate, target_obj, method));
     205             : 
     206             :   // This line can be removed when JSTypedArray::Validate throws
     207             :   // if array.[[ViewedArrayBuffer]] is neutered(v8:4648)
     208         421 :   if (V8_UNLIKELY(array->WasNeutered())) return *array;
     209             : 
     210         421 :   size_t length = array->length_value();
     211         421 :   if (length <= 1) return *array;
     212             : 
     213             :   Handle<FixedTypedArrayBase> elements(
     214         421 :       FixedTypedArrayBase::cast(array->elements()));
     215         421 :   switch (array->type()) {
     216             : #define TYPED_ARRAY_SORT(Type, type, TYPE, ctype, size)     \
     217             :   case kExternal##Type##Array: {                            \
     218             :     ctype* data = static_cast<ctype*>(elements->DataPtr()); \
     219             :     if (kExternal##Type##Array == kExternalFloat64Array ||  \
     220             :         kExternal##Type##Array == kExternalFloat32Array)    \
     221             :       std::sort(data, data + length, CompareNum<ctype>);    \
     222             :     else                                                    \
     223             :       std::sort(data, data + length);                       \
     224             :     break;                                                  \
     225             :   }
     226             : 
     227         421 :     TYPED_ARRAYS(TYPED_ARRAY_SORT)
     228             : #undef TYPED_ARRAY_SORT
     229             :   }
     230             : 
     231         421 :   return *array;
     232             : }
     233             : 
     234           0 : RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap) {
     235             :   DCHECK_EQ(0, args.length());
     236             :   DCHECK_OBJECT_SIZE(FLAG_typed_array_max_size_in_heap +
     237             :                      FixedTypedArrayBase::kDataOffset);
     238           0 :   return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
     239             : }
     240             : 
     241             : 
     242           0 : RUNTIME_FUNCTION(Runtime_IsTypedArray) {
     243           0 :   HandleScope scope(isolate);
     244             :   DCHECK_EQ(1, args.length());
     245           0 :   return isolate->heap()->ToBoolean(args[0]->IsJSTypedArray());
     246             : }
     247             : 
     248           0 : RUNTIME_FUNCTION(Runtime_IsSharedTypedArray) {
     249           0 :   HandleScope scope(isolate);
     250             :   DCHECK_EQ(1, args.length());
     251             :   return isolate->heap()->ToBoolean(
     252           0 :       args[0]->IsJSTypedArray() &&
     253           0 :       JSTypedArray::cast(args[0])->GetBuffer()->is_shared());
     254             : }
     255             : 
     256             : 
     257           0 : RUNTIME_FUNCTION(Runtime_IsSharedIntegerTypedArray) {
     258           0 :   HandleScope scope(isolate);
     259             :   DCHECK_EQ(1, args.length());
     260           0 :   if (!args[0]->IsJSTypedArray()) {
     261           0 :     return isolate->heap()->false_value();
     262             :   }
     263             : 
     264           0 :   Handle<JSTypedArray> obj(JSTypedArray::cast(args[0]));
     265           0 :   return isolate->heap()->ToBoolean(obj->GetBuffer()->is_shared() &&
     266           0 :                                     obj->type() != kExternalFloat32Array &&
     267           0 :                                     obj->type() != kExternalFloat64Array &&
     268           0 :                                     obj->type() != kExternalUint8ClampedArray);
     269             : }
     270             : 
     271             : 
     272           0 : RUNTIME_FUNCTION(Runtime_IsSharedInteger32TypedArray) {
     273           0 :   HandleScope scope(isolate);
     274             :   DCHECK_EQ(1, args.length());
     275           0 :   if (!args[0]->IsJSTypedArray()) {
     276           0 :     return isolate->heap()->false_value();
     277             :   }
     278             : 
     279           0 :   Handle<JSTypedArray> obj(JSTypedArray::cast(args[0]));
     280           0 :   return isolate->heap()->ToBoolean(obj->GetBuffer()->is_shared() &&
     281           0 :                                     obj->type() == kExternalInt32Array);
     282             : }
     283             : 
     284             : }  // namespace internal
     285             : }  // namespace v8

Generated by: LCOV version 1.10