PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_operators.h (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 151 159 95.0 %
Date: 2016-07-19 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       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             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      18             :    +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #ifndef ZEND_OPERATORS_H
      24             : #define ZEND_OPERATORS_H
      25             : 
      26             : #include <errno.h>
      27             : #include <math.h>
      28             : #include <assert.h>
      29             : 
      30             : #ifdef __GNUC__
      31             : #include <stddef.h>
      32             : #endif
      33             : 
      34             : #ifdef HAVE_IEEEFP_H
      35             : #include <ieeefp.h>
      36             : #endif
      37             : 
      38             : #include "zend_strtod.h"
      39             : #include "zend_multiply.h"
      40             : 
      41             : #if 0&&HAVE_BCMATH
      42             : #include "ext/bcmath/libbcmath/src/bcmath.h"
      43             : #endif
      44             : 
      45             : #define LONG_SIGN_MASK (((zend_long)1) << (8*sizeof(zend_long)-1))
      46             : 
      47             : BEGIN_EXTERN_C()
      48             : ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2);
      49             : ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2);
      50             : ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2);
      51             : ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2);
      52             : ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2);
      53             : ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2);
      54             : ZEND_API int ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, zval *op2);
      55             : ZEND_API int ZEND_FASTCALL boolean_not_function(zval *result, zval *op1);
      56             : ZEND_API int ZEND_FASTCALL bitwise_not_function(zval *result, zval *op1);
      57             : ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2);
      58             : ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2);
      59             : ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2);
      60             : ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2);
      61             : ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2);
      62             : ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2);
      63             : 
      64             : ZEND_API int ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2);
      65             : 
      66             : ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2);
      67             : ZEND_API int ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2);
      68             : ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2);
      69             : ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2);
      70             : ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2);
      71             : ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2);
      72             : 
      73             : ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only);
      74             : ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce);
      75             : 
      76             : /**
      77             :  * Checks whether the string "str" with length "length" is numeric. The value
      78             :  * of allow_errors determines whether it's required to be entirely numeric, or
      79             :  * just its prefix. Leading whitespace is allowed.
      80             :  *
      81             :  * The function returns 0 if the string did not contain a valid number; IS_LONG
      82             :  * if it contained a number that fits within the range of a long; or IS_DOUBLE
      83             :  * if the number was out of long range or contained a decimal point/exponent.
      84             :  * The number's value is returned into the respective pointer, *lval or *dval,
      85             :  * if that pointer is not NULL.
      86             :  *
      87             :  * This variant also gives information if a string that represents an integer
      88             :  * could not be represented as such due to overflow. It writes 1 to oflow_info
      89             :  * if the integer is larger than ZEND_LONG_MAX and -1 if it's smaller than ZEND_LONG_MIN.
      90             :  */
      91             : ZEND_API zend_uchar ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info);
      92             : 
      93             : ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end);
      94             : ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end);
      95             : 
      96             : #if SIZEOF_ZEND_LONG == 4
      97             : #       define ZEND_DOUBLE_FITS_LONG(d) (!((d) > ZEND_LONG_MAX || (d) < ZEND_LONG_MIN))
      98             : #else
      99             :         /* >= as (double)ZEND_LONG_MAX is outside signed range */
     100             : #       define ZEND_DOUBLE_FITS_LONG(d) (!((d) >= ZEND_LONG_MAX || (d) < ZEND_LONG_MIN))
     101             : #endif
     102             : 
     103             : #if ZEND_DVAL_TO_LVAL_CAST_OK
     104             : static zend_always_inline zend_long zend_dval_to_lval(double d)
     105             : {
     106             :     if (EXPECTED(zend_finite(d)) && EXPECTED(!zend_isnan(d))) {
     107             :         return (zend_long)d;
     108             :     } else {
     109             :         return 0;
     110             :     }
     111             : }
     112             : #else
     113             : ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d);
     114             : 
     115             : static zend_always_inline zend_long zend_dval_to_lval(double d)
     116             : {
     117       30457 :         if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
     118           7 :                 return 0;
     119       30450 :         } else if (!ZEND_DOUBLE_FITS_LONG(d)) {
     120         140 :                 return zend_dval_to_lval_slow(d);
     121             :         }
     122       30310 :         return (zend_long)d;
     123             : }
     124             : #endif
     125             : 
     126             : static zend_always_inline zend_long zend_dval_to_lval_cap(double d)
     127             : {
     128         457 :         if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
     129           0 :                 return 0;
     130         457 :         } else if (!ZEND_DOUBLE_FITS_LONG(d)) {
     131           0 :                 return (d > 0 ? ZEND_LONG_MAX : ZEND_LONG_MIN);
     132             :         }
     133         457 :         return (zend_long)d;
     134             : }
     135             : /* }}} */
     136             : 
     137             : #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
     138             : #define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))
     139             : 
     140             : static zend_always_inline zend_uchar is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info)
     141             : {
     142     1252925 :         if (*str > '9') {
     143      280510 :                 return 0;
     144             :         }
     145      972415 :         return _is_numeric_string_ex(str, length, lval, dval, allow_errors, oflow_info);
     146             : }
     147             : 
     148             : static zend_always_inline zend_uchar is_numeric_string(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors) {
     149      266266 :     return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
     150             : }
     151             : 
     152             : ZEND_API zend_uchar ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval);
     153             : 
     154             : static zend_always_inline const char *
     155             : zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const char *end)
     156             : {
     157     2936025 :         const char *p = haystack;
     158     2936025 :         const char ne = needle[needle_len-1];
     159             :         ptrdiff_t off_p;
     160             :         size_t off_s;
     161             : 
     162     2936025 :         if (needle_len == 1) {
     163     2025974 :                 return (const char *)memchr(p, *needle, (end-p));
     164             :         }
     165             : 
     166      910051 :         off_p = end - haystack;
     167      910051 :         off_s = (off_p > 0) ? (size_t)off_p : 0;
     168             : 
     169      910051 :         if (needle_len > off_s) {
     170       10839 :                 return NULL;
     171             :         }
     172             : 
     173      899212 :         if (EXPECTED(off_s < 1024 || needle_len < 3)) {
     174      883263 :                 end -= needle_len;
     175             : 
     176     3984660 :                 while (p <= end) {
     177     3897824 :                         if ((p = (const char *)memchr(p, *needle, (end-p+1))) && ne == p[needle_len-1]) {
     178      583061 :                                 if (!memcmp(needle, p, needle_len-1)) {
     179      227797 :                                         return p;
     180             :                                 }
     181             :                         }
     182             : 
     183     3670027 :                         if (p == NULL) {
     184      568630 :                                 return NULL;
     185             :                         }
     186             : 
     187     3101397 :                         p++;
     188             :                 }
     189             : 
     190       86836 :                 return NULL;
     191             :         } else {
     192       15949 :                 return zend_memnstr_ex(haystack, needle, needle_len, end);
     193             :         }
     194             : }
     195             : 
     196             : static zend_always_inline const void *zend_memrchr(const void *s, int c, size_t n)
     197             : {
     198             :         const unsigned char *e;
     199     3968532 :         if (n <= 0) {
     200         448 :                 return NULL;
     201             :         }
     202             : 
     203    68527758 :         for (e = (const unsigned char *)s + n - 1; e >= (const unsigned char *)s; e--) {
     204    64597613 :                 if (*e == (const unsigned char)c) {
     205       37939 :                         return (const void *)e;
     206             :                 }
     207             :         }
     208     3930145 :         return NULL;
     209             : }
     210             : 
     211             : 
     212             : static zend_always_inline const char *
     213             : zend_memnrstr(const char *haystack, const char *needle, size_t needle_len, char *end)
     214             : {
     215         579 :     const char *p = end;
     216         579 :     const char ne = needle[needle_len-1];
     217             :     ptrdiff_t off_p;
     218             :     size_t off_s;
     219             : 
     220         579 :     if (needle_len == 1) {
     221         488 :         return (const char *)zend_memrchr(haystack, *needle, (p - haystack));
     222             :     }
     223             : 
     224         335 :     off_p = end - haystack;
     225         335 :     off_s = (off_p > 0) ? (size_t)off_p : 0;
     226             : 
     227         335 :     if (needle_len > off_s) {
     228          29 :         return NULL;
     229             :     }
     230             : 
     231         306 :         if (EXPECTED(off_s < 1024 || needle_len < 3)) {
     232         306 :                 p -= needle_len;
     233             : 
     234             :                 do {
     235        1180 :                         if ((p = (const char *)zend_memrchr(haystack, *needle, (p - haystack) + 1)) && ne == p[needle_len-1]) {
     236         236 :                                 if (!memcmp(needle, p, needle_len - 1)) {
     237         208 :                                         return p;
     238             :                                 }
     239             :                         }
     240         382 :                 } while (p-- >= haystack);
     241             : 
     242          98 :                 return NULL;
     243             :         } else {
     244           0 :                 return zend_memnrstr_ex(haystack, needle, needle_len, end);
     245             :         }
     246             : }
     247             : 
     248             : ZEND_API int ZEND_FASTCALL increment_function(zval *op1);
     249             : ZEND_API int ZEND_FASTCALL decrement_function(zval *op2);
     250             : 
     251             : ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op);
     252             : ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC);
     253             : ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC);
     254             : ZEND_API void ZEND_FASTCALL convert_to_long(zval *op);
     255             : ZEND_API void ZEND_FASTCALL convert_to_double(zval *op);
     256             : ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base);
     257             : ZEND_API void ZEND_FASTCALL convert_to_null(zval *op);
     258             : ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op);
     259             : ZEND_API void ZEND_FASTCALL convert_to_array(zval *op);
     260             : ZEND_API void ZEND_FASTCALL convert_to_object(zval *op);
     261             : ZEND_API void multi_convert_to_long_ex(int argc, ...);
     262             : ZEND_API void multi_convert_to_double_ex(int argc, ...);
     263             : ZEND_API void multi_convert_to_string_ex(int argc, ...);
     264             : 
     265             : ZEND_API zend_long    ZEND_FASTCALL _zval_get_long_func(zval *op);
     266             : ZEND_API double       ZEND_FASTCALL _zval_get_double_func(zval *op);
     267             : ZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op);
     268             : 
     269             : static zend_always_inline zend_long _zval_get_long(zval *op) {
     270      546397 :         return Z_TYPE_P(op) == IS_LONG ? Z_LVAL_P(op) : _zval_get_long_func(op);
     271             : }
     272             : static zend_always_inline double _zval_get_double(zval *op) {
     273        6620 :         return Z_TYPE_P(op) == IS_DOUBLE ? Z_DVAL_P(op) : _zval_get_double_func(op);
     274             : }
     275             : static zend_always_inline zend_string *_zval_get_string(zval *op) {
     276     5143975 :         return Z_TYPE_P(op) == IS_STRING ? zend_string_copy(Z_STR_P(op)) : _zval_get_string_func(op);
     277             : }
     278             : 
     279             : #define zval_get_long(op) _zval_get_long((op))
     280             : #define zval_get_double(op) _zval_get_double((op))
     281             : #define zval_get_string(op) _zval_get_string((op))
     282             : 
     283             : #define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); }
     284             : #define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); }
     285             : 
     286             : 
     287             : ZEND_API int ZEND_FASTCALL zend_is_true(zval *op);
     288             : ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op);
     289             : 
     290             : #define zval_is_true(op) \
     291             :         zend_is_true(op)
     292             : 
     293             : static zend_always_inline int i_zend_is_true(zval *op)
     294             : {
     295     2979133 :         int result = 0;
     296             : 
     297             : again:
     298     3221778 :         switch (Z_TYPE_P(op)) {
     299             :                 case IS_TRUE:
     300      177288 :                         result = 1;
     301             :                         break;
     302             :                 case IS_LONG:
     303     2148987 :                         if (Z_LVAL_P(op)) {
     304      397275 :                                 result = 1;
     305             :                         }
     306             :                         break;
     307             :                 case IS_DOUBLE:
     308         264 :                         if (Z_DVAL_P(op)) {
     309         237 :                                 result = 1;
     310             :                         }
     311             :                         break;
     312             :                 case IS_STRING:
     313      101745 :                         if (Z_STRLEN_P(op) > 1 || (Z_STRLEN_P(op) && Z_STRVAL_P(op)[0] != '0')) {
     314       51002 :                                 result = 1;
     315             :                         }
     316             :                         break;
     317             :                 case IS_ARRAY:
     318      190557 :                         if (zend_hash_num_elements(Z_ARRVAL_P(op))) {
     319      159857 :                                 result = 1;
     320             :                         }
     321             :                         break;
     322             :                 case IS_OBJECT:
     323      162647 :                         result = zend_object_is_true(op);
     324             :                         break;
     325             :                 case IS_RESOURCE:
     326       47662 :                         if (EXPECTED(Z_RES_HANDLE_P(op))) {
     327       47662 :                                 result = 1;
     328             :                         }
     329             :                         break;
     330             :                 case IS_REFERENCE:
     331      242645 :                         op = Z_REFVAL_P(op);
     332             :                         goto again;
     333             :                         break;
     334             :                 default:
     335             :                         break;
     336             :         }
     337     2979132 :         return result;
     338             : }
     339             : 
     340             : ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2);
     341             : 
     342             : ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2);
     343             : ZEND_API int ZEND_FASTCALL string_compare_function_ex(zval *op1, zval *op2, zend_bool case_insensitive);
     344             : ZEND_API int ZEND_FASTCALL string_compare_function(zval *op1, zval *op2);
     345             : ZEND_API int ZEND_FASTCALL string_case_compare_function(zval *op1, zval *op2);
     346             : #if HAVE_STRCOLL
     347             : ZEND_API int ZEND_FASTCALL string_locale_compare_function(zval *op1, zval *op2);
     348             : #endif
     349             : 
     350             : ZEND_API void         ZEND_FASTCALL zend_str_tolower(char *str, size_t length);
     351             : ZEND_API char*        ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length);
     352             : ZEND_API char*        ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length);
     353             : ZEND_API char*        ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length);
     354             : ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str);
     355             : 
     356             : ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2);
     357             : ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
     358             : ZEND_API int ZEND_FASTCALL zend_binary_zval_strcasecmp(zval *s1, zval *s2);
     359             : ZEND_API int ZEND_FASTCALL zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3);
     360             : ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2);
     361             : ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
     362             : ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2);
     363             : ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
     364             : ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2);
     365             : ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length);
     366             : 
     367             : ZEND_API zend_long ZEND_FASTCALL zendi_smart_strcmp(zend_string *s1, zend_string *s2);
     368             : ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2);
     369             : ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2);
     370             : ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2);
     371             : 
     372             : ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, int str_len);
     373             : ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len);
     374             : 
     375             : ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
     376             : 
     377             : #define convert_to_ex_master(pzv, lower_type, upper_type)       \
     378             :         if (Z_TYPE_P(pzv)!=upper_type) {                                        \
     379             :                 convert_to_##lower_type(pzv);                                           \
     380             :         }
     381             : 
     382             : #define convert_to_explicit_type(pzv, type)             \
     383             :         do {                                                                            \
     384             :                 switch (type) {                                                 \
     385             :                         case IS_NULL:                                           \
     386             :                                 convert_to_null(pzv);                   \
     387             :                                 break;                                                  \
     388             :                         case IS_LONG:                                           \
     389             :                                 convert_to_long(pzv);                   \
     390             :                                 break;                                                  \
     391             :                         case IS_DOUBLE:                                         \
     392             :                                 convert_to_double(pzv);                 \
     393             :                                 break;                                                  \
     394             :                         case _IS_BOOL:                                          \
     395             :                                 convert_to_boolean(pzv);                \
     396             :                                 break;                                                  \
     397             :                         case IS_ARRAY:                                          \
     398             :                                 convert_to_array(pzv);                  \
     399             :                                 break;                                                  \
     400             :                         case IS_OBJECT:                                         \
     401             :                                 convert_to_object(pzv);                 \
     402             :                                 break;                                                  \
     403             :                         case IS_STRING:                                         \
     404             :                                 convert_to_string(pzv);                 \
     405             :                                 break;                                                  \
     406             :                         default:                                                        \
     407             :                                 assert(0);                                              \
     408             :                                 break;                                                  \
     409             :                 }                                                                               \
     410             :         } while (0);
     411             : 
     412             : #define convert_to_explicit_type_ex(pzv, str_type)      \
     413             :         if (Z_TYPE_P(pzv) != str_type) {                                \
     414             :                 convert_to_explicit_type(pzv, str_type);        \
     415             :         }
     416             : 
     417             : #define convert_to_boolean_ex(pzv)      convert_to_ex_master(pzv, boolean, _IS_BOOL)
     418             : #define convert_to_long_ex(pzv)         convert_to_ex_master(pzv, long, IS_LONG)
     419             : #define convert_to_double_ex(pzv)       convert_to_ex_master(pzv, double, IS_DOUBLE)
     420             : #define convert_to_string_ex(pzv)       convert_to_ex_master(pzv, string, IS_STRING)
     421             : #define convert_to_array_ex(pzv)        convert_to_ex_master(pzv, array, IS_ARRAY)
     422             : #define convert_to_object_ex(pzv)       convert_to_ex_master(pzv, object, IS_OBJECT)
     423             : #define convert_to_null_ex(pzv)         convert_to_ex_master(pzv, null, IS_NULL)
     424             : 
     425             : #define convert_scalar_to_number_ex(pzv)                                                        \
     426             :         if (Z_TYPE_P(pzv)!=IS_LONG && Z_TYPE_P(pzv)!=IS_DOUBLE) {               \
     427             :                 convert_scalar_to_number(pzv);                                  \
     428             :         }
     429             : 
     430             : #if HAVE_SETLOCALE && defined(ZEND_WIN32) && !defined(ZTS) && defined(_MSC_VER)
     431             : /* This performance improvement of tolower() on Windows gives 10-18% on bench.php */
     432             : #define ZEND_USE_TOLOWER_L 1
     433             : #endif
     434             : 
     435             : #ifdef ZEND_USE_TOLOWER_L
     436             : ZEND_API void zend_update_current_locale(void);
     437             : #else
     438             : #define zend_update_current_locale()
     439             : #endif
     440             : 
     441             : /* The offset in bytes between the value and type fields of a zval */
     442             : #define ZVAL_OFFSETOF_TYPE      \
     443             :         (offsetof(zval, u1.type_info) - offsetof(zval, value))
     444             : 
     445             : static zend_always_inline void fast_long_increment_function(zval *op1)
     446             : {
     447             : #if defined(__GNUC__) && defined(__i386__)
     448             :         __asm__(
     449             :                 "incl (%0)\n\t"
     450             :                 "jno  0f\n\t"
     451             :                 "movl $0x0, (%0)\n\t"
     452             :                 "movl $0x41e00000, 0x4(%0)\n\t"
     453             :                 "movl %1, %c2(%0)\n"
     454             :                 "0:"
     455             :                 :
     456             :                 : "r"(&op1->value),
     457             :                   "n"(IS_DOUBLE),
     458             :                   "n"(ZVAL_OFFSETOF_TYPE)
     459             :                 : "cc", "memory");
     460             : #elif defined(__GNUC__) && defined(__x86_64__)
     461     8938915 :         __asm__(
     462             :                 "incq (%0)\n\t"
     463             :                 "jno  0f\n\t"
     464             :                 "movl $0x0, (%0)\n\t"
     465             :                 "movl $0x43e00000, 0x4(%0)\n\t"
     466             :                 "movl %1, %c2(%0)\n"
     467             :                 "0:"
     468             :                 :
     469     8938915 :                 : "r"(&op1->value),
     470             :                   "n"(IS_DOUBLE),
     471             :                   "n"(ZVAL_OFFSETOF_TYPE)
     472             :                 : "cc", "memory");
     473             : #else
     474             :         if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MAX)) {
     475             :                 /* switch to double */
     476             :                 ZVAL_DOUBLE(op1, (double)ZEND_LONG_MAX + 1.0);
     477             :         } else {
     478             :                 Z_LVAL_P(op1)++;
     479             :         }
     480             : #endif
     481             : }
     482             : 
     483             : static zend_always_inline void fast_long_decrement_function(zval *op1)
     484             : {
     485             : #if defined(__GNUC__) && defined(__i386__)
     486             :         __asm__(
     487             :                 "decl (%0)\n\t"
     488             :                 "jno  0f\n\t"
     489             :                 "movl $0x00200000, (%0)\n\t"
     490             :                 "movl $0xc1e00000, 0x4(%0)\n\t"
     491             :                 "movl %1,%c2(%0)\n"
     492             :                 "0:"
     493             :                 :
     494             :                 : "r"(&op1->value),
     495             :                   "n"(IS_DOUBLE),
     496             :                   "n"(ZVAL_OFFSETOF_TYPE)
     497             :                 : "cc", "memory");
     498             : #elif defined(__GNUC__) && defined(__x86_64__)
     499      261831 :         __asm__(
     500             :                 "decq (%0)\n\t"
     501             :                 "jno  0f\n\t"
     502             :                 "movl $0x00000000, (%0)\n\t"
     503             :                 "movl $0xc3e00000, 0x4(%0)\n\t"
     504             :                 "movl %1,%c2(%0)\n"
     505             :                 "0:"
     506             :                 :
     507      261831 :                 : "r"(&op1->value),
     508             :                   "n"(IS_DOUBLE),
     509             :                   "n"(ZVAL_OFFSETOF_TYPE)
     510             :                 : "cc", "memory");
     511             : #else
     512             :         if (UNEXPECTED(Z_LVAL_P(op1) == ZEND_LONG_MIN)) {
     513             :                 /* switch to double */
     514             :                 ZVAL_DOUBLE(op1, (double)ZEND_LONG_MIN - 1.0);
     515             :         } else {
     516             :                 Z_LVAL_P(op1)--;
     517             :         }
     518             : #endif
     519             : }
     520             : 
     521             : static zend_always_inline void fast_long_add_function(zval *result, zval *op1, zval *op2)
     522             : {
     523             : #if defined(__GNUC__) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__)
     524             :         __asm__(
     525             :                 "movl      (%1), %%eax\n\t"
     526             :                 "addl   (%2), %%eax\n\t"
     527             :                 "jo     0f\n\t"
     528             :                 "movl   %%eax, (%0)\n\t"
     529             :                 "movl   %3, %c5(%0)\n\t"
     530             :                 "jmp    1f\n"
     531             :                 "0:\n\t"
     532             :                 "fildl     (%1)\n\t"
     533             :                 "fildl     (%2)\n\t"
     534             :                 "faddp     %%st, %%st(1)\n\t"
     535             :                 "movl   %4, %c5(%0)\n\t"
     536             :                 "fstpl     (%0)\n"
     537             :                 "1:"
     538             :                 :
     539             :                 : "r"(&result->value),
     540             :                   "r"(&op1->value),
     541             :                   "r"(&op2->value),
     542             :                   "n"(IS_LONG),
     543             :                   "n"(IS_DOUBLE),
     544             :                   "n"(ZVAL_OFFSETOF_TYPE)
     545             :                 : "eax","cc", "memory");
     546             : #elif defined(__GNUC__) && defined(__x86_64__)
     547     3505892 :         __asm__(
     548             :                 "movq      (%1), %%rax\n\t"
     549             :                 "addq   (%2), %%rax\n\t"
     550             :                 "jo     0f\n\t"
     551             :                 "movq   %%rax, (%0)\n\t"
     552             :                 "movl   %3, %c5(%0)\n\t"
     553             :                 "jmp    1f\n"
     554             :                 "0:\n\t"
     555             :                 "fildq     (%1)\n\t"
     556             :                 "fildq     (%2)\n\t"
     557             :                 "faddp     %%st, %%st(1)\n\t"
     558             :                 "movl   %4, %c5(%0)\n\t"
     559             :                 "fstpl     (%0)\n"
     560             :                 "1:"
     561             :                 :
     562     3505892 :                 : "r"(&result->value),
     563     3505892 :                   "r"(&op1->value),
     564     3505892 :                   "r"(&op2->value),
     565             :                   "n"(IS_LONG),
     566             :                   "n"(IS_DOUBLE),
     567             :                   "n"(ZVAL_OFFSETOF_TYPE)
     568             :                 : "rax","cc", "memory");
     569             : #else
     570             :         /*
     571             :          * 'result' may alias with op1 or op2, so we need to
     572             :          * ensure that 'result' is not updated until after we
     573             :          * have read the values of op1 and op2.
     574             :          */
     575             : 
     576             :         if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
     577             :                 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
     578             :                 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
     579             :         } else {
     580             :                 ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2));
     581             :         }
     582             : #endif
     583             : }
     584             : 
     585             : static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *op2)
     586             : {
     587      202150 :         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
     588      202106 :                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
     589             :                         fast_long_add_function(result, op1, op2);
     590      202097 :                         return SUCCESS;
     591           9 :                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
     592           9 :                         ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
     593           9 :                         return SUCCESS;
     594             :                 }
     595          44 :         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
     596          44 :                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
     597          35 :                         ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
     598          35 :                         return SUCCESS;
     599           9 :                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
     600           9 :                         ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
     601           9 :                         return SUCCESS;
     602             :                 }
     603             :         }
     604           0 :         return add_function(result, op1, op2);
     605             : }
     606             : 
     607             : static zend_always_inline void fast_long_sub_function(zval *result, zval *op1, zval *op2)
     608             : {
     609             : #if defined(__GNUC__) && defined(__i386__) && !(4 == __GNUC__ && 8 == __GNUC_MINOR__)
     610             :         __asm__(
     611             :                 "movl      (%1), %%eax\n\t"
     612             :                 "subl   (%2), %%eax\n\t"
     613             :                 "jo     0f\n\t"
     614             :                 "movl   %%eax, (%0)\n\t"
     615             :                 "movl   %3, %c5(%0)\n\t"
     616             :                 "jmp    1f\n"
     617             :                 "0:\n\t"
     618             :                 "fildl     (%2)\n\t"
     619             :                 "fildl     (%1)\n\t"
     620             : #if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
     621             :                 "fsubp  %%st(1), %%st\n\t"  /* LLVM bug #9164 */
     622             : #else
     623             :                 "fsubp     %%st, %%st(1)\n\t"
     624             : #endif
     625             :                 "movl   %4, %c5(%0)\n\t"
     626             :                 "fstpl     (%0)\n"
     627             :                 "1:"
     628             :                 :
     629             :                 : "r"(&result->value),
     630             :                   "r"(&op1->value),
     631             :                   "r"(&op2->value),
     632             :                   "n"(IS_LONG),
     633             :                   "n"(IS_DOUBLE),
     634             :                   "n"(ZVAL_OFFSETOF_TYPE)
     635             :                 : "eax","cc", "memory");
     636             : #elif defined(__GNUC__) && defined(__x86_64__)
     637     3194946 :         __asm__(
     638             :                 "movq      (%1), %%rax\n\t"
     639             :                 "subq   (%2), %%rax\n\t"
     640             :                 "jo     0f\n\t"
     641             :                 "movq   %%rax, (%0)\n\t"
     642             :                 "movl   %3, %c5(%0)\n\t"
     643             :                 "jmp    1f\n"
     644             :                 "0:\n\t"
     645             :                 "fildq     (%2)\n\t"
     646             :                 "fildq     (%1)\n\t"
     647             : #if defined(__clang__) && (__clang_major__ < 2 || (__clang_major__ == 2 && __clang_minor__ < 10))
     648             :                 "fsubp  %%st(1), %%st\n\t"  /* LLVM bug #9164 */
     649             : #else
     650             :                 "fsubp     %%st, %%st(1)\n\t"
     651             : #endif
     652             :                 "movl   %4, %c5(%0)\n\t"
     653             :                 "fstpl     (%0)\n"
     654             :                 "1:"
     655             :                 :
     656     3194946 :                 : "r"(&result->value),
     657     3194946 :                   "r"(&op1->value),
     658     3194946 :                   "r"(&op2->value),
     659             :                   "n"(IS_LONG),
     660             :                   "n"(IS_DOUBLE),
     661             :                   "n"(ZVAL_OFFSETOF_TYPE)
     662             :                 : "rax","cc", "memory");
     663             : #else
     664             :         ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
     665             : 
     666             :         if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
     667             :                 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
     668             :                 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
     669             :         }
     670             : #endif
     671             : }
     672             : 
     673             : static zend_always_inline int fast_div_function(zval *result, zval *op1, zval *op2)
     674             : {
     675      127096 :         return div_function(result, op1, op2);
     676             : }
     677             : 
     678             : static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2)
     679             : {
     680             :         zval result;
     681       14210 :         if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
     682          21 :                 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
     683           0 :                         return Z_LVAL_P(op1) == Z_LVAL_P(op2);
     684          21 :                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
     685           0 :                         return ((double)Z_LVAL_P(op1)) == Z_DVAL_P(op2);
     686             :                 }
     687       14189 :         } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
     688         316 :                 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
     689          16 :                         return Z_DVAL_P(op1) == Z_DVAL_P(op2);
     690         300 :                 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
     691         128 :                         return Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2));
     692             :                 }
     693       13873 :         } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
     694          35 :                 if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
     695          25 :                         if (Z_STR_P(op1) == Z_STR_P(op2)) {
     696           0 :                                 return 1;
     697          25 :                         } else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
     698           9 :                                 if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
     699           8 :                                         return 0;
     700             :                                 } else {
     701           1 :                                         return memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0;
     702             :                                 }
     703             :                         } else {
     704          16 :                                 return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)) == 0;
     705             :                         }
     706             :                 }
     707             :         }
     708       14041 :         compare_function(&result, op1, op2);
     709       14041 :         return Z_LVAL(result) == 0;
     710             : }
     711             : 
     712             : static zend_always_inline int fast_equal_check_long(zval *op1, zval *op2)
     713             : {
     714             :         zval result;
     715        8252 :         if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
     716        8051 :                 return Z_LVAL_P(op1) == Z_LVAL_P(op2);
     717             :         }
     718         201 :         compare_function(&result, op1, op2);
     719         201 :         return Z_LVAL(result) == 0;
     720             : }
     721             : 
     722             : static zend_always_inline int fast_equal_check_string(zval *op1, zval *op2)
     723             : {
     724             :         zval result;
     725      480505 :         if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
     726      479854 :                 if (Z_STR_P(op1) == Z_STR_P(op2)) {
     727          53 :                         return 1;
     728      479801 :                 } else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
     729      475731 :                         if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
     730      420970 :                                 return 0;
     731             :                         } else {
     732       54761 :                                 return memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0;
     733             :                         }
     734             :                 } else {
     735        4070 :                         return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)) == 0;
     736             :                 }
     737             :         }
     738         651 :         compare_function(&result, op1, op2);
     739         651 :         return Z_LVAL(result) == 0;
     740             : }
     741             : 
     742             : static zend_always_inline int fast_is_identical_function(zval *op1, zval *op2)
     743             : {
     744     3500999 :         if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
     745     2514672 :                 return 0;
     746      986327 :         } else if (Z_TYPE_P(op1) <= IS_TRUE) {
     747       38575 :                 return 1;
     748             :         }
     749      947752 :         return zend_is_identical(op1, op2);
     750             : }
     751             : 
     752             : static zend_always_inline int fast_is_not_identical_function(zval *op1, zval *op2)
     753             : {
     754      690328 :         if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
     755      630741 :                 return 1;
     756       59587 :         } else if (Z_TYPE_P(op1) <= IS_TRUE) {
     757       20836 :                 return 0;
     758             :         }
     759       38751 :         return !zend_is_identical(op1, op2);
     760             : }
     761             : 
     762             : #define ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode, binary_op)                                            \
     763             :         if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT)                                                             \
     764             :                 && op1 == result                                                                                   \
     765             :                 && UNEXPECTED(Z_OBJ_HANDLER_P(op1, get))                                                           \
     766             :                 && EXPECTED(Z_OBJ_HANDLER_P(op1, set))) {                                                          \
     767             :                 int ret;                                                                                           \
     768             :                 zval rv;                                                                                           \
     769             :                 zval *objval = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);                                      \
     770             :                 Z_TRY_ADDREF_P(objval);                                                                                \
     771             :                 ret = binary_op(objval, objval, op2);                                                    \
     772             :                 Z_OBJ_HANDLER_P(op1, set)(op1, objval);                                                  \
     773             :                 zval_ptr_dtor(objval);                                                                             \
     774             :                 return ret;                                                                                        \
     775             :         } else if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT)                                                      \
     776             :                 && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation))) {                                               \
     777             :                 if (EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, op2))) { \
     778             :                         return SUCCESS;                                                                                \
     779             :                 }                                                                                                  \
     780             :         }
     781             : 
     782             : #define ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode)                                                       \
     783             :         if (UNEXPECTED(Z_TYPE_P(op2) == IS_OBJECT)                                                             \
     784             :                 && UNEXPECTED(Z_OBJ_HANDLER_P(op2, do_operation))                                                  \
     785             :                 && EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op2, do_operation)(opcode, result, op1, op2))) {  \
     786             :                 return SUCCESS;                                                                                    \
     787             :         }
     788             : 
     789             : #define ZEND_TRY_BINARY_OBJECT_OPERATION(opcode, binary_op)                                                \
     790             :         ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(opcode, binary_op)                                                \
     791             :         else                                                                                                   \
     792             :         ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(opcode)
     793             : 
     794             : #define ZEND_TRY_UNARY_OBJECT_OPERATION(opcode)                                                            \
     795             :         if (UNEXPECTED(Z_TYPE_P(op1) == IS_OBJECT)                                                             \
     796             :                 && UNEXPECTED(Z_OBJ_HANDLER_P(op1, do_operation))                                                  \
     797             :                 && EXPECTED(SUCCESS == Z_OBJ_HANDLER_P(op1, do_operation)(opcode, result, op1, NULL))) { \
     798             :                 return SUCCESS;                                                                                    \
     799             :         }
     800             : 
     801             : /* buf points to the END of the buffer */
     802             : static zend_always_inline char *zend_print_ulong_to_buf(char *buf, zend_ulong num) {
     803     1420321 :         *buf = '\0';
     804             :         do {
     805     2782064 :                 *--buf = (char) (num % 10) + '0';
     806     2782064 :                 num /= 10;
     807     2782064 :         } while (num > 0);
     808     1420321 :         return buf;
     809             : }
     810             : 
     811             : /* buf points to the END of the buffer */
     812             : static zend_always_inline char *zend_print_long_to_buf(char *buf, zend_long num) {
     813     1011584 :         if (num < 0) {
     814        8456 :             char *result = zend_print_ulong_to_buf(buf, ~((zend_ulong) num) + 1);
     815        4228 :             *--result = '-';
     816        4228 :                 return result;
     817             :         } else {
     818     2014712 :             return zend_print_ulong_to_buf(buf, num);
     819             :         }
     820             : }
     821             : 
     822             : ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num);
     823             : 
     824             : static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
     825             : {
     826          12 :         if (Z_REFCOUNT_P(op) == 1) {
     827           0 :                 ZVAL_UNREF(op);
     828             :         } else {
     829             :                 Z_DELREF_P(op);
     830          12 :                 ZVAL_COPY(op, Z_REFVAL_P(op));
     831             :         }
     832             : }
     833             : /* }}} */
     834             : 
     835             : 
     836             : END_EXTERN_C()
     837             : 
     838             : #endif
     839             : 
     840             : /*
     841             :  * Local variables:
     842             :  * tab-width: 4
     843             :  * c-basic-offset: 4
     844             :  * indent-tabs-mode: t
     845             :  * End:
     846             :  */

Generated by: LCOV version 1.10

Generated at Wed, 20 Jul 2016 02:56:14 +0000 (5 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.