| 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 |