@@ -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+
19612035static 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 ;
0 commit comments