@@ -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
@@ -2164,127 +2164,133 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
21642164}
21652165/* }}} */
21662166
2167- ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2167+ static int ZEND_FASTCALL zend_compare_fast (zval * op1 , zval * op2 , bool converted );
2168+
2169+ static int ZEND_FASTCALL zend_compare_slow (zval * op1 , zval * op2 , bool converted )
21682170{
2169- int converted = 0 ;
2170- zval op1_copy , op2_copy ;
2171+ if (Z_ISREF_P (op1 ) || Z_ISREF_P (op2 )) {
2172+ ZVAL_DEREF (op1 );
2173+ ZVAL_DEREF (op2 );
2174+ return zend_compare_fast (op1 , op2 , converted );
2175+ }
21712176
2172- while (1 ) {
2173- switch (TYPE_PAIR (Z_TYPE_P (op1 ), Z_TYPE_P (op2 ))) {
2174- case TYPE_PAIR (IS_LONG , IS_LONG ):
2175- return Z_LVAL_P (op1 )> Z_LVAL_P (op2 )?1 :(Z_LVAL_P (op1 )< Z_LVAL_P (op2 )?-1 :0 );
2177+ if (Z_TYPE_P (op1 ) == IS_OBJECT
2178+ && Z_TYPE_P (op2 ) == IS_OBJECT
2179+ && Z_OBJ_P (op1 ) == Z_OBJ_P (op2 )) {
2180+ return 0 ;
2181+ } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
2182+ return Z_OBJ_HANDLER_P (op1 , compare )(op1 , op2 );
2183+ } else if (Z_TYPE_P (op2 ) == IS_OBJECT ) {
2184+ return Z_OBJ_HANDLER_P (op2 , compare )(op1 , op2 );
2185+ }
2186+
2187+ if (!converted ) {
2188+ if (Z_TYPE_P (op1 ) < IS_TRUE ) {
2189+ return zval_is_true (op2 ) ? -1 : 0 ;
2190+ } else if (Z_TYPE_P (op1 ) == IS_TRUE ) {
2191+ return zval_is_true (op2 ) ? 0 : 1 ;
2192+ } else if (Z_TYPE_P (op2 ) < IS_TRUE ) {
2193+ return zval_is_true (op1 ) ? 1 : 0 ;
2194+ } else if (Z_TYPE_P (op2 ) == IS_TRUE ) {
2195+ return zval_is_true (op1 ) ? 0 : -1 ;
2196+ } else {
2197+ zval op1_copy , op2_copy ;
2198+ op1 = _zendi_convert_scalar_to_number_silent (op1 , & op1_copy );
2199+ op2 = _zendi_convert_scalar_to_number_silent (op2 , & op2_copy );
2200+ if (EG (exception )) {
2201+ return 1 ; /* to stop comparison of arrays */
2202+ }
2203+ return zend_compare_fast (op1 , op2 , true);
2204+ }
2205+ } else if (Z_TYPE_P (op1 )== IS_ARRAY ) {
2206+ return 1 ;
2207+ } else if (Z_TYPE_P (op2 )== IS_ARRAY ) {
2208+ return -1 ;
2209+ } else {
2210+ ZEND_UNREACHABLE ();
2211+ zend_throw_error (NULL , "Unsupported operand types" );
2212+ return 1 ;
2213+ }
2214+ }
21762215
2177- case TYPE_PAIR (IS_DOUBLE , IS_LONG ):
2178- return ZEND_THREEWAY_COMPARE (Z_DVAL_P (op1 ), (double )Z_LVAL_P (op2 ));
2216+ static inline int ZEND_FASTCALL zend_compare_fast (zval * op1 , zval * op2 , bool converted )
2217+ {
2218+ switch (TYPE_PAIR (Z_TYPE_P (op1 ), Z_TYPE_P (op2 ))) {
2219+ case TYPE_PAIR (IS_LONG , IS_LONG ):
2220+ return Z_LVAL_P (op1 )> Z_LVAL_P (op2 )?1 :(Z_LVAL_P (op1 )< Z_LVAL_P (op2 )?-1 :0 );
21792221
2180- case TYPE_PAIR (IS_LONG , IS_DOUBLE ):
2181- return ZEND_THREEWAY_COMPARE (( double ) Z_LVAL_P ( op1 ), Z_DVAL_P (op2 ));
2222+ case TYPE_PAIR (IS_DOUBLE , IS_LONG ):
2223+ return ZEND_THREEWAY_COMPARE (Z_DVAL_P ( op1 ), ( double ) Z_LVAL_P (op2 ));
21822224
2183- case TYPE_PAIR (IS_DOUBLE , IS_DOUBLE ):
2184- return ZEND_THREEWAY_COMPARE (Z_DVAL_P (op1 ), Z_DVAL_P (op2 ));
2225+ case TYPE_PAIR (IS_LONG , IS_DOUBLE ):
2226+ return ZEND_THREEWAY_COMPARE (( double ) Z_LVAL_P (op1 ), Z_DVAL_P (op2 ));
21852227
2186- case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2187- return zend_compare_arrays ( op1 , op2 );
2228+ case TYPE_PAIR (IS_DOUBLE , IS_DOUBLE ):
2229+ return ZEND_THREEWAY_COMPARE ( Z_DVAL_P ( op1 ), Z_DVAL_P ( op2 ) );
21882230
2189- case TYPE_PAIR (IS_NULL , IS_NULL ):
2190- case TYPE_PAIR (IS_NULL , IS_FALSE ):
2191- case TYPE_PAIR (IS_FALSE , IS_NULL ):
2192- case TYPE_PAIR (IS_FALSE , IS_FALSE ):
2193- case TYPE_PAIR (IS_TRUE , IS_TRUE ):
2194- return 0 ;
2231+ case TYPE_PAIR (IS_ARRAY , IS_ARRAY ):
2232+ return zend_compare_arrays (op1 , op2 );
21952233
2196- case TYPE_PAIR (IS_NULL , IS_TRUE ):
2197- return -1 ;
2234+ case TYPE_PAIR (IS_NULL , IS_NULL ):
2235+ case TYPE_PAIR (IS_NULL , IS_FALSE ):
2236+ case TYPE_PAIR (IS_FALSE , IS_NULL ):
2237+ case TYPE_PAIR (IS_FALSE , IS_FALSE ):
2238+ case TYPE_PAIR (IS_TRUE , IS_TRUE ):
2239+ return 0 ;
21982240
2199- case TYPE_PAIR (IS_TRUE , IS_NULL ):
2200- return 1 ;
2241+ case TYPE_PAIR (IS_NULL , IS_TRUE ):
2242+ return - 1 ;
22012243
2202- case TYPE_PAIR (IS_STRING , IS_STRING ):
2203- if (Z_STR_P (op1 ) == Z_STR_P (op2 )) {
2204- return 0 ;
2205- }
2206- return zendi_smart_strcmp (Z_STR_P (op1 ), Z_STR_P (op2 ));
2244+ case TYPE_PAIR (IS_TRUE , IS_NULL ):
2245+ return 1 ;
22072246
2208- case TYPE_PAIR (IS_NULL , IS_STRING ):
2209- return Z_STRLEN_P (op2 ) == 0 ? 0 : -1 ;
2247+ case TYPE_PAIR (IS_STRING , IS_STRING ):
2248+ if (Z_STR_P (op1 ) == Z_STR_P (op2 )) {
2249+ return 0 ;
2250+ }
2251+ return zendi_smart_strcmp (Z_STR_P (op1 ), Z_STR_P (op2 ));
22102252
2211- case TYPE_PAIR (IS_STRING , IS_NULL ):
2212- return Z_STRLEN_P (op1 ) == 0 ? 0 : 1 ;
2253+ case TYPE_PAIR (IS_NULL , IS_STRING ):
2254+ return Z_STRLEN_P (op2 ) == 0 ? 0 : - 1 ;
22132255
2214- case TYPE_PAIR (IS_LONG , IS_STRING ):
2215- return compare_long_to_string ( Z_LVAL_P ( op1 ), Z_STR_P ( op2 )) ;
2256+ case TYPE_PAIR (IS_STRING , IS_NULL ):
2257+ return Z_STRLEN_P ( op1 ) == 0 ? 0 : 1 ;
22162258
2217- case TYPE_PAIR (IS_STRING , IS_LONG ):
2218- return - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ));
2259+ case TYPE_PAIR (IS_LONG , IS_STRING ):
2260+ return compare_long_to_string (Z_LVAL_P (op1 ), Z_STR_P (op2 ));
22192261
2220- case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2221- if (zend_isnan (Z_DVAL_P (op1 ))) {
2222- return 1 ;
2223- }
2262+ case TYPE_PAIR (IS_STRING , IS_LONG ):
2263+ return - compare_long_to_string (Z_LVAL_P (op2 ), Z_STR_P (op1 ));
22242264
2225- return compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ));
2226-
2227- case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2228- if (zend_isnan (Z_DVAL_P (op2 ))) {
2229- return 1 ;
2230- }
2265+ case TYPE_PAIR (IS_DOUBLE , IS_STRING ):
2266+ if (zend_isnan (Z_DVAL_P (op1 ))) {
2267+ return 1 ;
2268+ }
22312269
2232- return - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ));
2270+ return compare_double_to_string (Z_DVAL_P (op1 ), Z_STR_P (op2 ));
22332271
2234- case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2272+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2273+ if (zend_isnan (Z_DVAL_P (op2 ))) {
22352274 return 1 ;
2275+ }
22362276
2237- case TYPE_PAIR (IS_NULL , IS_OBJECT ):
2238- return -1 ;
2277+ return - compare_double_to_string (Z_DVAL_P (op2 ), Z_STR_P (op1 ));
22392278
2240- default :
2241- if (Z_ISREF_P (op1 )) {
2242- op1 = Z_REFVAL_P (op1 );
2243- continue ;
2244- } else if (Z_ISREF_P (op2 )) {
2245- op2 = Z_REFVAL_P (op2 );
2246- continue ;
2247- }
2279+ case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2280+ return 1 ;
22482281
2249- if (Z_TYPE_P (op1 ) == IS_OBJECT
2250- && Z_TYPE_P (op2 ) == IS_OBJECT
2251- && Z_OBJ_P (op1 ) == Z_OBJ_P (op2 )) {
2252- return 0 ;
2253- } else if (Z_TYPE_P (op1 ) == IS_OBJECT ) {
2254- return Z_OBJ_HANDLER_P (op1 , compare )(op1 , op2 );
2255- } else if (Z_TYPE_P (op2 ) == IS_OBJECT ) {
2256- return Z_OBJ_HANDLER_P (op2 , compare )(op1 , op2 );
2257- }
2282+ case TYPE_PAIR (IS_NULL , IS_OBJECT ):
2283+ return -1 ;
22582284
2259- if (!converted ) {
2260- if (Z_TYPE_P (op1 ) < IS_TRUE ) {
2261- return zval_is_true (op2 ) ? -1 : 0 ;
2262- } else if (Z_TYPE_P (op1 ) == IS_TRUE ) {
2263- return zval_is_true (op2 ) ? 0 : 1 ;
2264- } else if (Z_TYPE_P (op2 ) < IS_TRUE ) {
2265- return zval_is_true (op1 ) ? 1 : 0 ;
2266- } else if (Z_TYPE_P (op2 ) == IS_TRUE ) {
2267- return zval_is_true (op1 ) ? 0 : -1 ;
2268- } else {
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- converted = 1 ;
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- }
2285+ default :
2286+ return zend_compare_slow (op1 , op2 , converted );
22862287 }
22872288}
2289+
2290+ ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2291+ {
2292+ return zend_compare_fast (op1 , op2 , false);
2293+ }
22882294/* }}} */
22892295
22902296/* return int to be compatible with compare_func_t */
@@ -3190,8 +3196,7 @@ ZEND_API int ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2)
31903196 * so a numeric comparison would be inaccurate */
31913197 goto string_cmp ;
31923198 }
3193- dval1 = dval1 - dval2 ;
3194- return ZEND_NORMALIZE_BOOL (dval1 );
3199+ return ZEND_THREEWAY_COMPARE (dval1 , dval2 );
31953200 } else { /* they both have to be long's */
31963201 return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0 );
31973202 }
0 commit comments