@@ -291,34 +291,41 @@ static bool safe_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
291
291
}
292
292
293
293
static inline bool can_elide_return_type_check (
294
- zend_op_array * op_array , zend_ssa * ssa , zend_ssa_op * ssa_op ) {
295
- zend_arg_info * info = & op_array -> arg_info [-1 ];
294
+ const zend_script * script , zend_op_array * op_array , zend_ssa * ssa , zend_ssa_op * ssa_op ) {
295
+ zend_arg_info * arg_info = & op_array -> arg_info [-1 ];
296
296
zend_ssa_var_info * use_info = & ssa -> var_info [ssa_op -> op1_use ];
297
- zend_ssa_var_info * def_info = & ssa -> var_info [ssa_op -> op1_def ];
298
-
299
- /* TODO: It would be better to rewrite this without using def_info,
300
- * which may not be an exact representation of the type. */
301
- if (use_info -> type & MAY_BE_REF ) {
297
+ uint32_t use_type = use_info -> type & (MAY_BE_ANY |MAY_BE_UNDEF );
298
+ if (use_type & MAY_BE_REF ) {
302
299
return 0 ;
303
300
}
304
301
305
- /* A type is possible that is not in the allowed types */
306
- if (( use_info -> type & ( MAY_BE_ANY | MAY_BE_UNDEF )) & ~( def_info -> type & MAY_BE_ANY )) {
307
- return 0 ;
302
+ if ( use_type & MAY_BE_UNDEF ) {
303
+ use_type &= ~ MAY_BE_UNDEF ;
304
+ use_type |= MAY_BE_NULL ;
308
305
}
309
306
310
- /* These types are not represented exactly */
311
- if (ZEND_TYPE_FULL_MASK (info -> type ) & (MAY_BE_CALLABLE |MAY_BE_ITERABLE |MAY_BE_STATIC )) {
312
- return 0 ;
307
+ uint32_t disallowed_types = use_type & ~ZEND_TYPE_PURE_MASK (arg_info -> type );
308
+ if (!disallowed_types ) {
309
+ /* Only contains allowed types. */
310
+ return true;
313
311
}
314
312
315
- if (ZEND_TYPE_HAS_CLASS (info -> type )) {
316
- if (!use_info -> ce || !def_info -> ce || !safe_instanceof (use_info -> ce , def_info -> ce )) {
317
- return 0 ;
318
- }
313
+ if (disallowed_types == MAY_BE_OBJECT && use_info -> ce && ZEND_TYPE_HAS_CLASS (arg_info -> type )) {
314
+ zend_type * single_type ;
315
+ ZEND_TYPE_FOREACH (arg_info -> type , single_type ) {
316
+ if (ZEND_TYPE_HAS_NAME (* single_type )) {
317
+ zend_string * lcname = zend_string_tolower (ZEND_TYPE_NAME (* single_type ));
318
+ zend_class_entry * ce = zend_optimizer_get_class_entry (script , lcname );
319
+ zend_string_release (lcname );
320
+ if (ce && safe_instanceof (use_info -> ce , ce )) {
321
+ /* One of the class union types matched. */
322
+ return true;
323
+ }
324
+ }
325
+ } ZEND_TYPE_FOREACH_END ();
319
326
}
320
327
321
- return 1 ;
328
+ return false ;
322
329
}
323
330
324
331
static bool opline_supports_assign_contraction (
@@ -1235,7 +1242,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
1235
1242
&& ssa -> ops [op_1 ].op1_def == v
1236
1243
&& ssa -> ops [op_1 ].op1_use >= 0
1237
1244
&& ssa -> ops [op_1 ].op1_use_chain == -1
1238
- && can_elide_return_type_check (op_array , ssa , & ssa -> ops [op_1 ])) {
1245
+ && can_elide_return_type_check (ctx -> script , op_array , ssa , & ssa -> ops [op_1 ])) {
1239
1246
1240
1247
// op_1: VERIFY_RETURN_TYPE #orig_var.? [T] -> #v.? [T] => NOP
1241
1248
0 commit comments