]> granicus.if.org Git - php/commitdiff
Added ZEND_FUNC_NUM_ARGS, ZEND_FUNC_GET_ARGS instructions, to implement corresponding...
authorDmitry Stogov <dmitry@zend.com>
Tue, 30 May 2017 10:23:17 +0000 (13:23 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 30 May 2017 10:23:17 +0000 (13:23 +0300)
Special optimisation for "array_slice(INT, func_get_args())" pattern.

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_func_info.c
ext/opcache/Optimizer/zend_inference.c

diff --git a/NEWS b/NEWS
index 56f25666a92e18326f348fcc644e26b2f98a0a68..8f07dbe7613b378c0d07224044479b6b77c249b8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,8 +3,9 @@ PHP                                                                        NEWS
 ?? ??? ????, PHP 7.2
 
 - Core:
-  . Added ZEND_COUNT, ZEND_GET_CLASS, ZEND_GET_CALLED_CLASS, ZEND_GET_TYPE
-    instructions, to implement corresponding builtin functions. (Dmitry)
+  . Added ZEND_COUNT, ZEND_GET_CLASS, ZEND_GET_CALLED_CLASS, ZEND_GET_TYPE,
+    ZEND_FUNC_NUM_ARGS, ZEND_FUNC_GET_ARGS instructions, to implement
+    corresponding builtin functions. (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 e210a26e43560dbe63850b6a33a7e856a36429b2..43e65f0edecc5b48d4a557e66892c78840535ec1 100644 (file)
@@ -3807,6 +3807,57 @@ int zend_compile_func_gettype(znode *result, zend_ast_list *args) /* {{{ */
 }
 /* }}} */
 
+int zend_compile_func_num_args(znode *result, zend_ast_list *args) /* {{{ */
+{
+       if (CG(active_op_array)->function_name && args->children == 0) {
+               zend_emit_op_tmp(result, ZEND_FUNC_NUM_ARGS, NULL, NULL);
+               return SUCCESS;
+       } else {
+               return FAILURE;
+       }
+}
+/* }}} */
+
+int zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */
+{
+       if (CG(active_op_array)->function_name && args->children == 0) {
+               zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, NULL, NULL);
+               return SUCCESS;
+       } else {
+               return FAILURE;
+       }
+}
+/* }}} */
+
+int zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */
+{
+       if (CG(active_op_array)->function_name
+        && args->children == 2
+        && args->child[0]->kind == ZEND_AST_CALL
+        && args->child[0]->child[0]->kind == ZEND_AST_ZVAL
+        && args->child[0]->child[1]->kind == ZEND_AST_ARG_LIST
+        && args->child[1]->kind == ZEND_AST_ZVAL) {
+
+               zval *name = zend_ast_get_zval(args->child[0]->child[0]);
+               zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]);
+               zval *zv = zend_ast_get_zval(args->child[1]);
+               znode first;
+
+               if (Z_TYPE_P(name) == IS_STRING
+                && zend_string_equals_literal_ci(Z_STR_P(name), "func_get_args")
+                && list->children == 0
+                && Z_TYPE_P(zv) == IS_LONG
+                && Z_LVAL_P(zv) >= 0) {
+                       first.op_type = IS_CONST;
+                       ZVAL_LONG(&first.u.constant, Z_LVAL_P(zv));
+                       zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, &first, NULL);
+                       return SUCCESS;
+               }
+       }
+       return FAILURE;
+}
+/* }}} */
+
 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)) {
@@ -3875,6 +3926,12 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l
                return zend_compile_func_get_called_class(result, args);
        } else if (zend_string_equals_literal(lcname, "gettype")) {
                return zend_compile_func_gettype(result, args);
+       } else if (zend_string_equals_literal(lcname, "func_num_args")) {
+               return zend_compile_func_num_args(result, args);
+       } else if (zend_string_equals_literal(lcname, "func_get_args")) {
+               return zend_compile_func_get_args(result, args);
+       } else if (zend_string_equals_literal(lcname, "array_slice")) {
+               return zend_compile_func_array_slice(result, args);
        } else {
                return FAILURE;
        }
index d26f9e78cbe186a99b8ddc340209bdc2c38e0d61..bd82456661890e09424805618e2797eaf90137f3 100644 (file)
@@ -8311,6 +8311,78 @@ ZEND_VM_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+ZEND_VM_HANDLER(194, ZEND_FUNC_NUM_ARGS, UNUSED, UNUSED)
+{
+       ZVAL_LONG(EX_VAR(opline->result.var), EX_NUM_ARGS());
+       ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
+{
+       USE_OPLINE
+       zend_array *ht;
+       uint32_t arg_count, first_extra_arg, i, n;
+       zval *p, *q;
+
+       arg_count = EX_NUM_ARGS();
+       ht = (zend_array *) emalloc(sizeof(zend_array));
+       if (OP1_TYPE == IS_CONST) {
+               i = Z_LVAL_P(EX_CONSTANT(opline->op1));
+               if (arg_count < i) {
+                       i = 0;
+               } else {
+                       i = arg_count - i;
+               }
+               zend_hash_init(ht, i, NULL, ZVAL_PTR_DTOR, 0);
+       } else {
+               zend_hash_init(ht, arg_count, NULL, ZVAL_PTR_DTOR, 0);
+       }
+       ZVAL_ARR(EX_VAR(opline->result.var), ht);
+       if (arg_count) {
+               first_extra_arg = EX(func)->op_array.num_args;
+               zend_hash_real_init(ht, 1);
+               ZEND_HASH_FILL_PACKED(ht) {
+                       i = 0;
+                       n = 0;
+                       if (OP1_TYPE == IS_CONST) {
+                               i = Z_LVAL_P(EX_CONSTANT(opline->op1));
+                       }
+                       p = EX_VAR_NUM(i);
+                       if (arg_count > first_extra_arg) {
+                               while (i < first_extra_arg) {
+                                       q = p;
+                                       if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
+                                               ZVAL_DEREF(q);
+                                               if (Z_OPT_REFCOUNTED_P(q)) {
+                                                       Z_ADDREF_P(q);
+                                               }
+                                               n++;
+                                       }
+                                       ZEND_HASH_FILL_ADD(q);
+                                       p++;
+                                       i++;
+                               }
+                               p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
+                       }
+                       while (i < arg_count) {
+                               q = p;
+                               if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
+                                       ZVAL_DEREF(q);
+                                       if (Z_OPT_REFCOUNTED_P(q)) {
+                                               Z_ADDREF_P(q);
+                                       }
+                                       n++;
+                               }
+                               ZEND_HASH_FILL_ADD(q);
+                               p++;
+                               i++;
+                       }
+               } ZEND_HASH_FILL_END();
+               ht->nNumOfElements = n;
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
 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 2427327af6d9c64100ff7fbe0e7763e8d351daa7..c6ceb078f4d73c398a118791ec5070d9bddd142d 100644 (file)
@@ -8219,6 +8219,72 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CONST_UNUSED_HAN
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_array *ht;
+       uint32_t arg_count, first_extra_arg, i, n;
+       zval *p, *q;
+
+       arg_count = EX_NUM_ARGS();
+       ht = (zend_array *) emalloc(sizeof(zend_array));
+       if (IS_CONST == IS_CONST) {
+               i = Z_LVAL_P(EX_CONSTANT(opline->op1));
+               if (arg_count < i) {
+                       i = 0;
+               } else {
+                       i = arg_count - i;
+               }
+               zend_hash_init(ht, i, NULL, ZVAL_PTR_DTOR, 0);
+       } else {
+               zend_hash_init(ht, arg_count, NULL, ZVAL_PTR_DTOR, 0);
+       }
+       ZVAL_ARR(EX_VAR(opline->result.var), ht);
+       if (arg_count) {
+               first_extra_arg = EX(func)->op_array.num_args;
+               zend_hash_real_init(ht, 1);
+               ZEND_HASH_FILL_PACKED(ht) {
+                       i = 0;
+                       n = 0;
+                       if (IS_CONST == IS_CONST) {
+                               i = Z_LVAL_P(EX_CONSTANT(opline->op1));
+                       }
+                       p = EX_VAR_NUM(i);
+                       if (arg_count > first_extra_arg) {
+                               while (i < first_extra_arg) {
+                                       q = p;
+                                       if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
+                                               ZVAL_DEREF(q);
+                                               if (Z_OPT_REFCOUNTED_P(q)) {
+                                                       Z_ADDREF_P(q);
+                                               }
+                                               n++;
+                                       }
+                                       ZEND_HASH_FILL_ADD(q);
+                                       p++;
+                                       i++;
+                               }
+                               p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
+                       }
+                       while (i < arg_count) {
+                               q = p;
+                               if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
+                                       ZVAL_DEREF(q);
+                                       if (Z_OPT_REFCOUNTED_P(q)) {
+                                               Z_ADDREF_P(q);
+                                       }
+                                       n++;
+                               }
+                               ZEND_HASH_FILL_ADD(q);
+                               p++;
+                               i++;
+                       }
+               } ZEND_HASH_FILL_END();
+               ht->nNumOfElements = n;
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -29517,6 +29583,78 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CALLED_CLASS_SPEC_UNUSED_U
        ZEND_VM_NEXT_OPCODE();
 }
 
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       ZVAL_LONG(EX_VAR(opline->result.var), EX_NUM_ARGS());
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_array *ht;
+       uint32_t arg_count, first_extra_arg, i, n;
+       zval *p, *q;
+
+       arg_count = EX_NUM_ARGS();
+       ht = (zend_array *) emalloc(sizeof(zend_array));
+       if (IS_UNUSED == IS_CONST) {
+               i = Z_LVAL_P(EX_CONSTANT(opline->op1));
+               if (arg_count < i) {
+                       i = 0;
+               } else {
+                       i = arg_count - i;
+               }
+               zend_hash_init(ht, i, NULL, ZVAL_PTR_DTOR, 0);
+       } else {
+               zend_hash_init(ht, arg_count, NULL, ZVAL_PTR_DTOR, 0);
+       }
+       ZVAL_ARR(EX_VAR(opline->result.var), ht);
+       if (arg_count) {
+               first_extra_arg = EX(func)->op_array.num_args;
+               zend_hash_real_init(ht, 1);
+               ZEND_HASH_FILL_PACKED(ht) {
+                       i = 0;
+                       n = 0;
+                       if (IS_UNUSED == IS_CONST) {
+                               i = Z_LVAL_P(EX_CONSTANT(opline->op1));
+                       }
+                       p = EX_VAR_NUM(i);
+                       if (arg_count > first_extra_arg) {
+                               while (i < first_extra_arg) {
+                                       q = p;
+                                       if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
+                                               ZVAL_DEREF(q);
+                                               if (Z_OPT_REFCOUNTED_P(q)) {
+                                                       Z_ADDREF_P(q);
+                                               }
+                                               n++;
+                                       }
+                                       ZEND_HASH_FILL_ADD(q);
+                                       p++;
+                                       i++;
+                               }
+                               p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
+                       }
+                       while (i < arg_count) {
+                               q = p;
+                               if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
+                                       ZVAL_DEREF(q);
+                                       if (Z_OPT_REFCOUNTED_P(q)) {
+                                               Z_ADDREF_P(q);
+                                       }
+                                       n++;
+                               }
+                               ZEND_HASH_FILL_ADD(q);
+                               p++;
+                               i++;
+                       }
+               } ZEND_HASH_FILL_END();
+               ht->nNumOfElements = n;
+       }
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC)
 {
        USE_OPLINE
@@ -58544,6 +58682,56 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        (void*)&&ZEND_GET_TYPE_SPEC_CV_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_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_NULL_LABEL,
+                       (void*)&&ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_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_FUNC_GET_ARGS_SPEC_CONST_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_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_NULL_LABEL,
+                       (void*)&&ZEND_FUNC_GET_ARGS_SPEC_UNUSED_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_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_LABEL,
                        (void*)&&ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_LABEL,
                        (void*)&&ZEND_NULL_LABEL,
@@ -60058,6 +60246,9 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_GET_TYPE_SPEC_CONST_UNUSED):
                                ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED):
+                               ZEND_FUNC_GET_ARGS_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();
@@ -61507,6 +61698,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
                        HYBRID_CASE(ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED):
                                ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED):
+                               ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
+                       HYBRID_CASE(ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED):
+                               ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+                               HYBRID_BREAK();
                        HYBRID_CASE(ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_OBJ):
                                ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_OBJ_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
                                HYBRID_BREAK();
@@ -67363,6 +67560,56 @@ void zend_init_opcodes_handlers(void)
                ZEND_GET_TYPE_SPEC_CV_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_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_NULL_HANDLER,
+               ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_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_FUNC_GET_ARGS_SPEC_CONST_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_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_HANDLER,
+               ZEND_NULL_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,
@@ -68430,7 +68677,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,
-               4771,
+               4821,
                2332,
                2333,
                2334,
@@ -68515,7 +68762,7 @@ 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,
-               4771,
+               4821,
                3606 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3631 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3656 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
@@ -68524,7 +68771,9 @@ void zend_init_opcodes_handlers(void)
                3731 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3756 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
                3781 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
-               4771
+               3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               3831 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
+               4821
        };
 #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
        zend_opcode_handler_funcs = labels;
@@ -68719,7 +68968,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 = 3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3856 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68727,7 +68976,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 = 3831 | 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);
                                }
@@ -68735,7 +68984,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 = 3906 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68746,17 +68995,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 = 3881 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3931 | 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 = 3906 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3956 | 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 = 3931 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 3981 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        }
                        break;
                case ZEND_MUL:
@@ -68764,7 +69013,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 = 3956 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 4006 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68772,7 +69021,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 = 3981 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 4031 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68780,7 +69029,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 = 4056 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68791,7 +69040,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 = 4031 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4081 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68799,7 +69048,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 = 4106 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4156 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68810,7 +69059,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 = 4181 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4231 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68818,7 +69067,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 = 4256 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4306 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                                if (op->op1_type > op->op2_type) {
                                        zend_swap_operands(op);
                                }
@@ -68829,12 +69078,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 = 4331 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4381 | 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 = 4406 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4456 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        }
                        break;
                case ZEND_IS_SMALLER_OR_EQUAL:
@@ -68842,70 +69091,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 = 4481 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4531 | 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 = 4556 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
+                               spec = 4606 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
                        }
                        break;
                case ZEND_QM_ASSIGN:
                        if (op1_info == MAY_BE_DOUBLE) {
-                               spec = 4721 | SPEC_RULE_OP1;
+                               spec = 4771 | 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 = 4726 | SPEC_RULE_OP1;
+                               spec = 4776 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_PRE_INC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4631 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4681 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4641 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4691 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4651 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4701 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_PRE_DEC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4661 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4711 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4671 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4721 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4681 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
+                               spec = 4731 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
                        }
                        break;
                case ZEND_POST_INC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4691 | SPEC_RULE_OP1;
+                               spec = 4741 | SPEC_RULE_OP1;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4696 | SPEC_RULE_OP1;
+                               spec = 4746 | SPEC_RULE_OP1;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4701 | SPEC_RULE_OP1;
+                               spec = 4751 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_POST_DEC:
                        if (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG) {
-                               spec = 4706 | SPEC_RULE_OP1;
+                               spec = 4756 | SPEC_RULE_OP1;
                        } else if (op1_info == MAY_BE_LONG) {
-                               spec = 4711 | SPEC_RULE_OP1;
+                               spec = 4761 | SPEC_RULE_OP1;
                        } else if (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)) {
-                               spec = 4716 | SPEC_RULE_OP1;
+                               spec = 4766 | SPEC_RULE_OP1;
                        }
                        break;
                case ZEND_SEND_VAR_EX:
                        if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
-                               spec = 4761 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
+                               spec = 4811 | 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 = 4731 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
+                               spec = 4781 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
                        }
                        break;
                case ZEND_SEND_VAR:
                        if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) {
-                               spec = 4756 | SPEC_RULE_OP1;
+                               spec = 4806 | SPEC_RULE_OP1;
                        }
                        break;
                default:
index 0d0fc51455cbd7724322d73611c3c8a8901c69d7..8a58a12450b2be936fdb57a04172961109d42034 100644 (file)
@@ -21,7 +21,7 @@
 #include <stdio.h>
 #include <zend.h>
 
-static const char *zend_vm_opcodes_names[194] = {
+static const char *zend_vm_opcodes_names[196] = {
        "ZEND_NOP",
        "ZEND_ADD",
        "ZEND_SUB",
@@ -216,9 +216,11 @@ static const char *zend_vm_opcodes_names[194] = {
        "ZEND_GET_CLASS",
        "ZEND_GET_CALLED_CLASS",
        "ZEND_GET_TYPE",
+       "ZEND_FUNC_NUM_ARGS",
+       "ZEND_FUNC_GET_ARGS",
 };
 
-static uint32_t zend_vm_opcodes_flags[194] = {
+static uint32_t zend_vm_opcodes_flags[196] = {
        0x00000000,
        0x00000707,
        0x00000707,
@@ -413,6 +415,8 @@ static uint32_t zend_vm_opcodes_flags[194] = {
        0x00000103,
        0x00000101,
        0x00000103,
+       0x00000101,
+       0x00000103,
 };
 
 ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
index ed4bb73b27c6e90607697b41ed1438955b80c4d7..6001400bf8eb7ddb37252a49252fe1d12e7f3725 100644 (file)
@@ -265,7 +265,9 @@ END_EXTERN_C()
 #define ZEND_GET_CLASS                       191
 #define ZEND_GET_CALLED_CLASS                192
 #define ZEND_GET_TYPE                        193
+#define ZEND_FUNC_NUM_ARGS                   194
+#define ZEND_FUNC_GET_ARGS                   195
 
-#define ZEND_VM_LAST_OPCODE                  193
+#define ZEND_VM_LAST_OPCODE                  195
 
 #endif
index f9992d539a9577230ee38aed7036a79e8e48edb7..6cb55a11a87293f12e050ad2f1d3de543c3ed658 100644 (file)
@@ -224,7 +224,7 @@ static const func_info_t func_infos[] = {
        F0("gc_disable",              MAY_BE_NULL),
        F0("func_num_args",           MAY_BE_LONG),
        FN("func_get_arg",            UNKNOWN_INFO),
-       F1("func_get_args",           MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF),
+       F1("func_get_args",           MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_ANY),
        FC("strlen",                  zend_strlen_info),
        FC("strcmp",                  zend_l_ss_info),
        FC("strncmp",                 zend_lb_ssn_info),
index ee242c4253215f04c92cd23135637e0d559ab2f6..3c3a81032229eea5e80a7072741961fb9c852991 100644 (file)
@@ -1354,6 +1354,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
                        }
                        break;
                case ZEND_COUNT:
+               case ZEND_FUNC_NUM_ARGS:
                        tmp->min = 0;
                        tmp->max = ZEND_LONG_MAX;
                        return 1;
@@ -3161,8 +3162,12 @@ 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:
+               case ZEND_FUNC_NUM_ARGS:
                        UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_ops[i].result_def);
                        break;
+               case ZEND_FUNC_GET_ARGS:
+                       UPDATE_SSA_TYPE(MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_ANY, ssa_ops[i].result_def);
+                       break;
                case ZEND_GET_CLASS:
                case ZEND_GET_CALLED_CLASS:
                        UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_STRING, ssa_ops[i].result_def);