com php-src: Added ZEND_COUNT instruction, to impleme nt corresponding builtin.: NEWS Zend/zend_compile .c Zend/zend_vm_def.h Zend/zend_vm_execute.h Zend/zend_vm_opcodes.c Zend/zend_vm_opcodes.h ext/opcache/Optimizer/zend_inference.c
[email protected] (Dmitry Stogov)
| Newsgroups | php.cvs |
|---|---|
| Message-ID | <[email protected]> |
Commit: cd953269d3d486f775f1935731b1d6d44f12a350 Author: Dmitry Stogov <[email protected]> Thu, 25 May 2017 12:52:34 +0300 Parents: 27e7aea4124ffdecb6d40a2f5723e413a7b40562 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=cd953269d3d486f775f1935731b1d6d44f12a350 Log: Added ZEND_COUNT instruction, to implement corresponding builtin. Changed paths: M NEWS M Zend/zend_compile.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h M Zend/zend_vm_opcodes.c M Zend/zend_vm_opcodes.h M ext/opcache/Optimizer/zend_inference.c
diff_cd953269d3d486f775f1935731b1d6d44f12a350.txt
(text/plain, 25.3 KB)
diff --git a/NEWS b/NEWS
index e0a9e92..1e3803a 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PHP NEWS
?? ??? ????, PHP 7.2
- Core:
+ . Added ZEND_COUNT instruction, to implement corresponding builtin. (Dmitry)
. "Countable" interface is moved from SPL to Core. (Dmitry)
. Added ZEND_IN_ARRAY instruction, implementing optimized in_array() builtin
function, through hash lookup in flipped array. (Dmitry)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 0a368a4..2858e6a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3723,6 +3723,20 @@ static int zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{
}
/* }}} */
+int zend_compile_func_count(znode *result, zend_ast_list *args) /* {{{ */
+{
+ znode arg_node;
+
+ if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
+ return FAILURE;
+ }
+
+ zend_compile_expr(&arg_node, args->child[0]);
+ zend_emit_op_tmp(result, ZEND_COUNT, &arg_node, NULL);
+ return SUCCESS;
+}
+/* }}} */
+
int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */
{
if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) {
@@ -3783,6 +3797,8 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l
return zend_compile_func_cuf(result, args, lcname);
} else if (zend_string_equals_literal(lcname, "in_array")) {
return zend_compile_func_in_array(result, args);
+ } else if (zend_string_equals_literal(lcname, "count")) {
+ return zend_compile_func_count(result, args);
} else {
return FAILURE;
}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b1888cc..621e5a7 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -8142,6 +8142,52 @@ ZEND_VM_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ZEND_VM_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *op1;
+ zend_long count;
+
+ SAVE_OPLINE();
+ op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
+ do {
+ if (Z_TYPE_P(op1) == IS_ARRAY) {
+ count = zend_array_count(Z_ARRVAL_P(op1));
+ break;
+ } else if (Z_TYPE_P(op1) == IS_OBJECT) {
+ /* first, we check if the handler is defined */
+ if (Z_OBJ_HT_P(op1)->count_elements) {
+ if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
+ break;
+ }
+ }
+
+ /* if not and the object implements Countable we call its count() method */
+ if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) {
+ zval retval;
+
+ zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval);
+ count = zval_get_long(&retval);
+ zval_ptr_dtor(&retval);
+ break;
+ }
+
+ /* If There's no handler and it doesn't implement Countable then add a warning */
+ count = 1;
+ } else if (Z_TYPE_P(op1) == IS_NULL) {
+ count = 0;
+ } else {
+ count = 1;
+ }
+ zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
+ } while (0);
+
+ ZVAL_LONG(EX_VAR(opline->result.var), count);
+ FREE_OP1();
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 4be3872..b2c701c 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -8069,6 +8069,52 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
ZEND_VM_RETURN();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *op1;
+ zend_long count;
+
+ SAVE_OPLINE();
+ op1 = EX_CONSTANT(opline->op1);
+ do {
+ if (Z_TYPE_P(op1) == IS_ARRAY) {
+ count = zend_array_count(Z_ARRVAL_P(op1));
+ break;
+ } else if (Z_TYPE_P(op1) == IS_OBJECT) {
+ /* first, we check if the handler is defined */
+ if (Z_OBJ_HT_P(op1)->count_elements) {
+ if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
+ break;
+ }
+ }
+
+ /* if not and the object implements Countable we call its count() method */
+ if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) {
+ zval retval;
+
+ zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval);
+ count = zval_get_long(&retval);
+ zval_ptr_dtor(&retval);
+ break;
+ }
+
+ /* If There's no handler and it doesn't implement Countable then add a warning */
+ count = 1;
+ } else if (Z_TYPE_P(op1) == IS_NULL) {
+ count = 0;
+ } else {
+ count = 1;
+ }
+ zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
+ } while (0);
+
+ ZVAL_LONG(EX_VAR(opline->result.var), count);
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -14537,6 +14583,52 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
ZEND_VM_RETURN();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *op1;
+ zend_long count;
+
+ SAVE_OPLINE();
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ do {
+ if (Z_TYPE_P(op1) == IS_ARRAY) {
+ count = zend_array_count(Z_ARRVAL_P(op1));
+ break;
+ } else if (Z_TYPE_P(op1) == IS_OBJECT) {
+ /* first, we check if the handler is defined */
+ if (Z_OBJ_HT_P(op1)->count_elements) {
+ if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
+ break;
+ }
+ }
+
+ /* if not and the object implements Countable we call its count() method */
+ if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) {
+ zval retval;
+
+ zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval);
+ count = zval_get_long(&retval);
+ zval_ptr_dtor(&retval);
+ break;
+ }
+
+ /* If There's no handler and it doesn't implement Countable then add a warning */
+ count = 1;
+ } else if (Z_TYPE_P(op1) == IS_NULL) {
+ count = 0;
+ } else {
+ count = 1;
+ }
+ zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
+ } while (0);
+
+ ZVAL_LONG(EX_VAR(opline->result.var), count);
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -21613,6 +21705,52 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *op1;
+ zend_long count;
+
+ SAVE_OPLINE();
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ do {
+ if (Z_TYPE_P(op1) == IS_ARRAY) {
+ count = zend_array_count(Z_ARRVAL_P(op1));
+ break;
+ } else if (Z_TYPE_P(op1) == IS_OBJECT) {
+ /* first, we check if the handler is defined */
+ if (Z_OBJ_HT_P(op1)->count_elements) {
+ if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
+ break;
+ }
+ }
+
+ /* if not and the object implements Countable we call its count() method */
+ if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) {
+ zval retval;
+
+ zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval);
+ count = zval_get_long(&retval);
+ zval_ptr_dtor(&retval);
+ break;
+ }
+
+ /* If There's no handler and it doesn't implement Countable then add a warning */
+ count = 1;
+ } else if (Z_TYPE_P(op1) == IS_NULL) {
+ count = 0;
+ } else {
+ count = 1;
+ }
+ zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
+ } while (0);
+
+ ZVAL_LONG(EX_VAR(opline->result.var), count);
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -40669,6 +40807,52 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *op1;
+ zend_long count;
+
+ SAVE_OPLINE();
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ do {
+ if (Z_TYPE_P(op1) == IS_ARRAY) {
+ count = zend_array_count(Z_ARRVAL_P(op1));
+ break;
+ } else if (Z_TYPE_P(op1) == IS_OBJECT) {
+ /* first, we check if the handler is defined */
+ if (Z_OBJ_HT_P(op1)->count_elements) {
+ if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
+ break;
+ }
+ }
+
+ /* if not and the object implements Countable we call its count() method */
+ if (instanceof_function(Z_OBJCE_P(op1), zend_ce_countable)) {
+ zval retval;
+
+ zend_call_method_with_0_params(op1, NULL, NULL, "count", &retval);
+ count = zval_get_long(&retval);
+ zval_ptr_dtor(&retval);
+ break;
+ }
+
+ /* If There's no handler and it doesn't implement Countable then add a warning */
+ count = 1;
+ } else if (Z_TYPE_P(op1) == IS_NULL) {
+ count = 0;
+ } else {
+ count = 1;
+ }
+ zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
+ } while (0);
+
+ ZVAL_LONG(EX_VAR(opline->result.var), count);
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -57956,6 +58140,31 @@ ZEND_API void execute_ex(zend_execute_data *ex)
(void*)&&ZEND_NULL_LABEL,
(void*)&&ZEND_NULL_LABEL,
(void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_COUNT_SPEC_CONST_UNUSED_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_COUNT_SPEC_TMP_UNUSED_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_COUNT_SPEC_VAR_UNUSED_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_COUNT_SPEC_CV_UNUSED_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
+ (void*)&&ZEND_NULL_LABEL,
(void*)&&ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_LABEL,
(void*)&&ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_LABEL,
(void*)&&ZEND_NULL_LABEL,
@@ -59461,6 +59670,9 @@ ZEND_API void execute_ex(zend_execute_data *ex)
HYBRID_CASE(ZEND_YIELD_SPEC_CONST_UNUSED):
ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
+ HYBRID_CASE(ZEND_COUNT_SPEC_CONST_UNUSED):
+ ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ HYBRID_BREAK();
HYBRID_CASE(ZEND_ADD_SPEC_CONST_CV):
ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
@@ -59896,6 +60108,9 @@ ZEND_API void execute_ex(zend_execute_data *ex)
HYBRID_CASE(ZEND_YIELD_SPEC_TMP_UNUSED):
ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
+ HYBRID_CASE(ZEND_COUNT_SPEC_TMP_UNUSED):
+ ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ HYBRID_BREAK();
HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_CV):
ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
@@ -60364,6 +60579,9 @@ ZEND_API void execute_ex(zend_execute_data *ex)
HYBRID_CASE(ZEND_MAKE_REF_SPEC_VAR_UNUSED):
ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
+ HYBRID_CASE(ZEND_COUNT_SPEC_VAR_UNUSED):
+ ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ HYBRID_BREAK();
HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_VAR_CV):
ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
@@ -61702,6 +61920,9 @@ ZEND_API void execute_ex(zend_execute_data *ex)
HYBRID_CASE(ZEND_MAKE_REF_SPEC_CV_UNUSED):
ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
+ HYBRID_CASE(ZEND_COUNT_SPEC_CV_UNUSED):
+ ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ HYBRID_BREAK();
HYBRID_CASE(ZEND_ADD_SPEC_CV_CV):
ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
HYBRID_BREAK();
@@ -66633,6 +66854,31 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_COUNT_SPEC_TMP_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_COUNT_SPEC_VAR_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_COUNT_SPEC_CV_UNUSED_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER,
ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER,
ZEND_NULL_HANDLER,
@@ -67700,7 +67946,7 @@ void zend_init_opcodes_handlers(void)
2257 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2282 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2307 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
- 4671,
+ 4696,
2332,
2333,
2334,
@@ -67785,12 +68031,13 @@ void zend_init_opcodes_handlers(void)
3531 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3556 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3581 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
- 4671,
+ 4696,
3606 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3631 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3656 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3681 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
- 4671
+ 3706 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+ 4696
};
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
zend_opcode_handler_funcs = labels;
@@ -67985,7 +68232,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3706 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3731 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -67993,7 +68240,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3731 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3756 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68001,7 +68248,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3756 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3781 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68012,17 +68259,17 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3781 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} else if (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3831 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3831 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3856 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
}
break;
case ZEND_MUL:
@@ -68030,7 +68277,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3856 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3881 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68038,7 +68285,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3881 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3906 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68046,7 +68293,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3906 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 3931 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68057,7 +68304,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 3931 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 3956 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68065,7 +68312,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4006 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4031 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68076,7 +68323,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4081 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4106 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68084,7 +68331,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4156 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4181 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@@ -68095,12 +68342,12 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4231 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4256 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4306 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4331 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
}
break;
case ZEND_IS_SMALLER_OR_EQUAL:
@@ -68108,70 +68355,70 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4381 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4406 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} else if (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
- spec = 4456 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+ spec = 4481 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
}
break;
case ZEND_QM_ASSIGN:
if (op1_info == MAY_BE_DOUBLE) {
- spec = 4621 | SPEC_RULE_OP1;
+ spec = 4646 | SPEC_RULE_OP1;
} else if (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE)))) {
- spec = 4626 | SPEC_RULE_OP1;
+ spec = 4651 | SPEC_RULE_OP1;
}
break;
case ZEND_PRE_INC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
- spec = 4531 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+ spec = 4556 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if (op1_info == MAY_BE_LONG) {
- spec = 4541 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+ spec = 4566 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
- spec = 4551 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+ spec = 4576 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
}
break;
case ZEND_PRE_DEC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
- spec = 4561 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+ spec = 4586 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if (op1_info == MAY_BE_LONG) {
- spec = 4571 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+ spec = 4596 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
- spec = 4581 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+ spec = 4606 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
}
break;
case ZEND_POST_INC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
- spec = 4591 | SPEC_RULE_OP1;
+ spec = 4616 | SPEC_RULE_OP1;
} else if (op1_info == MAY_BE_LONG) {
- spec = 4596 | SPEC_RULE_OP1;
+ spec = 4621 | SPEC_RULE_OP1;
} else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
- spec = 4601 | SPEC_RULE_OP1;
+ spec = 4626 | SPEC_RULE_OP1;
}
break;
case ZEND_POST_DEC:
if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
- spec = 4606 | SPEC_RULE_OP1;
+ spec = 4631 | SPEC_RULE_OP1;
} else if (op1_info == MAY_BE_LONG) {
- spec = 4611 | SPEC_RULE_OP1;
+ spec = 4636 | SPEC_RULE_OP1;
} else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
- spec = 4616 | SPEC_RULE_OP1;
+ spec = 4641 | SPEC_RULE_OP1;
}
break;
case ZEND_SEND_VAR_EX:
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
- spec = 4661 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
+ spec = 4686 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
}
break;
case ZEND_FETCH_DIM_R:
if (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
- spec = 4631 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+ spec = 4656 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
}
break;
case ZEND_SEND_VAR:
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
- spec = 4656 | SPEC_RULE_OP1;
+ spec = 4681 | SPEC_RULE_OP1;
}
break;
default:
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index eba8400..2234919 100644
--- a/Zend/zend_vm_opcodes.c
+++ b/Zend/zend_vm_opcodes.c
@@ -21,7 +21,7 @@
#include <stdio.h>
#include <zend.h>
-static const char *zend_vm_opcodes_names[190] = {
+static const char *zend_vm_opcodes_names[191] = {
"ZEND_NOP",
"ZEND_ADD",
"ZEND_SUB",
@@ -212,9 +212,10 @@ static const char *zend_vm_opcodes_names[190] = {
"ZEND_SWITCH_LONG",
"ZEND_SWITCH_STRING",
"ZEND_IN_ARRAY",
+ "ZEND_COUNT",
};
-static uint32_t zend_vm_opcodes_flags[190] = {
+static uint32_t zend_vm_opcodes_flags[191] = {
0x00000000,
0x00000707,
0x00000707,
@@ -405,6 +406,7 @@ static uint32_t zend_vm_opcodes_flags[190] = {
0x03000307,
0x03000307,
0x01000303,
+ 0x00000103,
};
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 299a3c2..60a1a26 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -261,7 +261,8 @@ END_EXTERN_C()
#define ZEND_SWITCH_LONG 187
#define ZEND_SWITCH_STRING 188
#define ZEND_IN_ARRAY 189
+#define ZEND_COUNT 190
-#define ZEND_VM_LAST_OPCODE 189
+#define ZEND_VM_LAST_OPCODE 190
#endif
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index 5c064be..01d40bf 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -1353,6 +1353,10 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
return 1;
}
break;
+ case ZEND_COUNT:
+ tmp->min = 0;
+ tmp->max = ZEND_LONG_MAX;
+ return 1;
case ZEND_DO_FCALL:
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
@@ -3156,6 +3160,9 @@ static void zend_update_type_info(const zend_op_array *op_array,
}
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
break;
+ case ZEND_COUNT:
+ UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_ops[i].result_def);
+ break;
case ZEND_TYPE_CHECK:
case ZEND_DEFINED:
UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_ops[i].result_def);