Skip to content

Commit 597a5da

Browse files
committed
Support computing func info from ret arg info for internal funcs
1 parent 3cca014 commit 597a5da

File tree

3 files changed

+32
-25
lines changed

3 files changed

+32
-25
lines changed

ext/opcache/Optimizer/zend_func_info.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,38 +1473,48 @@ uint32_t zend_get_func_info(const zend_call_info *call_info, const zend_ssa *ssa
14731473

14741474
if (callee_func->type == ZEND_INTERNAL_FUNCTION) {
14751475
zval *zv;
1476-
func_info_t *info;
1476+
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));
14771477

1478-
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);
1478+
zv = zend_hash_find_ex(&func_info, lcname, 1);
14791479
if (zv) {
1480-
info = Z_PTR_P(zv);
1480+
func_info_t *info = Z_PTR_P(zv);
14811481
if (UNEXPECTED(zend_optimizer_is_disabled_func(info->name, info->name_len))) {
14821482
ret = MAY_BE_NULL;
14831483
} else if (info->info_func) {
14841484
ret = info->info_func(call_info, ssa);
14851485
} else {
14861486
ret = info->info;
14871487
}
1488-
#if 0
1488+
return ret;
1489+
}
1490+
1491+
if (callee_func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1492+
zend_class_entry *ce; // TODO: Use the CE.
1493+
ret = zend_fetch_arg_info_type(NULL, callee_func->common.arg_info - 1, &ce);
14891494
} else {
1495+
#if 0
14901496
fprintf(stderr, "Unknown internal function '%s'\n", func->common.function_name);
14911497
#endif
1498+
ret = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
1499+
| MAY_BE_RC1 | MAY_BE_RCN;
1500+
}
1501+
if (callee_func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
1502+
ret |= MAY_BE_REF;
14921503
}
14931504
} else {
14941505
// FIXME: the order of functions matters!!!
14951506
zend_func_info *info = ZEND_FUNC_INFO((zend_op_array*)callee_func);
14961507
if (info) {
14971508
ret = info->return_info.type;
14981509
}
1499-
}
1500-
if (!ret) {
1501-
ret = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
1502-
if (callee_func->common.fn_flags & ZEND_ACC_GENERATOR) {
1503-
ret = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
1504-
} else if (callee_func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
1505-
ret |= MAY_BE_REF;
1506-
} else {
1507-
ret |= MAY_BE_RC1 | MAY_BE_RCN;
1510+
if (!ret) {
1511+
ret = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
1512+
| MAY_BE_RC1 | MAY_BE_RCN;
1513+
/* For generators RETURN_REFERENCE refers to the yielded values. */
1514+
if ((callee_func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
1515+
&& !(callee_func->common.fn_flags & ZEND_ACC_GENERATOR)) {
1516+
ret |= MAY_BE_REF;
1517+
}
15081518
}
15091519
}
15101520
return ret;

ext/opcache/Optimizer/zend_inference.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,7 +2250,7 @@ static uint32_t zend_convert_type_code_to_may_be(zend_uchar type_code) {
22502250
}
22512251
}
22522252

2253-
static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
2253+
uint32_t zend_fetch_arg_info_type(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
22542254
{
22552255
uint32_t tmp = 0;
22562256

@@ -2269,6 +2269,9 @@ static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *ar
22692269
if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
22702270
tmp |= MAY_BE_NULL;
22712271
}
2272+
if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
2273+
tmp |= MAY_BE_RC1 | MAY_BE_RCN;
2274+
}
22722275
return tmp;
22732276
}
22742277

@@ -3100,16 +3103,14 @@ static int zend_update_type_info(const zend_op_array *op_array,
31003103

31013104
ce = NULL;
31023105
if (arg_info) {
3103-
tmp = zend_fetch_arg_info(script, arg_info, &ce);
3106+
tmp = zend_fetch_arg_info_type(script, arg_info, &ce);
31043107
if (opline->opcode == ZEND_RECV_INIT &&
31053108
Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)) == IS_CONSTANT_AST) {
31063109
/* The constant may resolve to NULL */
31073110
tmp |= MAY_BE_NULL;
31083111
}
31093112
if (arg_info->pass_by_reference) {
31103113
tmp |= MAY_BE_REF;
3111-
} else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
3112-
tmp |= MAY_BE_RC1|MAY_BE_RCN;
31133114
}
31143115
} else {
31153116
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,
36133614
ce = NULL;
36143615
} else {
36153616
zend_arg_info *ret_info = op_array->arg_info - 1;
3616-
3617-
tmp = zend_fetch_arg_info(script, ret_info, &ce);
3618-
if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
3619-
tmp |= MAY_BE_RC1 | MAY_BE_RCN;
3620-
}
3617+
tmp = zend_fetch_arg_info_type(script, ret_info, &ce);
36213618
}
36223619
if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) {
36233620
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,
40444041
zend_arg_info *ret_info = op_array->arg_info - 1;
40454042
zend_ssa_range tmp_range = {0, 0, 0, 0};
40464043

4047-
ret->type = zend_fetch_arg_info(script, ret_info, &ret->ce);
4044+
ret->type = zend_fetch_arg_info_type(script, ret_info, &ret->ce);
40484045
if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
40494046
ret->type |= MAY_BE_REF;
4050-
} else if (ret->type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
4051-
ret->type |= MAY_BE_RC1|MAY_BE_RCN;
40524047
}
40534048
ret->is_instanceof = (ret->ce) ? 1 : 0;
40544049
ret->range = tmp_range;

ext/opcache/Optimizer/zend_inference.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ void zend_inference_check_recursive_dependencies(zend_op_array *op_array);
263263

264264
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);
265265

266+
uint32_t zend_fetch_arg_info_type(
267+
const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce);
266268
void zend_init_func_return_info(const zend_op_array *op_array,
267269
const zend_script *script,
268270
zend_ssa_var_info *ret);

0 commit comments

Comments
 (0)