1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/builtin/Array.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1127 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 + /* ES5 15.4.4.14. */ 1.9 +function ArrayIndexOf(searchElement/*, fromIndex*/) { 1.10 + /* Step 1. */ 1.11 + var O = ToObject(this); 1.12 + 1.13 + /* Steps 2-3. */ 1.14 + var len = TO_UINT32(O.length); 1.15 + 1.16 + /* Step 4. */ 1.17 + if (len === 0) 1.18 + return -1; 1.19 + 1.20 + /* Step 5. */ 1.21 + var n = arguments.length > 1 ? ToInteger(arguments[1]) : 0; 1.22 + 1.23 + /* Step 6. */ 1.24 + if (n >= len) 1.25 + return -1; 1.26 + 1.27 + var k; 1.28 + /* Step 7. */ 1.29 + if (n >= 0) 1.30 + k = n; 1.31 + /* Step 8. */ 1.32 + else { 1.33 + /* Step a. */ 1.34 + k = len + n; 1.35 + /* Step b. */ 1.36 + if (k < 0) 1.37 + k = 0; 1.38 + } 1.39 + 1.40 + /* Step 9. */ 1.41 + if (IsPackedArray(O)) { 1.42 + for (; k < len; k++) { 1.43 + if (O[k] === searchElement) 1.44 + return k; 1.45 + } 1.46 + } else { 1.47 + for (; k < len; k++) { 1.48 + if (k in O && O[k] === searchElement) 1.49 + return k; 1.50 + } 1.51 + } 1.52 + 1.53 + /* Step 10. */ 1.54 + return -1; 1.55 +} 1.56 + 1.57 +function ArrayStaticIndexOf(list, searchElement/*, fromIndex*/) { 1.58 + if (arguments.length < 1) 1.59 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.indexOf'); 1.60 + var fromIndex = arguments.length > 2 ? arguments[2] : 0; 1.61 + return callFunction(ArrayIndexOf, list, searchElement, fromIndex); 1.62 +} 1.63 + 1.64 +/* ES5 15.4.4.15. */ 1.65 +function ArrayLastIndexOf(searchElement/*, fromIndex*/) { 1.66 + /* Step 1. */ 1.67 + var O = ToObject(this); 1.68 + 1.69 + /* Steps 2-3. */ 1.70 + var len = TO_UINT32(O.length); 1.71 + 1.72 + /* Step 4. */ 1.73 + if (len === 0) 1.74 + return -1; 1.75 + 1.76 + /* Step 5. */ 1.77 + var n = arguments.length > 1 ? ToInteger(arguments[1]) : len - 1; 1.78 + 1.79 + /* Steps 6-7. */ 1.80 + var k; 1.81 + if (n > len - 1) 1.82 + k = len - 1; 1.83 + else if (n < 0) 1.84 + k = len + n; 1.85 + else 1.86 + k = n; 1.87 + 1.88 + /* Step 8. */ 1.89 + if (IsPackedArray(O)) { 1.90 + for (; k >= 0; k--) { 1.91 + if (O[k] === searchElement) 1.92 + return k; 1.93 + } 1.94 + } else { 1.95 + for (; k >= 0; k--) { 1.96 + if (k in O && O[k] === searchElement) 1.97 + return k; 1.98 + } 1.99 + } 1.100 + 1.101 + /* Step 9. */ 1.102 + return -1; 1.103 +} 1.104 + 1.105 +function ArrayStaticLastIndexOf(list, searchElement/*, fromIndex*/) { 1.106 + if (arguments.length < 1) 1.107 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.lastIndexOf'); 1.108 + var fromIndex; 1.109 + if (arguments.length > 2) { 1.110 + fromIndex = arguments[2]; 1.111 + } else { 1.112 + var O = ToObject(list); 1.113 + var len = TO_UINT32(O.length); 1.114 + fromIndex = len - 1; 1.115 + } 1.116 + return callFunction(ArrayLastIndexOf, list, searchElement, fromIndex); 1.117 +} 1.118 + 1.119 +/* ES5 15.4.4.16. */ 1.120 +function ArrayEvery(callbackfn/*, thisArg*/) { 1.121 + /* Step 1. */ 1.122 + var O = ToObject(this); 1.123 + 1.124 + /* Steps 2-3. */ 1.125 + var len = TO_UINT32(O.length); 1.126 + 1.127 + /* Step 4. */ 1.128 + if (arguments.length === 0) 1.129 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.every'); 1.130 + if (!IsCallable(callbackfn)) 1.131 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 1.132 + 1.133 + /* Step 5. */ 1.134 + var T = arguments.length > 1 ? arguments[1] : void 0; 1.135 + 1.136 + /* Steps 6-7. */ 1.137 + /* Steps a (implicit), and d. */ 1.138 + for (var k = 0; k < len; k++) { 1.139 + /* Step b */ 1.140 + if (k in O) { 1.141 + /* Step c. */ 1.142 + if (!callFunction(callbackfn, T, O[k], k, O)) 1.143 + return false; 1.144 + } 1.145 + } 1.146 + 1.147 + /* Step 8. */ 1.148 + return true; 1.149 +} 1.150 + 1.151 +function ArrayStaticEvery(list, callbackfn/*, thisArg*/) { 1.152 + if (arguments.length < 2) 1.153 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.every'); 1.154 + if (!IsCallable(callbackfn)) 1.155 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 1.156 + var T = arguments.length > 2 ? arguments[2] : void 0; 1.157 + return callFunction(ArrayEvery, list, callbackfn, T); 1.158 +} 1.159 + 1.160 +/* ES5 15.4.4.17. */ 1.161 +function ArraySome(callbackfn/*, thisArg*/) { 1.162 + /* Step 1. */ 1.163 + var O = ToObject(this); 1.164 + 1.165 + /* Steps 2-3. */ 1.166 + var len = TO_UINT32(O.length); 1.167 + 1.168 + /* Step 4. */ 1.169 + if (arguments.length === 0) 1.170 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.some'); 1.171 + if (!IsCallable(callbackfn)) 1.172 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 1.173 + 1.174 + /* Step 5. */ 1.175 + var T = arguments.length > 1 ? arguments[1] : void 0; 1.176 + 1.177 + /* Steps 6-7. */ 1.178 + /* Steps a (implicit), and d. */ 1.179 + for (var k = 0; k < len; k++) { 1.180 + /* Step b */ 1.181 + if (k in O) { 1.182 + /* Step c. */ 1.183 + if (callFunction(callbackfn, T, O[k], k, O)) 1.184 + return true; 1.185 + } 1.186 + } 1.187 + 1.188 + /* Step 8. */ 1.189 + return false; 1.190 +} 1.191 + 1.192 +function ArrayStaticSome(list, callbackfn/*, thisArg*/) { 1.193 + if (arguments.length < 2) 1.194 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.some'); 1.195 + if (!IsCallable(callbackfn)) 1.196 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 1.197 + var T = arguments.length > 2 ? arguments[2] : void 0; 1.198 + return callFunction(ArraySome, list, callbackfn, T); 1.199 +} 1.200 + 1.201 +/* ES5 15.4.4.18. */ 1.202 +function ArrayForEach(callbackfn/*, thisArg*/) { 1.203 + /* Step 1. */ 1.204 + var O = ToObject(this); 1.205 + 1.206 + /* Steps 2-3. */ 1.207 + var len = TO_UINT32(O.length); 1.208 + 1.209 + /* Step 4. */ 1.210 + if (arguments.length === 0) 1.211 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.forEach'); 1.212 + if (!IsCallable(callbackfn)) 1.213 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 1.214 + 1.215 + /* Step 5. */ 1.216 + var T = arguments.length > 1 ? arguments[1] : void 0; 1.217 + 1.218 + /* Steps 6-7. */ 1.219 + /* Steps a (implicit), and d. */ 1.220 + for (var k = 0; k < len; k++) { 1.221 + /* Step b */ 1.222 + if (k in O) { 1.223 + /* Step c. */ 1.224 + callFunction(callbackfn, T, O[k], k, O); 1.225 + } 1.226 + } 1.227 + 1.228 + /* Step 8. */ 1.229 + return void 0; 1.230 +} 1.231 + 1.232 +/* ES5 15.4.4.19. */ 1.233 +function ArrayMap(callbackfn/*, thisArg*/) { 1.234 + /* Step 1. */ 1.235 + var O = ToObject(this); 1.236 + 1.237 + /* Step 2-3. */ 1.238 + var len = TO_UINT32(O.length); 1.239 + 1.240 + /* Step 4. */ 1.241 + if (arguments.length === 0) 1.242 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.map'); 1.243 + if (!IsCallable(callbackfn)) 1.244 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 1.245 + 1.246 + /* Step 5. */ 1.247 + var T = arguments.length > 1 ? arguments[1] : void 0; 1.248 + 1.249 + /* Step 6. */ 1.250 + var A = NewDenseArray(len); 1.251 + 1.252 + /* Step 7-8. */ 1.253 + /* Step a (implicit), and d. */ 1.254 + for (var k = 0; k < len; k++) { 1.255 + /* Step b */ 1.256 + if (k in O) { 1.257 + /* Step c.i-iii. */ 1.258 + var mappedValue = callFunction(callbackfn, T, O[k], k, O); 1.259 + // UnsafePutElements doesn't invoke setters, so we can use it here. 1.260 + UnsafePutElements(A, k, mappedValue); 1.261 + } 1.262 + } 1.263 + 1.264 + /* Step 9. */ 1.265 + return A; 1.266 +} 1.267 + 1.268 +function ArrayStaticMap(list, callbackfn/*, thisArg*/) { 1.269 + if (arguments.length < 2) 1.270 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.map'); 1.271 + if (!IsCallable(callbackfn)) 1.272 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 1.273 + var T = arguments.length > 2 ? arguments[2] : void 0; 1.274 + return callFunction(ArrayMap, list, callbackfn, T); 1.275 +} 1.276 + 1.277 +function ArrayStaticForEach(list, callbackfn/*, thisArg*/) { 1.278 + if (arguments.length < 2) 1.279 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.forEach'); 1.280 + if (!IsCallable(callbackfn)) 1.281 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 1.282 + var T = arguments.length > 2 ? arguments[2] : void 0; 1.283 + callFunction(ArrayForEach, list, callbackfn, T); 1.284 +} 1.285 + 1.286 +/* ES5 15.4.4.21. */ 1.287 +function ArrayReduce(callbackfn/*, initialValue*/) { 1.288 + /* Step 1. */ 1.289 + var O = ToObject(this); 1.290 + 1.291 + /* Steps 2-3. */ 1.292 + var len = TO_UINT32(O.length); 1.293 + 1.294 + /* Step 4. */ 1.295 + if (arguments.length === 0) 1.296 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce'); 1.297 + if (!IsCallable(callbackfn)) 1.298 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 1.299 + 1.300 + /* Step 6. */ 1.301 + var k = 0; 1.302 + 1.303 + /* Steps 5, 7-8. */ 1.304 + var accumulator; 1.305 + if (arguments.length > 1) { 1.306 + accumulator = arguments[1]; 1.307 + } else { 1.308 + /* Step 5. */ 1.309 + if (len === 0) 1.310 + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); 1.311 + if (IsPackedArray(O)) { 1.312 + accumulator = O[k++]; 1.313 + } else { 1.314 + var kPresent = false; 1.315 + for (; k < len; k++) { 1.316 + if (k in O) { 1.317 + accumulator = O[k]; 1.318 + kPresent = true; 1.319 + k++; 1.320 + break; 1.321 + } 1.322 + } 1.323 + if (!kPresent) 1.324 + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); 1.325 + } 1.326 + } 1.327 + 1.328 + /* Step 9. */ 1.329 + /* Steps a (implicit), and d. */ 1.330 + for (; k < len; k++) { 1.331 + /* Step b */ 1.332 + if (k in O) { 1.333 + /* Step c. */ 1.334 + accumulator = callbackfn(accumulator, O[k], k, O); 1.335 + } 1.336 + } 1.337 + 1.338 + /* Step 10. */ 1.339 + return accumulator; 1.340 +} 1.341 + 1.342 +function ArrayStaticReduce(list, callbackfn) { 1.343 + if (arguments.length < 2) 1.344 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduce'); 1.345 + if (!IsCallable(callbackfn)) 1.346 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 1.347 + if (arguments.length > 2) 1.348 + return callFunction(ArrayReduce, list, callbackfn, arguments[2]); 1.349 + else 1.350 + return callFunction(ArrayReduce, list, callbackfn); 1.351 +} 1.352 + 1.353 +/* ES5 15.4.4.22. */ 1.354 +function ArrayReduceRight(callbackfn/*, initialValue*/) { 1.355 + /* Step 1. */ 1.356 + var O = ToObject(this); 1.357 + 1.358 + /* Steps 2-3. */ 1.359 + var len = TO_UINT32(O.length); 1.360 + 1.361 + /* Step 4. */ 1.362 + if (arguments.length === 0) 1.363 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce'); 1.364 + if (!IsCallable(callbackfn)) 1.365 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 1.366 + 1.367 + /* Step 6. */ 1.368 + var k = len - 1; 1.369 + 1.370 + /* Steps 5, 7-8. */ 1.371 + var accumulator; 1.372 + if (arguments.length > 1) { 1.373 + accumulator = arguments[1]; 1.374 + } else { 1.375 + /* Step 5. */ 1.376 + if (len === 0) 1.377 + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); 1.378 + if (IsPackedArray(O)) { 1.379 + accumulator = O[k--]; 1.380 + } else { 1.381 + var kPresent = false; 1.382 + for (; k >= 0; k--) { 1.383 + if (k in O) { 1.384 + accumulator = O[k]; 1.385 + kPresent = true; 1.386 + k--; 1.387 + break; 1.388 + } 1.389 + } 1.390 + if (!kPresent) 1.391 + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); 1.392 + } 1.393 + } 1.394 + 1.395 + /* Step 9. */ 1.396 + /* Steps a (implicit), and d. */ 1.397 + for (; k >= 0; k--) { 1.398 + /* Step b */ 1.399 + if (k in O) { 1.400 + /* Step c. */ 1.401 + accumulator = callbackfn(accumulator, O[k], k, O); 1.402 + } 1.403 + } 1.404 + 1.405 + /* Step 10. */ 1.406 + return accumulator; 1.407 +} 1.408 + 1.409 +function ArrayStaticReduceRight(list, callbackfn) { 1.410 + if (arguments.length < 2) 1.411 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduceRight'); 1.412 + if (!IsCallable(callbackfn)) 1.413 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn)); 1.414 + if (arguments.length > 2) 1.415 + return callFunction(ArrayReduceRight, list, callbackfn, arguments[2]); 1.416 + else 1.417 + return callFunction(ArrayReduceRight, list, callbackfn); 1.418 +} 1.419 + 1.420 +/* ES6 draft 2013-05-14 15.4.3.23. */ 1.421 +function ArrayFind(predicate/*, thisArg*/) { 1.422 + /* Steps 1-2. */ 1.423 + var O = ToObject(this); 1.424 + 1.425 + /* Steps 3-5. */ 1.426 + var len = ToInteger(O.length); 1.427 + 1.428 + /* Step 6. */ 1.429 + if (arguments.length === 0) 1.430 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.find'); 1.431 + if (!IsCallable(predicate)) 1.432 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); 1.433 + 1.434 + /* Step 7. */ 1.435 + var T = arguments.length > 1 ? arguments[1] : undefined; 1.436 + 1.437 + /* Steps 8-9. */ 1.438 + /* Steps a (implicit), and e. */ 1.439 + /* Note: this will hang in some corner-case situations, because of IEEE-754 numbers' 1.440 + * imprecision for large values. Example: 1.441 + * var obj = { 18014398509481984: true, length: 18014398509481988 }; 1.442 + * Array.prototype.find.call(obj, () => true); 1.443 + */ 1.444 + for (var k = 0; k < len; k++) { 1.445 + /* Steps b and c (implicit) */ 1.446 + if (k in O) { 1.447 + /* Step d. */ 1.448 + var kValue = O[k]; 1.449 + if (callFunction(predicate, T, kValue, k, O)) 1.450 + return kValue; 1.451 + } 1.452 + } 1.453 + 1.454 + /* Step 10. */ 1.455 + return undefined; 1.456 +} 1.457 + 1.458 +/* ES6 draft 2013-05-14 15.4.3.23. */ 1.459 +function ArrayFindIndex(predicate/*, thisArg*/) { 1.460 + /* Steps 1-2. */ 1.461 + var O = ToObject(this); 1.462 + 1.463 + /* Steps 3-5. */ 1.464 + var len = ToInteger(O.length); 1.465 + 1.466 + /* Step 6. */ 1.467 + if (arguments.length === 0) 1.468 + ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.find'); 1.469 + if (!IsCallable(predicate)) 1.470 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); 1.471 + 1.472 + /* Step 7. */ 1.473 + var T = arguments.length > 1 ? arguments[1] : undefined; 1.474 + 1.475 + /* Steps 8-9. */ 1.476 + /* Steps a (implicit), and e. */ 1.477 + /* Note: this will hang in some corner-case situations, because of IEEE-754 numbers' 1.478 + * imprecision for large values. Example: 1.479 + * var obj = { 18014398509481984: true, length: 18014398509481988 }; 1.480 + * Array.prototype.find.call(obj, () => true); 1.481 + */ 1.482 + for (var k = 0; k < len; k++) { 1.483 + /* Steps b and c (implicit) */ 1.484 + if (k in O) { 1.485 + /* Step d. */ 1.486 + if (callFunction(predicate, T, O[k], k, O)) 1.487 + return k; 1.488 + } 1.489 + } 1.490 + 1.491 + /* Step 10. */ 1.492 + return -1; 1.493 +} 1.494 + 1.495 +// ES6 draft 2014-04-05 22.1.3.6 1.496 +function ArrayFill(value, start = 0, end = undefined) { 1.497 + // Steps 1-2. 1.498 + var O = ToObject(this); 1.499 + 1.500 + // Steps 3-5. 1.501 + // FIXME: Array operations should use ToLength (bug 924058). 1.502 + var len = ToInteger(O.length); 1.503 + 1.504 + // Steps 6-7. 1.505 + var relativeStart = ToInteger(start); 1.506 + 1.507 + // Step 8. 1.508 + var k = relativeStart < 0 1.509 + ? std_Math_max(len + relativeStart, 0) 1.510 + : std_Math_min(relativeStart, len); 1.511 + 1.512 + // Steps 9-10. 1.513 + var relativeEnd = end === undefined ? len : ToInteger(end); 1.514 + 1.515 + // Step 11. 1.516 + var final = relativeEnd < 0 1.517 + ? std_Math_max(len + relativeEnd, 0) 1.518 + : std_Math_min(relativeEnd, len); 1.519 + 1.520 + // Step 12. 1.521 + for (; k < final; k++) { 1.522 + O[k] = value; 1.523 + } 1.524 + 1.525 + // Step 13. 1.526 + return O; 1.527 +} 1.528 + 1.529 +#define ARRAY_ITERATOR_SLOT_ITERATED_OBJECT 0 1.530 +#define ARRAY_ITERATOR_SLOT_NEXT_INDEX 1 1.531 +#define ARRAY_ITERATOR_SLOT_ITEM_KIND 2 1.532 + 1.533 +#define ITEM_KIND_VALUE 0 1.534 +#define ITEM_KIND_KEY_AND_VALUE 1 1.535 +#define ITEM_KIND_KEY 2 1.536 + 1.537 +// ES6 draft specification, section 22.1.5.1, version 2013-09-05. 1.538 +function CreateArrayIteratorAt(obj, kind, n) { 1.539 + var iteratedObject = ToObject(obj); 1.540 + var iterator = NewArrayIterator(); 1.541 + UnsafeSetReservedSlot(iterator, ARRAY_ITERATOR_SLOT_ITERATED_OBJECT, iteratedObject); 1.542 + UnsafeSetReservedSlot(iterator, ARRAY_ITERATOR_SLOT_NEXT_INDEX, n); 1.543 + UnsafeSetReservedSlot(iterator, ARRAY_ITERATOR_SLOT_ITEM_KIND, kind); 1.544 + return iterator; 1.545 +} 1.546 +function CreateArrayIterator(obj, kind) { 1.547 + return CreateArrayIteratorAt(obj, kind, 0); 1.548 +} 1.549 + 1.550 +function ArrayIteratorIdentity() { 1.551 + return this; 1.552 +} 1.553 + 1.554 +function ArrayIteratorNext() { 1.555 + // FIXME: ArrayIterator prototype should not pass this test. Bug 924059. 1.556 + if (!IsObject(this) || !IsArrayIterator(this)) 1.557 + ThrowError(JSMSG_INCOMPATIBLE_METHOD, "ArrayIterator", "next", ToString(this)); 1.558 + 1.559 + var a = UnsafeGetReservedSlot(this, ARRAY_ITERATOR_SLOT_ITERATED_OBJECT); 1.560 + var index = UnsafeGetReservedSlot(this, ARRAY_ITERATOR_SLOT_NEXT_INDEX); 1.561 + var itemKind = UnsafeGetReservedSlot(this, ARRAY_ITERATOR_SLOT_ITEM_KIND); 1.562 + 1.563 + // FIXME: This should be ToLength, which clamps at 2**53. Bug 924058. 1.564 + if (index >= TO_UINT32(a.length)) { 1.565 + // When the above is changed to ToLength, use +1/0 here instead 1.566 + // of MAX_UINT32. 1.567 + UnsafeSetReservedSlot(this, ARRAY_ITERATOR_SLOT_NEXT_INDEX, 0xffffffff); 1.568 + return { value: undefined, done: true }; 1.569 + } 1.570 + 1.571 + UnsafeSetReservedSlot(this, ARRAY_ITERATOR_SLOT_NEXT_INDEX, index + 1); 1.572 + 1.573 + if (itemKind === ITEM_KIND_VALUE) 1.574 + return { value: a[index], done: false }; 1.575 + 1.576 + if (itemKind === ITEM_KIND_KEY_AND_VALUE) { 1.577 + var pair = NewDenseArray(2); 1.578 + pair[0] = index; 1.579 + pair[1] = a[index]; 1.580 + return { value: pair, done : false }; 1.581 + } 1.582 + 1.583 + assert(itemKind === ITEM_KIND_KEY, itemKind); 1.584 + return { value: index, done: false }; 1.585 +} 1.586 + 1.587 +function ArrayValuesAt(n) { 1.588 + return CreateArrayIteratorAt(this, ITEM_KIND_VALUE, n); 1.589 +} 1.590 + 1.591 +function ArrayValues() { 1.592 + return CreateArrayIterator(this, ITEM_KIND_VALUE); 1.593 +} 1.594 + 1.595 +function ArrayEntries() { 1.596 + return CreateArrayIterator(this, ITEM_KIND_KEY_AND_VALUE); 1.597 +} 1.598 + 1.599 +function ArrayKeys() { 1.600 + return CreateArrayIterator(this, ITEM_KIND_KEY); 1.601 +} 1.602 + 1.603 +#ifdef ENABLE_PARALLEL_JS 1.604 + 1.605 +/* 1.606 + * Strawman spec: 1.607 + * http://wiki.ecmascript.org/doku.php?id=strawman:data_parallelism 1.608 + */ 1.609 + 1.610 +/** 1.611 + * Creates a new array by applying |func(e, i, self)| for each element |e| 1.612 + * with index |i|. 1.613 + */ 1.614 +function ArrayMapPar(func, mode) { 1.615 + if (!IsCallable(func)) 1.616 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func)); 1.617 + 1.618 + var self = ToObject(this); 1.619 + var length = self.length; 1.620 + var buffer = NewDenseArray(length); 1.621 + 1.622 + parallel: for (;;) { 1.623 + // Avoid parallel compilation if we are already nested in another 1.624 + // parallel section or the user told us not to parallelize. The 1.625 + // use of a for (;;) loop is working around some ion limitations: 1.626 + // 1.627 + // - Breaking out of named blocks does not currently work (bug 684384); 1.628 + // - Unreachable Code Elim. can't properly handle if (a && b) (bug 669796) 1.629 + if (ShouldForceSequential()) 1.630 + break parallel; 1.631 + if (!TRY_PARALLEL(mode)) 1.632 + break parallel; 1.633 + 1.634 + var slicesInfo = ComputeSlicesInfo(length); 1.635 + ForkJoin(mapThread, 0, slicesInfo.count, ForkJoinMode(mode)); 1.636 + return buffer; 1.637 + } 1.638 + 1.639 + // Sequential fallback: 1.640 + ASSERT_SEQUENTIAL_IS_OK(mode); 1.641 + for (var i = 0; i < length; i++) 1.642 + UnsafePutElements(buffer, i, func(self[i], i, self)); 1.643 + return buffer; 1.644 + 1.645 + function mapThread(workerId, sliceStart, sliceEnd) { 1.646 + var sliceShift = slicesInfo.shift; 1.647 + var sliceId; 1.648 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.649 + var indexStart = SLICE_START_INDEX(sliceShift, sliceId); 1.650 + var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length); 1.651 + for (var i = indexStart; i < indexEnd; i++) 1.652 + UnsafePutElements(buffer, i, func(self[i], i, self)); 1.653 + } 1.654 + return sliceId; 1.655 + } 1.656 + 1.657 + return undefined; 1.658 +} 1.659 + 1.660 +/** 1.661 + * Reduces the elements in an array in parallel. Order is not fixed and |func| 1.662 + * is assumed to be associative. 1.663 + */ 1.664 +function ArrayReducePar(func, mode) { 1.665 + if (!IsCallable(func)) 1.666 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func)); 1.667 + 1.668 + var self = ToObject(this); 1.669 + var length = self.length; 1.670 + 1.671 + if (length === 0) 1.672 + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); 1.673 + 1.674 + parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc 1.675 + if (ShouldForceSequential()) 1.676 + break parallel; 1.677 + if (!TRY_PARALLEL(mode)) 1.678 + break parallel; 1.679 + 1.680 + var slicesInfo = ComputeSlicesInfo(length); 1.681 + var numSlices = slicesInfo.count; 1.682 + var subreductions = NewDenseArray(numSlices); 1.683 + 1.684 + ForkJoin(reduceThread, 0, numSlices, ForkJoinMode(mode)); 1.685 + 1.686 + var accumulator = subreductions[0]; 1.687 + for (var i = 1; i < numSlices; i++) 1.688 + accumulator = func(accumulator, subreductions[i]); 1.689 + return accumulator; 1.690 + } 1.691 + 1.692 + // Sequential fallback: 1.693 + ASSERT_SEQUENTIAL_IS_OK(mode); 1.694 + var accumulator = self[0]; 1.695 + for (var i = 1; i < length; i++) 1.696 + accumulator = func(accumulator, self[i]); 1.697 + return accumulator; 1.698 + 1.699 + function reduceThread(workerId, sliceStart, sliceEnd) { 1.700 + var sliceShift = slicesInfo.shift; 1.701 + var sliceId; 1.702 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.703 + var indexStart = SLICE_START_INDEX(sliceShift, sliceId); 1.704 + var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length); 1.705 + var accumulator = self[indexStart]; 1.706 + for (var i = indexStart + 1; i < indexEnd; i++) 1.707 + accumulator = func(accumulator, self[i]); 1.708 + UnsafePutElements(subreductions, sliceId, accumulator); 1.709 + } 1.710 + return sliceId; 1.711 + } 1.712 + 1.713 + return undefined; 1.714 +} 1.715 + 1.716 +/** 1.717 + * Returns an array [s_0, ..., s_N] where |s_i| is equal to the reduction (as 1.718 + * per |reduce()|) of elements |0..i|. This is the generalization of partial 1.719 + * sum. 1.720 + */ 1.721 +function ArrayScanPar(func, mode) { 1.722 + if (!IsCallable(func)) 1.723 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func)); 1.724 + 1.725 + var self = ToObject(this); 1.726 + var length = self.length; 1.727 + 1.728 + if (length === 0) 1.729 + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); 1.730 + 1.731 + var buffer = NewDenseArray(length); 1.732 + 1.733 + parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc 1.734 + if (ShouldForceSequential()) 1.735 + break parallel; 1.736 + if (!TRY_PARALLEL(mode)) 1.737 + break parallel; 1.738 + 1.739 + var slicesInfo = ComputeSlicesInfo(length); 1.740 + var numSlices = slicesInfo.count; 1.741 + 1.742 + // Scan slices individually (see comment on phase1()). 1.743 + ForkJoin(phase1, 0, numSlices, ForkJoinMode(mode)); 1.744 + 1.745 + // Compute intermediates array (see comment on phase2()). 1.746 + var intermediates = []; 1.747 + var accumulator = buffer[finalElement(0)]; 1.748 + ARRAY_PUSH(intermediates, accumulator); 1.749 + for (var i = 1; i < numSlices - 1; i++) { 1.750 + accumulator = func(accumulator, buffer[finalElement(i)]); 1.751 + ARRAY_PUSH(intermediates, accumulator); 1.752 + } 1.753 + 1.754 + // Complete each slice using intermediates array (see comment on phase2()). 1.755 + // 1.756 + // We start from slice 1 instead of 0 since there is no work to be done 1.757 + // for slice 0. 1.758 + if (numSlices > 1) 1.759 + ForkJoin(phase2, 1, numSlices, ForkJoinMode(mode)); 1.760 + return buffer; 1.761 + } 1.762 + 1.763 + // Sequential fallback: 1.764 + ASSERT_SEQUENTIAL_IS_OK(mode); 1.765 + scan(self[0], 0, length); 1.766 + return buffer; 1.767 + 1.768 + function scan(accumulator, start, end) { 1.769 + UnsafePutElements(buffer, start, accumulator); 1.770 + for (var i = start + 1; i < end; i++) { 1.771 + accumulator = func(accumulator, self[i]); 1.772 + UnsafePutElements(buffer, i, accumulator); 1.773 + } 1.774 + return accumulator; 1.775 + } 1.776 + 1.777 + /** 1.778 + * In phase 1, we divide the source array into |numSlices| slices and 1.779 + * compute scan on each slice sequentially as if it were the entire 1.780 + * array. This function is responsible for computing one of those 1.781 + * slices. 1.782 + * 1.783 + * So, if we have an array [A,B,C,D,E,F,G,H,I], |numSlices === 3|, 1.784 + * and our function |func| is sum, then we would wind up computing a 1.785 + * result array like: 1.786 + * 1.787 + * [A, A+B, A+B+C, D, D+E, D+E+F, G, G+H, G+H+I] 1.788 + * ^~~~~~~~~~~~^ ^~~~~~~~~~~~^ ^~~~~~~~~~~~~^ 1.789 + * Slice 0 Slice 1 Slice 2 1.790 + * 1.791 + * Read on in phase2 to see what we do next! 1.792 + */ 1.793 + function phase1(workerId, sliceStart, sliceEnd) { 1.794 + var sliceShift = slicesInfo.shift; 1.795 + var sliceId; 1.796 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.797 + var indexStart = SLICE_START_INDEX(sliceShift, sliceId); 1.798 + var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length); 1.799 + scan(self[indexStart], indexStart, indexEnd); 1.800 + } 1.801 + return sliceId; 1.802 + } 1.803 + 1.804 + /** 1.805 + * Computes the index of the final element computed by the slice |sliceId|. 1.806 + */ 1.807 + function finalElement(sliceId) { 1.808 + var sliceShift = slicesInfo.shift; 1.809 + return SLICE_END_INDEX(sliceShift, SLICE_START_INDEX(sliceShift, sliceId), length) - 1; 1.810 + } 1.811 + 1.812 + /** 1.813 + * After computing the phase1 results, we compute an 1.814 + * |intermediates| array. |intermediates[i]| contains the result 1.815 + * of reducing the final value from each preceding slice j<i with 1.816 + * the final value of slice i. So, to continue our previous 1.817 + * example, the intermediates array would contain: 1.818 + * 1.819 + * [A+B+C, (A+B+C)+(D+E+F), ((A+B+C)+(D+E+F))+(G+H+I)] 1.820 + * 1.821 + * Here I have used parenthesization to make clear the order of 1.822 + * evaluation in each case. 1.823 + * 1.824 + * An aside: currently the intermediates array is computed 1.825 + * sequentially. In principle, we could compute it in parallel, 1.826 + * at the cost of doing duplicate work. This did not seem 1.827 + * particularly advantageous to me, particularly as the number 1.828 + * of slices is typically quite small (one per core), so I opted 1.829 + * to just compute it sequentially. 1.830 + * 1.831 + * Phase 2 combines the results of phase1 with the intermediates 1.832 + * array to produce the final scan results. The idea is to 1.833 + * reiterate over each element S[i] in the slice |sliceId|, which 1.834 + * currently contains the result of reducing with S[0]...S[i] 1.835 + * (where S0 is the first thing in the slice), and combine that 1.836 + * with |intermediate[sliceId-1]|, which represents the result of 1.837 + * reducing everything in the input array prior to the slice. 1.838 + * 1.839 + * To continue with our example, in phase 1 we computed slice 1 to 1.840 + * be [D, D+E, D+E+F]. We will combine those results with 1.841 + * |intermediates[1-1]|, which is |A+B+C|, so that the final 1.842 + * result is [(A+B+C)+D, (A+B+C)+(D+E), (A+B+C)+(D+E+F)]. Again I 1.843 + * am using parentheses to clarify how these results were reduced. 1.844 + */ 1.845 + function phase2(workerId, sliceStart, sliceEnd) { 1.846 + var sliceShift = slicesInfo.shift; 1.847 + var sliceId; 1.848 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.849 + var indexPos = SLICE_START_INDEX(sliceShift, sliceId); 1.850 + var indexEnd = SLICE_END_INDEX(sliceShift, indexPos, length); 1.851 + var intermediate = intermediates[sliceId - 1]; 1.852 + for (; indexPos < indexEnd; indexPos++) 1.853 + UnsafePutElements(buffer, indexPos, func(intermediate, buffer[indexPos])); 1.854 + } 1.855 + return sliceId; 1.856 + } 1.857 + 1.858 + return undefined; 1.859 +} 1.860 + 1.861 +/** 1.862 + * |scatter()| redistributes the elements in the array into a new array. 1.863 + * 1.864 + * - targets: The index targets[i] indicates where the ith element 1.865 + * should appear in the result. 1.866 + * 1.867 + * - defaultValue: what value to use for indices in the output array that 1.868 + * are never targeted. 1.869 + * 1.870 + * - conflictFunc: The conflict function. Used to resolve what 1.871 + * happens if two indices i and j in the source array are targeted 1.872 + * as the same destination (i.e., targets[i] === targets[j]), then 1.873 + * the final result is determined by applying func(targets[i], 1.874 + * targets[j]). If no conflict function is provided, it is an error 1.875 + * if targets[i] === targets[j]. 1.876 + * 1.877 + * - length: length of the output array (if not specified, uses the 1.878 + * length of the input). 1.879 + * 1.880 + * - mode: internal debugging specification. 1.881 + */ 1.882 +function ArrayScatterPar(targets, defaultValue, conflictFunc, length, mode) { 1.883 + if (conflictFunc && !IsCallable(conflictFunc)) 1.884 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(2, conflictFunc)); 1.885 + 1.886 + var self = ToObject(this); 1.887 + 1.888 + if (length === undefined) 1.889 + length = self.length; 1.890 + 1.891 + var targetsLength = std_Math_min(targets.length, self.length); 1.892 + 1.893 + if (!IS_UINT32(targetsLength) || !IS_UINT32(length)) 1.894 + ThrowError(JSMSG_BAD_ARRAY_LENGTH); 1.895 + 1.896 + // FIXME: Bug 965609: Find a better parallel startegy for scatter. 1.897 + 1.898 + // Sequential fallback: 1.899 + ASSERT_SEQUENTIAL_IS_OK(mode); 1.900 + return seq(); 1.901 + 1.902 + function seq() { 1.903 + var buffer = NewDenseArray(length); 1.904 + var conflicts = NewDenseArray(length); 1.905 + 1.906 + for (var i = 0; i < length; i++) { 1.907 + UnsafePutElements(buffer, i, defaultValue); 1.908 + UnsafePutElements(conflicts, i, false); 1.909 + } 1.910 + 1.911 + for (var i = 0; i < targetsLength; i++) { 1.912 + var x = self[i]; 1.913 + var t = checkTarget(i, targets[i]); 1.914 + if (conflicts[t]) 1.915 + x = collide(x, buffer[t]); 1.916 + 1.917 + UnsafePutElements(buffer, t, x, conflicts, t, true); 1.918 + } 1.919 + 1.920 + return buffer; 1.921 + } 1.922 + 1.923 + function collide(elem1, elem2) { 1.924 + if (conflictFunc === undefined) 1.925 + ThrowError(JSMSG_PAR_ARRAY_SCATTER_CONFLICT); 1.926 + 1.927 + return conflictFunc(elem1, elem2); 1.928 + } 1.929 + 1.930 + function checkTarget(i, t) { 1.931 + if (TO_INT32(t) !== t) 1.932 + ThrowError(JSMSG_PAR_ARRAY_SCATTER_BAD_TARGET, i); 1.933 + 1.934 + if (t < 0 || t >= length) 1.935 + ThrowError(JSMSG_PAR_ARRAY_SCATTER_BOUNDS); 1.936 + 1.937 + // It's not enough to return t, as -0 | 0 === -0. 1.938 + return TO_INT32(t); 1.939 + } 1.940 + 1.941 + return undefined; 1.942 +} 1.943 + 1.944 +/** 1.945 + * The filter operation applied in parallel. 1.946 + */ 1.947 +function ArrayFilterPar(func, mode) { 1.948 + if (!IsCallable(func)) 1.949 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, func)); 1.950 + 1.951 + var self = ToObject(this); 1.952 + var length = self.length; 1.953 + 1.954 + parallel: for (;;) { // see ArrayMapPar() to explain why for(;;) etc 1.955 + if (ShouldForceSequential()) 1.956 + break parallel; 1.957 + if (!TRY_PARALLEL(mode)) 1.958 + break parallel; 1.959 + 1.960 + var slicesInfo = ComputeSlicesInfo(length); 1.961 + 1.962 + // Step 1. Compute which items from each slice of the result buffer should 1.963 + // be preserved. When we're done, we have a uint8 array |survivors| 1.964 + // containing 0 or 1 for each source element, indicating which members of 1.965 + // the chunk survived. We also keep an array |counts| containing the total 1.966 + // number of items that are being preserved from within one slice. 1.967 + var numSlices = slicesInfo.count; 1.968 + var counts = NewDenseArray(numSlices); 1.969 + for (var i = 0; i < numSlices; i++) 1.970 + UnsafePutElements(counts, i, 0); 1.971 + 1.972 + var survivors = new Uint8Array(length); 1.973 + ForkJoin(findSurvivorsThread, 0, numSlices, ForkJoinMode(mode)); 1.974 + 1.975 + // Step 2. Compress the slices into one contiguous set. 1.976 + var count = 0; 1.977 + for (var i = 0; i < numSlices; i++) 1.978 + count += counts[i]; 1.979 + var buffer = NewDenseArray(count); 1.980 + if (count > 0) 1.981 + ForkJoin(copySurvivorsThread, 0, numSlices, ForkJoinMode(mode)); 1.982 + 1.983 + return buffer; 1.984 + } 1.985 + 1.986 + // Sequential fallback: 1.987 + ASSERT_SEQUENTIAL_IS_OK(mode); 1.988 + var buffer = []; 1.989 + for (var i = 0; i < length; i++) { 1.990 + var elem = self[i]; 1.991 + if (func(elem, i, self)) 1.992 + ARRAY_PUSH(buffer, elem); 1.993 + } 1.994 + return buffer; 1.995 + 1.996 + /** 1.997 + * As described above, our goal is to determine which items we will preserve 1.998 + * from a given slice, storing "to-keep" bits into 32-bit chunks. 1.999 + */ 1.1000 + function findSurvivorsThread(workerId, sliceStart, sliceEnd) { 1.1001 + var sliceShift = slicesInfo.shift; 1.1002 + var sliceId; 1.1003 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.1004 + var count = 0; 1.1005 + var indexStart = SLICE_START_INDEX(sliceShift, sliceId); 1.1006 + var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length); 1.1007 + for (var indexPos = indexStart; indexPos < indexEnd; indexPos++) { 1.1008 + var keep = !!func(self[indexPos], indexPos, self); 1.1009 + UnsafePutElements(survivors, indexPos, keep); 1.1010 + count += keep; 1.1011 + } 1.1012 + UnsafePutElements(counts, sliceId, count); 1.1013 + } 1.1014 + return sliceId; 1.1015 + } 1.1016 + 1.1017 + /** 1.1018 + * Copies the survivors from this slice into the correct position. Note 1.1019 + * that this is an idempotent operation that does not invoke user 1.1020 + * code. Therefore, we don't expect bailouts and make an effort to proceed 1.1021 + * chunk by chunk or avoid duplicating work. 1.1022 + */ 1.1023 + function copySurvivorsThread(workerId, sliceStart, sliceEnd) { 1.1024 + var sliceShift = slicesInfo.shift; 1.1025 + var sliceId; 1.1026 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.1027 + // Total up the items preserved by previous slices. 1.1028 + var total = 0; 1.1029 + for (var i = 0; i < sliceId + 1; i++) 1.1030 + total += counts[i]; 1.1031 + 1.1032 + // Are we done? 1.1033 + var count = total - counts[sliceId]; 1.1034 + if (count === total) 1.1035 + continue; 1.1036 + 1.1037 + var indexStart = SLICE_START_INDEX(sliceShift, sliceId); 1.1038 + var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length); 1.1039 + for (var indexPos = indexStart; indexPos < indexEnd; indexPos++) { 1.1040 + if (survivors[indexPos]) { 1.1041 + UnsafePutElements(buffer, count++, self[indexPos]); 1.1042 + if (count == total) 1.1043 + break; 1.1044 + } 1.1045 + } 1.1046 + } 1.1047 + 1.1048 + return sliceId; 1.1049 + } 1.1050 + 1.1051 + return undefined; 1.1052 +} 1.1053 + 1.1054 +/** 1.1055 + * "Comprehension form": This is the function invoked for 1.1056 + * |Array.{build,buildPar}(len, fn)| It creates a new array with length |len| 1.1057 + * where index |i| is equal to |fn(i)|. 1.1058 + * 1.1059 + * The final |mode| argument is an internal argument used only during our 1.1060 + * unit-testing. 1.1061 + */ 1.1062 +function ArrayStaticBuild(length, func) { 1.1063 + if (!IS_UINT32(length)) 1.1064 + ThrowError(JSMSG_BAD_ARRAY_LENGTH); 1.1065 + if (!IsCallable(func)) 1.1066 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, func)); 1.1067 + 1.1068 + var buffer = NewDenseArray(length); 1.1069 + 1.1070 + for (var i = 0; i < length; i++) 1.1071 + UnsafePutElements(buffer, i, func(i)); 1.1072 + 1.1073 + return buffer; 1.1074 +} 1.1075 + 1.1076 +function ArrayStaticBuildPar(length, func, mode) { 1.1077 + if (!IS_UINT32(length)) 1.1078 + ThrowError(JSMSG_BAD_ARRAY_LENGTH); 1.1079 + if (!IsCallable(func)) 1.1080 + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(1, func)); 1.1081 + 1.1082 + var buffer = NewDenseArray(length); 1.1083 + 1.1084 + parallel: for (;;) { 1.1085 + if (ShouldForceSequential()) 1.1086 + break parallel; 1.1087 + if (!TRY_PARALLEL(mode)) 1.1088 + break parallel; 1.1089 + 1.1090 + var slicesInfo = ComputeSlicesInfo(length); 1.1091 + ForkJoin(constructThread, 0, slicesInfo.count, ForkJoinMode(mode)); 1.1092 + return buffer; 1.1093 + } 1.1094 + 1.1095 + // Sequential fallback: 1.1096 + ASSERT_SEQUENTIAL_IS_OK(mode); 1.1097 + for (var i = 0; i < length; i++) 1.1098 + UnsafePutElements(buffer, i, func(i)); 1.1099 + return buffer; 1.1100 + 1.1101 + function constructThread(workerId, sliceStart, sliceEnd) { 1.1102 + var sliceShift = slicesInfo.shift; 1.1103 + var sliceId; 1.1104 + while (GET_SLICE(sliceStart, sliceEnd, sliceId)) { 1.1105 + var indexStart = SLICE_START_INDEX(sliceShift, sliceId); 1.1106 + var indexEnd = SLICE_END_INDEX(sliceShift, indexStart, length); 1.1107 + for (var i = indexStart; i < indexEnd; i++) 1.1108 + UnsafePutElements(buffer, i, func(i)); 1.1109 + } 1.1110 + return sliceId; 1.1111 + } 1.1112 + 1.1113 + return undefined; 1.1114 +} 1.1115 + 1.1116 +/* 1.1117 + * Mark the main operations as clone-at-callsite for better precision. 1.1118 + * This is slightly overkill, as all that we really need is to 1.1119 + * specialize to the receiver and the elemental function, but in 1.1120 + * practice this is likely not so different, since element functions 1.1121 + * are often used in exactly one place. 1.1122 + */ 1.1123 +SetScriptHints(ArrayMapPar, { cloneAtCallsite: true }); 1.1124 +SetScriptHints(ArrayReducePar, { cloneAtCallsite: true }); 1.1125 +SetScriptHints(ArrayScanPar, { cloneAtCallsite: true }); 1.1126 +SetScriptHints(ArrayScatterPar, { cloneAtCallsite: true }); 1.1127 +SetScriptHints(ArrayFilterPar, { cloneAtCallsite: true }); 1.1128 +SetScriptHints(ArrayStaticBuildPar, { cloneAtCallsite: true }); 1.1129 + 1.1130 +#endif /* ENABLE_PARALLEL_JS */