root/Zend/zend_operators.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. zend_dval_to_lval
  2. zend_dval_to_lval
  3. is_numeric_string_ex
  4. is_numeric_string
  5. zend_memnstr
  6. zend_memrchr
  7. fast_increment_function
  8. fast_decrement_function
  9. fast_add_function
  10. fast_sub_function
  11. fast_mul_function
  12. fast_div_function
  13. fast_mod_function
  14. fast_equal_function
  15. fast_not_equal_function
  16. fast_is_smaller_function
  17. fast_is_smaller_or_equal_function

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 2.00 of the Zend license,     |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.zend.com/license/2_00.txt.                                |
  11    | If you did not receive a copy of the Zend license and are unable to  |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@zend.com so we can mail you a copy immediately.              |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #ifndef ZEND_OPERATORS_H
  23 #define ZEND_OPERATORS_H
  24 
  25 #include <errno.h>
  26 #include <math.h>
  27 #include <assert.h>
  28 
  29 #ifdef __GNUC__
  30 #include <stddef.h>
  31 #endif
  32 
  33 #ifdef HAVE_IEEEFP_H
  34 #include <ieeefp.h>
  35 #endif
  36 
  37 #include "zend_strtod.h"
  38 #include "zend_multiply.h"
  39 
  40 #if 0&&HAVE_BCMATH
  41 #include "ext/bcmath/libbcmath/src/bcmath.h"
  42 #endif
  43 
  44 #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
  45 
  46 BEGIN_EXTERN_C()
  47 ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  48 ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  49 ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  50 ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  51 ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  52 ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  53 ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  54 ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC);
  55 ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC);
  56 ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  57 ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  58 ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  59 ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  60 ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  61 ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  62 
  63 ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  64 ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  65 ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  66 ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  67 ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  68 ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
  69 
  70 ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC);
  71 ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC);
  72 END_EXTERN_C()
  73 
  74 #if ZEND_DVAL_TO_LVAL_CAST_OK
  75 # define zend_dval_to_lval(d) ((long) (d))
  76 #elif SIZEOF_LONG == 4
  77 static zend_always_inline long zend_dval_to_lval(double d)
  78 {
  79         if (d > LONG_MAX || d < LONG_MIN) {
  80                 double  two_pow_32 = pow(2., 32.),
  81                                 dmod;
  82 
  83                 dmod = fmod(d, two_pow_32);
  84                 if (dmod < 0) {
  85                         /* we're going to make this number positive; call ceil()
  86                          * to simulate rounding towards 0 of the negative number */
  87                         dmod = ceil(dmod) + two_pow_32;
  88                 }
  89                 return (long)(unsigned long)dmod;
  90         }
  91         return (long)d;
  92 }
  93 #else
  94 static zend_always_inline long zend_dval_to_lval(double d)
  95 {
  96         /* >= as (double)LONG_MAX is outside signed range */
  97         if (d >= LONG_MAX || d < LONG_MIN) {
  98                 double  two_pow_64 = pow(2., 64.),
  99                                 dmod;
 100 
 101                 dmod = fmod(d, two_pow_64);
 102                 if (dmod < 0) {
 103                         /* no need to call ceil; original double must have had no
 104                          * fractional part, hence dmod does not have one either */
 105                         dmod += two_pow_64;
 106                 }
 107                 return (long)(unsigned long)dmod;
 108         }
 109         return (long)d;
 110 }
 111 #endif
 112 /* }}} */
 113 
 114 #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
 115 #define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
 116 
 117 /**
 118  * Checks whether the string "str" with length "length" is numeric. The value
 119  * of allow_errors determines whether it's required to be entirely numeric, or
 120  * just its prefix. Leading whitespace is allowed.
 121  *
 122  * The function returns 0 if the string did not contain a valid number; IS_LONG
 123  * if it contained a number that fits within the range of a long; or IS_DOUBLE
 124  * if the number was out of long range or contained a decimal point/exponent.
 125  * The number's value is returned into the respective pointer, *lval or *dval,
 126  * if that pointer is not NULL.
 127  *
 128  * This variant also gives information if a string that represents an integer
 129  * could not be represented as such due to overflow. It writes 1 to oflow_info
 130  * if the integer is larger than LONG_MAX and -1 if it's smaller than LONG_MIN.
 131  */
 132 static inline zend_uchar is_numeric_string_ex(const char *str, int length, long *lval, double *dval, int allow_errors, int *oflow_info)
 133 {
 134         const char *ptr;
 135         int base = 10, digits = 0, dp_or_e = 0;
 136         double local_dval = 0.0;
 137         zend_uchar type;
 138 
 139         if (!length) {
 140                 return 0;
 141         }
 142 
 143         if (oflow_info != NULL) {
 144                 *oflow_info = 0;
 145         }
 146 
 147         /* Skip any whitespace
 148          * This is much faster than the isspace() function */
 149         while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
 150                 str++;
 151                 length--;
 152         }
 153         ptr = str;
 154 
 155         if (*ptr == '-' || *ptr == '+') {
 156                 ptr++;
 157         }
 158 
 159         if (ZEND_IS_DIGIT(*ptr)) {
 160                 /* Handle hex numbers
 161                  * str is used instead of ptr to disallow signs and keep old behavior */
 162                 if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
 163                         base = 16;
 164                         ptr += 2;
 165                 }
 166 
 167                 /* Skip any leading 0s */
 168                 while (*ptr == '0') {
 169                         ptr++;
 170                 }
 171 
 172                 /* Count the number of digits. If a decimal point/exponent is found,
 173                  * it's a double. Otherwise, if there's a dval or no need to check for
 174                  * a full match, stop when there are too many digits for a long */
 175                 for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
 176 check_digits:
 177                         if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
 178                                 continue;
 179                         } else if (base == 10) {
 180                                 if (*ptr == '.' && dp_or_e < 1) {
 181                                         goto process_double;
 182                                 } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
 183                                         const char *e = ptr + 1;
 184 
 185                                         if (*e == '-' || *e == '+') {
 186                                                 ptr = e++;
 187                                         }
 188                                         if (ZEND_IS_DIGIT(*e)) {
 189                                                 goto process_double;
 190                                         }
 191                                 }
 192                         }
 193 
 194                         break;
 195                 }
 196 
 197                 if (base == 10) {
 198                         if (digits >= MAX_LENGTH_OF_LONG) {
 199                                 if (oflow_info != NULL) {
 200                                         *oflow_info = *str == '-' ? -1 : 1;
 201                                 }
 202                                 dp_or_e = -1;
 203                                 goto process_double;
 204                         }
 205                 } else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) {
 206                         if (dval) {
 207                                 local_dval = zend_hex_strtod(str, &ptr);
 208                         }
 209                         if (oflow_info != NULL) {
 210                                 *oflow_info = 1;
 211                         }
 212                         type = IS_DOUBLE;
 213                 }
 214         } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
 215 process_double:
 216                 type = IS_DOUBLE;
 217 
 218                 /* If there's a dval, do the conversion; else continue checking
 219                  * the digits if we need to check for a full match */
 220                 if (dval) {
 221                         local_dval = zend_strtod(str, &ptr);
 222                 } else if (allow_errors != 1 && dp_or_e != -1) {
 223                         dp_or_e = (*ptr++ == '.') ? 1 : 2;
 224                         goto check_digits;
 225                 }
 226         } else {
 227                 return 0;
 228         }
 229 
 230         if (ptr != str + length) {
 231                 if (!allow_errors) {
 232                         return 0;
 233                 }
 234                 if (allow_errors == -1) {
 235                         zend_error(E_NOTICE, "A non well formed numeric value encountered");
 236                 }
 237         }
 238 
 239         if (type == IS_LONG) {
 240                 if (digits == MAX_LENGTH_OF_LONG - 1) {
 241                         int cmp = strcmp(&ptr[-digits], long_min_digits);
 242 
 243                         if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
 244                                 if (dval) {
 245                                         *dval = zend_strtod(str, NULL);
 246                                 }
 247                                 if (oflow_info != NULL) {
 248                                         *oflow_info = *str == '-' ? -1 : 1;
 249                                 }
 250 
 251                                 return IS_DOUBLE;
 252                         }
 253                 }
 254 
 255                 if (lval) {
 256                         *lval = strtol(str, NULL, base);
 257                 }
 258 
 259                 return IS_LONG;
 260         } else {
 261                 if (dval) {
 262                         *dval = local_dval;
 263                 }
 264 
 265                 return IS_DOUBLE;
 266         }
 267 }
 268 
 269 static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors) {
 270     return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
 271 }
 272 
 273 static inline const char *
 274 zend_memnstr(const char *haystack, const char *needle, int needle_len, char *end)
 275 {
 276         const char *p = haystack;
 277         const char ne = needle[needle_len-1];
 278 
 279         if (needle_len == 1) {
 280                 return (char *)memchr(p, *needle, (end-p));
 281         }
 282 
 283         if (needle_len > end-haystack) {
 284                 return NULL;
 285         }
 286 
 287         end -= needle_len;
 288 
 289         while (p <= end) {
 290                 if ((p = (char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
 291                         if (!memcmp(needle, p, needle_len-1)) {
 292                                 return p;
 293                         }
 294                 }
 295 
 296                 if (p == NULL) {
 297                         return NULL;
 298                 }
 299 
 300                 p++;
 301         }
 302 
 303         return NULL;
 304 }
 305 
 306 static inline const void *zend_memrchr(const void *s, int c, size_t n)
 307 {
 308         register const unsigned char *e;
 309 
 310         if (n <= 0) {
 311                 return NULL;
 312         }
 313 
 314         for (e = (const unsigned char *)s + n - 1; e >= (const unsigned char *)s; e--) {
 315                 if (*e == (const unsigned char)c) {
 316                         return (const void *)e;
 317                 }
 318         }
 319 
 320         return NULL;
 321 }
 322 
 323 BEGIN_EXTERN_C()
 324 ZEND_API int increment_function(zval *op1);
 325 ZEND_API int decrement_function(zval *op2);
 326 
 327 ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC);
 328 ZEND_API void _convert_to_cstring(zval *op ZEND_FILE_LINE_DC);
 329 ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC);
 330 ZEND_API void convert_to_long(zval *op);
 331 ZEND_API void convert_to_double(zval *op);
 332 ZEND_API void convert_to_long_base(zval *op, int base);
 333 ZEND_API void convert_to_null(zval *op);
 334 ZEND_API void convert_to_boolean(zval *op);
 335 ZEND_API void convert_to_array(zval *op);
 336 ZEND_API void convert_to_object(zval *op);
 337 ZEND_API void multi_convert_to_long_ex(int argc, ...);
 338 ZEND_API void multi_convert_to_double_ex(int argc, ...);
 339 ZEND_API void multi_convert_to_string_ex(int argc, ...);
 340 ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2);
 341 ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2);
 342 #define convert_to_cstring(op) if ((op)->type != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
 343 #define convert_to_string(op) if ((op)->type != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
 344 
 345 ZEND_API double zend_string_to_double(const char *number, zend_uint length);
 346 
 347 ZEND_API int zval_is_true(zval *op);
 348 ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
 349 ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
 350 ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC);
 351 ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
 352 ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
 353 #if HAVE_STRCOLL
 354 ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
 355 #endif
 356 
 357 ZEND_API void zend_str_tolower(char *str, unsigned int length);
 358 ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
 359 ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length);
 360 
 361 ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2);
 362 ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
 363 ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2);
 364 ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3);
 365 ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2);
 366 ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
 367 ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2);
 368 ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length);
 369 ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length);
 370 
 371 ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
 372 ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC);
 373 ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC);
 374 ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
 375 
 376 ZEND_API int zend_atoi(const char *str, int str_len);
 377 ZEND_API long zend_atol(const char *str, int str_len);
 378 
 379 ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
 380 END_EXTERN_C()
 381 
 382 #define convert_to_ex_master(ppzv, lower_type, upper_type)      \
 383         if (Z_TYPE_PP(ppzv)!=IS_##upper_type) {                                 \
 384                 SEPARATE_ZVAL_IF_NOT_REF(ppzv);                                         \
 385                 convert_to_##lower_type(*ppzv);                                         \
 386         }
 387 
 388 #define convert_to_explicit_type(pzv, type)             \
 389         do {                                                                            \
 390                 switch (type) {                                                 \
 391                         case IS_NULL:                                           \
 392                                 convert_to_null(pzv);                   \
 393                                 break;                                                  \
 394                         case IS_LONG:                                           \
 395                                 convert_to_long(pzv);                   \
 396                                 break;                                                  \
 397                         case IS_DOUBLE:                                         \
 398                                 convert_to_double(pzv);                 \
 399                                 break;                                                  \
 400                         case IS_BOOL:                                           \
 401                                 convert_to_boolean(pzv);                \
 402                                 break;                                                  \
 403                         case IS_ARRAY:                                          \
 404                                 convert_to_array(pzv);                  \
 405                                 break;                                                  \
 406                         case IS_OBJECT:                                         \
 407                                 convert_to_object(pzv);                 \
 408                                 break;                                                  \
 409                         case IS_STRING:                                         \
 410                                 convert_to_string(pzv);                 \
 411                                 break;                                                  \
 412                         default:                                                        \
 413                                 assert(0);                                              \
 414                                 break;                                                  \
 415                 }                                                                               \
 416         } while (0);
 417 
 418 #define convert_to_explicit_type_ex(ppzv, str_type)     \
 419         if (Z_TYPE_PP(ppzv) != str_type) {                              \
 420                 SEPARATE_ZVAL_IF_NOT_REF(ppzv);                         \
 421                 convert_to_explicit_type(*ppzv, str_type);      \
 422         }
 423 
 424 #define convert_to_boolean_ex(ppzv)     convert_to_ex_master(ppzv, boolean, BOOL)
 425 #define convert_to_long_ex(ppzv)        convert_to_ex_master(ppzv, long, LONG)
 426 #define convert_to_double_ex(ppzv)      convert_to_ex_master(ppzv, double, DOUBLE)
 427 #define convert_to_string_ex(ppzv)      convert_to_ex_master(ppzv, string, STRING)
 428 #define convert_to_array_ex(ppzv)       convert_to_ex_master(ppzv, array, ARRAY)
 429 #define convert_to_object_ex(ppzv)      convert_to_ex_master(ppzv, object, OBJECT)
 430 #define convert_to_null_ex(ppzv)        convert_to_ex_master(ppzv, null, NULL)
 431 
 432 #define convert_scalar_to_number_ex(ppzv)                                                       \
 433         if (Z_TYPE_PP(ppzv)!=IS_LONG && Z_TYPE_PP(ppzv)!=IS_DOUBLE) {   \
 434                 if (!Z_ISREF_PP(ppzv)) {                                                                        \
 435                         SEPARATE_ZVAL(ppzv);                                                                    \
 436                 }                                                                                                                       \
 437                 convert_scalar_to_number(*ppzv TSRMLS_CC);                                      \
 438         }
 439 
 440 
 441 #define Z_LVAL(zval)                    (zval).value.lval
 442 #define Z_BVAL(zval)                    ((zend_bool)(zval).value.lval)
 443 #define Z_DVAL(zval)                    (zval).value.dval
 444 #define Z_STRVAL(zval)                  (zval).value.str.val
 445 #define Z_STRLEN(zval)                  (zval).value.str.len
 446 #define Z_ARRVAL(zval)                  (zval).value.ht
 447 #define Z_AST(zval)                     (zval).value.ast
 448 #define Z_OBJVAL(zval)                  (zval).value.obj
 449 #define Z_OBJ_HANDLE(zval)              Z_OBJVAL(zval).handle
 450 #define Z_OBJ_HT(zval)                  Z_OBJVAL(zval).handlers
 451 #define Z_OBJCE(zval)                   zend_get_class_entry(&(zval) TSRMLS_CC)
 452 #define Z_OBJPROP(zval)                 Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
 453 #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
 454 #define Z_RESVAL(zval)                  (zval).value.lval
 455 #define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
 456 
 457 #define Z_LVAL_P(zval_p)                Z_LVAL(*zval_p)
 458 #define Z_BVAL_P(zval_p)                Z_BVAL(*zval_p)
 459 #define Z_DVAL_P(zval_p)                Z_DVAL(*zval_p)
 460 #define Z_STRVAL_P(zval_p)              Z_STRVAL(*zval_p)
 461 #define Z_STRLEN_P(zval_p)              Z_STRLEN(*zval_p)
 462 #define Z_ARRVAL_P(zval_p)              Z_ARRVAL(*zval_p)
 463 #define Z_AST_P(zval_p)                 Z_AST(*zval_p)
 464 #define Z_OBJPROP_P(zval_p)             Z_OBJPROP(*zval_p)
 465 #define Z_OBJCE_P(zval_p)               Z_OBJCE(*zval_p)
 466 #define Z_RESVAL_P(zval_p)              Z_RESVAL(*zval_p)
 467 #define Z_OBJVAL_P(zval_p)              Z_OBJVAL(*zval_p)
 468 #define Z_OBJ_HANDLE_P(zval_p)  Z_OBJ_HANDLE(*zval_p)
 469 #define Z_OBJ_HT_P(zval_p)              Z_OBJ_HT(*zval_p)
 470 #define Z_OBJ_HANDLER_P(zval_p, h)      Z_OBJ_HANDLER(*zval_p, h)
 471 #define Z_OBJDEBUG_P(zval_p,is_tmp)     Z_OBJDEBUG(*zval_p,is_tmp)
 472 
 473 #define Z_LVAL_PP(zval_pp)              Z_LVAL(**zval_pp)
 474 #define Z_BVAL_PP(zval_pp)              Z_BVAL(**zval_pp)
 475 #define Z_DVAL_PP(zval_pp)              Z_DVAL(**zval_pp)
 476 #define Z_STRVAL_PP(zval_pp)    Z_STRVAL(**zval_pp)
 477 #define Z_STRLEN_PP(zval_pp)    Z_STRLEN(**zval_pp)
 478 #define Z_ARRVAL_PP(zval_pp)    Z_ARRVAL(**zval_pp)
 479 #define Z_AST_PP(zval_p)                Z_AST(**zval_p)
 480 #define Z_OBJPROP_PP(zval_pp)   Z_OBJPROP(**zval_pp)
 481 #define Z_OBJCE_PP(zval_pp)             Z_OBJCE(**zval_pp)
 482 #define Z_RESVAL_PP(zval_pp)    Z_RESVAL(**zval_pp)
 483 #define Z_OBJVAL_PP(zval_pp)    Z_OBJVAL(**zval_pp)
 484 #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
 485 #define Z_OBJ_HT_PP(zval_p)             Z_OBJ_HT(**zval_p)
 486 #define Z_OBJ_HANDLER_PP(zval_p, h)             Z_OBJ_HANDLER(**zval_p, h)
 487 #define Z_OBJDEBUG_PP(zval_pp,is_tmp)   Z_OBJDEBUG(**zval_pp,is_tmp)
 488 
 489 #define Z_TYPE(zval)            (zval).type
 490 #define Z_TYPE_P(zval_p)        Z_TYPE(*zval_p)
 491 #define Z_TYPE_PP(zval_pp)      Z_TYPE(**zval_pp)
 492 
 493 #if HAVE_SETLOCALE && defined(ZEND_WIN32) && !defined(ZTS) && defined(_MSC_VER) && (_MSC_VER >= 1400)
 494 /* This is performance improvement of tolower() on Windows and VC2005
 495  * Gives 10-18% on bench.php
 496  */
 497 #define ZEND_USE_TOLOWER_L 1
 498 #endif
 499 
 500 #ifdef ZEND_USE_TOLOWER_L
 501 ZEND_API void zend_update_current_locale(void);
 502 #else
 503 #define zend_update_current_locale()
 504 #endif
 505 
 506 /* The offset in bytes between the value and type fields of a zval */
 507 #define ZVAL_OFFSETOF_TYPE      \
 508         (offsetof(zval,type) - offsetof(zval,value))
 509 
 510 static zend_always_inline int fast_increment_function(zval *op1)
 511 {
 512         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 513 #if defined(__GNUC__) && defined(__i386__)
 514                 __asm__(
 515                         "incl (%0)\n\t"
 516                         "jno  0f\n\t"
 517                         "movl $0x0, (%0)\n\t"
 518                         "movl $0x41e00000, 0x4(%0)\n\t"
 519                         "movb %1, %c2(%0)\n"
 520                         "0:"
 521                         :
 522                         : "r"(&op1->value),
 523                           "n"(IS_DOUBLE),
 524                           "n"(ZVAL_OFFSETOF_TYPE)
 525                         : "cc");
 526 #elif defined(__GNUC__) && defined(__x86_64__)
 527                 __asm__(
 528                         "incq (%0)\n\t"
 529                         "jno  0f\n\t"
 530                         "movl $0x0, (%0)\n\t"
 531                         "movl $0x43e00000, 0x4(%0)\n\t"
 532                         "movb %1, %c2(%0)\n"
 533                         "0:"
 534                         :
 535                         : "r"(&op1->value),
 536                           "n"(IS_DOUBLE),
 537                           "n"(ZVAL_OFFSETOF_TYPE)
 538                         : "cc");
 539 #else
 540                 if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) {
 541                         /* switch to double */
 542                         Z_DVAL_P(op1) = (double)LONG_MAX + 1.0;
 543                         Z_TYPE_P(op1) = IS_DOUBLE;
 544                 } else {
 545                         Z_LVAL_P(op1)++;
 546                 }
 547 #endif
 548                 return SUCCESS;
 549         }
 550         return increment_function(op1);
 551 }
 552 
 553 static zend_always_inline int fast_decrement_function(zval *op1)
 554 {
 555         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 556 #if defined(__GNUC__) && defined(__i386__)
 557                 __asm__(
 558                         "decl (%0)\n\t"
 559                         "jno  0f\n\t"
 560                         "movl $0x00200000, (%0)\n\t"
 561                         "movl $0xc1e00000, 0x4(%0)\n\t"
 562                         "movb %1,%c2(%0)\n"
 563                         "0:"
 564                         :
 565                         : "r"(&op1->value),
 566                           "n"(IS_DOUBLE),
 567                           "n"(ZVAL_OFFSETOF_TYPE)
 568                         : "cc");
 569 #elif defined(__GNUC__) && defined(__x86_64__)
 570                 __asm__(
 571                         "decq (%0)\n\t"
 572                         "jno  0f\n\t"
 573                         "movl $0x00000000, (%0)\n\t"
 574                         "movl $0xc3e00000, 0x4(%0)\n\t"
 575                         "movb %1,%c2(%0)\n"
 576                         "0:"
 577                         :
 578                         : "r"(&op1->value),
 579                           "n"(IS_DOUBLE),
 580                           "n"(ZVAL_OFFSETOF_TYPE)
 581                         : "cc");
 582 #else
 583                 if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) {
 584                         /* switch to double */
 585                         Z_DVAL_P(op1) = (double)LONG_MIN - 1.0;
 586                         Z_TYPE_P(op1) = IS_DOUBLE;
 587                 } else {
 588                         Z_LVAL_P(op1)--;
 589                 }
 590 #endif
 591                 return SUCCESS;
 592         }
 593         return decrement_function(op1);
 594 }
 595 
 596 static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 597 {
 598         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 599                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 600 #if defined(__GNUC__) && defined(__i386__)
 601                 __asm__(
 602                         "movl   (%1), %%eax\n\t"
 603                         "addl   (%2), %%eax\n\t"
 604                         "jo     0f\n\t"     
 605                         "movl   %%eax, (%0)\n\t"
 606                         "movb   %3, %c5(%0)\n\t"
 607                         "jmp    1f\n"
 608                         "0:\n\t"
 609                         "fildl  (%1)\n\t"
 610                         "fildl  (%2)\n\t"
 611                         "faddp  %%st, %%st(1)\n\t"
 612                         "movb   %4, %c5(%0)\n\t"
 613                         "fstpl  (%0)\n"
 614                         "1:"
 615                         : 
 616                         : "r"(&result->value),
 617                           "r"(&op1->value),
 618                           "r"(&op2->value),
 619                           "n"(IS_LONG),
 620                           "n"(IS_DOUBLE),
 621                           "n"(ZVAL_OFFSETOF_TYPE)
 622                         : "eax","cc");
 623 #elif defined(__GNUC__) && defined(__x86_64__)
 624                 __asm__(
 625                         "movq   (%1), %%rax\n\t"
 626                         "addq   (%2), %%rax\n\t"
 627                         "jo     0f\n\t"     
 628                         "movq   %%rax, (%0)\n\t"
 629                         "movb   %3, %c5(%0)\n\t"
 630                         "jmp    1f\n"
 631                         "0:\n\t"
 632                         "fildq  (%1)\n\t"
 633                         "fildq  (%2)\n\t"
 634                         "faddp  %%st, %%st(1)\n\t"
 635                         "movb   %4, %c5(%0)\n\t"
 636                         "fstpl  (%0)\n"
 637                         "1:"
 638                         : 
 639                         : "r"(&result->value),
 640                           "r"(&op1->value),
 641                           "r"(&op2->value),
 642                           "n"(IS_LONG),
 643                           "n"(IS_DOUBLE),
 644                           "n"(ZVAL_OFFSETOF_TYPE)
 645                         : "rax","cc");
 646 #else
 647                         /*
 648                          * 'result' may alias with op1 or op2, so we need to
 649                          * ensure that 'result' is not updated until after we
 650                          * have read the values of op1 and op2.
 651                          */
 652 
 653                         if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
 654                                 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
 655                                 Z_DVAL_P(result) = (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2);
 656                                 Z_TYPE_P(result) = IS_DOUBLE;
 657                         } else {
 658                                 Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
 659                                 Z_TYPE_P(result) = IS_LONG;
 660                         }
 661 #endif
 662                         return SUCCESS;
 663                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 664                         Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2);
 665                         Z_TYPE_P(result) = IS_DOUBLE;
 666                         return SUCCESS;
 667                 }
 668         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 669                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 670                         Z_DVAL_P(result) = Z_DVAL_P(op1) + Z_DVAL_P(op2);
 671                         Z_TYPE_P(result) = IS_DOUBLE;
 672                         return SUCCESS;
 673                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 674                         Z_DVAL_P(result) = Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2));
 675                         Z_TYPE_P(result) = IS_DOUBLE;
 676                         return SUCCESS;
 677                 }
 678         }
 679         return add_function(result, op1, op2 TSRMLS_CC);
 680 }
 681 
 682 static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 683 {
 684         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 685                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 686 #if defined(__GNUC__) && defined(__i386__)
 687                 __asm__(
 688                         "movl   (%1), %%eax\n\t"
 689                         "subl   (%2), %%eax\n\t"
 690                         "jo     0f\n\t"     
 691                         "movl   %%eax, (%0)\n\t"
 692                         "movb   %3, %c5(%0)\n\t"
 693                         "jmp    1f\n"
 694                         "0:\n\t"
 695                         "fildl  (%2)\n\t"
 696                         "fildl  (%1)\n\t"
 697 #if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
 698                         "fsubp  %%st(1), %%st\n\t"  /* LLVM bug #9164 */
 699 #else
 700                         "fsubp  %%st, %%st(1)\n\t"
 701 #endif
 702                         "movb   %4, %c5(%0)\n\t"
 703                         "fstpl  (%0)\n"
 704                         "1:"
 705                         : 
 706                         : "r"(&result->value),
 707                           "r"(&op1->value),
 708                           "r"(&op2->value),
 709                           "n"(IS_LONG),
 710                           "n"(IS_DOUBLE),
 711                           "n"(ZVAL_OFFSETOF_TYPE)
 712                         : "eax","cc");
 713 #elif defined(__GNUC__) && defined(__x86_64__)
 714                 __asm__(
 715                         "movq   (%1), %%rax\n\t"
 716                         "subq   (%2), %%rax\n\t"
 717                         "jo     0f\n\t"     
 718                         "movq   %%rax, (%0)\n\t"
 719                         "movb   %3, %c5(%0)\n\t"
 720                         "jmp    1f\n"
 721                         "0:\n\t"
 722                         "fildq  (%2)\n\t"
 723                         "fildq  (%1)\n\t"
 724 #if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
 725                         "fsubp  %%st(1), %%st\n\t"  /* LLVM bug #9164 */
 726 #else
 727                         "fsubp  %%st, %%st(1)\n\t"
 728 #endif
 729                         "movb   %4, %c5(%0)\n\t"
 730                         "fstpl  (%0)\n"
 731                         "1:"
 732                         : 
 733                         : "r"(&result->value),
 734                           "r"(&op1->value),
 735                           "r"(&op2->value),
 736                           "n"(IS_LONG),
 737                           "n"(IS_DOUBLE),
 738                           "n"(ZVAL_OFFSETOF_TYPE)
 739                         : "rax","cc");
 740 #else
 741                         Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);
 742 
 743                         if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
 744                                 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
 745                                 Z_DVAL_P(result) = (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2);
 746                                 Z_TYPE_P(result) = IS_DOUBLE;
 747                         } else {
 748                                 Z_TYPE_P(result) = IS_LONG;
 749                         }
 750 #endif
 751                         return SUCCESS;
 752                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 753                         Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2);
 754                         Z_TYPE_P(result) = IS_DOUBLE;
 755                         return SUCCESS;
 756                 }
 757         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 758                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 759                         Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
 760                         Z_TYPE_P(result) = IS_DOUBLE;
 761                         return SUCCESS;
 762                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 763                         Z_DVAL_P(result) = Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2));
 764                         Z_TYPE_P(result) = IS_DOUBLE;
 765                         return SUCCESS;
 766                 }
 767         }
 768         return sub_function(result, op1, op2 TSRMLS_CC);
 769 }
 770 
 771 static zend_always_inline int fast_mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 772 {
 773         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 774                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 775                         long overflow;
 776 
 777                         ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
 778                         Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
 779                         return SUCCESS;
 780                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 781                         Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2);
 782                         Z_TYPE_P(result) = IS_DOUBLE;
 783                         return SUCCESS;
 784                 }
 785         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 786                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 787                         Z_DVAL_P(result) = Z_DVAL_P(op1) * Z_DVAL_P(op2);
 788                         Z_TYPE_P(result) = IS_DOUBLE;
 789                         return SUCCESS;
 790                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 791                         Z_DVAL_P(result) = Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2));
 792                         Z_TYPE_P(result) = IS_DOUBLE;
 793                         return SUCCESS;
 794                 }
 795         }
 796         return mul_function(result, op1, op2 TSRMLS_CC);
 797 }
 798 
 799 static zend_always_inline int fast_div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 800 {
 801 #if 0
 802         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && 0) {
 803                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 804                         if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
 805                                 zend_error(E_WARNING, "Division by zero");
 806                                 Z_LVAL_P(result) = 0;
 807                                 Z_TYPE_P(result) = IS_BOOL;
 808                                 return FAILURE;
 809                         } else if (UNEXPECTED(Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN)) {
 810                                 /* Prevent overflow error/crash */
 811                                 Z_DVAL_P(result) = (double) LONG_MIN / -1;
 812                                 Z_TYPE_P(result) = IS_DOUBLE;
 813                         } else if (EXPECTED(Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0)) {
 814                                 /* integer */
 815                                 Z_LVAL_P(result) = Z_LVAL_P(op1) / Z_LVAL_P(op2);
 816                                 Z_TYPE_P(result) = IS_LONG;
 817                         } else {
 818                                 Z_DVAL_P(result) = ((double) Z_LVAL_P(op1)) / ((double)Z_LVAL_P(op2));
 819                                 Z_TYPE_P(result) = IS_DOUBLE;
 820                         }
 821                         return SUCCESS;
 822                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 823                         if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
 824                                 zend_error(E_WARNING, "Division by zero");
 825                                 Z_LVAL_P(result) = 0;
 826                                 Z_TYPE_P(result) = IS_BOOL;
 827                                 return FAILURE;
 828                         }
 829                         Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) / Z_DVAL_P(op2);
 830                         Z_TYPE_P(result) = IS_DOUBLE;
 831                         return SUCCESS;
 832                 }
 833         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE) && 0) {
 834                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 835                         if (UNEXPECTED(Z_DVAL_P(op2) == 0)) {
 836                                 zend_error(E_WARNING, "Division by zero");
 837                                 Z_LVAL_P(result) = 0;
 838                                 Z_TYPE_P(result) = IS_BOOL;
 839                                 return FAILURE;
 840                         }
 841                         Z_DVAL_P(result) = Z_DVAL_P(op1) / Z_DVAL_P(op2);
 842                         Z_TYPE_P(result) = IS_DOUBLE;
 843                         return SUCCESS;
 844                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 845                         if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
 846                                 zend_error(E_WARNING, "Division by zero");
 847                                 Z_LVAL_P(result) = 0;
 848                                 Z_TYPE_P(result) = IS_BOOL;
 849                                 return FAILURE;
 850                         }
 851                         Z_DVAL_P(result) = Z_DVAL_P(op1) / ((double)Z_LVAL_P(op2));
 852                         Z_TYPE_P(result) = IS_DOUBLE;
 853                         return SUCCESS;
 854                 }
 855         }
 856 #endif
 857         return div_function(result, op1, op2 TSRMLS_CC);
 858 }
 859 
 860 static zend_always_inline int fast_mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 861 {
 862         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 863                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 864                         if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
 865                                 zend_error(E_WARNING, "Division by zero");
 866                                 Z_LVAL_P(result) = 0;
 867                                 Z_TYPE_P(result) = IS_BOOL;
 868                                 return FAILURE;
 869                         } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
 870                                 /* Prevent overflow error/crash if op1==LONG_MIN */
 871                                 Z_LVAL_P(result) = 0;
 872                                 Z_TYPE_P(result) = IS_LONG;
 873                                 return SUCCESS;
 874                         }
 875                         Z_LVAL_P(result) = Z_LVAL_P(op1) % Z_LVAL_P(op2);
 876                         Z_TYPE_P(result) = IS_LONG;
 877                         return SUCCESS;
 878                 }
 879         }
 880         return mod_function(result, op1, op2 TSRMLS_CC);
 881 }
 882 
 883 static zend_always_inline int fast_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 884 {
 885         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 886                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 887                         return Z_LVAL_P(op1) == Z_LVAL_P(op2);
 888                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 889                         return ((double)Z_LVAL_P(op1)) == Z_DVAL_P(op2);
 890                 }
 891         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 892                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 893                         return Z_DVAL_P(op1) == Z_DVAL_P(op2);
 894                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 895                         return Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2));
 896                 }
 897         }
 898         compare_function(result, op1, op2 TSRMLS_CC);
 899         return Z_LVAL_P(result) == 0;
 900 }
 901 
 902 static zend_always_inline int fast_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 903 {
 904         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 905                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 906                         return Z_LVAL_P(op1) != Z_LVAL_P(op2);
 907                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 908                         return ((double)Z_LVAL_P(op1)) != Z_DVAL_P(op2);
 909                 }
 910         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 911                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 912                         return Z_DVAL_P(op1) != Z_DVAL_P(op2);
 913                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 914                         return Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2));
 915                 }
 916         }
 917         compare_function(result, op1, op2 TSRMLS_CC);
 918         return Z_LVAL_P(result) != 0;
 919 }
 920 
 921 static zend_always_inline int fast_is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 922 {
 923         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 924                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 925                         return Z_LVAL_P(op1) < Z_LVAL_P(op2);
 926                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 927                         return ((double)Z_LVAL_P(op1)) < Z_DVAL_P(op2);
 928                 }
 929         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 930                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 931                         return Z_DVAL_P(op1) < Z_DVAL_P(op2);
 932                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 933                         return Z_DVAL_P(op1) < ((double)Z_LVAL_P(op2));
 934                 }
 935         }
 936         compare_function(result, op1, op2 TSRMLS_CC);
 937         return Z_LVAL_P(result) < 0;
 938 }
 939 
 940 static zend_always_inline int fast_is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 941 {
 942         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
 943                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 944                         return Z_LVAL_P(op1) <= Z_LVAL_P(op2);
 945                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 946                         return ((double)Z_LVAL_P(op1)) <= Z_DVAL_P(op2);
 947                 }
 948         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
 949                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
 950                         return Z_DVAL_P(op1) <= Z_DVAL_P(op2);
 951                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
 952                         return Z_DVAL_P(op1) <= ((double)Z_LVAL_P(op2));
 953                 }
 954         }
 955         compare_function(result, op1, op2 TSRMLS_CC);
 956         return Z_LVAL_P(result) <= 0;
 957 }
 958 
 959 #define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode)                                                  \
 960         if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation)) {                       \
 961                 if (SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) {  \
 962                         return SUCCESS;                                                                       \
 963                 }                                                                                         \
 964         } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, do_operation)) {                \
 965                 if (SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2 TSRMLS_CC)) {  \
 966                         return SUCCESS;                                                                       \
 967                 }                                                                                         \
 968         }
 969 
 970 #define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode)                                                   \
 971         if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, do_operation)                          \
 972          && SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, NULL TSRMLS_CC)        \
 973         ) {                                                                                           \
 974                 return SUCCESS;                                                                           \
 975         }
 976 
 977 #endif
 978 
 979 /*
 980  * Local variables:
 981  * tab-width: 4
 982  * c-basic-offset: 4
 983  * indent-tabs-mode: t
 984  * End:
 985  */

/* [<][>][^][v][top][bottom][index][help] */