diff options
author | Dmitry Stogov <dmitry@zend.com> | 2018-05-30 14:03:48 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2018-05-30 14:03:48 +0300 |
commit | ff58d7054899015a7871ff4ae23ae025abc94629 (patch) | |
tree | a46e2f585840bc7556902344a2fce73683bf6dc6 /Zend/zend_operators.c | |
parent | 84aab1d4e1a6394cd3fb89d027c0b7890ca49ab2 (diff) | |
download | php-git-ff58d7054899015a7871ff4ae23ae025abc94629.tar.gz |
Avoid agressive inlining in rarely used paths
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r-- | Zend/zend_operators.c | 185 |
1 files changed, 114 insertions, 71 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 70ea7e5404..cd0e7047d0 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -156,7 +156,7 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { /* }}} */ -void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{ */ +static void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent, zend_bool check) /* {{{ */ { try_again: switch (Z_TYPE_P(op)) { @@ -196,6 +196,9 @@ try_again: zval dst; convert_object_to_type(op, &dst, _IS_NUMBER, convert_scalar_to_number); + if (check && UNEXPECTED(EG(exception))) { + return; + } zval_dtor(op); if (Z_TYPE(dst) == IS_LONG || Z_TYPE(dst) == IS_DOUBLE) { @@ -211,63 +214,67 @@ try_again: ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ { - _convert_scalar_to_number(op, 1); -} -/* }}} */ - -/* {{{ zendi_convert_scalar_to_number */ -#define zendi_convert_scalar_to_number(op, holder, result, silent) \ - if (Z_TYPE_P(op) != IS_LONG) { \ - if (op==result && Z_TYPE_P(op) != IS_OBJECT) { \ - _convert_scalar_to_number(op, silent); \ - } else { \ - switch (Z_TYPE_P(op)) { \ - case IS_STRING: \ - if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), silent ? 1 : -1)) == 0) { \ - ZVAL_LONG(&(holder), 0); \ - if (!silent) { \ - zend_error(E_WARNING, "A non-numeric value encountered"); \ - } \ - } \ - (op) = &(holder); \ - break; \ - case IS_NULL: \ - case IS_FALSE: \ - ZVAL_LONG(&(holder), 0); \ - (op) = &(holder); \ - break; \ - case IS_TRUE: \ - ZVAL_LONG(&(holder), 1); \ - (op) = &(holder); \ - break; \ - case IS_RESOURCE: \ - ZVAL_LONG(&(holder), Z_RES_HANDLE_P(op)); \ - (op) = &(holder); \ - break; \ - case IS_OBJECT: \ - ZVAL_COPY(&(holder), op); \ - _convert_scalar_to_number(&(holder), silent); \ - if (UNEXPECTED(EG(exception))) { \ - if (result != op1) { \ - ZVAL_UNDEF(result); \ - } \ - return FAILURE; \ - } \ - if (Z_TYPE(holder) == IS_LONG || Z_TYPE(holder) == IS_DOUBLE) { \ - if (op == result) { \ - zval_ptr_dtor(op); \ - ZVAL_COPY(op, &(holder)); \ - } else { \ - (op) = &(holder); \ - } \ - } \ - break; \ - } \ - } \ + _convert_scalar_to_number(op, 1, 0); +} +/* }}} */ + +/* {{{ _zendi_convert_scalar_to_number_ex */ +static zend_always_inline zval* _zendi_convert_scalar_to_number_ex(zval *op, zval *holder, zend_bool silent) /* {{{ */ +{ + switch (Z_TYPE_P(op)) { + case IS_NULL: + case IS_FALSE: + ZVAL_LONG(holder, 0); + return holder; + case IS_TRUE: + ZVAL_LONG(holder, 1); + return holder; + case IS_STRING: + if ((Z_TYPE_INFO_P(holder) = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL_P(holder), &Z_DVAL_P(holder), silent ? 1 : -1)) == 0) { + ZVAL_LONG(holder, 0); + if (!silent) { + zend_error(E_WARNING, "A non-numeric value encountered"); + } + } + return holder; + case IS_RESOURCE: + ZVAL_LONG(holder, Z_RES_HANDLE_P(op)); + return holder; + case IS_OBJECT: + convert_object_to_type(op, holder, _IS_NUMBER, convert_scalar_to_number); + if (UNEXPECTED(EG(exception)) || + UNEXPECTED(Z_TYPE_P(holder) != IS_LONG && Z_TYPE_P(holder) != IS_DOUBLE)) { + ZVAL_LONG(holder, 1); + } + return holder; + case IS_LONG: + case IS_DOUBLE: + default: + return op; } +} +/* }}} */ + +/* {{{ _zendi_convert_scalar_to_number */ +static zend_never_inline zval* ZEND_FASTCALL _zendi_convert_scalar_to_number(zval *op, zval *holder) /* {{{ */ +{ + return _zendi_convert_scalar_to_number_ex(op, holder, 1); +} +/* }}} */ +/* {{{ _zendi_convert_scalar_to_number_noisy */ +static zend_never_inline zval* ZEND_FASTCALL _zendi_convert_scalar_to_number_noisy(zval *op, zval *holder) /* {{{ */ +{ + return _zendi_convert_scalar_to_number_ex(op, holder, 0); +} /* }}} */ +#define zendi_convert_scalar_to_number(op, holder, result, silent) \ + ((Z_TYPE_P(op) == IS_LONG || Z_TYPE_P(op) == IS_DOUBLE) ? (op) : \ + (((op) == result) ? (_convert_scalar_to_number((op), silent, 1), (op)) : \ + (silent ? _zendi_convert_scalar_to_number((op), holder) : \ + _zendi_convert_scalar_to_number_noisy((op), holder)))) + #define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, op, op_func) \ do { \ if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \ @@ -946,12 +953,18 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function); if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); op2 = op1; } + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); + } + return FAILURE; + } converted = 1; } else { if (result != op1) { @@ -998,12 +1011,18 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function); if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); op2 = op1; } + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); + } + return FAILURE; + } converted = 1; } else { if (result != op1) { @@ -1053,12 +1072,18 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function); if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); op2 = op1; } + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); + } + return FAILURE; + } converted = 1; } else { if (result != op1) { @@ -1144,23 +1169,29 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* { ZVAL_LONG(result, 0); return SUCCESS; } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); } if (Z_TYPE_P(op2) == IS_ARRAY) { ZVAL_LONG(result, 1L); return SUCCESS; } else { - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); } } else { if (Z_TYPE_P(op1) == IS_ARRAY) { ZVAL_LONG(result, 0); return SUCCESS; } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); } op2 = op1; } + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); + } + return FAILURE; + } converted = 1; } else { if (result != op1) { @@ -1229,12 +1260,18 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function); if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0); } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0); op2 = op1; } + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); + } + return FAILURE; + } converted = 1; } else { if (result != op1) { @@ -2095,8 +2132,14 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1); return SUCCESS; } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 1); - zendi_convert_scalar_to_number(op2, op2_copy, result, 1); + op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 1); + op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 1); + if (EG(exception)) { + if (result != op1) { + ZVAL_UNDEF(result); + } + return FAILURE; + } converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { |