@@ -1095,24 +1095,62 @@ static void zend_jit_allocate_registers(zend_jit_ctx *ctx, const zend_op_array *
10951095
10961096 /* Remove intervals used once */
10971097 for (i = 0 ; i < ssa -> vars_count ; i ++ ) {
1098- if (ra [i ].ref &&
1099- (ra [i ].flags & ZREG_LOAD ) &&
1100- (ra [i ].flags & ZREG_STORE ) &&
1101- (ssa -> vars [i ].use_chain < 0 ||
1102- zend_ssa_next_use (ssa -> ops , i , ssa -> vars [i ].use_chain ) < 0 )) {
1103- bool may_remove = 1 ;
1104- zend_ssa_phi * phi = ssa -> vars [i ].phi_use_chain ;
1105-
1106- while (phi ) {
1107- if (ra [phi -> ssa_var ].ref &&
1108- !(ra [phi -> ssa_var ].flags & ZREG_LOAD )) {
1109- may_remove = 0 ;
1110- break ;
1098+ if (ra [i ].ref ) {
1099+ if (!(ra [i ].flags & (ZREG_LOAD |ZREG_STORE ))) {
1100+ uint32_t var_num = ssa -> vars [i ].var ;
1101+ uint32_t op_num = ssa -> vars [i ].definition ;
1102+
1103+ /* Check if a tempoary variable may be freed by exception handler */
1104+ if (op_array -> last_live_range
1105+ && var_num >= op_array -> last_var
1106+ && ssa -> vars [i ].definition >= 0
1107+ && ssa -> ops [op_num ].result_def == i ) {
1108+ const zend_live_range * range = op_array -> live_range ;
1109+ int j ;
1110+
1111+ op_num ++ ;
1112+ if (op_array -> opcodes [op_num ].opcode == ZEND_OP_DATA ) {
1113+ op_num ++ ;
1114+ }
1115+ for (j = 0 ; j < op_array -> last_live_range ; range ++ , j ++ ) {
1116+ if (range -> start > op_num ) {
1117+ /* further blocks will not be relevant... */
1118+ break ;
1119+ } else if (op_num < range -> end && var_num == (range -> var & ~ZEND_LIVE_MASK )) {
1120+ /* check if opcodes in range may throw */
1121+ do {
1122+ if (zend_may_throw (op_array -> opcodes + op_num , ssa -> ops + op_num , op_array , ssa )) {
1123+ ra [i ].flags |= ZREG_STORE ;
1124+ break ;
1125+ }
1126+ op_num ++ ;
1127+ if (op_array -> opcodes [op_num ].opcode == ZEND_OP_DATA ) {
1128+ op_num ++ ;
1129+ }
1130+ } while (op_num < range -> end );
1131+ break ;
1132+ }
1133+ }
11111134 }
1112- phi = zend_ssa_next_use_phi (ssa , i , phi );
11131135 }
1114- if (may_remove ) {
1115- ra [i ].ref = IR_UNUSED ;
1136+ if ((ra [i ].flags & ZREG_LOAD )
1137+ && (ra [i ].flags & ZREG_STORE )
1138+ && (ssa -> vars [i ].use_chain < 0
1139+ || zend_ssa_next_use (ssa -> ops , i , ssa -> vars [i ].use_chain ) < 0 )) {
1140+ bool may_remove = 1 ;
1141+ zend_ssa_phi * phi = ssa -> vars [i ].phi_use_chain ;
1142+
1143+ while (phi ) {
1144+ if (ra [phi -> ssa_var ].ref &&
1145+ !(ra [phi -> ssa_var ].flags & ZREG_LOAD )) {
1146+ may_remove = 0 ;
1147+ break ;
1148+ }
1149+ phi = zend_ssa_next_use_phi (ssa , i , phi );
1150+ }
1151+ if (may_remove ) {
1152+ ra [i ].ref = IR_UNUSED ;
1153+ }
11161154 }
11171155 }
11181156 }
0 commit comments