]> granicus.if.org Git - php/commitdiff
Added ZEND_COUNT instruction, to implement corresponding builtin.
authorDmitry Stogov <dmitry@zend.com>
Thu, 25 May 2017 09:52:34 +0000 (12:52 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 25 May 2017 09:52:34 +0000 (12:52 +0300)
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

diff --git a/NEWS b/NEWS
index e0a9e92d8e78b08e55d2fe348dd5bd3d1ec7999e..1e3803a6e6fa710d68e781cf398a144ec5d058d2 100644 (file)
--- 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)
index 0a368a4a4bf2885635f596206bba455bd7b9d8df..2858e6a9065ddbf45cacc95ec572a1a091930402 100644 (file)
@@ -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;
        }
index b1888cc85705833e38f0f76082ea12a8fbc516df..621e5a75d0b92d2023b5eb2220c7ca9c2bc4da3c 100644 (file)
@@ -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
index 4be3872bcefddba00b032ad69826769f69e42f30..b2c701c47bfb5f03305d32243b4d0e6cf1ce3d65 100644 (file)
@@ -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:
index eba840096de221fad9ee82c5dd86b79f4cd0bc31..22349193f9970ad484c2bc1f0bb422d0475905f6 100644 (file)
@@ -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) {
index 299a3c2ebc030d9e87581bce3164bab1f8ed11b9..60a1a26168f702c994945bee79207d49e5d08342 100644 (file)
@@ -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
index 5c064be607ced1a43929230881d4ee137b4e04de..01d40bf15d8eac1a2a09a3a92453defaba57c650 100644 (file)
@@ -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);