@@ -2360,119 +2360,52 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */
2360
2360
} /* ecma_object_list_lazy_property_names */
2361
2361
2362
2362
/**
2363
- * Helper method for sorting the given property names based on [[OwnPropertyKeys]]
2363
+ * Helper routine for heapsort algorithm.
2364
2364
*/
2365
2365
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 */
2368
2369
{
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)
2398
2371
{
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 ;
2402
2374
2403
- /* sort array index named properties in ascending order */
2404
- if (index != ECMA_STRING_NOT_ARRAY_INDEX )
2375
+ if (current_index >= item_count )
2405
2376
{
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
+ }
2423
2379
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 ]));
2425
2382
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
+ }
2429
2388
2430
- move_pos -- ;
2431
- }
2389
+ current_index ++ ;
2432
2390
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 ])))
2439
2393
{
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 ;
2451
2395
}
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 );
2458
2396
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 ;
2467
2400
}
2468
- }
2469
2401
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 */
2476
2409
2477
2410
/**
2478
2411
* Object's [[OwnPropertyKeys]] internal method
@@ -2491,7 +2424,7 @@ ecma_object_sort_property_names (ecma_collection_t *prop_names_p, /**< prop name
2491
2424
*/
2492
2425
ecma_collection_t *
2493
2426
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 */
2495
2428
{
2496
2429
#if JERRY_BUILTIN_PROXY
2497
2430
if (ECMA_OBJECT_IS_PROXY (obj_p ))
@@ -2506,13 +2439,10 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */
2506
2439
}
2507
2440
2508
2441
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 };
2510
2443
2511
2444
ecma_object_list_lazy_property_names (obj_p , prop_names_p , & prop_counter , filter );
2512
2445
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
-
2516
2446
jmem_cpointer_t prop_iter_cp = obj_p -> u1 .property_list_cp ;
2517
2447
2518
2448
#if JERRY_PROPERTY_HASHMAP
@@ -2527,6 +2457,118 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */
2527
2457
}
2528
2458
#endif /* JERRY_PROPERTY_HASHMAP */
2529
2459
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
+
2530
2572
while (prop_iter_cp != JMEM_CP_NULL )
2531
2573
{
2532
2574
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 */
2536
2578
{
2537
2579
ecma_property_t * property_p = prop_iter_p -> types + i ;
2538
2580
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 ))
2541
2583
{
2542
- ecma_property_pair_t * prop_pair_p = (ecma_property_pair_t * ) prop_iter_p ;
2584
+ continue ;
2585
+ }
2543
2586
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
+ }
2550
2595
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 ]);
2553
2598
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 ))
2555
2602
{
2556
- prop_counter .array_index_named_props ++ ;
2603
+ * (-- array_index_current_p ) = ecma_make_string_value (name_p );
2604
+ continue ;
2557
2605
}
2606
+ }
2558
2607
#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 ))
2560
2611
{
2561
- prop_counter .symbol_named_props ++ ;
2612
+ * (-- symbol_current_p ) = ecma_make_symbol_value (name_p );
2613
+ continue ;
2562
2614
}
2615
+ }
2563
2616
#endif /* JERRY_ESNEXT */
2564
- else
2617
+ else
2618
+ {
2619
+ if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS ))
2565
2620
{
2566
- prop_counter .string_named_props ++ ;
2621
+ * (-- string_current_p ) = ecma_make_string_value (name_p );
2622
+ continue ;
2567
2623
}
2568
-
2569
- ecma_collection_push_back (prop_names_p , ecma_make_prop_name_value (name_p ));
2570
2624
}
2625
+
2626
+ ecma_deref_ecma_string (name_p );
2571
2627
}
2572
2628
2573
2629
prop_iter_cp = prop_iter_p -> next_property_cp ;
2574
2630
}
2575
2631
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 ))
2577
2634
{
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 );
2579
2677
}
2580
2678
2581
2679
return prop_names_p ;
0 commit comments