zend_operators.h 32 KB

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