diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index ff847a2ba..22fe0bb07 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -202,11 +202,9 @@ ecma_gc_mark_property (ecma_property_t *property_p) /**< property */ { case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */ - case ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */ { break; } - default: { JERRY_ASSERT (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p) == ECMA_SPECIAL_PROPERTY_DELETED @@ -405,6 +403,26 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ { ecma_object_type_t object_type = ecma_get_object_type (object_p); + size_t ext_object_size = sizeof (ecma_extended_object_t); + + if (ecma_get_object_is_builtin (object_p)) + { + uint8_t length_and_bitset_size; + + if (object_type == ECMA_OBJECT_TYPE_CLASS + || object_type == ECMA_OBJECT_TYPE_ARRAY) + { + ext_object_size = sizeof (ecma_extended_built_in_object_t); + length_and_bitset_size = ((ecma_extended_built_in_object_t *) object_p)->built_in.length_and_bitset_size; + } + else + { + length_and_bitset_size = ((ecma_extended_object_t *) object_p)->u.built_in.length_and_bitset_size; + } + + ext_object_size += (2 * sizeof (uint32_t)) * (length_and_bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT); + } + if (object_type == ECMA_OBJECT_TYPE_CLASS) { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; @@ -461,25 +479,15 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ } } - size_t size = (ecma_get_object_is_builtin (object_p) ? sizeof (ecma_extended_built_in_object_t) - : sizeof (ecma_extended_object_t)); - ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, size); - return; - } - - if (object_type == ECMA_OBJECT_TYPE_ARRAY) - { - size_t size = (ecma_get_object_is_builtin (object_p) ? sizeof (ecma_extended_built_in_object_t) - : sizeof (ecma_extended_object_t)); - - ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, size); + ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, ext_object_size); return; } if (ecma_get_object_is_builtin (object_p) + || object_type == ECMA_OBJECT_TYPE_ARRAY || object_type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION) { - ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, sizeof (ecma_extended_object_t)); + ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, ext_object_size); return; } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 0bc847774..99b6da3a3 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -192,7 +192,7 @@ typedef int32_t ecma_integer_value_t; typedef uintptr_t ecma_external_pointer_t; /** - * Internal properties' identifiers. + * Special property identifiers. */ typedef enum { @@ -204,10 +204,8 @@ typedef enum ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */ ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< object's native free callback */ - ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63, /**< Bit-mask of non-instantiated - * built-in's properties (bits 32-63) */ - ECMA_INTERNAL_PROPERTY__COUNT /**< Number of internal properties' types */ + ECMA_SPECIAL_PROPERTY__COUNT /**< Number of special property types */ } ecma_internal_property_id_t; /** @@ -598,11 +596,17 @@ typedef struct typedef struct { uint8_t id; /**< built-in id */ - uint8_t length; /**< length for built-in functions */ + uint8_t length_and_bitset_size; /**< length for built-in functions and + * bit set size for all built-ins */ uint16_t routine_id; /**< routine id for built-in functions */ - uint32_t instantiated_bitset; /**< bit set for instantiated properties */ + uint32_t instantiated_bitset[1]; /**< bit set for instantiated properties */ } ecma_built_in_props_t; +/** + * Start position of bit set size in length_and_bitset_size field. + */ +#define ECMA_BUILT_IN_BITSET_SHIFT 5 + /** * Description of extended ECMA-object. * diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index c5328a220..530fb750b 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -792,12 +792,6 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */ break; } - - case ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */ - { - break; - } - default: { JERRY_UNREACHABLE (); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h index d824e2eab..e3402a1ea 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h @@ -54,6 +54,9 @@ #undef ROUTINE_ARG_LIST_0 #undef ROUTINE_ARG +/** + * List of built-in routine identifiers. + */ enum { PASTE (ECMA_ROUTINE_START_, BUILTIN_UNDERSCORED_ID) = ECMA_BUILTIN_ID__COUNT - 1, diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index 19bb33255..392b1912f 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -34,6 +34,46 @@ static void ecma_instantiate_builtin (ecma_builtin_id_t id); +/** + * Helper definition for ecma_builtin_property_list_references. + */ +typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t; + +/** + * Property descriptor lists for all built-ins. + */ +static const ecma_builtin_property_list_reference_t ecma_builtin_property_list_references[] = +{ +#define BUILTIN(builtin_id, \ + object_type, \ + object_prototype_builtin_id, \ + is_extensible, \ + is_static, \ + lowercase_name) \ + ecma_builtin_ ## lowercase_name ## _property_descriptor_list, +#include "ecma-builtins.inc.h" +}; + +/** + * Get the number of properties of a built-in object. + * + * @return the number of properties + */ +static size_t +ecma_builtin_get_property_count (ecma_builtin_id_t builtin_id) +{ + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) + { + curr_property_p++; + } + + return (size_t) (curr_property_p - property_list_p); +} /* ecma_builtin_get_property_count */ + /** * Check if passed object is the instance of specified built-in. */ @@ -109,6 +149,17 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ size_t ext_object_size = (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t) : sizeof (ecma_extended_object_t)); + size_t property_count = ecma_builtin_get_property_count (obj_builtin_id); + + if (property_count > 32) + { + /* Only 64 extra properties supported at the moment. + * This can be extended to 256 later. */ + JERRY_ASSERT (property_count <= (32 + 64)); + + ext_object_size += sizeof (uint32_t) * 2; + } + ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, ext_object_size, obj_type); if (!is_extensible) @@ -136,7 +187,20 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ built_in_props_p->id = obj_builtin_id; built_in_props_p->routine_id = obj_builtin_id; - built_in_props_p->instantiated_bitset = 0; + built_in_props_p->instantiated_bitset[0] = 0; + + if (property_count > 32) + { + built_in_props_p->length_and_bitset_size = 1 << ECMA_BUILT_IN_BITSET_SHIFT; + + uint32_t *instantiated_bitset_p = built_in_props_p->instantiated_bitset; + instantiated_bitset_p[1] = 0; + instantiated_bitset_p[2] = 0; + } + else + { + built_in_props_p->length_and_bitset_size = 0; + } /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */ switch (obj_builtin_id) @@ -309,10 +373,25 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /** * object's routine property */ uint8_t length_prop_value) /**< value of 'length' property */ { + JERRY_ASSERT (length_prop_value < (1 << ECMA_BUILT_IN_BITSET_SHIFT)); + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + size_t ext_object_size = sizeof (ecma_extended_object_t); + + size_t property_count = ecma_builtin_get_property_count (builtin_id); + + if (property_count > 32) + { + /* Only 64 extra properties supported at the moment. + * This can be extended to 256 later. */ + JERRY_ASSERT (property_count <= (32 + 64)); + + ext_object_size += sizeof (uint32_t) * 2; + } + ecma_object_t *func_obj_p = ecma_create_object (prototype_obj_p, - sizeof (ecma_extended_object_t), + ext_object_size, ECMA_OBJECT_TYPE_FUNCTION); ecma_deref_object (prototype_obj_p); @@ -323,9 +402,19 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /** ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; ext_func_obj_p->u.built_in.id = builtin_id; - ext_func_obj_p->u.built_in.length = length_prop_value; ext_func_obj_p->u.built_in.routine_id = routine_id; - ext_func_obj_p->u.built_in.instantiated_bitset = 0; + ext_func_obj_p->u.built_in.instantiated_bitset[0] = 0; + + if (property_count > 32) + { + length_prop_value = (uint8_t) (length_prop_value | (1 << ECMA_BUILT_IN_BITSET_SHIFT)); + + uint32_t *instantiated_bitset_p = ext_func_obj_p->u.built_in.instantiated_bitset; + instantiated_bitset_p[1] = 0; + instantiated_bitset_p[2] = 0; + } + + ext_func_obj_p->u.built_in.length_and_bitset_size = length_prop_value; return func_obj_p; } /* ecma_builtin_make_function_object_for_routine */ @@ -356,20 +445,6 @@ ecma_builtin_make_function_object_for_setter_accessor (ecma_builtin_id_t builtin return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, 1); } /* ecma_builtin_make_function_object_for_setter_accessor */ -typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t; - -static const ecma_builtin_property_list_reference_t ecma_builtin_property_list_references[] = -{ -#define BUILTIN(builtin_id, \ - object_type, \ - object_prototype_builtin_id, \ - is_extensible, \ - is_static, \ - lowercase_name) \ - ecma_builtin_ ## lowercase_name ## _property_descriptor_list, -#include "ecma-builtins.inc.h" -}; - /** * If the property's name is one of built-in properties of the object * that is not instantiated yet, instantiate the property and @@ -404,7 +479,10 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * &len_prop_p); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; - len_prop_value_p->value = ecma_make_integer_value (ext_obj_p->u.built_in.length); + + uint8_t length = ext_obj_p->u.built_in.length_and_bitset_size & ((1 << ECMA_BUILT_IN_BITSET_SHIFT) - 1); + + len_prop_value_p->value = ecma_make_integer_value (length); return len_prop_p; } @@ -451,46 +529,17 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * uint32_t index = (uint32_t) (curr_property_p - property_list_p); - JERRY_ASSERT (index < 64); + uint32_t *bitset_p = built_in_props_p->instantiated_bitset + (index >> 5); - if (likely (index < 32)) + uint32_t bit_for_index = (uint32_t) (1u << (index & 0x1f)); + + if (*bitset_p & bit_for_index) { - uint32_t bit_for_index = (uint32_t) 1u << index; - - if (built_in_props_p->instantiated_bitset & bit_for_index) - { - /* This property was instantiated before. */ - return NULL; - } - - built_in_props_p->instantiated_bitset |= bit_for_index; + /* This property was instantiated before. */ + return NULL; } - else - { - uint32_t bit_for_index = (uint32_t) 1u << (index - 32); - ecma_value_t *mask_prop_p = ecma_find_internal_property (object_p, - ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63); - uint32_t instantiated_bitset; - - if (mask_prop_p == NULL) - { - mask_prop_p = ecma_create_internal_property (object_p, ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63); - instantiated_bitset = 0; - } - else - { - instantiated_bitset = *mask_prop_p; - - if (instantiated_bitset & bit_for_index) - { - /* This property was instantiated before. */ - return NULL; - } - } - - *mask_prop_p = (instantiated_bitset | bit_for_index); - } + *bitset_p |= bit_for_index; ecma_value_t value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); bool is_accessor = false; @@ -695,50 +744,24 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; ecma_length_t index = 0; - uint32_t instantiated_bitset = built_in_props_p->instantiated_bitset; + uint32_t *bitset_p = built_in_props_p->instantiated_bitset; ecma_collection_header_t *for_non_enumerable_p = (separate_enumerable ? non_enum_collection_p : main_collection_p); while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) { - JERRY_ASSERT (index < 64); - if (index == 32) { - ecma_value_t *mask_prop_p = ecma_find_internal_property (object_p, - ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63); - - if (mask_prop_p == NULL) - { - instantiated_bitset = 0; - } - else - { - instantiated_bitset = *mask_prop_p; - } - } - - uint32_t bit_for_index; - if (index >= 32) - { - bit_for_index = (uint32_t) 1u << (index - 32); - } - else - { - bit_for_index = (uint32_t) 1u << index; - } - - bool was_instantiated = false; - - if (instantiated_bitset & bit_for_index) - { - was_instantiated = true; + bitset_p++; + index = 0; } ecma_string_t *name_p = ecma_get_magic_string (curr_property_p->magic_string_id); - if (!was_instantiated || ecma_op_object_has_own_property (object_p, name_p)) + uint32_t bit_for_index = (uint32_t) 1u << index; + + if (!(*bitset_p & bit_for_index) || ecma_op_object_has_own_property (object_p, name_p)) { ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p),