@@ -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
@@ -2169,131 +2169,137 @@ static int compare_double_to_string(double dval, zend_string *str) /* {{{ */
2169
2169
}
2170
2170
/* }}} */
2171
2171
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 );
2176
2173
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
+ }
2181
2181
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
+ }
2184
2220
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 );
2187
2226
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 ));
2194
2229
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 ) );
2197
2232
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 )) {
2203
2235
return 0 ;
2236
+ } else {
2237
+ return ZEND_NORMALIZE_BOOL (Z_DVAL_P (op1 ) - Z_DVAL_P (op2 ));
2238
+ }
2204
2239
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 ) ;
2207
2242
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 ;
2210
2249
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 ;
2216
2252
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 ;
2219
2255
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 ));
2222
2261
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 ;
2225
2264
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 ;
2228
2267
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 ));
2233
2270
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 ));
2235
2273
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
+ }
2240
2278
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 ));
2242
2280
2243
- case TYPE_PAIR (IS_OBJECT , IS_NULL ):
2281
+ case TYPE_PAIR (IS_STRING , IS_DOUBLE ):
2282
+ if (zend_isnan (Z_DVAL_P (op2 ))) {
2244
2283
return 1 ;
2284
+ }
2245
2285
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 ));
2248
2287
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 ;
2257
2290
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 ;
2267
2293
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 );
2295
2296
}
2296
2297
}
2298
+
2299
+ ZEND_API int ZEND_FASTCALL zend_compare (zval * op1 , zval * op2 ) /* {{{ */
2300
+ {
2301
+ return zend_compare_fast (op1 , op2 , false);
2302
+ }
2297
2303
/* }}} */
2298
2304
2299
2305
/* return int to be compatible with compare_func_t */
0 commit comments