diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index b3853e2293..7e42c62574 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -186,13 +186,6 @@ ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mod ecma_deref_object (object_p); } /* ecma_fast_array_convert_to_normal */ -/** - * Maximum number of array holes in a fast mode access array. - * If the number of holes exceeds this limit, the array is converted back - * to normal property list based array. - */ -#define ECMA_FAST_ARRAY_MAX_HOLE_COUNT 32 - #if ENABLED (JERRY_SYSTEM_ALLOCATOR) /** * Maximum length of the array length to allocate fast mode access for it diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index 17865bcccb..876878be7f 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -25,6 +25,13 @@ * @{ */ +/** + * Maximum number of array holes in a fast mode access array. + * If the number of holes exceeds this limit, the array is converted back + * to normal property list based array. + */ +#define ECMA_FAST_ARRAY_MAX_HOLE_COUNT 32 + /** * Flags for ecma_op_array_object_set_length */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index f20f3ecef5..3efb4d6b9e 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1668,23 +1668,58 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; uint32_t old_length = ext_array_obj_p->u.array.length; - JERRY_ASSERT (ext_array_obj_p->u.array.is_fast_mode); + if (JERRY_LIKELY (ext_array_obj_p->u.array.is_fast_mode)) + { + ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length); - ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length); + for (uint32_t i = 0; i < values_length; i++) + { + values_p[old_length + i] = stack_top_p[i]; - for (uint32_t i = 0; i < values_length; i++) - { - values_p[old_length + i] = stack_top_p[i]; + if (JERRY_UNLIKELY (ecma_is_value_array_hole (stack_top_p[i]))) + { + ext_array_obj_p->u.array.hole_count++; + } + else if (ecma_is_value_object (stack_top_p[i])) + { + ecma_deref_object (ecma_get_object_from_value (stack_top_p[i])); + } + } - if (JERRY_UNLIKELY (ecma_is_value_array_hole (stack_top_p[i]))) + if (JERRY_UNLIKELY (ext_array_obj_p->u.array.length > ECMA_FAST_ARRAY_MAX_HOLE_COUNT)) { - ext_array_obj_p->u.array.hole_count++; + ecma_fast_array_convert_to_normal (array_obj_p); } - else if (ecma_is_value_object (stack_top_p[i])) + } + else + { + for (uint32_t i = 0; i < values_length; i++) { - ecma_deref_object (ecma_get_object_from_value (stack_top_p[i])); + if (!ecma_is_value_array_hole (stack_top_p[i])) + { + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (old_length + i); + + ecma_property_value_t *prop_value_p; + + prop_value_p = ecma_create_named_data_property (array_obj_p, + index_str_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + ecma_deref_ecma_string (index_str_p); + prop_value_p->value = stack_top_p[i]; + + if (ecma_is_value_object (stack_top_p[i])) + { + ecma_free_value (stack_top_p[i]); + } + + } } + + ext_array_obj_p->u.array.length = old_length + values_length; } + continue; } case VM_OC_PUSH_UNDEFINED_BASE: diff --git a/tests/jerry/regression-test-issue-3072.js b/tests/jerry/regression-test-issue-3072.js new file mode 100644 index 0000000000..4defdee632 --- /dev/null +++ b/tests/jerry/regression-test-issue-3072.js @@ -0,0 +1,18 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var arr = [ , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ]; +arr [4294967294] = 0 +assert (arr.length === 4294967295); +assert (arr[4294967294] === 0);