V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
runtime-typedarray.cc
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 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
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  if (!argument->IsJSArrayBuffer()) {
26  THROW_NEW_ERROR_RETURN_FAILURE(
27  isolate, NewTypeError(MessageTemplate::kNotTypedArray));
28  }
29  Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(argument);
30  if (!array_buffer->is_neuterable()) {
31  return ReadOnlyRoots(isolate).undefined_value();
32  }
33  if (array_buffer->backing_store() == nullptr) {
34  CHECK_EQ(0, array_buffer->byte_length());
35  return ReadOnlyRoots(isolate).undefined_value();
36  }
37  // Shared array buffers should never be neutered.
38  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  isolate->heap()->UnregisterArrayBuffer(*array_buffer);
44  array_buffer->Neuter();
45  isolate->array_buffer_allocator()->Free(backing_store, byte_length);
46  return ReadOnlyRoots(isolate).undefined_value();
47 }
48 
49 RUNTIME_FUNCTION(Runtime_TypedArrayCopyElements) {
50  HandleScope scope(isolate);
51  DCHECK_EQ(3, args.length());
52  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target, 0);
53  CONVERT_ARG_HANDLE_CHECKED(Object, source, 1);
54  CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 2);
55 
56  size_t length;
57  CHECK(TryNumberToSize(*length_obj, &length));
58 
59  ElementsAccessor* accessor = target->GetElementsAccessor();
60  return accessor->CopyElements(source, target, length);
61 }
62 
63 RUNTIME_FUNCTION(Runtime_TypedArrayGetLength) {
64  HandleScope scope(isolate);
65  DCHECK_EQ(1, args.length());
66  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
67  return holder->length();
68 }
69 
70 RUNTIME_FUNCTION(Runtime_ArrayBufferViewWasNeutered) {
71  HandleScope scope(isolate);
72  DCHECK_EQ(1, args.length());
73  return isolate->heap()->ToBoolean(JSTypedArray::cast(args[0])->WasNeutered());
74 }
75 
76 RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
77  HandleScope scope(isolate);
78  DCHECK_EQ(1, args.length());
79  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
80  return *holder->GetBuffer();
81 }
82 
83 
84 namespace {
85 
86 template <typename T>
87 bool CompareNum(T x, T y) {
88  if (x < y) {
89  return true;
90  } else if (x > y) {
91  return false;
92  } else if (!std::is_integral<T>::value) {
93  double _x = x, _y = y;
94  if (x == 0 && x == y) {
95  /* -0.0 is less than +0.0 */
96  return std::signbit(_x) && !std::signbit(_y);
97  } else if (!std::isnan(_x) && std::isnan(_y)) {
98  /* number is less than NaN */
99  return true;
100  }
101  }
102  return false;
103 }
104 
105 } // namespace
106 
107 RUNTIME_FUNCTION(Runtime_TypedArraySortFast) {
108  HandleScope scope(isolate);
109  DCHECK_EQ(1, args.length());
110 
111  CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
112 
113  Handle<JSTypedArray> array;
114  const char* method = "%TypedArray%.prototype.sort";
115  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
116  isolate, array, JSTypedArray::Validate(isolate, target_obj, method));
117 
118  // This line can be removed when JSTypedArray::Validate throws
119  // if array.[[ViewedArrayBuffer]] is neutered(v8:4648)
120  if (V8_UNLIKELY(array->WasNeutered())) return *array;
121 
122  size_t length = array->length_value();
123  if (length <= 1) return *array;
124 
125  Handle<FixedTypedArrayBase> elements(
126  FixedTypedArrayBase::cast(array->elements()), isolate);
127  switch (array->type()) {
128 #define TYPED_ARRAY_SORT(Type, type, TYPE, ctype) \
129  case kExternal##Type##Array: { \
130  ctype* data = static_cast<ctype*>(elements->DataPtr()); \
131  if (kExternal##Type##Array == kExternalFloat64Array || \
132  kExternal##Type##Array == kExternalFloat32Array) \
133  std::sort(data, data + length, CompareNum<ctype>); \
134  else \
135  std::sort(data, data + length); \
136  break; \
137  }
138 
139  TYPED_ARRAYS(TYPED_ARRAY_SORT)
140 #undef TYPED_ARRAY_SORT
141  }
142 
143  return *array;
144 }
145 
146 RUNTIME_FUNCTION(Runtime_IsTypedArray) {
147  HandleScope scope(isolate);
148  DCHECK_EQ(1, args.length());
149  return isolate->heap()->ToBoolean(args[0]->IsJSTypedArray());
150 }
151 
152 // 22.2.3.23 %TypedArray%.prototype.set ( overloaded [ , offset ] )
153 RUNTIME_FUNCTION(Runtime_TypedArraySet) {
154  HandleScope scope(isolate);
155  Handle<JSTypedArray> target = args.at<JSTypedArray>(0);
156  Handle<Object> obj = args.at(1);
157  Handle<Smi> offset = args.at<Smi>(2);
158 
159  DCHECK(!target->WasNeutered()); // Checked in TypedArrayPrototypeSet.
160  DCHECK(!obj->IsJSTypedArray()); // Should be handled by CSA.
161  DCHECK_LE(0, offset->value());
162 
163  const uint32_t uint_offset = static_cast<uint32_t>(offset->value());
164 
165  if (obj->IsNumber()) {
166  // For number as a first argument, throw TypeError
167  // instead of silently ignoring the call, so that
168  // users know they did something wrong.
169  // (Consistent with Firefox and Blink/WebKit)
170  THROW_NEW_ERROR_RETURN_FAILURE(
171  isolate, NewTypeError(MessageTemplate::kInvalidArgument));
172  }
173 
174  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj,
175  Object::ToObject(isolate, obj));
176 
177  Handle<Object> len;
178  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
179  isolate, len,
180  Object::GetProperty(isolate, obj, isolate->factory()->length_string()));
181  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len,
182  Object::ToLength(isolate, len));
183 
184  if (uint_offset + len->Number() > target->length_value()) {
185  THROW_NEW_ERROR_RETURN_FAILURE(
186  isolate, NewRangeError(MessageTemplate::kTypedArraySetSourceTooLarge));
187  }
188 
189  uint32_t int_l;
190  CHECK(DoubleToUint32IfEqualToSelf(len->Number(), &int_l));
191 
192  Handle<JSReceiver> source = Handle<JSReceiver>::cast(obj);
193  ElementsAccessor* accessor = target->GetElementsAccessor();
194  return accessor->CopyElements(source, target, int_l, uint_offset);
195 }
196 
197 } // namespace internal
198 } // namespace v8
Definition: libplatform.h:13