Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8b3eb93

Browse files
authoredSep 28, 2021
Add property key filters for general object property enumeration (#4778)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
1 parent 14ff5bf commit 8b3eb93

File tree

3 files changed

+223
-127
lines changed

3 files changed

+223
-127
lines changed
 

‎jerry-core/ecma/base/ecma-globals.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,8 +2439,6 @@ typedef struct
24392439
uint32_t array_index_named_props; /**< number of array index named properties */
24402440
uint32_t string_named_props; /**< number of string named properties */
24412441
uint32_t symbol_named_props; /**< number of symbol named properties */
2442-
uint32_t lazy_string_named_props; /**< number of lazy instantiated string properties */
2443-
uint32_t lazy_symbol_named_props; /**< number of lazy instantiated symbol properties */
24442442
} ecma_property_counter_t;
24452443

24462444
/**

‎jerry-core/ecma/base/ecma-module.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ ecma_module_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */
670670
while (true)
671671
{
672672
uint32_t highest_index = item_index;
673-
uint32_t current_index = item_index * 2 + 2;
673+
uint32_t current_index = (item_index << 1) + 2;
674674

675675
if (current_index >= item_count)
676676
{

‎jerry-core/ecma/operations/ecma-objects.c

Lines changed: 222 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -2360,119 +2360,52 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */
23602360
} /* ecma_object_list_lazy_property_names */
23612361

23622362
/**
2363-
* Helper method for sorting the given property names based on [[OwnPropertyKeys]]
2363+
* Helper routine for heapsort algorithm.
23642364
*/
23652365
static void
2366-
ecma_object_sort_property_names (ecma_collection_t *prop_names_p, /**< prop name collection */
2367-
ecma_property_counter_t *prop_counter) /**< prop counter */
2366+
ecma_op_object_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */
2367+
uint32_t item_count, /**< number of items */
2368+
uint32_t item_index) /**< index of updated item */
23682369
{
2369-
uint32_t lazy_string_prop_name_count = prop_counter->lazy_string_named_props;
2370-
#if JERRY_ESNEXT
2371-
uint32_t lazy_symbol_prop_name_count = prop_counter->lazy_symbol_named_props;
2372-
#endif /* JERRY_ESNEXT */
2373-
2374-
uint32_t string_name_pos = prop_counter->string_named_props;
2375-
#if JERRY_ESNEXT
2376-
uint32_t symbol_name_pos = prop_counter->symbol_named_props;
2377-
#endif /* JERRY_ESNEXT */
2378-
2379-
uint32_t all_prop_count = (prop_counter->array_index_named_props) + (string_name_pos);
2380-
#if JERRY_ESNEXT
2381-
all_prop_count += symbol_name_pos;
2382-
#endif /* JERRY_ESNEXT */
2383-
2384-
ecma_value_t *names_p = jmem_heap_alloc_block (all_prop_count * sizeof (ecma_value_t));
2385-
2386-
ecma_value_t *string_names_p = names_p + prop_counter->array_index_named_props;
2387-
#if JERRY_ESNEXT
2388-
ecma_value_t *symbol_names_p = string_names_p + string_name_pos;
2389-
#endif /* JERRY_ESNEXT */
2390-
2391-
uint32_t array_index_name_pos = 0;
2392-
uint32_t lazy_string_name_pos = 0;
2393-
#if JERRY_ESNEXT
2394-
uint32_t lazy_symbol_name_pos = 0;
2395-
#endif /* JERRY_ESNEXT */
2396-
2397-
for (uint32_t i = 0; i < prop_names_p->item_count; i++)
2370+
while (true)
23982371
{
2399-
ecma_value_t prop_name = prop_names_p->buffer_p[i];
2400-
ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name);
2401-
uint32_t index = ecma_string_get_array_index (name_p);
2372+
uint32_t highest_index = item_index;
2373+
uint32_t current_index = (item_index << 1) + 1;
24022374

2403-
/* sort array index named properties in ascending order */
2404-
if (index != ECMA_STRING_NOT_ARRAY_INDEX)
2375+
if (current_index >= item_count)
24052376
{
2406-
JERRY_ASSERT (array_index_name_pos < prop_counter->array_index_named_props);
2407-
2408-
uint32_t insert_pos = 0;
2409-
while (insert_pos < array_index_name_pos
2410-
&& index > ecma_string_get_array_index (ecma_get_string_from_value (names_p[insert_pos])))
2411-
{
2412-
insert_pos++;
2413-
}
2414-
2415-
if (insert_pos == array_index_name_pos)
2416-
{
2417-
names_p[array_index_name_pos++] = prop_name;
2418-
}
2419-
else
2420-
{
2421-
JERRY_ASSERT (insert_pos < array_index_name_pos);
2422-
JERRY_ASSERT (index <= ecma_string_get_array_index (ecma_get_string_from_value (names_p[insert_pos])));
2377+
return;
2378+
}
24232379

2424-
uint32_t move_pos = array_index_name_pos++;
2380+
uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[highest_index]));
2381+
uint32_t left_value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index]));
24252382

2426-
while (move_pos > insert_pos)
2427-
{
2428-
names_p[move_pos] = names_p[move_pos - 1u];
2383+
if (value < left_value)
2384+
{
2385+
highest_index = current_index;
2386+
value = left_value;
2387+
}
24292388

2430-
move_pos--;
2431-
}
2389+
current_index++;
24322390

2433-
names_p[insert_pos] = prop_name;
2434-
}
2435-
}
2436-
#if JERRY_ESNEXT
2437-
/* sort symbol named properites in creation order */
2438-
else if (ecma_prop_name_is_symbol (name_p))
2391+
if (current_index < item_count
2392+
&& value < ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index])))
24392393
{
2440-
JERRY_ASSERT (symbol_name_pos > 0);
2441-
JERRY_ASSERT (symbol_name_pos <= prop_counter->symbol_named_props);
2442-
2443-
if (i < lazy_symbol_prop_name_count)
2444-
{
2445-
symbol_names_p[lazy_symbol_name_pos++] = prop_name;
2446-
}
2447-
else
2448-
{
2449-
symbol_names_p[--symbol_name_pos] = prop_name;
2450-
}
2394+
highest_index = current_index;
24512395
}
2452-
#endif /* JERRY_ESNEXT */
2453-
/* sort string named properties in creation order */
2454-
else
2455-
{
2456-
JERRY_ASSERT (string_name_pos > 0);
2457-
JERRY_ASSERT (string_name_pos <= prop_counter->string_named_props);
24582396

2459-
if (i < lazy_string_prop_name_count)
2460-
{
2461-
string_names_p[lazy_string_name_pos++] = prop_name;
2462-
}
2463-
else
2464-
{
2465-
string_names_p[--string_name_pos] = prop_name;
2466-
}
2397+
if (highest_index == item_index)
2398+
{
2399+
return;
24672400
}
2468-
}
24692401

2470-
/* Free the unsorted buffer and copy the sorted one in its place */
2471-
jmem_heap_free_block (prop_names_p->buffer_p, ECMA_COLLECTION_ALLOCATED_SIZE (prop_names_p->capacity));
2472-
prop_names_p->buffer_p = names_p;
2473-
prop_names_p->item_count = all_prop_count;
2474-
prop_names_p->capacity = all_prop_count;
2475-
} /* ecma_object_sort_property_names */
2402+
ecma_value_t tmp = buffer_p[highest_index];
2403+
buffer_p[highest_index] = buffer_p[item_index];
2404+
buffer_p[item_index] = tmp;
2405+
2406+
item_index = highest_index;
2407+
}
2408+
} /* ecma_op_object_heap_sort_shift_down */
24762409

24772410
/**
24782411
* Object's [[OwnPropertyKeys]] internal method
@@ -2491,7 +2424,7 @@ ecma_object_sort_property_names (ecma_collection_t *prop_names_p, /**< prop name
24912424
*/
24922425
ecma_collection_t *
24932426
ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */
2494-
jerry_property_filter_t filter) /**< property name filter options */
2427+
jerry_property_filter_t filter) /**< name filters */
24952428
{
24962429
#if JERRY_BUILTIN_PROXY
24972430
if (ECMA_OBJECT_IS_PROXY (obj_p))
@@ -2506,13 +2439,10 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */
25062439
}
25072440

25082441
ecma_collection_t *prop_names_p = ecma_new_collection ();
2509-
ecma_property_counter_t prop_counter = {0, 0, 0, 0, 0};
2442+
ecma_property_counter_t prop_counter = {0, 0, 0};
25102443

25112444
ecma_object_list_lazy_property_names (obj_p, prop_names_p, &prop_counter, filter);
25122445

2513-
prop_counter.lazy_string_named_props = prop_names_p->item_count - prop_counter.symbol_named_props;
2514-
prop_counter.lazy_symbol_named_props = prop_counter.symbol_named_props;
2515-
25162446
jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp;
25172447

25182448
#if JERRY_PROPERTY_HASHMAP
@@ -2527,6 +2457,118 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */
25272457
}
25282458
#endif /* JERRY_PROPERTY_HASHMAP */
25292459

2460+
jmem_cpointer_t counter_prop_iter_cp = prop_iter_cp;
2461+
2462+
uint32_t array_index_named_props = 0;
2463+
uint32_t string_named_props = 0;
2464+
#if JERRY_ESNEXT
2465+
uint32_t symbol_named_props = 0;
2466+
#endif /* JERRY_ESNEXT */
2467+
2468+
while (counter_prop_iter_cp != JMEM_CP_NULL)
2469+
{
2470+
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, counter_prop_iter_cp);
2471+
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
2472+
2473+
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
2474+
{
2475+
ecma_property_t *property_p = prop_iter_p->types + i;
2476+
2477+
if (!ECMA_PROPERTY_IS_RAW (*property_p)
2478+
|| (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN))
2479+
{
2480+
continue;
2481+
}
2482+
2483+
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
2484+
2485+
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC
2486+
&& prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT
2487+
&& prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT)
2488+
{
2489+
continue;
2490+
}
2491+
2492+
ecma_string_t *name_p = ecma_string_from_property_name (*property_p,
2493+
prop_pair_p->names_cp[i]);
2494+
2495+
if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX)
2496+
{
2497+
array_index_named_props++;
2498+
}
2499+
#if JERRY_ESNEXT
2500+
else if (ecma_prop_name_is_symbol (name_p))
2501+
{
2502+
symbol_named_props++;
2503+
}
2504+
#endif /* JERRY_ESNEXT */
2505+
else
2506+
{
2507+
string_named_props++;
2508+
}
2509+
2510+
ecma_deref_ecma_string (name_p);
2511+
}
2512+
2513+
counter_prop_iter_cp = prop_iter_p->next_property_cp;
2514+
}
2515+
2516+
if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)
2517+
{
2518+
JERRY_ASSERT (prop_counter.array_index_named_props == 0);
2519+
array_index_named_props = 0;
2520+
}
2521+
2522+
if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)
2523+
{
2524+
JERRY_ASSERT (prop_counter.string_named_props == 0);
2525+
string_named_props = 0;
2526+
}
2527+
2528+
#if JERRY_ESNEXT
2529+
if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS)
2530+
{
2531+
JERRY_ASSERT (prop_counter.symbol_named_props == 0);
2532+
symbol_named_props = 0;
2533+
}
2534+
2535+
uint32_t total = array_index_named_props + string_named_props + symbol_named_props;
2536+
#else /* !JERRY_ESNEXT */
2537+
uint32_t total = array_index_named_props + string_named_props;
2538+
#endif /* JERRY_ESNEXT */
2539+
2540+
if (total == 0)
2541+
{
2542+
return prop_names_p;
2543+
}
2544+
2545+
ecma_collection_reserve (prop_names_p, total);
2546+
prop_names_p->item_count += total;
2547+
2548+
ecma_value_t *buffer_p = prop_names_p->buffer_p;
2549+
ecma_value_t *array_index_current_p = buffer_p + array_index_named_props + prop_counter.array_index_named_props;
2550+
ecma_value_t *string_current_p = array_index_current_p + string_named_props + prop_counter.string_named_props;
2551+
2552+
#if JERRY_ESNEXT
2553+
ecma_value_t *symbol_current_p = string_current_p + symbol_named_props + prop_counter.symbol_named_props;
2554+
2555+
if (prop_counter.symbol_named_props > 0
2556+
&& (array_index_named_props + string_named_props) > 0)
2557+
{
2558+
memmove ((void *) string_current_p,
2559+
(void *) (buffer_p + prop_counter.array_index_named_props + prop_counter.string_named_props),
2560+
prop_counter.symbol_named_props * sizeof (ecma_value_t));
2561+
}
2562+
#endif /* JERRY_ESNEXT */
2563+
2564+
if (prop_counter.string_named_props > 0
2565+
&& array_index_named_props > 0)
2566+
{
2567+
memmove ((void *) array_index_current_p,
2568+
(void *) (buffer_p + prop_counter.array_index_named_props),
2569+
prop_counter.string_named_props * sizeof (ecma_value_t));
2570+
}
2571+
25302572
while (prop_iter_cp != JMEM_CP_NULL)
25312573
{
25322574
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
@@ -2536,46 +2578,102 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */
25362578
{
25372579
ecma_property_t *property_p = prop_iter_p->types + i;
25382580

2539-
if (ECMA_PROPERTY_IS_RAW (*property_p)
2540-
&& !(*property_p & ECMA_PROPERTY_FLAG_BUILT_IN))
2581+
if (!ECMA_PROPERTY_IS_RAW (*property_p)
2582+
|| (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN))
25412583
{
2542-
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
2584+
continue;
2585+
}
25432586

2544-
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC
2545-
&& prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT
2546-
&& prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT)
2547-
{
2548-
continue;
2549-
}
2587+
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
2588+
2589+
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC
2590+
&& prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT
2591+
&& prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT)
2592+
{
2593+
continue;
2594+
}
25502595

2551-
ecma_string_t *name_p = ecma_string_from_property_name (*property_p,
2552-
prop_pair_p->names_cp[i]);
2596+
ecma_string_t *name_p = ecma_string_from_property_name (*property_p,
2597+
prop_pair_p->names_cp[i]);
25532598

2554-
if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX)
2599+
if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX)
2600+
{
2601+
if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES))
25552602
{
2556-
prop_counter.array_index_named_props++;
2603+
*(--array_index_current_p) = ecma_make_string_value (name_p);
2604+
continue;
25572605
}
2606+
}
25582607
#if JERRY_ESNEXT
2559-
else if (ecma_prop_name_is_symbol (name_p))
2608+
else if (ecma_prop_name_is_symbol (name_p))
2609+
{
2610+
if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS))
25602611
{
2561-
prop_counter.symbol_named_props++;
2612+
*(--symbol_current_p) = ecma_make_symbol_value (name_p);
2613+
continue;
25622614
}
2615+
}
25632616
#endif /* JERRY_ESNEXT */
2564-
else
2617+
else
2618+
{
2619+
if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS))
25652620
{
2566-
prop_counter.string_named_props++;
2621+
*(--string_current_p) = ecma_make_string_value (name_p);
2622+
continue;
25672623
}
2568-
2569-
ecma_collection_push_back (prop_names_p, ecma_make_prop_name_value (name_p));
25702624
}
2625+
2626+
ecma_deref_ecma_string (name_p);
25712627
}
25722628

25732629
prop_iter_cp = prop_iter_p->next_property_cp;
25742630
}
25752631

2576-
if (prop_names_p->item_count != 0)
2632+
if (array_index_named_props > 1
2633+
|| (array_index_named_props == 1 && prop_counter.array_index_named_props > 0))
25772634
{
2578-
ecma_object_sort_property_names (prop_names_p, &prop_counter);
2635+
uint32_t prev_value = 0;
2636+
ecma_value_t *array_index_p = buffer_p + prop_counter.array_index_named_props;
2637+
ecma_value_t *array_index_end_p = array_index_p + array_index_named_props;
2638+
2639+
if (prop_counter.array_index_named_props > 0)
2640+
{
2641+
prev_value = ecma_string_get_array_index (ecma_get_string_from_value (array_index_p[-1]));
2642+
}
2643+
2644+
do
2645+
{
2646+
uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (*array_index_p++));
2647+
2648+
if (value < prev_value)
2649+
{
2650+
uint32_t array_props = prop_counter.array_index_named_props + array_index_named_props;
2651+
uint32_t i = (array_props >> 1) - 1;
2652+
2653+
do
2654+
{
2655+
ecma_op_object_heap_sort_shift_down (buffer_p, array_props, i);
2656+
}
2657+
while (i-- > 0);
2658+
2659+
i = array_props - 1;
2660+
2661+
do
2662+
{
2663+
ecma_value_t tmp = buffer_p[i];
2664+
buffer_p[i] = buffer_p[0];
2665+
buffer_p[0] = tmp;
2666+
2667+
ecma_op_object_heap_sort_shift_down (buffer_p, i, 0);
2668+
}
2669+
while (--i > 0);
2670+
2671+
break;
2672+
}
2673+
2674+
prev_value = value;
2675+
}
2676+
while (array_index_p < array_index_end_p);
25792677
}
25802678

25812679
return prop_names_p;

0 commit comments

Comments
 (0)
Please sign in to comment.