@@ -5753,6 +5753,68 @@ PHP_FUNCTION(array_diff_ukey)
57535753}
57545754/* }}} */
57555755
5756+ static zend_always_inline bool php_array_values_are_all_long (HashTable * ht )
5757+ {
5758+ zval * value ;
5759+
5760+ ZEND_HASH_FOREACH_VAL (ht , value ) {
5761+ ZVAL_DEREF (value );
5762+ if (UNEXPECTED (Z_TYPE_P (value ) != IS_LONG )) {
5763+ return false;
5764+ }
5765+ } ZEND_HASH_FOREACH_END ();
5766+
5767+ return true;
5768+ }
5769+
5770+ static zend_never_inline bool php_array_diff_long (zval * args , uint32_t argc , uint32_t exclude_count , zval * return_value )
5771+ {
5772+ HashTable exclude ;
5773+ zval * value , * entry ;
5774+ zend_string * key ;
5775+ zend_long idx ;
5776+ uint32_t i ;
5777+
5778+ /* The copy loop below cannot cheaply undo a partially built result, so
5779+ * the first array must be checked upfront. */
5780+ if (!php_array_values_are_all_long (Z_ARRVAL (args [0 ]))) {
5781+ return false;
5782+ }
5783+
5784+ /* Create the exclude map while checking the value types, bailing out to
5785+ * the generic implementation on the first non-long value. A late bailout
5786+ * discards the partially built map, but that is cheaper than always
5787+ * paying an extra type-check pass on the all-long path. */
5788+ zend_hash_init (& exclude , exclude_count , NULL , NULL , 0 );
5789+ for (i = 1 ; i < argc ; i ++ ) {
5790+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL (args [i ]), value ) {
5791+ ZVAL_DEREF (value );
5792+ if (UNEXPECTED (Z_TYPE_P (value ) != IS_LONG )) {
5793+ zend_hash_destroy (& exclude );
5794+ return false;
5795+ }
5796+ zend_hash_index_add_empty_element (& exclude , Z_LVAL_P (value ));
5797+ } ZEND_HASH_FOREACH_END ();
5798+ }
5799+
5800+ array_init_size (return_value , zend_hash_num_elements (Z_ARRVAL (args [0 ])));
5801+ ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL (args [0 ]), idx , key , value ) {
5802+ entry = value ;
5803+ ZVAL_DEREF (entry );
5804+ if (!zend_hash_index_exists (& exclude , Z_LVAL_P (entry ))) {
5805+ if (key ) {
5806+ value = zend_hash_add_new (Z_ARRVAL_P (return_value ), key , value );
5807+ } else {
5808+ value = zend_hash_index_add_new (Z_ARRVAL_P (return_value ), idx , value );
5809+ }
5810+ zval_add_ref (value );
5811+ }
5812+ } ZEND_HASH_FOREACH_END ();
5813+
5814+ zend_hash_destroy (& exclude );
5815+ return true;
5816+ }
5817+
57565818/* {{{ Returns the entries of arr1 that have values which are not present in any of the others arguments. */
57575819PHP_FUNCTION (array_diff )
57585820{
@@ -5853,6 +5915,10 @@ PHP_FUNCTION(array_diff)
58535915 RETURN_THROWS ();
58545916 }
58555917
5918+ if (php_array_diff_long (args , argc , (uint32_t )num , return_value )) {
5919+ return ;
5920+ }
5921+
58565922 ZVAL_NULL (& dummy );
58575923 /* create exclude map */
58585924 zend_hash_init (& exclude , num , NULL , NULL , 0 );
0 commit comments