@@ -58,7 +58,7 @@ static _locale_t current_locale = NULL;
58
58
#define zend_tolower (c ) tolower(c)
59
59
#endif
60
60
61
- #define TYPE_PAIR (t1 ,t2 ) ((( t1) << 4) | (t2))
61
+ #define TYPE_PAIR (t1 ,t2 ) ((unsigned char) ((( t1) << 4) | (t2) ))
62
62
63
63
#ifdef ZEND_INTRIN_AVX2_NATIVE
64
64
#define HAVE_BLOCKCONV
@@ -2235,127 +2235,133 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2235
2235
}
2236
2236
/* }}} */
2237
2237
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 )
2239
2241
{
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
+ }
2242
2247
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
+ }
2247
2286
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 );
2250
2292
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 ));
2253
2295
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 ));
2256
2298
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 ) );
2259
2301
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 );
2266
2304
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 ;
2269
2311
2270
- case TYPE_PAIR (IS_TRUE , IS_NULL ):
2271
- return 1 ;
2312
+ case TYPE_PAIR (IS_NULL , IS_TRUE ):
2313
+ return - 1 ;
2272
2314
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 ;
2278
2317
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 ));
2281
2323
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 ;
2284
2326
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 ;
2287
2329
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 ));
2290
2332
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 ));
2295
2335
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
+ }
2302
2340
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 ));
2304
2342
2305
- case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2343
+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2344
+ if (zend_isnan (Z_DVAL_P (op2 ))) {
2306
2345
return 1 ;
2346
+ }
2307
2347
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 ));
2310
2349
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 ;
2319
2352
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 ;
2329
2355
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 );
2357
2358
}
2358
2359
}
2360
+
2361
+ ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2362
+ {
2363
+ return zend_compare_fast (op1 , op2 , false);
2364
+ }
2359
2365
/* }}} */
2360
2366
2361
2367
/* 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)
3353
3359
* so a numeric comparison would be inaccurate */
3354
3360
goto string_cmp ;
3355
3361
}
3356
- dval1 = dval1 - dval2 ;
3357
- return ZEND_NORMALIZE_BOOL (dval1 );
3362
+ return ZEND_THREEWAY_COMPARE (dval1 , dval2 );
3358
3363
} else { /* they both have to be long's */
3359
3364
return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0 );
3360
3365
}
0 commit comments