com php-src: Constant evaluation of in_array() (suppo rt for more cases).: ext/opcache/Optimizer/dce. c ext/opcache/Optimizer/sccp.c
| From: | Dmitry Stogov | Date: | Mon, 17 Jul 2017 20:08:10 +0000 |
| Subject: | com php-src: Constant evaluation of in_array() (suppo rt for more cases).: ext/opcache/Optimizer/dce. c ext/opcache/Optimizer/sccp.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-98589@lists.php.net to get a copy of this message | ||
Commit: 37542728183490ca4d321ee9f03466536c3b9a76
Author: Dmitry Stogov <dmitry@zend.com> Mon, 17 Jul 2017 17:27:21 +0300
Parents: d9d3b2c20641b61b4d02258cd1363aa713de37b8
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=37542728183490ca4d321ee9f03466536c3b9a76
Log:
Constant evaluation of in_array() (support for more cases).
Changed paths:
M ext/opcache/Optimizer/dce.c
M ext/opcache/Optimizer/sccp.c
Diff:
diff --git a/ext/opcache/Optimizer/dce.c b/ext/opcache/Optimizer/dce.c
index 2c21154..26df94d 100644
--- a/ext/opcache/Optimizer/dce.c
+++ b/ext/opcache/Optimizer/dce..c
@@ -118,6 +118,7 @@ static inline zend_bool may_have_side_effects(
case ZEND_FETCH_DIM_IS:
case ZEND_ISSET_ISEMPTY_VAR:
case ZEND_FETCH_IS:
+ case ZEND_IN_ARRAY:
/* No side effects */
return 0;
case ZEND_JMP:
diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c
index 1e023f1..4e315c0 100644
--- a/ext/opcache/Optimizer/sccp.c
+++ b/ext/opcache/Optimizer/sccp.c
@@ -461,6 +461,42 @@ static inline void ct_eval_type_check(zval *result, uint32_t type, zval *op1) {
}
}
+static inline int ct_eval_in_array(zval *result, uint32_t extended_value, zval *op1, zval *op2) {
+ HashTable *ht;
+ zend_bool res;
+
+ if (Z_TYPE_P(op2) != IS_ARRAY) {
+ return FAILURE;
+ }
+ ht = Z_ARRVAL_P(op2);
+ if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ res = zend_hash_exists(ht, Z_STR_P(op1));
+ } else if (extended_value) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ res = zend_hash_index_exists(ht, Z_LVAL_P(op1));
+ } else {
+ res = 0;
+ }
+ } else if (Z_TYPE_P(op1) <= IS_FALSE) {
+ res = zend_hash_exists(ht, ZSTR_EMPTY_ALLOC());
+ } else {
+ zend_string *key;
+ zval tmp;
+
+ res = 0;
+ ZEND_HASH_FOREACH_STR_KEY(ht, key) {
+ ZVAL_STR(&tmp, key);
+ compare_function(&tmp, op1, &tmp);
+ if (Z_LVAL(tmp) == 0) {
+ res = 1;
+ break;
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ ZVAL_BOOL(result, res);
+ return SUCCESS;
+}
+
/* The functions chosen here are simple to implement and either likely to affect a branch,
* or just happened to be commonly used with constant operands in WP (need to test other
* applications as well, of course). */
@@ -506,7 +542,11 @@ static inline int ct_eval_func_call(
}
return SUCCESS;
} else if (zend_string_equals_literal(name, "in_array")) {
- if (num_args != 2 || Z_TYPE_P(args[1]) != IS_ARRAY) {
+ if ((num_args != 2
+ && (num_args != 3
+ || (Z_TYPE_P(args[2]) != IS_FALSE
+ && Z_TYPE_P(args[2]) != IS_TRUE)))
+ || Z_TYPE_P(args[1]) != IS_ARRAY) {
return FAILURE;
}
/* pass */
@@ -843,6 +883,16 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op
*ssa_o
}
SET_RESULT_BOT(result);
break;
+ case ZEND_IN_ARRAY:
+ SKIP_IF_TOP(op1);
+ SKIP_IF_TOP(op2);
+ if (ct_eval_in_array(&zv, opline->extended_value, op1, op2) == SUCCESS) {
+ SET_RESULT(result, &zv);
+ zval_ptr_dtor_nogc(&zv);
+ break;
+ }
+ SET_RESULT_BOT(result);
+ break;
case ZEND_FETCH_DIM_R:
case ZEND_FETCH_DIM_IS:
case ZEND_FETCH_LIST: