73
73
#endif
74
74
75
75
typedef struct _sccp_ctx {
76
- zend_op_array * op_array ;
77
- zend_ssa * ssa ;
76
+ scdf_ctx scdf ;
78
77
zend_call_info * * call_map ;
79
78
zval * values ;
80
79
zval top ;
@@ -121,7 +120,7 @@ static void set_value(scdf_ctx *scdf, sccp_ctx *ctx, int var, zval *new) {
121
120
122
121
static zval * get_op1_value (sccp_ctx * ctx , zend_op * opline , zend_ssa_op * ssa_op ) {
123
122
if (opline -> op1_type == IS_CONST ) {
124
- return CT_CONSTANT_EX (ctx -> op_array , opline -> op1 .constant );
123
+ return CT_CONSTANT_EX (ctx -> scdf . op_array , opline -> op1 .constant );
125
124
} else if (ssa_op -> op1_use != -1 ) {
126
125
return & ctx -> values [ssa_op -> op1_use ];
127
126
} else {
@@ -131,7 +130,7 @@ static zval *get_op1_value(sccp_ctx *ctx, zend_op *opline, zend_ssa_op *ssa_op)
131
130
132
131
static zval * get_op2_value (sccp_ctx * ctx , zend_op * opline , zend_ssa_op * ssa_op ) {
133
132
if (opline -> op2_type == IS_CONST ) {
134
- return CT_CONSTANT_EX (ctx -> op_array , opline -> op2 .constant );
133
+ return CT_CONSTANT_EX (ctx -> scdf . op_array , opline -> op2 .constant );
135
134
} else if (ssa_op -> op2_use != -1 ) {
136
135
return & ctx -> values [ssa_op -> op2_use ];
137
136
} else {
@@ -233,10 +232,10 @@ static zend_bool can_replace_op2(
233
232
234
233
static zend_bool try_replace_op1 (
235
234
sccp_ctx * ctx , zend_op * opline , zend_ssa_op * ssa_op , int var , zval * value ) {
236
- if (ssa_op -> op1_use == var && can_replace_op1 (ctx -> op_array , opline , ssa_op )) {
235
+ if (ssa_op -> op1_use == var && can_replace_op1 (ctx -> scdf . op_array , opline , ssa_op )) {
237
236
zval zv ;
238
237
ZVAL_COPY (& zv , value );
239
- if (zend_optimizer_update_op1_const (ctx -> op_array , opline , & zv )) {
238
+ if (zend_optimizer_update_op1_const (ctx -> scdf . op_array , opline , & zv )) {
240
239
return 1 ;
241
240
} else {
242
241
// TODO: check the following special cases ???
@@ -248,7 +247,7 @@ static zend_bool try_replace_op1(
248
247
if (Z_TYPE (zv ) == IS_STRING ) {
249
248
zend_string_hash_val (Z_STR (zv ));
250
249
}
251
- opline -> op1 .constant = zend_optimizer_add_literal (ctx -> op_array , & zv );
250
+ opline -> op1 .constant = zend_optimizer_add_literal (ctx -> scdf . op_array , & zv );
252
251
opline -> op1_type = IS_CONST ;
253
252
return 1 ;
254
253
}
@@ -260,10 +259,10 @@ static zend_bool try_replace_op1(
260
259
261
260
static zend_bool try_replace_op2 (
262
261
sccp_ctx * ctx , zend_op * opline , zend_ssa_op * ssa_op , int var , zval * value ) {
263
- if (ssa_op -> op2_use == var && can_replace_op2 (ctx -> op_array , opline , ssa_op )) {
262
+ if (ssa_op -> op2_use == var && can_replace_op2 (ctx -> scdf . op_array , opline , ssa_op )) {
264
263
zval zv ;
265
264
ZVAL_COPY (& zv , value );
266
- if (zend_optimizer_update_op2_const (ctx -> op_array , opline , & zv )) {
265
+ if (zend_optimizer_update_op2_const (ctx -> scdf . op_array , opline , & zv )) {
267
266
return 1 ;
268
267
} else {
269
268
zval_ptr_dtor_nogc (& zv );
@@ -614,7 +613,7 @@ static inline int ct_eval_func_call(
614
613
#define SKIP_IF_TOP (op ) if (IS_TOP(op)) break;
615
614
616
615
static void sccp_visit_instr (scdf_ctx * scdf , zend_op * opline , zend_ssa_op * ssa_op ) {
617
- sccp_ctx * ctx = (sccp_ctx * ) scdf -> ctx ;
616
+ sccp_ctx * ctx = (sccp_ctx * ) scdf ;
618
617
zval * op1 , * op2 , zv ; /* zv is a temporary to hold result values */
619
618
620
619
op1 = get_op1_value (ctx , opline , ssa_op );
@@ -624,7 +623,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
624
623
case ZEND_ASSIGN :
625
624
/* The value of op1 is irrelevant here, because we are overwriting it
626
625
* -- unless it can be a reference, in which case we propagate a BOT. */
627
- if (IS_BOT (op1 ) && (ctx -> ssa -> var_info [ssa_op -> op1_use ].type & MAY_BE_REF )) {
626
+ if (IS_BOT (op1 ) && (ctx -> scdf . ssa -> var_info [ssa_op -> op1_use ].type & MAY_BE_REF )) {
628
627
SET_RESULT_BOT (op1 );
629
628
} else {
630
629
SET_RESULT (op1 , op2 );
@@ -636,7 +635,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
636
635
/* We may be able to evaluate TYPE_CHECK based on type inference info,
637
636
* even if we don't know the precise value. */
638
637
if (!value_known (op1 )) {
639
- uint32_t type = ctx -> ssa -> var_info [ssa_op -> op1_use ].type ;
638
+ uint32_t type = ctx -> scdf . ssa -> var_info [ssa_op -> op1_use ].type ;
640
639
uint32_t expected_type = opline -> extended_value == _IS_BOOL
641
640
? (MAY_BE_TRUE |MAY_BE_FALSE ) : (1 << opline -> extended_value );
642
641
if (!(type & expected_type ) && !(type & MAY_BE_UNDEF )) {
@@ -654,7 +653,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
654
653
break ;
655
654
case ZEND_ASSIGN_DIM :
656
655
/* If $a in $a[$b]=$c is UNDEF, treat it like NULL. There is no warning. */
657
- if ((ctx -> ssa -> var_info [ssa_op -> op1_use ].type & MAY_BE_ANY ) == 0 ) {
656
+ if ((ctx -> scdf . ssa -> var_info [ssa_op -> op1_use ].type & MAY_BE_ANY ) == 0 ) {
658
657
op1 = & EG (uninitialized_zval );
659
658
}
660
659
break ;
@@ -668,13 +667,13 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
668
667
return ;
669
668
}
670
669
671
- call = ctx -> call_map [opline - ctx -> op_array -> opcodes ];
670
+ call = ctx -> call_map [opline - ctx -> scdf . op_array -> opcodes ];
672
671
if (IS_TOP (op1 ) || !call || call -> caller_call_opline -> opcode != ZEND_DO_ICALL ) {
673
672
return ;
674
673
}
675
674
676
675
opline = call -> caller_call_opline ;
677
- ssa_op = & ctx -> ssa -> ops [opline - ctx -> op_array -> opcodes ];
676
+ ssa_op = & ctx -> scdf . ssa -> ops [opline - ctx -> scdf . op_array -> opcodes ];
678
677
break ;
679
678
}
680
679
}
@@ -983,8 +982,8 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
983
982
break ;
984
983
}
985
984
986
- call = ctx -> call_map [opline - ctx -> op_array -> opcodes ];
987
- name = CT_CONSTANT_EX (ctx -> op_array , call -> caller_init_opline -> op2 .constant );
985
+ call = ctx -> call_map [opline - ctx -> scdf . op_array -> opcodes ];
986
+ name = CT_CONSTANT_EX (ctx -> scdf . op_array , call -> caller_init_opline -> op2 .constant );
988
987
989
988
/* We already know it can't be evaluated, don't bother checking again */
990
989
if (ssa_op -> result_def < 0 || IS_BOT (& ctx -> values [ssa_op -> result_def ])) {
@@ -1005,7 +1004,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
1005
1004
}
1006
1005
1007
1006
args [i ] = get_op1_value (ctx , opline ,
1008
- & ctx -> ssa -> ops [opline - ctx -> op_array -> opcodes ]);
1007
+ & ctx -> scdf . ssa -> ops [opline - ctx -> scdf . op_array -> opcodes ]);
1009
1008
if (args [i ]) {
1010
1009
if (IS_BOT (args [i ])) {
1011
1010
SET_RESULT_BOT (result );
@@ -1056,7 +1055,7 @@ static void sccp_mark_feasible_successors(
1056
1055
scdf_ctx * scdf ,
1057
1056
int block_num , zend_basic_block * block ,
1058
1057
zend_op * opline , zend_ssa_op * ssa_op ) {
1059
- sccp_ctx * ctx = (sccp_ctx * ) scdf -> ctx ;
1058
+ sccp_ctx * ctx = (sccp_ctx * ) scdf ;
1060
1059
zval * op1 ;
1061
1060
int s ;
1062
1061
@@ -1136,8 +1135,8 @@ static void join_phi_values(zval *a, zval *b) {
1136
1135
}
1137
1136
1138
1137
static void sccp_visit_phi (scdf_ctx * scdf , zend_ssa_phi * phi ) {
1139
- sccp_ctx * ctx = (sccp_ctx * ) scdf -> ctx ;
1140
- zend_ssa * ssa = ctx -> ssa ;
1138
+ sccp_ctx * ctx = (sccp_ctx * ) scdf ;
1139
+ zend_ssa * ssa = scdf -> ssa ;
1141
1140
ZEND_ASSERT (phi -> ssa_var >= 0 );
1142
1141
if (!IS_BOT (& ctx -> values [phi -> ssa_var ])) {
1143
1142
zend_basic_block * block = & ssa -> cfg .blocks [phi -> block ];
@@ -1170,10 +1169,10 @@ static void sccp_visit_phi(scdf_ctx *scdf, zend_ssa_phi *phi) {
1170
1169
}
1171
1170
1172
1171
static zval * value_from_type_and_range (sccp_ctx * ctx , int var_num , zval * tmp ) {
1173
- zend_ssa * ssa = ctx -> ssa ;
1172
+ zend_ssa * ssa = ctx -> scdf . ssa ;
1174
1173
zend_ssa_var_info * info = & ssa -> var_info [var_num ];
1175
1174
1176
- if (ssa -> vars [var_num ].var >= ctx -> op_array -> last_var ) {
1175
+ if (ssa -> vars [var_num ].var >= ctx -> scdf . op_array -> last_var ) {
1177
1176
// TODO Non-CVs may cause issues with FREEs
1178
1177
return NULL ;
1179
1178
}
@@ -1210,8 +1209,8 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) {
1210
1209
* can be replaced, because some instructions don't accept constant operands or only accept them
1211
1210
* if they have a certain type. */
1212
1211
static int replace_constant_operands (sccp_ctx * ctx ) {
1213
- zend_ssa * ssa = ctx -> ssa ;
1214
- zend_op_array * op_array = ctx -> op_array ;
1212
+ zend_ssa * ssa = ctx -> scdf . ssa ;
1213
+ zend_op_array * op_array = ctx -> scdf . op_array ;
1215
1214
int i ;
1216
1215
zval tmp ;
1217
1216
int removed_ops ;
@@ -1352,8 +1351,6 @@ static int replace_constant_operands(sccp_ctx *ctx) {
1352
1351
static void sccp_context_init (sccp_ctx * ctx ,
1353
1352
zend_ssa * ssa , zend_op_array * op_array , zend_call_info * * call_map ) {
1354
1353
int i ;
1355
- ctx -> op_array = op_array ;
1356
- ctx -> ssa = ssa ;
1357
1354
ctx -> call_map = call_map ;
1358
1355
ctx -> values = emalloc (sizeof (zval ) * ssa -> vars_count );
1359
1356
@@ -1377,32 +1374,31 @@ static void sccp_context_init(sccp_ctx *ctx,
1377
1374
1378
1375
static void sccp_context_free (sccp_ctx * ctx ) {
1379
1376
int i ;
1380
- for (i = ctx -> op_array -> last_var ; i < ctx -> ssa -> vars_count ; ++ i ) {
1377
+ for (i = ctx -> scdf . op_array -> last_var ; i < ctx -> scdf . ssa -> vars_count ; ++ i ) {
1381
1378
zval_ptr_dtor_nogc (& ctx -> values [i ]);
1382
1379
}
1383
1380
efree (ctx -> values );
1384
1381
}
1385
1382
1386
1383
int sccp_optimize_op_array (zend_op_array * op_array , zend_ssa * ssa , zend_call_info * * call_map )
1387
1384
{
1388
- scdf_ctx scdf ;
1389
1385
sccp_ctx ctx ;
1390
1386
int removed_ops = 0 ;
1391
1387
1392
1388
sccp_context_init (& ctx , ssa , op_array , call_map );
1393
1389
1394
- scdf .handlers .visit_instr = sccp_visit_instr ;
1395
- scdf .handlers .visit_phi = sccp_visit_phi ;
1396
- scdf .handlers .mark_feasible_successors = sccp_mark_feasible_successors ;
1390
+ ctx . scdf .handlers .visit_instr = sccp_visit_instr ;
1391
+ ctx . scdf .handlers .visit_phi = sccp_visit_phi ;
1392
+ ctx . scdf .handlers .mark_feasible_successors = sccp_mark_feasible_successors ;
1397
1393
1398
- scdf_init (& scdf , op_array , ssa , & ctx );
1399
- scdf_solve (& scdf , "SCCP" );
1394
+ scdf_init (& ctx . scdf , op_array , ssa );
1395
+ scdf_solve (& ctx . scdf , "SCCP" );
1400
1396
1401
- removed_ops += scdf_remove_unreachable_blocks (& scdf );
1397
+ removed_ops += scdf_remove_unreachable_blocks (& ctx . scdf );
1402
1398
removed_ops += replace_constant_operands (& ctx );
1403
1399
1404
- scdf_free (& scdf );
1405
1400
sccp_context_free (& ctx );
1401
+ scdf_free (& ctx .scdf );
1406
1402
1407
1403
return removed_ops ;
1408
1404
}
0 commit comments