OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 #include "src/counters.h" | 7 #include "src/counters.h" |
8 #include "src/elements.h" | 8 #include "src/elements.h" |
9 #include "src/objects-inl.h" | 9 #include "src/objects-inl.h" |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 // +Infinity / -Infinity | 34 // +Infinity / -Infinity |
35 DCHECK(!std::isnan(fp)); | 35 DCHECK(!std::isnan(fp)); |
36 return fp < 0 ? minimum : maximum; | 36 return fp < 0 ? minimum : maximum; |
37 } | 37 } |
38 relative = static_cast<int64_t>(fp); | 38 relative = static_cast<int64_t>(fp); |
39 } | 39 } |
40 return relative < 0 ? std::max<int64_t>(relative + maximum, minimum) | 40 return relative < 0 ? std::max<int64_t>(relative + maximum, minimum) |
41 : std::min<int64_t>(relative, maximum); | 41 : std::min<int64_t>(relative, maximum); |
42 } | 42 } |
43 | 43 |
44 // ES7 section 22.2.4.6 TypedArrayCreate ( constructor, argumentList ) | |
45 MaybeHandle<JSTypedArray> TypedArrayCreate(Isolate* isolate, | |
46 Handle<JSFunction> default_ctor, | |
47 int argc, Handle<Object>* argv, | |
48 const char* method_name) { | |
49 // 1. Let newTypedArray be ? Construct(constructor, argumentList). | |
50 Handle<Object> new_obj; | |
51 ASSIGN_RETURN_ON_EXCEPTION( | |
52 isolate, new_obj, Execution::New(default_ctor, argc, argv), JSTypedArray); | |
53 | |
54 // 2. Perform ? ValidateTypedArray(newTypedArray). | |
55 Handle<JSTypedArray> new_array; | |
56 ASSIGN_RETURN_ON_EXCEPTION( | |
57 isolate, new_array, JSTypedArray::Validate(isolate, new_obj, method_name), | |
58 JSTypedArray); | |
59 | |
60 // 3. If argumentList is a List of a single Number, then | |
61 // If newTypedArray.[[ArrayLength]] < size, throw a TypeError exception. | |
62 DCHECK_IMPLIES(argc == 1, argv[0]->IsSmi()); | |
63 if (argc == 1 && new_array->length_value() < argv[0]->Number()) { | |
64 const MessageTemplate::Template message = | |
65 MessageTemplate::kTypedArrayTooShort; | |
66 THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray); | |
67 } | |
68 | |
69 // 4. Return newTypedArray. | |
70 return new_array; | |
71 } | |
72 | |
73 // ES7 section 22.2.4.7 TypedArraySpeciesCreate ( exemplar, argumentList ) | |
74 MaybeHandle<JSTypedArray> TypedArraySpeciesCreate(Isolate* isolate, | |
75 Handle<JSTypedArray> exemplar, | |
76 int argc, | |
77 Handle<Object>* argv, | |
78 const char* method_name) { | |
79 // 1. Assert: exemplar is an Object that has a [[TypedArrayName]] internal | |
80 // slot. | |
81 DCHECK(exemplar->IsJSTypedArray()); | |
82 | |
83 // 2. Let defaultConstructor be the intrinsic object listed in column one of | |
84 // Table 51 for exemplar.[[TypedArrayName]]. | |
85 Handle<JSFunction> default_ctor = isolate->uint8_array_fun(); | |
86 switch (exemplar->type()) { | |
87 #define TYPED_ARRAY_CTOR(Type, type, TYPE, ctype, size) \ | |
88 case kExternal##Type##Array: { \ | |
89 default_ctor = isolate->type##_array_fun(); \ | |
90 break; \ | |
91 } | |
92 | |
93 TYPED_ARRAYS(TYPED_ARRAY_CTOR) | |
94 #undef TYPED_ARRAY_CTOR | |
95 default: | |
96 UNREACHABLE(); | |
97 } | |
98 | |
99 // 3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor). | |
100 Handle<Object> ctor; | |
101 ASSIGN_RETURN_ON_EXCEPTION( | |
102 isolate, ctor, | |
103 Object::SpeciesConstructor(isolate, exemplar, default_ctor), | |
104 JSTypedArray); | |
105 | |
106 // 4. Return ? TypedArrayCreate(constructor, argumentList). | |
107 return TypedArrayCreate(isolate, Handle<JSFunction>::cast(ctor), argc, argv, | |
108 method_name); | |
109 } | |
110 | |
111 MaybeHandle<JSTypedArray> TypedArraySpeciesCreateByLength( | 44 MaybeHandle<JSTypedArray> TypedArraySpeciesCreateByLength( |
112 Isolate* isolate, Handle<JSTypedArray> exemplar, const char* method_name, | 45 Isolate* isolate, Handle<JSTypedArray> exemplar, int64_t length) { |
113 int64_t length) { | |
114 const int argc = 1; | 46 const int argc = 1; |
115 ScopedVector<Handle<Object>> argv(argc); | 47 ScopedVector<Handle<Object>> argv(argc); |
116 argv[0] = isolate->factory()->NewNumberFromInt64(length); | 48 argv[0] = isolate->factory()->NewNumberFromInt64(length); |
117 return TypedArraySpeciesCreate(isolate, exemplar, argc, argv.start(), | 49 return JSTypedArray::SpeciesCreate(isolate, exemplar, argc, argv.start()); |
118 method_name); | |
119 } | 50 } |
120 | 51 |
121 } // namespace | 52 } // namespace |
122 | 53 |
123 BUILTIN(TypedArrayPrototypeCopyWithin) { | 54 BUILTIN(TypedArrayPrototypeCopyWithin) { |
124 HandleScope scope(isolate); | 55 HandleScope scope(isolate); |
125 | 56 |
126 Handle<JSTypedArray> array; | 57 Handle<JSTypedArray> array; |
127 const char* method = "%TypedArray%.prototype.copyWithin"; | |
128 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 58 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
129 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 59 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
130 | 60 |
131 if (V8_UNLIKELY(array->WasNeutered())) return *array; | 61 if (V8_UNLIKELY(array->WasNeutered())) return *array; |
132 | 62 |
133 int64_t len = array->length_value(); | 63 int64_t len = array->length_value(); |
134 int64_t to = 0; | 64 int64_t to = 0; |
135 int64_t from = 0; | 65 int64_t from = 0; |
136 int64_t final = len; | 66 int64_t final = len; |
137 | 67 |
138 if (V8_LIKELY(args.length() > 1)) { | 68 if (V8_LIKELY(args.length() > 1)) { |
139 Handle<Object> num; | 69 Handle<Object> num; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 uint8_t* data = static_cast<uint8_t*>(elements->DataPtr()); | 112 uint8_t* data = static_cast<uint8_t*>(elements->DataPtr()); |
183 std::memmove(data + to, data + from, count); | 113 std::memmove(data + to, data + from, count); |
184 | 114 |
185 return *array; | 115 return *array; |
186 } | 116 } |
187 | 117 |
188 BUILTIN(TypedArrayPrototypeFill) { | 118 BUILTIN(TypedArrayPrototypeFill) { |
189 HandleScope scope(isolate); | 119 HandleScope scope(isolate); |
190 | 120 |
191 Handle<JSTypedArray> array; | 121 Handle<JSTypedArray> array; |
192 const char* method = "%TypedArray%.prototype.fill"; | |
193 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 122 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
194 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 123 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
195 | 124 |
196 if (V8_UNLIKELY(array->WasNeutered())) return *array; | 125 if (V8_UNLIKELY(array->WasNeutered())) return *array; |
197 | 126 |
198 Handle<Object> obj_value = args.atOrUndefined(isolate, 1); | 127 Handle<Object> obj_value = args.atOrUndefined(isolate, 1); |
199 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 128 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
200 isolate, obj_value, Object::ToNumber(obj_value)); | 129 isolate, obj_value, Object::ToNumber(obj_value)); |
201 | 130 |
202 int64_t len = array->length_value(); | 131 int64_t len = array->length_value(); |
203 int64_t start = 0; | 132 int64_t start = 0; |
204 int64_t end = len; | 133 int64_t end = len; |
(...skipping 28 matching lines...) Expand all Loading... |
233 | 162 |
234 return array->GetElementsAccessor()->Fill(isolate, array, obj_value, | 163 return array->GetElementsAccessor()->Fill(isolate, array, obj_value, |
235 static_cast<uint32_t>(start), | 164 static_cast<uint32_t>(start), |
236 static_cast<uint32_t>(end)); | 165 static_cast<uint32_t>(end)); |
237 } | 166 } |
238 | 167 |
239 BUILTIN(TypedArrayPrototypeIncludes) { | 168 BUILTIN(TypedArrayPrototypeIncludes) { |
240 HandleScope scope(isolate); | 169 HandleScope scope(isolate); |
241 | 170 |
242 Handle<JSTypedArray> array; | 171 Handle<JSTypedArray> array; |
243 const char* method = "%TypedArray%.prototype.includes"; | |
244 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 172 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
245 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 173 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
246 | 174 |
247 if (args.length() < 2) return isolate->heap()->false_value(); | 175 if (args.length() < 2) return isolate->heap()->false_value(); |
248 | 176 |
249 int64_t len = array->length_value(); | 177 int64_t len = array->length_value(); |
250 if (len == 0) return isolate->heap()->false_value(); | 178 if (len == 0) return isolate->heap()->false_value(); |
251 | 179 |
252 int64_t index = 0; | 180 int64_t index = 0; |
253 if (args.length() > 2) { | 181 if (args.length() > 2) { |
254 Handle<Object> num; | 182 Handle<Object> num; |
255 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 183 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
(...skipping 10 matching lines...) Expand all Loading... |
266 static_cast<uint32_t>(index), | 194 static_cast<uint32_t>(index), |
267 static_cast<uint32_t>(len)); | 195 static_cast<uint32_t>(len)); |
268 MAYBE_RETURN(result, isolate->heap()->exception()); | 196 MAYBE_RETURN(result, isolate->heap()->exception()); |
269 return *isolate->factory()->ToBoolean(result.FromJust()); | 197 return *isolate->factory()->ToBoolean(result.FromJust()); |
270 } | 198 } |
271 | 199 |
272 BUILTIN(TypedArrayPrototypeIndexOf) { | 200 BUILTIN(TypedArrayPrototypeIndexOf) { |
273 HandleScope scope(isolate); | 201 HandleScope scope(isolate); |
274 | 202 |
275 Handle<JSTypedArray> array; | 203 Handle<JSTypedArray> array; |
276 const char* method = "%TypedArray%.prototype.indexOf"; | |
277 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 204 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
278 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 205 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
279 | 206 |
280 int64_t len = array->length_value(); | 207 int64_t len = array->length_value(); |
281 if (len == 0) return Smi::FromInt(-1); | 208 if (len == 0) return Smi::FromInt(-1); |
282 | 209 |
283 int64_t index = 0; | 210 int64_t index = 0; |
284 if (args.length() > 2) { | 211 if (args.length() > 2) { |
285 Handle<Object> num; | 212 Handle<Object> num; |
286 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 213 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
287 isolate, num, Object::ToInteger(isolate, args.at<Object>(2))); | 214 isolate, num, Object::ToInteger(isolate, args.at<Object>(2))); |
288 index = CapRelativeIndex(num, 0, len); | 215 index = CapRelativeIndex(num, 0, len); |
289 } | 216 } |
290 | 217 |
291 // TODO(cwhan.tunz): throw. See the above comment in CopyWithin. | 218 // TODO(cwhan.tunz): throw. See the above comment in CopyWithin. |
292 if (V8_UNLIKELY(array->WasNeutered())) return Smi::FromInt(-1); | 219 if (V8_UNLIKELY(array->WasNeutered())) return Smi::FromInt(-1); |
293 | 220 |
294 Handle<Object> search_element = args.atOrUndefined(isolate, 1); | 221 Handle<Object> search_element = args.atOrUndefined(isolate, 1); |
295 ElementsAccessor* elements = array->GetElementsAccessor(); | 222 ElementsAccessor* elements = array->GetElementsAccessor(); |
296 Maybe<int64_t> result = elements->IndexOfValue(isolate, array, search_element, | 223 Maybe<int64_t> result = elements->IndexOfValue(isolate, array, search_element, |
297 static_cast<uint32_t>(index), | 224 static_cast<uint32_t>(index), |
298 static_cast<uint32_t>(len)); | 225 static_cast<uint32_t>(len)); |
299 MAYBE_RETURN(result, isolate->heap()->exception()); | 226 MAYBE_RETURN(result, isolate->heap()->exception()); |
300 return *isolate->factory()->NewNumberFromInt64(result.FromJust()); | 227 return *isolate->factory()->NewNumberFromInt64(result.FromJust()); |
301 } | 228 } |
302 | 229 |
303 BUILTIN(TypedArrayPrototypeLastIndexOf) { | 230 BUILTIN(TypedArrayPrototypeLastIndexOf) { |
304 HandleScope scope(isolate); | 231 HandleScope scope(isolate); |
305 | 232 |
306 Handle<JSTypedArray> array; | 233 Handle<JSTypedArray> array; |
307 const char* method = "%TypedArray%.prototype.lastIndexOf"; | |
308 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 234 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
309 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 235 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
310 | 236 |
311 int64_t len = array->length_value(); | 237 int64_t len = array->length_value(); |
312 if (len == 0) return Smi::FromInt(-1); | 238 if (len == 0) return Smi::FromInt(-1); |
313 | 239 |
314 int64_t index = len - 1; | 240 int64_t index = len - 1; |
315 if (args.length() > 2) { | 241 if (args.length() > 2) { |
316 Handle<Object> num; | 242 Handle<Object> num; |
317 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 243 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
318 isolate, num, Object::ToInteger(isolate, args.at<Object>(2))); | 244 isolate, num, Object::ToInteger(isolate, args.at<Object>(2))); |
319 // Set a negative value (-1) for returning -1 if num is negative and | 245 // Set a negative value (-1) for returning -1 if num is negative and |
(...skipping 11 matching lines...) Expand all Loading... |
331 Maybe<int64_t> result = elements->LastIndexOfValue( | 257 Maybe<int64_t> result = elements->LastIndexOfValue( |
332 isolate, array, search_element, static_cast<uint32_t>(index)); | 258 isolate, array, search_element, static_cast<uint32_t>(index)); |
333 MAYBE_RETURN(result, isolate->heap()->exception()); | 259 MAYBE_RETURN(result, isolate->heap()->exception()); |
334 return *isolate->factory()->NewNumberFromInt64(result.FromJust()); | 260 return *isolate->factory()->NewNumberFromInt64(result.FromJust()); |
335 } | 261 } |
336 | 262 |
337 BUILTIN(TypedArrayPrototypeReverse) { | 263 BUILTIN(TypedArrayPrototypeReverse) { |
338 HandleScope scope(isolate); | 264 HandleScope scope(isolate); |
339 | 265 |
340 Handle<JSTypedArray> array; | 266 Handle<JSTypedArray> array; |
341 const char* method = "%TypedArray%.prototype.reverse"; | |
342 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 267 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
343 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 268 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
344 | 269 |
345 if (V8_UNLIKELY(array->WasNeutered())) return *array; | 270 if (V8_UNLIKELY(array->WasNeutered())) return *array; |
346 | 271 |
347 ElementsAccessor* elements = array->GetElementsAccessor(); | 272 ElementsAccessor* elements = array->GetElementsAccessor(); |
348 elements->Reverse(*array); | 273 elements->Reverse(*array); |
349 return *array; | 274 return *array; |
350 } | 275 } |
351 | 276 |
352 BUILTIN(TypedArrayPrototypeSlice) { | 277 BUILTIN(TypedArrayPrototypeSlice) { |
353 HandleScope scope(isolate); | 278 HandleScope scope(isolate); |
354 | 279 |
355 Handle<JSTypedArray> array; | 280 Handle<JSTypedArray> array; |
356 const char* method = "%TypedArray%.prototype.slice"; | |
357 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 281 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
358 isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); | 282 isolate, array, JSTypedArray::Validate(isolate, args.receiver())); |
359 | 283 |
360 int64_t len = array->length_value(); | 284 int64_t len = array->length_value(); |
361 int64_t start = 0; | 285 int64_t start = 0; |
362 int64_t end = len; | 286 int64_t end = len; |
363 { | 287 { |
364 Handle<Object> num = args.atOrUndefined(isolate, 1); | 288 Handle<Object> num = args.atOrUndefined(isolate, 1); |
365 if (!num->IsUndefined(isolate)) { | 289 if (!num->IsUndefined(isolate)) { |
366 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num, | 290 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num, |
367 Object::ToInteger(isolate, num)); | 291 Object::ToInteger(isolate, num)); |
368 start = CapRelativeIndex(num, 0, len); | 292 start = CapRelativeIndex(num, 0, len); |
369 | 293 |
370 num = args.atOrUndefined(isolate, 2); | 294 num = args.atOrUndefined(isolate, 2); |
371 if (!num->IsUndefined(isolate)) { | 295 if (!num->IsUndefined(isolate)) { |
372 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num, | 296 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num, |
373 Object::ToInteger(isolate, num)); | 297 Object::ToInteger(isolate, num)); |
374 end = CapRelativeIndex(num, 0, len); | 298 end = CapRelativeIndex(num, 0, len); |
375 } | 299 } |
376 } | 300 } |
377 } | 301 } |
378 | 302 |
379 int64_t count = std::max<int64_t>(end - start, 0); | 303 int64_t count = std::max<int64_t>(end - start, 0); |
380 | 304 |
381 Handle<JSTypedArray> result_array; | 305 Handle<JSTypedArray> result_array; |
382 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 306 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
383 isolate, result_array, | 307 isolate, result_array, |
384 TypedArraySpeciesCreateByLength(isolate, array, method, count)); | 308 TypedArraySpeciesCreateByLength(isolate, array, count)); |
385 | 309 |
386 // TODO(cwhan.tunz): neutering check of the result_array should be done in | 310 // TODO(cwhan.tunz): neutering check of the result_array should be done in |
387 // TypedArraySpeciesCreate, but currently ValidateTypedArray does not throw | 311 // TypedArraySpeciesCreate, but currently ValidateTypedArray does not throw |
388 // for neutered buffer, so this is a temporary neutering check for the result | 312 // for neutered buffer, so this is a temporary neutering check for the result |
389 // array | 313 // array |
390 if (V8_UNLIKELY(result_array->WasNeutered())) return *result_array; | 314 if (V8_UNLIKELY(result_array->WasNeutered())) return *result_array; |
391 | 315 |
392 // TODO(cwhan.tunz): should throw. | 316 // TODO(cwhan.tunz): should throw. |
393 if (V8_UNLIKELY(array->WasNeutered())) return *result_array; | 317 if (V8_UNLIKELY(array->WasNeutered())) return *result_array; |
394 | 318 |
395 if (count == 0) return *result_array; | 319 if (count == 0) return *result_array; |
396 | 320 |
397 ElementsAccessor* accessor = array->GetElementsAccessor(); | 321 ElementsAccessor* accessor = array->GetElementsAccessor(); |
398 return *accessor->Slice(array, static_cast<uint32_t>(start), | 322 return *accessor->Slice(array, static_cast<uint32_t>(start), |
399 static_cast<uint32_t>(end), result_array); | 323 static_cast<uint32_t>(end), result_array); |
400 } | 324 } |
401 | 325 |
402 } // namespace internal | 326 } // namespace internal |
403 } // namespace v8 | 327 } // namespace v8 |
OLD | NEW |