@@ -55,7 +55,7 @@ static _locale_t current_locale = NULL;
55
55
#define zend_tolower (c ) tolower(c)
56
56
#endif
57
57
58
- #define TYPE_PAIR (t1 ,t2 ) ((( t1) << 4) | (t2))
58
+ #define TYPE_PAIR (t1 ,t2 ) ((unsigned char) ((( t1) << 4) | (t2) ))
59
59
60
60
#ifdef ZEND_INTRIN_AVX2_NATIVE
61
61
#define HAVE_BLOCKCONV
@@ -2164,127 +2164,133 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2164
2164
}
2165
2165
/* }}} */
2166
2166
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 )
2168
2170
{
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
+ }
2171
2176
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
+ }
2176
2215
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 );
2179
2221
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 ));
2182
2224
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 ));
2185
2227
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 ) );
2188
2230
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 );
2195
2233
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 ;
2198
2240
2199
- case TYPE_PAIR (IS_TRUE , IS_NULL ):
2200
- return 1 ;
2241
+ case TYPE_PAIR (IS_NULL , IS_TRUE ):
2242
+ return - 1 ;
2201
2243
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 ;
2207
2246
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 ));
2210
2252
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 ;
2213
2255
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 ;
2216
2258
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 ));
2219
2261
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 ));
2224
2264
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
+ }
2231
2269
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 ));
2233
2271
2234
- case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2272
+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2273
+ if (zend_isnan (Z_DVAL_P (op2 ))) {
2235
2274
return 1 ;
2275
+ }
2236
2276
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 ));
2239
2278
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 ;
2248
2281
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 ;
2258
2284
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 );
2286
2287
}
2287
2288
}
2289
+
2290
+ ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2291
+ {
2292
+ return zend_compare_fast (op1 , op2 , false);
2293
+ }
2288
2294
/* }}} */
2289
2295
2290
2296
/* 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)
3190
3196
* so a numeric comparison would be inaccurate */
3191
3197
goto string_cmp ;
3192
3198
}
3193
- dval1 = dval1 - dval2 ;
3194
- return ZEND_NORMALIZE_BOOL (dval1 );
3199
+ return ZEND_THREEWAY_COMPARE (dval1 , dval2 );
3195
3200
} else { /* they both have to be long's */
3196
3201
return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0 );
3197
3202
}
0 commit comments