Skip to content

Commit ab5f8f4

Browse files
committed
More accurate reference-counter inference (with support for ext/intl/tests/bug72241.phpt)
1 parent 15c265b commit ab5f8f4

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

ext/opcache/Optimizer/zend_inference.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,7 +1952,7 @@ static void emit_type_narrowing_warning(const zend_op_array *op_array, zend_ssa
19521952
zend_error(E_WARNING, "Narrowing occurred during type inference of %s. Please file a bug report on bugs.php.net", def_op_name);
19531953
}
19541954

1955-
uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
1955+
uint32_t zend_array_element_type(uint32_t t1, zend_uchar op_type, int write, int insert)
19561956
{
19571957
uint32_t tmp = 0;
19581958

@@ -1972,15 +1972,18 @@ uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
19721972
if (tmp & MAY_BE_ARRAY) {
19731973
tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
19741974
}
1975-
if (t1 & MAY_BE_ARRAY_OF_REF) {
1975+
if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
19761976
if (!write) {
19771977
/* can't be REF because of ZVAL_COPY_DEREF() usage */
1978-
tmp |= MAY_BE_RC1 | MAY_BE_RCN;
1979-
} else {
1978+
tmp |= MAY_BE_RCN;
1979+
if ((op_type & (IS_VAR|IS_TMP_VAR)) && (t1 & MAY_BE_RC1)) {
1980+
tmp |= MAY_BE_RC1;
1981+
}
1982+
} else if (t1 & MAY_BE_ARRAY_OF_REF) {
19801983
tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
1984+
} else {
1985+
tmp |= MAY_BE_RC1 | MAY_BE_RCN;
19811986
}
1982-
} else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
1983-
tmp |= MAY_BE_RC1 | MAY_BE_RCN;
19841987
}
19851988
}
19861989
if (write) {
@@ -2513,7 +2516,7 @@ static zend_always_inline int _zend_update_type_info(
25132516
tmp |= MAY_BE_REF;
25142517
}
25152518
orig = t1;
2516-
t1 = zend_array_element_type(t1, 1, 0);
2519+
t1 = zend_array_element_type(t1, opline->op1_type, 1, 0);
25172520
t2 = OP1_DATA_INFO();
25182521
} else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
25192522
prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline);
@@ -3380,6 +3383,7 @@ static zend_always_inline int _zend_update_type_info(
33803383
/* FETCH_LIST on a string behaves like FETCH_R on null */
33813384
tmp = zend_array_element_type(
33823385
opline->opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
3386+
opline->op1_type,
33833387
opline->result_type == IS_VAR,
33843388
opline->op2_type == IS_UNUSED);
33853389
if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) {

ext/opcache/Optimizer/zend_inference.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ss
249249
int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa);
250250
int zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level);
251251

252-
uint32_t zend_array_element_type(uint32_t t1, int write, int insert);
252+
uint32_t zend_array_element_type(uint32_t t1, zend_uchar op_type, int write, int insert);
253253

254254
int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp);
255255
void zend_inference_init_range(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_bool underflow, zend_long min, zend_long max, zend_bool overflow);

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5558,7 +5558,7 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, const ze
55585558
return 0;
55595559
}
55605560
} else {
5561-
uint32_t var_info = zend_array_element_type(op1_info, 0, 0);
5561+
uint32_t var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0);
55625562
zend_jit_addr var_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0);
55635563

55645564
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_VAR_W, op1_info, op2_info, 8, 8, NULL, NULL)) {
@@ -5571,6 +5571,9 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, const ze
55715571
if (op1_info & (MAY_BE_ARRAY_OF_REF|MAY_BE_OBJECT)) {
55725572
var_info |= MAY_BE_REF;
55735573
}
5574+
if (var_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
5575+
var_info |= MAY_BE_RC1;
5576+
}
55745577
| // value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE);
55755578
if (!zend_jit_assign_to_variable(Dst, opline, op_array, var_addr, var_info, -1, (opline+1)->op1_type, (opline+1)->op1, op3_addr, val_info, res_addr, 0)) {
55765579
return 0;
@@ -5756,7 +5759,7 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, const
57565759

57575760
if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_ARRAY)) {
57585761
uint32_t var_info;
5759-
uint32_t var_def_info = zend_array_element_type(op1_def_info, 1, 0);
5762+
uint32_t var_def_info = zend_array_element_type(op1_def_info, opline->op1_type, 1, 0);
57605763

57615764
|6:
57625765
if (opline->op2_type == IS_UNUSED) {
@@ -5777,10 +5780,13 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, const
57775780
|.code
57785781
| mov FCARG1a, r0
57795782
} else {
5780-
var_info = zend_array_element_type(op1_info, 0, 0);
5783+
var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0);
57815784
if (op1_info & (MAY_BE_ARRAY_OF_REF|MAY_BE_OBJECT)) {
57825785
var_info |= MAY_BE_REF;
57835786
}
5787+
if (var_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
5788+
var_info |= MAY_BE_RC1;
5789+
}
57845790

57855791
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_VAR_RW, op1_info, op2_info, 8, 8, NULL, NULL)) {
57865792
return 0;
@@ -11132,7 +11138,8 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen
1113211138
|9: // END
1113311139
if (opline->op1_type != IS_UNUSED && !use_this && !op1_indirect) {
1113411140
if (opline->op1_type == IS_VAR
11135-
&& opline->opcode == ZEND_FETCH_OBJ_W) {
11141+
&& opline->opcode == ZEND_FETCH_OBJ_W
11142+
&& (op1_info & MAY_BE_RC1)) {
1113611143
zend_jit_addr orig_op1_addr = OP1_ADDR();
1113711144

1113811145
| IF_NOT_ZVAL_REFCOUNTED orig_op1_addr, >1

0 commit comments

Comments
 (0)