com php-src: Introduce specialized functions to compare with integer and string, to eliminate repeatable checks on each loop iteration in in_array()
function.: Zend/zend_operators.h ext/standard/array.c
| From: | Dmitry Stogov | Date: | Sat, 27 Dec 2014 08:11:40 +0000 |
| Subject: | com php-src: Introduce specialized functions to compare with integer and string, to eliminate repeatable checks on each loop iteration in in_array() function.: Zend/zend_operators.h ext/standard/array.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-83896@lists.php.net to get a copy of this message | ||
Commit: 107ae86ca6baf2b79d8ddb32b54676a28269ba1f
Author: Dmitry Stogov <dmitry@zend.com> Sat, 27 Dec 2014 11:11:40 +0300
Parents: 37466b03686d234f38fc0ec4e0742cbf8dfb5e27
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=107ae86ca6baf2b79d8ddb32b54676a28269ba1f
Log:
Introduce specialized functions to compare with integer and string, to eliminate repeatable checks
on each loop iteration in in_array() function.
Changed paths:
M Zend/zend_operators.h
M ext/standard/array.c
Diff:
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 1426fe9..20f8ccd 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -913,6 +913,36 @@ static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2)
return Z_LVAL(result) == 0;
}
+static zend_always_inline int fast_equal_check_long(zval *op1, zval *op2)
+{
+ zval result;
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ return Z_LVAL_P(op1) == Z_LVAL_P(op2);
+ }
+ compare_function(&result, op1, op2);
+ return Z_LVAL(result) == 0;
+}
+
+static zend_always_inline int fast_equal_check_string(zval *op1, zval *op2)
+{
+ zval result;
+ if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ if (Z_STR_P(op1) == Z_STR_P(op2)) {
+ return 1;
+ } else if (Z_STRVAL_P(op1)[0] > '9' || Z_STRVAL_P(op2)[0] > '9') {
+ if (Z_STRLEN_P(op1) != Z_STRLEN_P(op2)) {
+ return 0;
+ } else {
+ return memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0;
+ }
+ } else {
+ return zendi_smart_strcmp(op1, op2) == 0;
+ }
+ }
+ compare_function(&result, op1, op2);
+ return Z_LVAL(result) == 0;
+}
+
static zend_always_inline void fast_equal_function(zval *result, zval *op1, zval *op2)
{
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 410ff21..2ae3119 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1273,20 +1273,53 @@ static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int
behavior)
}
} ZEND_HASH_FOREACH_END();
} else {
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
- if (fast_equal_check_function(value, entry)) {
- if (behavior == 0) {
- RETURN_TRUE;
- } else {
- if (str_idx) {
- RETVAL_STR(zend_string_copy(str_idx));
+ ZVAL_DEREF(value);
+ if (Z_TYPE_P(value) == IS_LONG) {
+ ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
+ if (fast_equal_check_long(value, entry)) {
+ if (behavior == 0) {
+ RETURN_TRUE;
} else {
- RETVAL_LONG(num_idx);
+ if (str_idx) {
+ RETVAL_STR(zend_string_copy(str_idx));
+ } else {
+ RETVAL_LONG(num_idx);
+ }
+ return;
}
- return;
}
- }
- } ZEND_HASH_FOREACH_END();
+ } ZEND_HASH_FOREACH_END();
+ } else if (Z_TYPE_P(value) == IS_STRING) {
+ ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
+ if (fast_equal_check_string(value, entry)) {
+ if (behavior == 0) {
+ RETURN_TRUE;
+ } else {
+ if (str_idx) {
+ RETVAL_STR(zend_string_copy(str_idx));
+ } else {
+ RETVAL_LONG(num_idx);
+ }
+ return;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ } else {
+ ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
+ if (fast_equal_check_function(value, entry)) {
+ if (behavior == 0) {
+ RETURN_TRUE;
+ } else {
+ if (str_idx) {
+ RETVAL_STR(zend_string_copy(str_idx));
+ } else {
+ RETVAL_LONG(num_idx);
+ }
+ return;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
}
RETURN_FALSE;