diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 25611fbe8..5383ddd8d 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -626,13 +626,6 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ } else { - jmem_cpointer_t proto_cp = object_p->u2.prototype_cp; - - if (proto_cp != JMEM_CP_NULL) - { - ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); - } - switch (ecma_get_object_type (object_p)) { case ECMA_OBJECT_TYPE_CLASS: @@ -765,6 +758,15 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; +#if ENABLED (JERRY_ESNEXT) + if (JERRY_UNLIKELY (ext_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL)) + { + /* Template objects are never marked. */ + JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE); + return; + } +#endif /* ENABLED (JERRY_ESNEXT) */ + if (ecma_op_array_is_fast_array (ext_object_p)) { if (object_p->u1.property_list_cp != JMEM_CP_NULL) @@ -780,6 +782,12 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ } } + jmem_cpointer_t proto_cp = object_p->u2.prototype_cp; + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } return; } break; @@ -792,6 +800,13 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ * Aside from the tag bits every other bit should be zero, */ JERRY_ASSERT ((object_p->u1.property_list_cp & ~JMEM_TAG_MASK) == 0); + + jmem_cpointer_t proto_cp = object_p->u2.prototype_cp; + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } return; } #endif /* ENABLED (JERRY_BUILTIN_PROXY) */ @@ -907,6 +922,13 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ break; } } + + jmem_cpointer_t proto_cp = object_p->u2.prototype_cp; + + if (proto_cp != JMEM_CP_NULL) + { + ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp)); + } } jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp; diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 74043c4e4..5420893ef 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -942,13 +942,8 @@ typedef struct struct { uint32_t length; /**< length property value */ - union - { - ecma_property_t length_prop; /**< length property */ - uint32_t hole_count; /**< number of array holes in a fast access mode array - * multiplied ECMA_FAST_ACCESS_HOLE_ONE */ - } u; - + uint32_t length_prop_and_hole_count; /**< length property attributes and number of array holes in + * a fast access mode array multiplied ECMA_FAST_ACCESS_HOLE_ONE */ } array; /** @@ -997,6 +992,17 @@ typedef struct ecma_built_in_props_t built_in; /**< built-in object part */ } ecma_extended_built_in_object_t; +/** + * Flags for array.length_prop_and_hole_count + */ +typedef enum +{ + ECMA_FAST_ARRAY_FLAG = 1u << (ECMA_PROPERTY_NAME_TYPE_SHIFT + 0), +#if ENABLED (JERRY_ESNEXT) + ECMA_ARRAY_TEMPLATE_LITERAL = 1u << (ECMA_PROPERTY_NAME_TYPE_SHIFT + 1), +#endif /* ENABLED (JERRY_ESNEXT) */ +} ecma_array_length_prop_and_hole_count_flags_t; + /** * Alignment for the fast access mode array length. * The real length is aligned up for allocating the underlying buffer. diff --git a/jerry-core/ecma/base/ecma-helpers-collection.c b/jerry-core/ecma/base/ecma-helpers-collection.c index 34a16a370..f3cf47d0e 100644 --- a/jerry-core/ecma/base/ecma-helpers-collection.c +++ b/jerry-core/ecma/base/ecma-helpers-collection.c @@ -79,6 +79,46 @@ ecma_collection_free_objects (ecma_collection_t *collection_p) /**< value collec ecma_collection_destroy (collection_p); } /* ecma_collection_free_objects */ +#if ENABLED (JERRY_ESNEXT) + +/** + * Free the template literal objects and deallocate the collection + */ +void +ecma_collection_free_template_literal (ecma_collection_t *collection_p) /**< value collection */ +{ + for (uint32_t i = 0; i < collection_p->item_count; i++) + { + ecma_object_t *object_p = ecma_get_object_from_value (collection_p->buffer_p[i]); + + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) object_p; + + JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL); + array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_property_value_t *property_value_p; + + property_value_p = ecma_get_named_data_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_RAW)); + ecma_object_t *raw_object_p = ecma_get_object_from_value (property_value_p->value); + + JERRY_ASSERT (ecma_get_object_type (raw_object_p) == ECMA_OBJECT_TYPE_ARRAY); + + array_object_p = (ecma_extended_object_t *) raw_object_p; + + JERRY_ASSERT (array_object_p->u.array.length_prop_and_hole_count & ECMA_ARRAY_TEMPLATE_LITERAL); + array_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ECMA_ARRAY_TEMPLATE_LITERAL; + + ecma_deref_object (raw_object_p); + ecma_deref_object (object_p); + } + + ecma_collection_destroy (collection_p); +} /* ecma_collection_free_template_literal */ + +#endif /* ENABLED (JERRY_ESNEXT) */ + /** * Free the non-object collection elements and deallocate the collection */ diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 5436db5ff..cccb5dc39 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -1476,8 +1476,8 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ /* Since the objects in the tagged template collection are not strong referenced anymore by the compiled code we can treat them as 'new' objects. */ - JERRY_CONTEXT (ecma_gc_new_objects) += collection_p->item_count; - ecma_collection_free (collection_p); + JERRY_CONTEXT (ecma_gc_new_objects) += collection_p->item_count * 2; + ecma_collection_free_template_literal (collection_p); } #endif /* ENABLED (JERRY_ESNEXT) */ diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 06a89b193..4be1c6596 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -439,6 +439,9 @@ void ecma_collection_destroy (ecma_collection_t *collection_p); void ecma_collection_free (ecma_collection_t *collection_p); void ecma_collection_free_if_not_object (ecma_collection_t *collection_p); void ecma_collection_free_objects (ecma_collection_t *collection_p); +#if ENABLED (JERRY_ESNEXT) +void ecma_collection_free_template_literal (ecma_collection_t *collection_p); +#endif /* ENABLED (JERRY_ESNEXT) */ bool ecma_collection_check_duplicated_entries (ecma_collection_t *collection_p); bool ecma_collection_has_string_value (ecma_collection_t *collection_p, ecma_string_t *string_p); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c index 5c025b4e7..d77173a88 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -465,7 +465,7 @@ ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, / buffer_p[index] = ecma_copy_value_if_not_object (argument_list_p[index]); } - ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * arguments_number; + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * arguments_number; return ecma_make_uint32_value (new_length); } @@ -539,7 +539,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar uint32_t middle = (uint32_t) len / 2; ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0 && ecma_op_ordinary_object_is_extensible (obj_p)) { @@ -725,7 +725,7 @@ ecma_builtin_array_prototype_object_shift (ecma_object_t *obj_p, /**< object */ { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0 && ecma_op_ordinary_object_is_extensible (obj_p)) { @@ -873,7 +873,7 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ { ecma_extended_object_t *ext_from_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_from_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + if (ext_from_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) { if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) { @@ -921,7 +921,7 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ to_buffer_p[n] = ecma_copy_value_if_not_object (from_buffer_p[k]); } - ext_to_obj_p->u.array.u.hole_count &= ECMA_FAST_ARRAY_HOLE_ONE - 1; + ext_to_obj_p->u.array.length_prop_and_hole_count &= ECMA_FAST_ARRAY_HOLE_ONE - 1; return ecma_make_object_value (new_array_p); } @@ -1513,7 +1513,7 @@ ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arg { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && len != 0 && ecma_op_ordinary_object_is_extensible (obj_p)) { @@ -1539,7 +1539,7 @@ ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arg index++; } - ext_obj_p->u.array.u.hole_count -= args_number * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count -= args_number * ECMA_FAST_ARRAY_HOLE_ONE; return ecma_make_uint32_value (new_length); } @@ -1670,7 +1670,7 @@ ecma_builtin_array_prototype_object_index_of (const ecma_value_t args[], /**< ar { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) { if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) { @@ -1776,7 +1776,7 @@ ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /* { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) { if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) { @@ -2302,7 +2302,7 @@ ecma_builtin_array_prototype_fill (ecma_value_t value, /**< value */ { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && ecma_op_ordinary_object_is_extensible (obj_p)) { if (JERRY_UNLIKELY (obj_p->u1.property_list_cp == JMEM_CP_NULL)) @@ -2501,7 +2501,7 @@ ecma_builtin_array_prototype_object_copy_within (const ecma_value_t args[], /**< ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; const uint32_t actual_length = ext_obj_p->u.array.length; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE && ((forward && (target + count - 1 < actual_length)) || (!forward && (target < actual_length)))) { if (obj_p->u1.property_list_cp != JMEM_CP_NULL) @@ -2617,7 +2617,7 @@ ecma_builtin_array_prototype_includes (const ecma_value_t args[], /**< arguments { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - if (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE) + if (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE) { if (obj_p->u1.property_list_cp != JMEM_CP_NULL) { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index f9a6143f1..941db1bc3 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -439,7 +439,7 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */ ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; ext_object_p->u.array.length = 0; - ext_object_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; + ext_object_p->u.array.length_prop_and_hole_count = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; break; } #endif /* ENABLED (JERRY_BUILTIN_ARRAY) */ @@ -539,20 +539,6 @@ ecma_finalize_builtins (void) { ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[id]); ecma_deref_object (obj_p); - -#if ENABLED (JERRY_ESNEXT) - /* Note: In ES2015 a function object may contain tagged template literal collection. Whenever - this function is assigned to a builtin function or function routine during the GC it may cause unresolvable - circle since one part of the circle is a weak reference (marked by GC) and the other part is hard reference - (reference count). In this case when the function which contains the tagged template literal collection - is getting GC marked the arrays in the collection are still holding weak references to properties/prototypes - which prevents these objects from getting freed. Releasing the property list and the prototype reference - manually eliminates the existence of the unresolvable circle described above. */ - ecma_gc_free_properties (obj_p); - obj_p->u1.property_list_cp = JMEM_CP_NULL; - obj_p->u2.prototype_cp = JMEM_CP_NULL; -#endif /* ENABLED (JERRY_ESNEXT) */ - JERRY_CONTEXT (ecma_builtin_objects)[id] = JMEM_CP_NULL; } } diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index 45d9acdbd..df78dc3c5 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -56,11 +56,6 @@ */ #define ECMA_FAST_ARRAY_UINT32_DIRECT_STRING_PROP_TYPE 0x80 -/** - * Property attribute for the array 'length' virtual property to indicate fast access mode array - */ -#define ECMA_FAST_ARRAY_FLAG (ECMA_DIRECT_STRING_MAGIC << ECMA_PROPERTY_NAME_TYPE_SHIFT) - /** * Allocate a new array object with the given length * @@ -87,8 +82,7 @@ ecma_op_alloc_array_object (uint32_t length) /**< length of the new array */ ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; ext_obj_p->u.array.length = length; - ext_obj_p->u.array.u.hole_count = 0; - ext_obj_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; + ext_obj_p->u.array.length_prop_and_hole_count = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; return object_p; } /* ecma_op_alloc_array_object */ @@ -117,7 +111,7 @@ ecma_op_array_is_fast_array (ecma_extended_object_t *array_p) /**< ecma-array-ob { JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) array_p) == ECMA_OBJECT_TYPE_ARRAY); - return array_p->u.array.u.length_prop & ECMA_FAST_ARRAY_FLAG; + return array_p->u.array.length_prop_and_hole_count & ECMA_FAST_ARRAY_FLAG; } /* ecma_op_array_is_fast_array */ /** @@ -151,8 +145,8 @@ ecma_op_new_array_object (uint32_t length) /**< length of the new array */ } ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; - ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop | ECMA_FAST_ARRAY_FLAG); - ext_obj_p->u.array.u.hole_count += length * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; + ext_obj_p->u.array.length_prop_and_hole_count += length * ECMA_FAST_ARRAY_HOLE_ONE; for (uint32_t i = 0; i < aligned_length; i++) { @@ -210,7 +204,7 @@ ecma_op_new_array_object_from_buffer (const ecma_value_t *args_p, /**< array ele if (values_p != NULL) { ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; - ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop | ECMA_FAST_ARRAY_FLAG); + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); for (uint32_t i = 0; i < length; i++) @@ -277,9 +271,9 @@ ecma_op_new_array_object_from_collection (ecma_collection_t *collection_p, /**< object_p = ecma_op_alloc_array_object (item_count); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; - ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop | ECMA_FAST_ARRAY_FLAG); + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_FAST_ARRAY_FLAG; JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL); - JERRY_ASSERT (ext_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE); + JERRY_ASSERT (ext_obj_p->u.array.length_prop_and_hole_count < ECMA_FAST_ARRAY_HOLE_ONE); ECMA_SET_POINTER (object_p->u1.property_list_cp, buffer_p); if (JERRY_UNLIKELY (unref_objects)) @@ -312,7 +306,7 @@ ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mod if (object_p->u1.property_list_cp == JMEM_CP_NULL) { - ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_FAST_ARRAY_FLAG); + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_FAST_ARRAY_FLAG; return; } @@ -358,7 +352,7 @@ ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mod prop_index = !prop_index; } - ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_FAST_ARRAY_FLAG); + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_FAST_ARRAY_FLAG; jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t)); ECMA_SET_POINTER (object_p->u1.property_list_cp, property_pair_p); @@ -392,7 +386,7 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr if (ecma_is_value_array_hole (values_p[index])) { - ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; } else { @@ -404,7 +398,7 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr return true; } - uint32_t old_holes = ext_obj_p->u.array.u.hole_count; + uint32_t old_holes = ext_obj_p->u.array.length_prop_and_hole_count; uint32_t new_holes = index - old_length; if (JERRY_UNLIKELY (new_holes > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT @@ -426,15 +420,15 @@ ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode arr JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); - /* This area is filled with ECMA_VALUE_ARRAY_HOLE, but not counted in u.array.u.hole_count */ + /* This area is filled with ECMA_VALUE_ARRAY_HOLE, but not counted in u.array.length_prop_and_hole_count */ JERRY_ASSERT (ecma_is_value_array_hole (values_p[index])); - ext_obj_p->u.array.u.hole_count += new_holes * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count += new_holes * ECMA_FAST_ARRAY_HOLE_ONE; ext_obj_p->u.array.length = new_length; } else { values_p = ecma_fast_array_extend (object_p, new_length); - ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; } values_p[index] = ecma_copy_value_if_not_object (value); @@ -452,7 +446,7 @@ ecma_fast_array_get_hole_count (ecma_object_t *obj_p) /**< fast access mode arra { JERRY_ASSERT (ecma_op_object_is_fast_array (obj_p)); - return ((ecma_extended_object_t *) obj_p)->u.array.u.hole_count >> ECMA_FAST_ARRAY_HOLE_SHIFT; + return ((ecma_extended_object_t *) obj_p)->u.array.length_prop_and_hole_count >> ECMA_FAST_ARRAY_HOLE_SHIFT; } /* ecma_fast_array_get_hole_count */ /** @@ -493,7 +487,7 @@ ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array obj new_values_p[i] = ECMA_VALUE_ARRAY_HOLE; } - ext_obj_p->u.array.u.hole_count += (new_length - old_length) * ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count += (new_length - old_length) * ECMA_FAST_ARRAY_HOLE_ONE; ext_obj_p->u.array.length = new_length; ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, new_values_p); @@ -538,7 +532,7 @@ ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */ ecma_free_value_if_not_object (values_p[index]); values_p[index] = ECMA_VALUE_ARRAY_HOLE; - ext_obj_p->u.array.u.hole_count += ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count += ECMA_FAST_ARRAY_HOLE_ONE; } /* ecma_array_object_delete_property */ /** @@ -565,7 +559,7 @@ ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mod { if (ecma_is_value_array_hole (values_p[i])) { - ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; + ext_obj_p->u.array.length_prop_and_hole_count -= ECMA_FAST_ARRAY_HOLE_ONE; } else { @@ -627,7 +621,7 @@ ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array return; } - uint32_t old_holes = ext_obj_p->u.array.u.hole_count; + uint32_t old_holes = ext_obj_p->u.array.length_prop_and_hole_count; uint32_t new_holes = new_length - old_length; if (JERRY_UNLIKELY (new_holes > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT @@ -1012,17 +1006,16 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object { if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { - uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE); - ext_object_p->u.array.u.length_prop = new_prop_value; + ext_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; } - else if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop)) + else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) { return ecma_reject (is_throw); } } return ECMA_VALUE_TRUE; } - else if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop)) + else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) { return ecma_reject (is_throw); } @@ -1043,8 +1036,7 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) && !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { - uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE); - ext_object_p->u.array.u.length_prop = new_prop_value; + ext_object_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; } if (current_len_uint32 == new_len_uint32) @@ -1166,7 +1158,8 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra bool update_length = (index >= ext_object_p->u.array.length); - if (update_length && !ecma_is_property_writable (ext_object_p->u.array.u.length_prop)) + if (update_length + && !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) { return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); } diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 3211bab04..d60c0d4fb 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -140,7 +140,8 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length); } - return ext_object_p->u.array.u.length_prop & (ECMA_PROPERTY_TYPE_VIRTUAL | ECMA_PROPERTY_FLAG_WRITABLE); + uint32_t length_prop = ext_object_p->u.array.length_prop_and_hole_count; + return length_prop & (ECMA_PROPERTY_TYPE_VIRTUAL | ECMA_PROPERTY_FLAG_WRITABLE); } if (ecma_op_array_is_fast_array (ext_object_p)) @@ -1210,7 +1211,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ if (ecma_string_is_length (property_name_p)) { - if (ecma_is_property_writable (ext_object_p->u.array.u.length_prop)) + if (ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) { return ecma_op_array_object_set_length (object_p, value, 0); } @@ -1509,7 +1510,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ if (index < UINT32_MAX && index >= ext_object_p->u.array.length) { - if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop)) + if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) { return ecma_reject (is_throw); } @@ -3034,16 +3035,6 @@ ecma_op_ordinary_object_set_prototype_of (ecma_object_t *obj_p, /**< base object /* 1. */ JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); - /** - * If the prototype of a fast array changes it is required to fall back to - * a "normal" array object. This ensures that all [[Get]]/[[Set]]/etc. calls - * works as expected. - */ - if (ecma_op_object_is_fast_array (obj_p)) - { - ecma_fast_array_convert_to_normal (obj_p); - } - /* 3. */ ecma_object_t *current_proto_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (obj_p)); ecma_object_t *new_proto_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); @@ -3060,6 +3051,16 @@ ecma_op_ordinary_object_set_prototype_of (ecma_object_t *obj_p, /**< base object return ECMA_VALUE_FALSE; } + /** + * When the prototype of a fast array changes, it is required to convert the + * array to a "normal" array. This ensures that all [[Get]]/[[Set]]/etc. + * calls works as expected. + */ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + /* 6. */ ecma_object_t *iter_p = new_proto_p; diff --git a/jerry-core/parser/js/js-parser-tagged-template-literal.c b/jerry-core/parser/js/js-parser-tagged-template-literal.c index b34f6afb4..db5a11d0e 100644 --- a/jerry-core/parser/js/js-parser-tagged-template-literal.c +++ b/jerry-core/parser/js/js-parser-tagged-template-literal.c @@ -114,7 +114,6 @@ parser_new_tagged_template_literal (ecma_object_t **raw_strings_p) /**< [out] ra ecma_get_magic_string (LIT_MAGIC_STRING_RAW), ecma_make_object_value (*raw_strings_p), ECMA_PROPERTY_FIXED); - ecma_deref_object (*raw_strings_p); return template_obj_p; } /* parser_new_tagged_template_literal */ @@ -129,8 +128,8 @@ parser_tagged_template_literal_freeze_array (ecma_object_t *obj_p) ecma_op_ordinary_object_prevent_extensions (obj_p); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - uint8_t new_prop_value = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE); - ext_obj_p->u.array.u.length_prop = new_prop_value; + ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; + ext_obj_p->u.array.length_prop_and_hole_count |= ECMA_ARRAY_TEMPLATE_LITERAL; } /* parser_tagged_template_literal_freeze_array */ /** diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 4ecc96a07..0290e64fc 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -2732,8 +2732,9 @@ parser_raise_error (parser_context_t *context_p, /**< context */ #if ENABLED (JERRY_ESNEXT) if (saved_context_p->tagged_template_literal_cp != JMEM_CP_NULL) { - ecma_collection_free (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, - saved_context_p->tagged_template_literal_cp)); + ecma_collection_t *collection = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, + saved_context_p->tagged_template_literal_cp); + ecma_collection_free_template_literal (collection); } #endif /* ENABLED (JERRY_ESNEXT) */ @@ -2743,8 +2744,9 @@ parser_raise_error (parser_context_t *context_p, /**< context */ #if ENABLED (JERRY_ESNEXT) if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) { - ecma_collection_free (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, - context_p->tagged_template_literal_cp)); + ecma_collection_t *collection = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, + context_p->tagged_template_literal_cp); + ecma_collection_free_template_literal (collection); } #endif /* ENABLED (JERRY_ESNEXT) */ diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index dc6289c05..6c67e3f92 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -605,7 +605,7 @@ opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */ } } - ext_array_obj_p->u.array.u.hole_count -= filled_holes * ECMA_FAST_ARRAY_HOLE_ONE; + ext_array_obj_p->u.array.length_prop_and_hole_count -= filled_holes * ECMA_FAST_ARRAY_HOLE_ONE; if (JERRY_UNLIKELY ((values_length - filled_holes) > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT)) {