summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2018-07-25 12:48:16 +0300
committerDmitry Stogov <dmitry@zend.com>2018-07-25 12:48:16 +0300
commitaed3de1bc58c21fa00e3e732992ea5e64bcbe1f0 (patch)
treeeafbab51f383964d7d9d45801c650cc2da5db929 /Zend/zend_operators.c
parentdf6bd506d492292ef4353b0f8da0c34eeb076be5 (diff)
downloadphp-git-aed3de1bc58c21fa00e3e732992ea5e64bcbe1f0.tar.gz
Split add/sub_function(s) into fast and slow parts
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c231
1 files changed, 132 insertions, 99 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index add1e4ecf9..d639eb6b9d 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -901,132 +901,165 @@ try_again:
}
/* }}} */
-ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
+static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
{
- zval op1_copy, op2_copy;
- int converted = 0;
-
- while (1) {
- zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
-
- if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
- fast_long_add_function(result, op1, op2);
- return SUCCESS;
+ if ((result == op1) && (result == op2)) {
+ /* $a += $a */
+ return;
+ }
+ if (result != op1) {
+ ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1)));
+ } else {
+ SEPARATE_ARRAY(result);
+ }
+ zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
+}
+/* }}} */
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
- return SUCCESS;
+static zend_always_inline int add_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
+{
+ zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
- ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
- return SUCCESS;
+ if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
+ fast_long_add_function(result, op1, op2);
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
+ ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_ARRAY, IS_ARRAY))) {
+ add_function_array(result, op1, op2);
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+} /* }}} */
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
- return SUCCESS;
+static zend_never_inline int ZEND_FASTCALL add_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
+{
+ zval op1_copy, op2_copy;
+ int converted = 0;
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_ARRAY, IS_ARRAY))) {
- if ((result == op1) && (result == op2)) {
- /* $a += $a */
- return SUCCESS;
- }
- if (result != op1) {
- ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1)));
+ while (1) {
+ if (Z_ISREF_P(op1)) {
+ op1 = Z_REFVAL_P(op1);
+ } else if (Z_ISREF_P(op2)) {
+ op2 = Z_REFVAL_P(op2);
+ } else if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
+
+ if (EXPECTED(op1 != op2)) {
+ op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
+ op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
} else {
- SEPARATE_ARRAY(result);
+ op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
+ op2 = op1;
}
- zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
- return SUCCESS;
-
- } else {
- if (Z_ISREF_P(op1)) {
- op1 = Z_REFVAL_P(op1);
- } else if (Z_ISREF_P(op2)) {
- op2 = Z_REFVAL_P(op2);
- } else if (!converted) {
- ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
-
- if (EXPECTED(op1 != op2)) {
- op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
- op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
- } else {
- 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 (EG(exception)) {
if (result != op1) {
ZVAL_UNDEF(result);
}
- zend_throw_error(NULL, "Unsupported operand types");
- return FAILURE; /* unknown datatype */
+ return FAILURE;
}
+ converted = 1;
+ } else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
+ zend_throw_error(NULL, "Unsupported operand types");
+ return FAILURE; /* unknown datatype */
}
+ if (add_function_fast(result, op1, op2) == SUCCESS) {
+ return SUCCESS;
+ }
+ }
+} /* }}} */
+
+ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
+{
+ if (add_function_fast(result, op1, op2) == SUCCESS) {
+ return SUCCESS;
+ } else {
+ return add_function_slow(result, op1, op2);
}
}
/* }}} */
-ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
+static zend_always_inline int sub_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
+{
+ zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
+
+ if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
+ fast_long_sub_function(result, op1, op2);
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
+ ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
+ return SUCCESS;
+ } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
+ ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
+/* }}} */
+
+static zend_never_inline int ZEND_FASTCALL sub_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
{
zval op1_copy, op2_copy;
int converted = 0;
-
while (1) {
- zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
-
- if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
- fast_long_sub_function(result, op1, op2);
- return SUCCESS;
-
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
- return SUCCESS;
-
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
- ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
- return SUCCESS;
-
- } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
- return SUCCESS;
-
- } else {
- if (Z_ISREF_P(op1)) {
- op1 = Z_REFVAL_P(op1);
- } else if (Z_ISREF_P(op2)) {
- op2 = Z_REFVAL_P(op2);
- } else if (!converted) {
- ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
-
- if (EXPECTED(op1 != op2)) {
- op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
- op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
- } else {
- 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;
+ if (Z_ISREF_P(op1)) {
+ op1 = Z_REFVAL_P(op1);
+ } else if (Z_ISREF_P(op2)) {
+ op2 = Z_REFVAL_P(op2);
+ } else if (!converted) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
+
+ if (EXPECTED(op1 != op2)) {
+ op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
+ op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
} else {
+ op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
+ op2 = op1;
+ }
+ if (EG(exception)) {
if (result != op1) {
ZVAL_UNDEF(result);
}
- zend_throw_error(NULL, "Unsupported operand types");
- return FAILURE; /* unknown datatype */
+ return FAILURE;
}
+ converted = 1;
+ } else {
+ if (result != op1) {
+ ZVAL_UNDEF(result);
+ }
+ zend_throw_error(NULL, "Unsupported operand types");
+ return FAILURE; /* unknown datatype */
+ }
+ if (sub_function_fast(result, op1, op2) == SUCCESS) {
+ return SUCCESS;
}
}
+
+}
+/* }}} */
+
+ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
+{
+ if (sub_function_fast(result, op1, op2) == SUCCESS) {
+ return SUCCESS;
+ } else {
+ return sub_function_slow(result, op1, op2);
+ }
}
/* }}} */