| Index: src/array.js
|
| diff --git a/src/array.js b/src/array.js
|
| index 35fd54540d0424ca4162f27523aa044317988e0b..29fa8318e2bfee8c8cfa4ba95af4da5bd777590e 100644
|
| --- a/src/array.js
|
| +++ b/src/array.js
|
| @@ -90,7 +90,8 @@ function UseSparseVariant(array, length, is_array, touched) {
|
| // Only use the sparse variant on arrays that are likely to be sparse and the
|
| // number of elements touched in the operation is relatively small compared to
|
| // the overall size of the array.
|
| - if (!is_array || length < 1000 || %IsObserved(array)) {
|
| + if (!is_array || length < 1000 || %IsObserved(array) ||
|
| + %HasComplexElements(array)) {
|
| return false;
|
| }
|
| if (!%_IsSmi(length)) {
|
| @@ -203,7 +204,7 @@ function ConvertToLocaleString(e) {
|
|
|
| // This function implements the optimized splice implementation that can use
|
| // special array operations to handle sparse arrays in a sensible fashion.
|
| -function SmartSlice(array, start_i, del_count, len, deleted_elements) {
|
| +function SparseSlice(array, start_i, del_count, len, deleted_elements) {
|
| // Move deleted elements to a new array (the return value from splice).
|
| var indices = %GetArrayKeys(array, start_i + del_count);
|
| if (IS_NUMBER(indices)) {
|
| @@ -211,7 +212,7 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) {
|
| for (var i = start_i; i < limit; ++i) {
|
| var current = array[i];
|
| if (!IS_UNDEFINED(current) || i in array) {
|
| - deleted_elements[i - start_i] = current;
|
| + %AddElement(deleted_elements, i - start_i, current, NONE);
|
| }
|
| }
|
| } else {
|
| @@ -222,7 +223,7 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) {
|
| if (key >= start_i) {
|
| var current = array[key];
|
| if (!IS_UNDEFINED(current) || key in array) {
|
| - deleted_elements[key - start_i] = current;
|
| + %AddElement(deleted_elements, key - start_i, current, NONE);
|
| }
|
| }
|
| }
|
| @@ -233,7 +234,9 @@ function SmartSlice(array, start_i, del_count, len, deleted_elements) {
|
|
|
| // This function implements the optimized splice implementation that can use
|
| // special array operations to handle sparse arrays in a sensible fashion.
|
| -function SmartMove(array, start_i, del_count, len, num_additional_args) {
|
| +function SparseMove(array, start_i, del_count, len, num_additional_args) {
|
| + // Bail out if no moving is necessary.
|
| + if (num_additional_args === del_count) return;
|
| // Move data to new array.
|
| var new_array = new InternalArray(len - del_count + num_additional_args);
|
| var indices = %GetArrayKeys(array, len);
|
| @@ -281,12 +284,11 @@ function SmartMove(array, start_i, del_count, len, num_additional_args) {
|
| function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
|
| for (var i = 0; i < del_count; i++) {
|
| var index = start_i + i;
|
| - // The spec could also be interpreted such that %HasOwnProperty
|
| - // would be the appropriate test. We follow KJS in consulting the
|
| - // prototype.
|
| - var current = array[index];
|
| - if (!IS_UNDEFINED(current) || index in array) {
|
| - deleted_elements[i] = current;
|
| + if (index in array) {
|
| + var current = array[index];
|
| + // The spec requires [[DefineOwnProperty]] here, %AddElement is close
|
| + // enough (in that it ignores the prototype).
|
| + %AddElement(deleted_elements, i, current, NONE);
|
| }
|
| }
|
| }
|
| @@ -300,12 +302,8 @@ function SimpleMove(array, start_i, del_count, len, num_additional_args) {
|
| for (var i = len - del_count; i > start_i; i--) {
|
| var from_index = i + del_count - 1;
|
| var to_index = i + num_additional_args - 1;
|
| - // The spec could also be interpreted such that
|
| - // %HasOwnProperty would be the appropriate test. We follow
|
| - // KJS in consulting the prototype.
|
| - var current = array[from_index];
|
| - if (!IS_UNDEFINED(current) || from_index in array) {
|
| - array[to_index] = current;
|
| + if (from_index in array) {
|
| + array[to_index] = array[from_index];
|
| } else {
|
| delete array[to_index];
|
| }
|
| @@ -314,12 +312,8 @@ function SimpleMove(array, start_i, del_count, len, num_additional_args) {
|
| for (var i = start_i; i < len - del_count; i++) {
|
| var from_index = i + del_count;
|
| var to_index = i + num_additional_args;
|
| - // The spec could also be interpreted such that
|
| - // %HasOwnProperty would be the appropriate test. We follow
|
| - // KJS in consulting the prototype.
|
| - var current = array[from_index];
|
| - if (!IS_UNDEFINED(current) || from_index in array) {
|
| - array[to_index] = current;
|
| + if (from_index in array) {
|
| + array[to_index] = array[from_index];
|
| } else {
|
| delete array[to_index];
|
| }
|
| @@ -349,7 +343,7 @@ function ArrayToString() {
|
| func = array.join;
|
| }
|
| if (!IS_SPEC_FUNCTION(func)) {
|
| - return %_CallFunction(array, ObjectToString);
|
| + return %_CallFunction(array, NoSideEffectsObjectToString);
|
| }
|
| return %_CallFunction(array, func);
|
| }
|
| @@ -604,8 +598,8 @@ function ArrayShift() {
|
|
|
| var first = array[0];
|
|
|
| - if (IS_ARRAY(array)) {
|
| - SmartMove(array, 0, 1, len, 0);
|
| + if (UseSparseVariant(array, len, IS_ARRAY(array), len)) {
|
| + SparseMove(array, 0, 1, len, 0);
|
| } else {
|
| SimpleMove(array, 0, 1, len, 0);
|
| }
|
| @@ -644,10 +638,10 @@ function ArrayUnshift(arg1) { // length == 1
|
| var array = TO_OBJECT_INLINE(this);
|
| var len = TO_UINT32(array.length);
|
| var num_arguments = %_ArgumentsLength();
|
| - var is_sealed = ObjectIsSealed(array);
|
|
|
| - if (IS_ARRAY(array) && !is_sealed && len > 0) {
|
| - SmartMove(array, 0, 0, len, num_arguments);
|
| + if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) &&
|
| + !ObjectIsSealed(array)) {
|
| + SparseMove(array, 0, 0, len, num_arguments);
|
| } else {
|
| SimpleMove(array, 0, 0, len, num_arguments);
|
| }
|
| @@ -693,7 +687,7 @@ function ArraySlice(start, end) {
|
| if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) {
|
| %NormalizeElements(array);
|
| %NormalizeElements(result);
|
| - SmartSlice(array, start_i, end_i - start_i, len, result);
|
| + SparseSlice(array, start_i, end_i - start_i, len, result);
|
| } else {
|
| SimpleSlice(array, start_i, end_i - start_i, len, result);
|
| }
|
| @@ -809,8 +803,8 @@ function ArraySplice(start, delete_count) {
|
| if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
|
| %NormalizeElements(array);
|
| %NormalizeElements(deleted_elements);
|
| - SmartSlice(array, start_i, del_count, len, deleted_elements);
|
| - SmartMove(array, start_i, del_count, len, num_elements_to_add);
|
| + SparseSlice(array, start_i, del_count, len, deleted_elements);
|
| + SparseMove(array, start_i, del_count, len, num_elements_to_add);
|
| } else {
|
| SimpleSlice(array, start_i, del_count, len, deleted_elements);
|
| SimpleMove(array, start_i, del_count, len, num_elements_to_add);
|
| @@ -1416,9 +1410,8 @@ function ArrayReduce(callback, current) {
|
| var i = 0;
|
| find_initial: if (%_ArgumentsLength() < 2) {
|
| for (; i < length; i++) {
|
| - current = array[i];
|
| - if (!IS_UNDEFINED(current) || i in array) {
|
| - i++;
|
| + if (i in array) {
|
| + current = array[i++];
|
| break find_initial;
|
| }
|
| }
|
| @@ -1453,9 +1446,8 @@ function ArrayReduceRight(callback, current) {
|
| var i = length - 1;
|
| find_initial: if (%_ArgumentsLength() < 2) {
|
| for (; i >= 0; i--) {
|
| - current = array[i];
|
| - if (!IS_UNDEFINED(current) || i in array) {
|
| - i--;
|
| + if (i in array) {
|
| + current = array[i--];
|
| break find_initial;
|
| }
|
| }
|
|
|