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