Skip to content

Commit 461d023

Browse files
committed
Avoid repeatable checks for $this.
1 parent 5d9e0f7 commit 461d023

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,80 @@ static zend_lifetime_interval** zend_jit_allocate_registers(zend_op_array *op_ar
19581958
return NULL;
19591959
}
19601960

1961+
static void zend_calc_checked_this_r(zend_bitset checked_this, zend_op_array *op_array, zend_cfg *cfg, int b, int checked)
1962+
{
1963+
zend_op *opline = &op_array->opcodes[cfg->blocks[b].start];
1964+
zend_op *end = opline + cfg->blocks[b].len;
1965+
int old_checked = checked;
1966+
int i;
1967+
1968+
for (; opline < end; opline++) {
1969+
switch (opline->opcode) {
1970+
case ZEND_ASSIGN_ADD:
1971+
case ZEND_ASSIGN_SUB:
1972+
case ZEND_ASSIGN_MUL:
1973+
case ZEND_ASSIGN_DIV:
1974+
case ZEND_ASSIGN_MOD:
1975+
case ZEND_ASSIGN_SL:
1976+
case ZEND_ASSIGN_SR:
1977+
case ZEND_ASSIGN_CONCAT:
1978+
case ZEND_ASSIGN_BW_OR:
1979+
case ZEND_ASSIGN_BW_AND:
1980+
case ZEND_ASSIGN_BW_XOR:
1981+
case ZEND_ASSIGN_POW:
1982+
if (opline->extended_value != ZEND_ASSIGN_OBJ) {
1983+
break;
1984+
}
1985+
case ZEND_PRE_INC_OBJ:
1986+
case ZEND_PRE_DEC_OBJ:
1987+
case ZEND_POST_INC_OBJ:
1988+
case ZEND_POST_DEC_OBJ:
1989+
case ZEND_FETCH_OBJ_R:
1990+
case ZEND_FETCH_OBJ_W:
1991+
case ZEND_FETCH_OBJ_RW:
1992+
case ZEND_FETCH_OBJ_IS:
1993+
case ZEND_FETCH_OBJ_FUNC_ARG:
1994+
case ZEND_FETCH_OBJ_UNSET:
1995+
case ZEND_ASSIGN_OBJ:
1996+
case ZEND_INIT_METHOD_CALL:
1997+
case ZEND_CLONE:
1998+
case ZEND_UNSET_OBJ:
1999+
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
2000+
if (opline->op1_type != IS_UNUSED) {
2001+
break;
2002+
}
2003+
case ZEND_FETCH_THIS:
2004+
if (checked) {
2005+
zend_bitset_incl(checked_this, (opline - op_array->opcodes));
2006+
} else {
2007+
checked = 1;
2008+
}
2009+
break;
2010+
default:
2011+
break;
2012+
}
2013+
opline++;
2014+
}
2015+
2016+
if (cfg->blocks[b].flags && ZEND_BB_TRY) {
2017+
checked = old_checked;
2018+
}
2019+
2020+
for (i = cfg->blocks[b].children; i >= 0; i = cfg->blocks[i].next_child) {
2021+
zend_calc_checked_this_r(checked_this, op_array, cfg, i, checked);
2022+
}
2023+
}
2024+
2025+
static zend_bitset zend_calc_checked_this(zend_arena **arena, zend_op_array *op_array, zend_cfg *cfg)
2026+
{
2027+
uint32_t bitset_len = zend_bitset_len(op_array->last);
2028+
zend_bitset checked_this = zend_arena_calloc(arena, bitset_len, ZEND_BITSET_ELM_SIZE);
2029+
2030+
zend_calc_checked_this_r(checked_this, op_array, cfg, 0, 0);
2031+
2032+
return checked_this;
2033+
}
2034+
19612035
static int zend_jit(zend_op_array *op_array, zend_ssa *ssa, const zend_op *rt_opline)
19622036
{
19632037
int b, i, end;
@@ -1967,6 +2041,7 @@ static int zend_jit(zend_op_array *op_array, zend_ssa *ssa, const zend_op *rt_op
19672041
int call_level = 0;
19682042
void *checkpoint = NULL;
19692043
zend_lifetime_interval **ra = NULL;
2044+
zend_bitset checked_this = NULL;
19702045

19712046
if (zend_jit_reg_alloc) {
19722047
checkpoint = zend_arena_checkpoint(CG(arena));
@@ -2316,7 +2391,10 @@ static int zend_jit(zend_op_array *op_array, zend_ssa *ssa, const zend_op *rt_op
23162391
goto done;
23172392
case ZEND_FETCH_OBJ_R:
23182393
case ZEND_FETCH_OBJ_IS:
2319-
if (!zend_jit_fetch_obj_read(&dasm_state, opline, op_array, ssa)) {
2394+
if (opline->op1_type == IS_UNUSED && !checked_this) {
2395+
checked_this = zend_calc_checked_this(&CG(arena), op_array, &ssa->cfg);
2396+
}
2397+
if (!zend_jit_fetch_obj_read(&dasm_state, opline, op_array, ssa, checked_this)) {
23202398
goto jit_failure;
23212399
}
23222400
goto done;

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9231,7 +9231,7 @@ static zend_bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string
92319231
return 0;
92329232
}
92339233

9234-
static int zend_jit_fetch_obj_read(dasm_State **Dst, zend_op *opline, zend_op_array *op_array, zend_ssa *ssa)
9234+
static int zend_jit_fetch_obj_read(dasm_State **Dst, zend_op *opline, zend_op_array *op_array, zend_ssa *ssa, zend_bitset checked_this)
92359235
{
92369236
uint32_t op1_info;
92379237
zend_class_entry *ce = NULL;
@@ -9274,12 +9274,14 @@ static int zend_jit_fetch_obj_read(dasm_State **Dst, zend_op *opline, zend_op_ar
92749274
offset = zend_get_known_property_offset(ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array->filename);
92759275

92769276
if (opline->op1_type == IS_UNUSED) {
9277-
| IF_ZVAL_TYPE this_addr, IS_UNDEF, >1
9278-
|.cold_code
9279-
|1:
9280-
| SAVE_VALID_OPLINE opline
9281-
| jmp ->not_obj
9282-
|.code
9277+
if (!checked_this || !zend_bitset_in(checked_this, (opline - op_array->opcodes))) {
9278+
| IF_ZVAL_TYPE this_addr, IS_UNDEF, >1
9279+
|.cold_code
9280+
|1:
9281+
| SAVE_VALID_OPLINE opline
9282+
| jmp ->not_obj
9283+
|.code
9284+
}
92839285
| GET_ZVAL_PTR FCARG1a, this_addr
92849286
} else {
92859287
if (op1_info & MAY_BE_REF) {

0 commit comments

Comments
 (0)