@@ -3938,20 +3938,29 @@ PHP_FUNCTION(array_keys)
3938
3938
zend_bool strict = 0 ; /* do strict comparison */
3939
3939
zend_ulong num_idx ;
3940
3940
zend_string * str_idx ;
3941
+ zend_array * arrval ;
3942
+ zend_ulong elem_count ;
3941
3943
3942
3944
ZEND_PARSE_PARAMETERS_START (1 , 3 )
3943
3945
Z_PARAM_ARRAY (input )
3944
3946
Z_PARAM_OPTIONAL
3945
3947
Z_PARAM_ZVAL (search_value )
3946
3948
Z_PARAM_BOOL (strict )
3947
3949
ZEND_PARSE_PARAMETERS_END ();
3950
+ arrval = Z_ARRVAL_P (input );
3951
+ elem_count = zend_hash_num_elements (arrval );
3952
+
3953
+ /* Base case: empty input */
3954
+ if (!elem_count ) {
3955
+ RETURN_ZVAL (input , 1 , 0 )
3956
+ }
3948
3957
3949
3958
/* Initialize return array */
3950
3959
if (search_value != NULL ) {
3951
3960
array_init (return_value );
3952
3961
3953
3962
if (strict ) {
3954
- ZEND_HASH_FOREACH_KEY_VAL_IND (Z_ARRVAL_P ( input ) , num_idx , str_idx , entry ) {
3963
+ ZEND_HASH_FOREACH_KEY_VAL_IND (arrval , num_idx , str_idx , entry ) {
3955
3964
ZVAL_DEREF (entry );
3956
3965
if (fast_is_identical_function (search_value , entry )) {
3957
3966
if (str_idx ) {
@@ -3963,7 +3972,7 @@ PHP_FUNCTION(array_keys)
3963
3972
}
3964
3973
} ZEND_HASH_FOREACH_END ();
3965
3974
} else {
3966
- ZEND_HASH_FOREACH_KEY_VAL_IND (Z_ARRVAL_P ( input ) , num_idx , str_idx , entry ) {
3975
+ ZEND_HASH_FOREACH_KEY_VAL_IND (arrval , num_idx , str_idx , entry ) {
3967
3976
if (fast_equal_check_function (search_value , entry )) {
3968
3977
if (str_idx ) {
3969
3978
ZVAL_STR_COPY (& new_val , str_idx );
@@ -3975,21 +3984,27 @@ PHP_FUNCTION(array_keys)
3975
3984
} ZEND_HASH_FOREACH_END ();
3976
3985
}
3977
3986
} else {
3978
- array_init_size (return_value , zend_hash_num_elements (Z_ARRVAL_P (input )));
3979
- if (!zend_hash_num_elements (Z_ARRVAL_P (input ))) {
3980
- return ;
3981
- }
3987
+ array_init_size (return_value , elem_count );
3982
3988
zend_hash_real_init (Z_ARRVAL_P (return_value ), 1 );
3983
3989
ZEND_HASH_FILL_PACKED (Z_ARRVAL_P (return_value )) {
3984
- /* Go through input array and add keys to the return array */
3985
- ZEND_HASH_FOREACH_KEY_VAL_IND ( Z_ARRVAL_P ( input ), num_idx , str_idx , entry ) {
3986
- if ( str_idx ) {
3987
- ZVAL_STR_COPY (& new_val , str_idx );
3988
- } else {
3989
- ZVAL_LONG (& new_val , num_idx );
3990
+ if ( HT_IS_PACKED ( arrval ) && HT_IS_WITHOUT_HOLES ( arrval )) {
3991
+ /* Optimistic case: range(0..n-1) for vector-like packed array */
3992
+ zval new_val ;
3993
+ ZVAL_LONG (& new_val , 0 );
3994
+ for (; Z_LVAL ( new_val ) < elem_count ; ++ Z_LVAL ( new_val )) {
3995
+ ZEND_HASH_FILL_ADD (& new_val );
3990
3996
}
3991
- ZEND_HASH_FILL_ADD (& new_val );
3992
- } ZEND_HASH_FOREACH_END ();
3997
+ } else {
3998
+ /* Go through input array and add keys to the return array */
3999
+ ZEND_HASH_FOREACH_KEY_VAL_IND (Z_ARRVAL_P (input ), num_idx , str_idx , entry ) {
4000
+ if (str_idx ) {
4001
+ ZVAL_STR_COPY (& new_val , str_idx );
4002
+ } else {
4003
+ ZVAL_LONG (& new_val , num_idx );
4004
+ }
4005
+ ZEND_HASH_FILL_ADD (& new_val );
4006
+ } ZEND_HASH_FOREACH_END ();
4007
+ }
3993
4008
} ZEND_HASH_FILL_END ();
3994
4009
}
3995
4010
}
@@ -4001,23 +4016,31 @@ PHP_FUNCTION(array_values)
4001
4016
{
4002
4017
zval * input , /* Input array */
4003
4018
* entry ; /* An entry in the input array */
4019
+ zend_array * arrval ;
4004
4020
4005
4021
ZEND_PARSE_PARAMETERS_START (1 , 1 )
4006
4022
Z_PARAM_ARRAY (input )
4007
4023
ZEND_PARSE_PARAMETERS_END ();
4008
4024
4009
- /* Initialize return array */
4010
- array_init_size (return_value , zend_hash_num_elements (Z_ARRVAL_P (input )));
4025
+ arrval = Z_ARRVAL_P (input );
4011
4026
4012
- if (!zend_hash_num_elements (Z_ARRVAL_P (input ))) {
4013
- return ;
4027
+ /* Return empty input as is */
4028
+ if (!zend_hash_num_elements (arrval )) {
4029
+ RETURN_ZVAL (input , 1 , 0 );
4014
4030
}
4015
4031
4032
+ /* Return vector-like packed arrays as-is */
4033
+ if (HT_IS_PACKED (arrval ) && HT_IS_WITHOUT_HOLES (arrval )) {
4034
+ RETURN_ZVAL (input , 1 , 0 );
4035
+ }
4036
+
4037
+ /* Initialize return array */
4038
+ array_init_size (return_value , zend_hash_num_elements (arrval ));
4016
4039
zend_hash_real_init (Z_ARRVAL_P (return_value ), 1 );
4017
4040
4018
4041
/* Go through input array and add values to the return array */
4019
4042
ZEND_HASH_FILL_PACKED (Z_ARRVAL_P (return_value )) {
4020
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P ( input ) , entry ) {
4043
+ ZEND_HASH_FOREACH_VAL (arrval , entry ) {
4021
4044
if (UNEXPECTED (Z_ISREF_P (entry ) && Z_REFCOUNT_P (entry ) == 1 )) {
4022
4045
entry = Z_REFVAL_P (entry );
4023
4046
}
0 commit comments