]> granicus.if.org Git - php/commitdiff
Support computing func info from ret arg info for internal funcs
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 3 Sep 2019 08:32:47 +0000 (10:32 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 3 Sep 2019 08:32:47 +0000 (10:32 +0200)
ext/opcache/Optimizer/zend_func_info.c
ext/opcache/Optimizer/zend_inference.c
ext/opcache/Optimizer/zend_inference.h

index 9a34e855e3c59eebf7a86eb035a83d81340609a2..936b46c96432a671cbe101159b40ff39e52e4847 100644 (file)
@@ -1473,11 +1473,11 @@ uint32_t zend_get_func_info(const zend_call_info *call_info, const zend_ssa *ssa
 
        if (callee_func->type == ZEND_INTERNAL_FUNCTION) {
                zval *zv;
-               func_info_t *info;
+               zend_string *lcname = Z_STR_P(CRT_CONSTANT_EX(call_info->caller_op_array, call_info->caller_init_opline, call_info->caller_init_opline->op2, ssa->rt_constants));
 
-               zv = zend_hash_find_ex(&func_info, Z_STR_P(CRT_CONSTANT_EX(call_info->caller_op_array, call_info->caller_init_opline, call_info->caller_init_opline->op2, ssa->rt_constants)), 1);
+               zv = zend_hash_find_ex(&func_info, lcname, 1);
                if (zv) {
-                       info = Z_PTR_P(zv);
+                       func_info_t *info = Z_PTR_P(zv);
                        if (UNEXPECTED(zend_optimizer_is_disabled_func(info->name, info->name_len))) {
                                ret = MAY_BE_NULL;
                        } else if (info->info_func) {
@@ -1485,10 +1485,21 @@ uint32_t zend_get_func_info(const zend_call_info *call_info, const zend_ssa *ssa
                        } else {
                                ret = info->info;
                        }
-#if 0
+                       return ret;
+               }
+
+               if (callee_func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
+                       zend_class_entry *ce; // TODO: Use the CE.
+                       ret = zend_fetch_arg_info_type(NULL, callee_func->common.arg_info - 1, &ce);
                } else {
+#if 0
                        fprintf(stderr, "Unknown internal function '%s'\n", func->common.function_name);
 #endif
+                       ret = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
+                               | MAY_BE_RC1 | MAY_BE_RCN;
+               }
+               if (callee_func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+                       ret |= MAY_BE_REF;
                }
        } else {
                // FIXME: the order of functions matters!!!
@@ -1496,15 +1507,14 @@ uint32_t zend_get_func_info(const zend_call_info *call_info, const zend_ssa *ssa
                if (info) {
                        ret = info->return_info.type;
                }
-       }
-       if (!ret) {
-               ret = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
-               if (callee_func->common.fn_flags & ZEND_ACC_GENERATOR) {
-                       ret = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
-               } else  if (callee_func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
-                       ret |= MAY_BE_REF;
-               } else {
-                       ret |= MAY_BE_RC1 | MAY_BE_RCN;
+               if (!ret) {
+                       ret = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
+                               | MAY_BE_RC1 | MAY_BE_RCN;
+                       /* For generators RETURN_REFERENCE refers to the yielded values. */
+                       if ((callee_func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                                       && !(callee_func->common.fn_flags & ZEND_ACC_GENERATOR)) {
+                               ret |= MAY_BE_REF;
+                       }
                }
        }
        return ret;
index 8e2c27890ecb067eb7abe091e0966c14b4cff307..da4f0846ef57112caaeddbe03bff05ad99589d5d 100644 (file)
@@ -2250,7 +2250,7 @@ static uint32_t zend_convert_type_code_to_may_be(zend_uchar type_code) {
        }
 }
 
-static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
+uint32_t zend_fetch_arg_info_type(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
 {
        uint32_t tmp = 0;
 
@@ -2269,6 +2269,9 @@ static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *ar
        if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
                tmp |= MAY_BE_NULL;
        }
+       if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
+               tmp |= MAY_BE_RC1 | MAY_BE_RCN;
+       }
        return tmp;
 }
 
@@ -3100,7 +3103,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
 
                        ce = NULL;
                        if (arg_info) {
-                               tmp = zend_fetch_arg_info(script, arg_info, &ce);
+                               tmp = zend_fetch_arg_info_type(script, arg_info, &ce);
                                if (opline->opcode == ZEND_RECV_INIT &&
                                           Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)) == IS_CONSTANT_AST) {
                                        /* The constant may resolve to NULL */
@@ -3108,8 +3111,6 @@ static int zend_update_type_info(const zend_op_array *op_array,
                                }
                                if (arg_info->pass_by_reference) {
                                        tmp |= MAY_BE_REF;
-                               } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
-                                       tmp |= MAY_BE_RC1|MAY_BE_RCN;
                                }
                        } else {
                                tmp = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
@@ -3613,11 +3614,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
                                ce = NULL;
                        } else {
                                zend_arg_info *ret_info = op_array->arg_info - 1;
-
-                               tmp = zend_fetch_arg_info(script, ret_info, &ce);
-                               if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
-                                       tmp |= MAY_BE_RC1 | MAY_BE_RCN;
-                               }
+                               tmp = zend_fetch_arg_info_type(script, ret_info, &ce);
                        }
                        if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) {
                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
@@ -4044,11 +4041,9 @@ void zend_init_func_return_info(const zend_op_array   *op_array,
                zend_arg_info *ret_info = op_array->arg_info - 1;
                zend_ssa_range tmp_range = {0, 0, 0, 0};
 
-               ret->type = zend_fetch_arg_info(script, ret_info, &ret->ce);
+               ret->type = zend_fetch_arg_info_type(script, ret_info, &ret->ce);
                if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                        ret->type |= MAY_BE_REF;
-               } else if (ret->type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
-                       ret->type |= MAY_BE_RC1|MAY_BE_RCN;
                }
                ret->is_instanceof = (ret->ce) ? 1 : 0;
                ret->range = tmp_range;
index ec98fcbef9f8d9c2a4d405863b2c75bb9d9fc2a2..03cbb5e82b627ce938037d87df659691f34c760d 100644 (file)
@@ -263,6 +263,8 @@ void zend_inference_check_recursive_dependencies(zend_op_array *op_array);
 
 int  zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist, zend_long optimization_level);
 
+uint32_t zend_fetch_arg_info_type(
+       const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce);
 void zend_init_func_return_info(const zend_op_array   *op_array,
                                 const zend_script     *script,
                                 zend_ssa_var_info     *ret);