]> granicus.if.org Git - php/commitdiff
Avoid agressive inlining in rarely used paths
authorDmitry Stogov <dmitry@zend.com>
Wed, 30 May 2018 11:03:48 +0000 (14:03 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 30 May 2018 11:03:48 +0000 (14:03 +0300)
Zend/zend_operators.c

index 70ea7e5404325292851f9f68a79e8e567fd23204..cd0e7047d0f5781807326b8353e920bb259c3e53 100644 (file)
@@ -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) {