@@ -58,7 +58,7 @@ static _locale_t current_locale = NULL;
5858#define zend_tolower (c ) tolower(c)
5959#endif
6060
61- #define TYPE_PAIR (t1 ,t2 ) ((( t1) << 4) | (t2))
61+ #define TYPE_PAIR (t1 ,t2 ) ((unsigned char) ((( t1) << 4) | (t2) ))
6262
6363#ifdef ZEND_INTRIN_AVX2_NATIVE
6464#define HAVE_BLOCKCONV
@@ -2235,127 +2235,133 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
22352235}
22362236/* }}} */
22372237
2238- ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2238+ static int ZEND_FASTCALL zend_compare_fast (zval * op1 , zval * op2 , bool converted );
2239+
2240+ static int ZEND_FASTCALL zend_compare_slow (zval * op1 , zval * op2 , bool converted )
22392241{
2240- int converted = 0 ;
2241- zval op1_copy , op2_copy ;
2242+ if (Z_ISREF_P (op1 ) || Z_ISREF_P (op2 )) {
2243+ ZVAL_DEREF (op1 );
2244+ ZVAL_DEREF (op2 );
2245+ return zend_compare_fast (op1 , op2 , converted );
2246+ }
22422247
2243- while (1 ) {
2244- switch (TYPE_PAIR (Z_TYPE_P (op1 ), Z_TYPE_P (op2 ))) {
2245- case TYPE_PAIR (IS_LONG , IS_LONG ):
2246- return Z_LVAL_P (op1 )> Z_LVAL_P (op2 )?1 :(Z_LVAL_P (op1 )< Z_LVAL_P (op2 )?-1 :0 );
2248+ if (Z_TYPE_P (op1 ) == IS_OBJECT
2249+ && Z_TYPE_P (op2 ) == IS_OBJECT
2250+ && Z_OBJ_P (op1 ) == Z_OBJ_P (op2 )) {
2251+ return 0 ;
2252+ } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
2253+ return Z_OBJ_HANDLER_P (op1 , compare )(op1 , op2 );
2254+ } else if (Z_TYPE_P (op2 ) == IS_OBJECT ) {
2255+ return Z_OBJ_HANDLER_P (op2 , compare )(op1 , op2 );
2256+ }
2257+
2258+ if (!converted ) {
2259+ if (Z_TYPE_P (op1 ) < IS_TRUE ) {
2260+ return zval_is_true (op2 ) ? -1 : 0 ;
2261+ } else if (Z_TYPE_P (op1 ) == IS_TRUE ) {
2262+ return zval_is_true (op2 ) ? 0 : 1 ;
2263+ } else if (Z_TYPE_P (op2 ) < IS_TRUE ) {
2264+ return zval_is_true (op1 ) ? 1 : 0 ;
2265+ } else if (Z_TYPE_P (op2 ) == IS_TRUE ) {
2266+ return zval_is_true (op1 ) ? 0 : -1 ;
2267+ } else {
2268+ zval op1_copy , op2_copy ;
2269+ op1 = _zendi_convert_scalar_to_number_silent (op1 , & op1_copy );
2270+ op2 = _zendi_convert_scalar_to_number_silent (op2 , & op2_copy );
2271+ if (EG (exception )) {
2272+ return 1 ; /* to stop comparison of arrays */
2273+ }
2274+ return zend_compare_fast (op1 , op2 , true);
2275+ }
2276+ } else if (Z_TYPE_P (op1 )== IS_ARRAY ) {
2277+ return 1 ;
2278+ } else if (Z_TYPE_P (op2 )== IS_ARRAY ) {
2279+ return -1 ;
2280+ } else {
2281+ ZEND_UNREACHABLE ();
2282+ zend_throw_error (NULL , "Unsupported operand types" );
2283+ return 1 ;
2284+ }
2285+ }
22472286
2248- case TYPE_PAIR (IS_DOUBLE , IS_LONG ):
2249- return ZEND_THREEWAY_COMPARE (Z_DVAL_P (op1 ), (double )Z_LVAL_P (op2 ));
2287+ static inline int ZEND_FASTCALL zend_compare_fast (zval * op1 , zval * op2 , bool converted )
2288+ {
2289+ switch (TYPE_PAIR (Z_TYPE_P (op1 ), Z_TYPE_P (op2 ))) {
2290+ case TYPE_PAIR (IS_LONG , IS_LONG ):
2291+ return Z_LVAL_P (op1 )> Z_LVAL_P (op2 )?1 :(Z_LVAL_P (op1 )< Z_LVAL_P (op2 )?-1 :0 );
22502292
2251- case TYPE_PAIR (IS_LONG , IS_DOUBLE ):
2252- return ZEND_THREEWAY_COMPARE (( double ) Z_LVAL_P ( op1 ), Z_DVAL_P (op2 ));
2293+ case TYPE_PAIR (IS_DOUBLE , IS_LONG ):
2294+ return ZEND_THREEWAY_COMPARE (Z_DVAL_P ( op1 ), ( double ) Z_LVAL_P (op2 ));
22532295
2254- case TYPE_PAIR (IS_DOUBLE , IS_DOUBLE ):
2255- return ZEND_THREEWAY_COMPARE (Z_DVAL_P (op1 ), Z_DVAL_P (op2 ));
2296+ case TYPE_PAIR (IS_LONG , IS_DOUBLE ):
2297+ return ZEND_THREEWAY_COMPARE (( double ) Z_LVAL_P (op1 ), Z_DVAL_P (op2 ));
22562298
2257- case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2258- return zend_compare_arrays ( op1 , op2 );
2299+ case TYPE_PAIR (IS_DOUBLE , IS_DOUBLE ):
2300+ return ZEND_THREEWAY_COMPARE ( Z_DVAL_P ( op1 ), Z_DVAL_P ( op2 ) );
22592301
2260- case TYPE_PAIR (IS_NULL , IS_NULL ):
2261- case TYPE_PAIR (IS_NULL , IS_FALSE ):
2262- case TYPE_PAIR (IS_FALSE , IS_NULL ):
2263- case TYPE_PAIR (IS_FALSE , IS_FALSE ):
2264- case TYPE_PAIR (IS_TRUE , IS_TRUE ):
2265- return 0 ;
2302+ case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2303+ return zend_compare_arrays (op1 , op2 );
22662304
2267- case TYPE_PAIR (IS_NULL , IS_TRUE ):
2268- return -1 ;
2305+ case TYPE_PAIR (IS_NULL , IS_NULL ):
2306+ case TYPE_PAIR (IS_NULL , IS_FALSE ):
2307+ case TYPE_PAIR (IS_FALSE , IS_NULL ):
2308+ case TYPE_PAIR (IS_FALSE , IS_FALSE ):
2309+ case TYPE_PAIR (IS_TRUE , IS_TRUE ):
2310+ return 0 ;
22692311
2270- case TYPE_PAIR (IS_TRUE , IS_NULL ):
2271- return 1 ;
2312+ case TYPE_PAIR (IS_NULL , IS_TRUE ):
2313+ return - 1 ;
22722314
2273- case TYPE_PAIR (IS_STRING , IS_STRING ):
2274- if (Z_STR_P (op1 ) == Z_STR_P (op2 )) {
2275- return 0 ;
2276- }
2277- return zendi_smart_strcmp (Z_STR_P (op1 ), Z_STR_P (op2 ));
2315+ case TYPE_PAIR (IS_TRUE , IS_NULL ):
2316+ return 1 ;
22782317
2279- case TYPE_PAIR (IS_NULL , IS_STRING ):
2280- return Z_STRLEN_P (op2 ) == 0 ? 0 : -1 ;
2318+ case TYPE_PAIR (IS_STRING , IS_STRING ):
2319+ if (Z_STR_P (op1 ) == Z_STR_P (op2 )) {
2320+ return 0 ;
2321+ }
2322+ return zendi_smart_strcmp (Z_STR_P (op1 ), Z_STR_P (op2 ));
22812323
2282- case TYPE_PAIR (IS_STRING , IS_NULL ):
2283- return Z_STRLEN_P (op1 ) == 0 ? 0 : 1 ;
2324+ case TYPE_PAIR (IS_NULL , IS_STRING ):
2325+ return Z_STRLEN_P (op2 ) == 0 ? 0 : - 1 ;
22842326
2285- case TYPE_PAIR (IS_LONG , IS_STRING ):
2286- return compare_long_to_string ( Z_LVAL_P ( op1 ), Z_STR_P ( op2 )) ;
2327+ case TYPE_PAIR (IS_STRING , IS_NULL ):
2328+ return Z_STRLEN_P ( op1 ) == 0 ? 0 : 1 ;
22872329
2288- case TYPE_PAIR (IS_STRING , IS_LONG ):
2289- return - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ));
2330+ case TYPE_PAIR (IS_LONG , IS_STRING ):
2331+ return compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 ));
22902332
2291- case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2292- if (zend_isnan (Z_DVAL_P (op1 ))) {
2293- return 1 ;
2294- }
2333+ case TYPE_PAIR (IS_STRING , IS_LONG ):
2334+ return - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ));
22952335
2296- return compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ));
2297-
2298- case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2299- if (zend_isnan (Z_DVAL_P (op2 ))) {
2300- return 1 ;
2301- }
2336+ case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2337+ if (zend_isnan (Z_DVAL_P (op1 ))) {
2338+ return 1 ;
2339+ }
23022340
2303- return - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ));
2341+ return compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ));
23042342
2305- case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2343+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2344+ if (zend_isnan (Z_DVAL_P (op2 ))) {
23062345 return 1 ;
2346+ }
23072347
2308- case TYPE_PAIR (IS_NULL , IS_OBJECT ):
2309- return -1 ;
2348+ return - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ));
23102349
2311- default :
2312- if (Z_ISREF_P (op1 )) {
2313- op1 = Z_REFVAL_P (op1 );
2314- continue ;
2315- } else if (Z_ISREF_P (op2 )) {
2316- op2 = Z_REFVAL_P (op2 );
2317- continue ;
2318- }
2350+ case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2351+ return 1 ;
23192352
2320- if (Z_TYPE_P (op1 ) == IS_OBJECT
2321- && Z_TYPE_P (op2 ) == IS_OBJECT
2322- && Z_OBJ_P (op1 ) == Z_OBJ_P (op2 )) {
2323- return 0 ;
2324- } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
2325- return Z_OBJ_HANDLER_P (op1 , compare )(op1 , op2 );
2326- } else if (Z_TYPE_P (op2 ) == IS_OBJECT ) {
2327- return Z_OBJ_HANDLER_P (op2 , compare )(op1 , op2 );
2328- }
2353+ case TYPE_PAIR (IS_NULL , IS_OBJECT ):
2354+ return -1 ;
23292355
2330- if (!converted ) {
2331- if (Z_TYPE_P (op1 ) < IS_TRUE ) {
2332- return zval_is_true (op2 ) ? -1 : 0 ;
2333- } else if (Z_TYPE_P (op1 ) == IS_TRUE ) {
2334- return zval_is_true (op2 ) ? 0 : 1 ;
2335- } else if (Z_TYPE_P (op2 ) < IS_TRUE ) {
2336- return zval_is_true (op1 ) ? 1 : 0 ;
2337- } else if (Z_TYPE_P (op2 ) == IS_TRUE ) {
2338- return zval_is_true (op1 ) ? 0 : -1 ;
2339- } else {
2340- op1 = _zendi_convert_scalar_to_number_silent (op1 , & op1_copy );
2341- op2 = _zendi_convert_scalar_to_number_silent (op2 , & op2_copy );
2342- if (EG (exception )) {
2343- return 1 ; /* to stop comparison of arrays */
2344- }
2345- converted = 1 ;
2346- }
2347- } else if (Z_TYPE_P (op1 )== IS_ARRAY ) {
2348- return 1 ;
2349- } else if (Z_TYPE_P (op2 )== IS_ARRAY ) {
2350- return -1 ;
2351- } else {
2352- ZEND_UNREACHABLE ();
2353- zend_throw_error (NULL , "Unsupported operand types" );
2354- return 1 ;
2355- }
2356- }
2356+ default :
2357+ return zend_compare_slow (op1 , op2 , converted );
23572358 }
23582359}
2360+
2361+ ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2362+ {
2363+ return zend_compare_fast (op1 , op2 , false);
2364+ }
23592365/* }}} */
23602366
23612367/* return int to be compatible with compare_func_t */
@@ -3353,8 +3359,7 @@ ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2)
33533359 * so a numeric comparison would be inaccurate */
33543360 goto string_cmp ;
33553361 }
3356- dval1 = dval1 - dval2 ;
3357- return ZEND_NORMALIZE_BOOL (dval1 );
3362+ return ZEND_THREEWAY_COMPARE (dval1 , dval2 );
33583363 } else { /* they both have to be long's */
33593364 return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0 );
33603365 }
0 commit comments