Skip to content

Commit

Permalink
Rework own property enumeration
Browse files Browse the repository at this point in the history
Properry name filtering is done during the enumeration.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
  • Loading branch information
zherczeg committed Sep 21, 2021
1 parent 053bfa0 commit fbb8496
Show file tree
Hide file tree
Showing 24 changed files with 601 additions and 498 deletions.
39 changes: 9 additions & 30 deletions jerry-core/api/jerry.c
Original file line number Diff line number Diff line change
Expand Up @@ -4604,10 +4604,16 @@ jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */

ecma_ref_object (obj_iter_p);

if ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
&& !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER))
{
filter |= JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES;
}

while (true)
{
/* Step 1. Get Object.[[OwnKeys]] */
ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p);
ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p, filter);

#if JERRY_BUILTIN_PROXY
if (prop_names_p == NULL)
Expand All @@ -4623,34 +4629,7 @@ jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */
ecma_string_t *key_p = ecma_get_prop_name_from_value (key);
uint32_t index = ecma_string_get_array_index (key_p);

/* Step 2. Filter by key type */
if (filter & (JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS
| JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS
| JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES))
{
if (ecma_is_value_symbol (key))
{
if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS)
{
continue;
}
}
else if (index != ECMA_STRING_NOT_ARRAY_INDEX)
{
if ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)
|| ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
&& !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER)))
{
continue;
}
}
else if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
{
continue;
}
}

/* Step 3. Filter property attributes */
/* Step 2. Filter property attributes */
if (filter & (JERRY_PROPERTY_FILTER_EXLCUDE_NON_CONFIGURABLE
| JERRY_PROPERTY_FILTER_EXLCUDE_NON_ENUMERABLE
| JERRY_PROPERTY_FILTER_EXLCUDE_NON_WRITABLE))
Expand Down Expand Up @@ -4729,7 +4708,7 @@ jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */

ecma_collection_free (prop_names_p);

/* Step 4: Traverse prototype chain */
/* Step 3: Traverse prototype chain */

if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) != JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN)
{
Expand Down
16 changes: 7 additions & 9 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,14 @@ enum
ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization
* or function call argument list */
/* Other values */
ECMA_VALUE_INITIALIZED = ECMA_MAKE_VALUE (12), /**< represents initialized mapped arguments formal parameter */
ECMA_VALUE_ARGUMENT_INITIALIZED = ECMA_MAKE_VALUE (12), /**< represents initialized mapped arguments formal parameter */
ECMA_VALUE_ARGUMENT_NO_TRACK = ECMA_MAKE_VALUE (13), /**< represents initialized mapped arguments formal parameter */
#if JERRY_ESNEXT
ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: sync iterator is requested */
ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: async iterator is requested */
ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: sync iterator is requested */
ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (15), /**< option for ecma_op_get_iterator: async iterator is requested */
#endif /* JERRY_ESNEXT */
#if JERRY_BUILTIN_GLOBAL_THIS
ECMA_VALUE_GLOBAL_THIS = ECMA_MAKE_VALUE (15), /**< globalThis built-in */
ECMA_VALUE_GLOBAL_THIS = ECMA_MAKE_VALUE (16), /**< globalThis built-in */
#endif /* JERRY_BUILTIN_GLOBAL_THIS */
};

Expand Down Expand Up @@ -2439,8 +2440,6 @@ typedef struct
uint32_t array_index_named_props; /**< number of array index named properties */
uint32_t string_named_props; /**< number of string named properties */
uint32_t symbol_named_props; /**< number of symbol named properties */
uint32_t lazy_string_named_props; /**< number of lazy instantiated string properties */
uint32_t lazy_symbol_named_props; /**< number of lazy instantiated symbol properties */
} ecma_property_counter_t;

/**
Expand All @@ -2452,9 +2451,8 @@ typedef enum
ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0), /* mapped arguments object */
ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE = (1 << 1), /* static mapped arguments object */
ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 2), /* 'callee' property has been lazy initialized */
ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED = (1 << 3), /* 'caller' property has been lazy initialized */
ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 4), /* 'length' property has been lazy initialized */
ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 5), /* 'Symbol.iterator' property has been lazy initialized */
ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 3), /* 'length' property has been lazy initialized */
ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 4), /* 'Symbol.iterator' property has been lazy initialized */
} ecma_arguments_object_flags_t;

/**
Expand Down
44 changes: 15 additions & 29 deletions jerry-core/ecma/builtin-objects/ecma-builtin-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */
}

/* 6. */
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p);
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL);

#if JERRY_BUILTIN_PROXY
if (props_p == NULL)
Expand Down Expand Up @@ -596,7 +596,7 @@ ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's a
ecma_value_t ret_value = ECMA_VALUE_TRUE;

/* 2. */
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p);
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL);

#if JERRY_BUILTIN_PROXY
if (props_p == NULL)
Expand Down Expand Up @@ -750,7 +750,7 @@ static ecma_value_t
ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) /**< routine's first argument */
{
/* 2 */
ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p);
ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL);

#if JERRY_BUILTIN_PROXY
if (prop_names_p == NULL)
Expand Down Expand Up @@ -831,7 +831,7 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine
ecma_object_t *props_p = ecma_get_object_from_value (props);

/* 3. */
ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p);
ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p, JERRY_PROPERTY_FILTER_ALL);
ecma_value_t ret_value = ECMA_VALUE_ERROR;

#if JERRY_BUILTIN_PROXY
Expand Down Expand Up @@ -1073,7 +1073,7 @@ ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object *
ecma_object_t *from_obj_p = ecma_get_object_from_value (from_value);

/* 5.b.iii */
ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p);
ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p, JERRY_PROPERTY_FILTER_ALL);

#if JERRY_BUILTIN_PROXY
if (props_p == NULL)
Expand Down Expand Up @@ -1327,41 +1327,27 @@ ecma_op_object_get_own_property_keys (ecma_value_t this_arg, /**< this argument
ecma_object_t *obj_p = ecma_get_object_from_value (object);

/* 2. */
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p);
jerry_property_filter_t filter = JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS;

if (props_p == NULL)
if (type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS)
{
ecma_deref_object (obj_p);
return ECMA_VALUE_ERROR;
filter = (JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS
| JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES);
}

/* 3. */
ecma_collection_t *name_list_p = ecma_new_collection ();
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, filter);
ecma_deref_object (obj_p);

/* 4. */
for (uint32_t i = 0; i < props_p->item_count; i++)
if (props_p == NULL)
{
ecma_value_t prop_name = props_p->buffer_p[i];
ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name);

if ((ecma_prop_name_is_symbol (name_p) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS)
|| (ecma_is_value_string (prop_name) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES))
{
ecma_ref_ecma_string (name_p);
ecma_collection_push_back (name_list_p, prop_name);
}
return ECMA_VALUE_ERROR;
}

ecma_value_t result_array = ecma_op_new_array_object_from_collection (name_list_p, false);

ecma_deref_object (obj_p);
ecma_collection_free (props_p);

return result_array;
return ecma_op_new_array_object_from_collection (props_p, false);
#else /* !JERRY_ESNEXT */
JERRY_UNUSED (type);
ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p);
ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL);
return ecma_op_new_array_object_from_collection (props_p, false);
#endif /* JERRY_ESNEXT */
} /* ecma_op_object_get_own_property_keys */
Expand Down
4 changes: 2 additions & 2 deletions jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in
ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);

/* 2. */
ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p);
ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p, JERRY_PROPERTY_FILTER_ALL);

#if JERRY_BUILTIN_PROXY
if (prop_names == NULL)
Expand Down Expand Up @@ -206,7 +206,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in
return ecma_raise_type_error (ECMA_ERR_MSG ("Reflect.construct expects an object as second argument"));
}

ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], false);
ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], ECMA_FROM_ARRAY_LIKE_ANY);

if (coll_p == NULL)
{
Expand Down
121 changes: 83 additions & 38 deletions jerry-core/ecma/builtin-objects/ecma-builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1414,11 +1414,17 @@ ecma_builtin_native_handler_list_lazy_property_names (ecma_object_t *object_p, /
void
ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */
ecma_collection_t *prop_names_p, /**< prop name collection */
ecma_property_counter_t *prop_counter_p) /**< prop counter */
ecma_property_counter_t *prop_counter_p, /**< property counters */
jerry_property_filter_t filter) /**< name filters */
{
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION);
JERRY_ASSERT (ecma_builtin_function_is_routine (object_p));

if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
{
return;
}

#if JERRY_ESNEXT
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;

Expand Down Expand Up @@ -1456,7 +1462,8 @@ ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a b
void
ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */
ecma_collection_t *prop_names_p, /**< prop name collection */
ecma_property_counter_t *prop_counter_p) /**< prop counter */
ecma_property_counter_t *prop_counter_p, /**< property counters */
jerry_property_filter_t filter) /**< name filters */
{
JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION
|| !ecma_builtin_function_is_routine (object_p));
Expand All @@ -1477,57 +1484,95 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in

JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);

const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id];

uint32_t index = 0;
uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0];
#if JERRY_ESNEXT
bool has_symbol = true;
#endif /* JERRY_BUILTIN_REALMS */

if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS))
{
const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id];
uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0];
#if JERRY_BUILTIN_REALMS
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t);
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t);
#else /* !JERRY_BUILTIN_REALMS */
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1;
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1;
#endif /* JERRY_BUILTIN_REALMS */
uint32_t index = 0;

while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
{
if (index == 8)
#if JERRY_ESNEXT
has_symbol = false;
#endif /* JERRY_BUILTIN_REALMS */

while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
{
bitset = *bitset_p++;
index = 0;
}
if (index == 8)
{
bitset = *bitset_p++;
index = 0;
}

uint32_t bit_for_index = (uint32_t) 1u << index;
uint32_t bit_for_index = (uint32_t) 1u << index;

if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)
{
#if JERRY_ESNEXT
if (LIT_IS_GLOBAL_SYMBOL (curr_property_p->magic_string_id))
{
ecma_string_t *name_p = ecma_op_get_global_symbol (curr_property_p->magic_string_id);
bool is_symbol = (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT);
#else /* !JERRY_ESNEXT */
bool is_symbol = false;
#endif /* JERRY_ESNEXT */

if (!(bitset & bit_for_index))
{
ecma_value_t name = ecma_make_symbol_value (name_p);
ecma_collection_push_back (prop_names_p, name);
prop_counter_p->symbol_named_props++;
}
else
{
ecma_deref_ecma_string (name_p);
}
}
if (is_symbol)
{
#if JERRY_ESNEXT
JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (curr_property_p->magic_string_id));
has_symbol = true;
#endif /* JERRY_ESNEXT */
}
else if (!(bitset & bit_for_index))
{
ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id);
ecma_collection_push_back (prop_names_p, name);
prop_counter_p->string_named_props++;
}

curr_property_p++;
index++;
}
else if (!(bitset & bit_for_index))
}

#if JERRY_ESNEXT
if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS) && has_symbol)
{
const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id];
uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0];
#if JERRY_BUILTIN_REALMS
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t);
#else /* !JERRY_BUILTIN_REALMS */
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1;
#endif /* JERRY_BUILTIN_REALMS */
uint32_t index = 0;

while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
{
ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id);
ecma_collection_push_back (prop_names_p, name);
prop_counter_p->string_named_props++;
}
if (index == 8)
{
bitset = *bitset_p++;
index = 0;
}

curr_property_p++;
index++;
uint32_t bit_for_index = (uint32_t) 1u << index;

if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT
&& !(bitset & bit_for_index))
{
ecma_string_t *name_p = ecma_op_get_global_symbol (curr_property_p->magic_string_id);
ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (name_p));
prop_counter_p->symbol_named_props++;
}

curr_property_p++;
index++;
}
}
#endif /* JERRY_ESNEXT */
} /* ecma_builtin_list_lazy_property_names */

/**
Expand Down
12 changes: 6 additions & 6 deletions jerry-core/ecma/builtin-objects/ecma-builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, ecma_str
void
ecma_builtin_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
void
ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p,
ecma_collection_t *prop_names_p,
ecma_property_counter_t *prop_counter_p);
ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p,
ecma_property_counter_t *prop_counter_p,
jerry_property_filter_t filter);
void
ecma_builtin_list_lazy_property_names (ecma_object_t *object_p,
ecma_collection_t *prop_names_p,
ecma_property_counter_t *prop_counter_p);
ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p,
ecma_property_counter_t *prop_counter_p,
jerry_property_filter_t filter);
bool
ecma_builtin_is_global (ecma_object_t *object_p);
ecma_object_t *
Expand Down
Loading

0 comments on commit fbb8496

Please sign in to comment.