@@ -55,7 +55,7 @@ static _locale_t current_locale = NULL;
5555#define zend_tolower (c ) tolower(c)
5656#endif
5757
58- #define TYPE_PAIR (t1 ,t2 ) ((( t1) << 4) | (t2))
58+ #define TYPE_PAIR (t1 ,t2 ) ((unsigned char) ((( t1) << 4) | (t2) ))
5959
6060#ifdef ZEND_INTRIN_AVX2_NATIVE
6161#define HAVE_BLOCKCONV
@@ -2169,131 +2169,137 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
21692169}
21702170/* }}} */
21712171
2172- ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2173- {
2174- int converted = 0 ;
2175- zval op1_copy , op2_copy ;
2172+ static int ZEND_FASTCALL zend_compare_fast (zval * op1 , zval * op2 , bool converted );
21762173
2177- while (1 ) {
2178- switch (TYPE_PAIR (Z_TYPE_P (op1 ), Z_TYPE_P (op2 ))) {
2179- case TYPE_PAIR (IS_LONG , IS_LONG ):
2180- return Z_LVAL_P (op1 )> Z_LVAL_P (op2 )?1 :(Z_LVAL_P (op1 )< Z_LVAL_P (op2 )?-1 :0 );
2174+ static int ZEND_FASTCALL zend_compare_slow (zval * op1 , zval * op2 , bool converted )
2175+ {
2176+ if (Z_ISREF_P (op1 ) || Z_ISREF_P (op2 )) {
2177+ ZVAL_DEREF (op1 );
2178+ ZVAL_DEREF (op2 );
2179+ return zend_compare_fast (op1 , op2 , converted );
2180+ }
21812181
2182- case TYPE_PAIR (IS_DOUBLE , IS_LONG ):
2183- return ZEND_NORMALIZE_BOOL (Z_DVAL_P (op1 ) - (double )Z_LVAL_P (op2 ));
2182+ if (Z_TYPE_P (op1 ) == IS_OBJECT
2183+ && Z_TYPE_P (op2 ) == IS_OBJECT
2184+ && Z_OBJ_P (op1 ) == Z_OBJ_P (op2 )) {
2185+ return 0 ;
2186+ } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
2187+ return Z_OBJ_HANDLER_P (op1 , compare )(op1 , op2 );
2188+ } else if (Z_TYPE_P (op2 ) == IS_OBJECT ) {
2189+ return Z_OBJ_HANDLER_P (op2 , compare )(op1 , op2 );
2190+ }
2191+
2192+ if (!converted ) {
2193+ if (Z_TYPE_P (op1 ) < IS_TRUE ) {
2194+ return zval_is_true (op2 ) ? -1 : 0 ;
2195+ } else if (Z_TYPE_P (op1 ) == IS_TRUE ) {
2196+ return zval_is_true (op2 ) ? 0 : 1 ;
2197+ } else if (Z_TYPE_P (op2 ) < IS_TRUE ) {
2198+ return zval_is_true (op1 ) ? 1 : 0 ;
2199+ } else if (Z_TYPE_P (op2 ) == IS_TRUE ) {
2200+ return zval_is_true (op1 ) ? 0 : -1 ;
2201+ } else {
2202+ zval op1_copy , op2_copy ;
2203+ op1 = _zendi_convert_scalar_to_number_silent (op1 , & op1_copy );
2204+ op2 = _zendi_convert_scalar_to_number_silent (op2 , & op2_copy );
2205+ if (EG (exception )) {
2206+ return 1 ; /* to stop comparison of arrays */
2207+ }
2208+ return zend_compare_fast (op1 , op2 , true);
2209+ }
2210+ } else if (Z_TYPE_P (op1 )== IS_ARRAY ) {
2211+ return 1 ;
2212+ } else if (Z_TYPE_P (op2 )== IS_ARRAY ) {
2213+ return -1 ;
2214+ } else {
2215+ ZEND_UNREACHABLE ();
2216+ zend_throw_error (NULL , "Unsupported operand types" );
2217+ return 1 ;
2218+ }
2219+ }
21842220
2185- case TYPE_PAIR (IS_LONG , IS_DOUBLE ):
2186- return ZEND_NORMALIZE_BOOL ((double )Z_LVAL_P (op1 ) - Z_DVAL_P (op2 ));
2221+ static inline int ZEND_FASTCALL zend_compare_fast (zval * op1 , zval * op2 , bool converted )
2222+ {
2223+ switch (TYPE_PAIR (Z_TYPE_P (op1 ), Z_TYPE_P (op2 ))) {
2224+ case TYPE_PAIR (IS_LONG , IS_LONG ):
2225+ return Z_LVAL_P (op1 )> Z_LVAL_P (op2 )?1 :(Z_LVAL_P (op1 )< Z_LVAL_P (op2 )?-1 :0 );
21872226
2188- case TYPE_PAIR (IS_DOUBLE , IS_DOUBLE ):
2189- if (Z_DVAL_P (op1 ) == Z_DVAL_P (op2 )) {
2190- return 0 ;
2191- } else {
2192- return ZEND_NORMALIZE_BOOL (Z_DVAL_P (op1 ) - Z_DVAL_P (op2 ));
2193- }
2227+ case TYPE_PAIR (IS_DOUBLE , IS_LONG ):
2228+ return ZEND_NORMALIZE_BOOL (Z_DVAL_P (op1 ) - (double )Z_LVAL_P (op2 ));
21942229
2195- case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2196- return zend_compare_arrays ( op1 , op2 );
2230+ case TYPE_PAIR (IS_LONG , IS_DOUBLE ):
2231+ return ZEND_NORMALIZE_BOOL (( double ) Z_LVAL_P ( op1 ) - Z_DVAL_P ( op2 ) );
21972232
2198- case TYPE_PAIR (IS_NULL , IS_NULL ):
2199- case TYPE_PAIR (IS_NULL , IS_FALSE ):
2200- case TYPE_PAIR (IS_FALSE , IS_NULL ):
2201- case TYPE_PAIR (IS_FALSE , IS_FALSE ):
2202- case TYPE_PAIR (IS_TRUE , IS_TRUE ):
2233+ case TYPE_PAIR (IS_DOUBLE , IS_DOUBLE ):
2234+ if (Z_DVAL_P (op1 ) == Z_DVAL_P (op2 )) {
22032235 return 0 ;
2236+ } else {
2237+ return ZEND_NORMALIZE_BOOL (Z_DVAL_P (op1 ) - Z_DVAL_P (op2 ));
2238+ }
22042239
2205- case TYPE_PAIR (IS_NULL , IS_TRUE ):
2206- return -1 ;
2240+ case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2241+ return zend_compare_arrays ( op1 , op2 ) ;
22072242
2208- case TYPE_PAIR (IS_TRUE , IS_NULL ):
2209- return 1 ;
2243+ case TYPE_PAIR (IS_NULL , IS_NULL ):
2244+ case TYPE_PAIR (IS_NULL , IS_FALSE ):
2245+ case TYPE_PAIR (IS_FALSE , IS_NULL ):
2246+ case TYPE_PAIR (IS_FALSE , IS_FALSE ):
2247+ case TYPE_PAIR (IS_TRUE , IS_TRUE ):
2248+ return 0 ;
22102249
2211- case TYPE_PAIR (IS_STRING , IS_STRING ):
2212- if (Z_STR_P (op1 ) == Z_STR_P (op2 )) {
2213- return 0 ;
2214- }
2215- return zendi_smart_strcmp (Z_STR_P (op1 ), Z_STR_P (op2 ));
2250+ case TYPE_PAIR (IS_NULL , IS_TRUE ):
2251+ return -1 ;
22162252
2217- case TYPE_PAIR (IS_NULL , IS_STRING ):
2218- return Z_STRLEN_P ( op2 ) == 0 ? 0 : - 1 ;
2253+ case TYPE_PAIR (IS_TRUE , IS_NULL ):
2254+ return 1 ;
22192255
2220- case TYPE_PAIR (IS_STRING , IS_NULL ):
2221- return Z_STRLEN_P (op1 ) == 0 ? 0 : 1 ;
2256+ case TYPE_PAIR (IS_STRING , IS_STRING ):
2257+ if (Z_STR_P (op1 ) == Z_STR_P (op2 )) {
2258+ return 0 ;
2259+ }
2260+ return zendi_smart_strcmp (Z_STR_P (op1 ), Z_STR_P (op2 ));
22222261
2223- case TYPE_PAIR (IS_LONG , IS_STRING ):
2224- return compare_long_to_string ( Z_LVAL_P ( op1 ), Z_STR_P ( op2 )) ;
2262+ case TYPE_PAIR (IS_NULL , IS_STRING ):
2263+ return Z_STRLEN_P ( op2 ) == 0 ? 0 : -1 ;
22252264
2226- case TYPE_PAIR (IS_STRING , IS_LONG ):
2227- return - compare_long_to_string ( Z_LVAL_P ( op2 ), Z_STR_P ( op1 )) ;
2265+ case TYPE_PAIR (IS_STRING , IS_NULL ):
2266+ return Z_STRLEN_P ( op1 ) == 0 ? 0 : 1 ;
22282267
2229- case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2230- if (zend_isnan (Z_DVAL_P (op1 ))) {
2231- return 1 ;
2232- }
2268+ case TYPE_PAIR (IS_LONG , IS_STRING ):
2269+ return compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 ));
22332270
2234- return compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ));
2271+ case TYPE_PAIR (IS_STRING , IS_LONG ):
2272+ return - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ));
22352273
2236- case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2237- if (zend_isnan (Z_DVAL_P (op2 ))) {
2238- return 1 ;
2239- }
2274+ case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2275+ if (zend_isnan (Z_DVAL_P (op1 ))) {
2276+ return 1 ;
2277+ }
22402278
2241- return - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ));
2279+ return compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ));
22422280
2243- case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2281+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2282+ if (zend_isnan (Z_DVAL_P (op2 ))) {
22442283 return 1 ;
2284+ }
22452285
2246- case TYPE_PAIR (IS_NULL , IS_OBJECT ):
2247- return -1 ;
2286+ return - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ));
22482287
2249- default :
2250- if (Z_ISREF_P (op1 )) {
2251- op1 = Z_REFVAL_P (op1 );
2252- continue ;
2253- } else if (Z_ISREF_P (op2 )) {
2254- op2 = Z_REFVAL_P (op2 );
2255- continue ;
2256- }
2288+ case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2289+ return 1 ;
22572290
2258- if (Z_TYPE_P (op1 ) == IS_OBJECT
2259- && Z_TYPE_P (op2 ) == IS_OBJECT
2260- && Z_OBJ_P (op1 ) == Z_OBJ_P (op2 )) {
2261- return 0 ;
2262- } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
2263- return Z_OBJ_HANDLER_P (op1 , compare )(op1 , op2 );
2264- } else if (Z_TYPE_P (op2 ) == IS_OBJECT ) {
2265- return Z_OBJ_HANDLER_P (op2 , compare )(op1 , op2 );
2266- }
2291+ case TYPE_PAIR (IS_NULL , IS_OBJECT ):
2292+ return -1 ;
22672293
2268- if (!converted ) {
2269- if (Z_TYPE_P (op1 ) < IS_TRUE ) {
2270- return zval_is_true (op2 ) ? -1 : 0 ;
2271- } else if (Z_TYPE_P (op1 ) == IS_TRUE ) {
2272- return zval_is_true (op2 ) ? 0 : 1 ;
2273- } else if (Z_TYPE_P (op2 ) < IS_TRUE ) {
2274- return zval_is_true (op1 ) ? 1 : 0 ;
2275- } else if (Z_TYPE_P (op2 ) == IS_TRUE ) {
2276- return zval_is_true (op1 ) ? 0 : -1 ;
2277- } else {
2278- op1 = _zendi_convert_scalar_to_number_silent (op1 , & op1_copy );
2279- op2 = _zendi_convert_scalar_to_number_silent (op2 , & op2_copy );
2280- if (EG (exception )) {
2281- return 1 ; /* to stop comparison of arrays */
2282- }
2283- converted = 1 ;
2284- }
2285- } else if (Z_TYPE_P (op1 )== IS_ARRAY ) {
2286- return 1 ;
2287- } else if (Z_TYPE_P (op2 )== IS_ARRAY ) {
2288- return -1 ;
2289- } else {
2290- ZEND_UNREACHABLE ();
2291- zend_throw_error (NULL , "Unsupported operand types" );
2292- return 1 ;
2293- }
2294- }
2294+ default :
2295+ return zend_compare_slow (op1 , op2 , converted );
22952296 }
22962297}
2298+
2299+ ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2300+ {
2301+ return zend_compare_fast (op1 , op2 , false);
2302+ }
22972303/* }}} */
22982304
22992305/* return int to be compatible with compare_func_t */
0 commit comments