Skip to content

Commit 3ed6985

Browse files
committed
drop compile-time $this return elision in favour of the optimizer
1 parent 15b87fd commit 3ed6985

11 files changed

Lines changed: 96 additions & 109 deletions

Zend/Optimizer/dfa_pass.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,16 @@ static inline bool can_elide_list_type(
342342
return is_intersection;
343343
}
344344

345+
/* Whether the SSA variable is the result of a ZEND_FETCH_THIS, i.e. is $this. */
346+
static bool zend_ssa_var_is_this(const zend_op_array *op_array, const zend_ssa *ssa, int var) {
347+
if (var < 0) {
348+
return false;
349+
}
350+
351+
int def = ssa->vars[var].definition;
352+
return def >= 0 && op_array->opcodes[def].opcode == ZEND_FETCH_THIS;
353+
}
354+
345355
static inline bool can_elide_return_type_check(
346356
const zend_script *script, zend_op_array *op_array, zend_ssa *ssa, zend_ssa_op *ssa_op) {
347357
zend_arg_info *arg_info = &op_array->arg_info[-1];
@@ -362,6 +372,16 @@ static inline bool can_elide_return_type_check(
362372
return true;
363373
}
364374

375+
/* A `static` return type only accepts the late-static-bound class. Returning
376+
* $this always satisfies it, since $this is by definition an instance of
377+
* `static`. Closures are excluded as they may be rebound to another scope. */
378+
if (disallowed_types == MAY_BE_OBJECT
379+
&& (ZEND_TYPE_PURE_MASK(arg_info->type) & MAY_BE_STATIC)
380+
&& !(op_array->fn_flags & ZEND_ACC_CLOSURE)
381+
&& zend_ssa_var_is_this(op_array, ssa, ssa_op->op1_use)) {
382+
return true;
383+
}
384+
365385
if (disallowed_types == MAY_BE_OBJECT && use_info->ce && ZEND_TYPE_IS_COMPLEX(arg_info->type)) {
366386
return can_elide_list_type(script, op_array, use_info, arg_info->type);
367387
}

Zend/zend_compile.c

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,58 +2642,6 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr, uint32_t t
26422642
}
26432643
/* }}} */
26442644

2645-
static bool zend_is_this_instance_of_name(const zend_string *type_name)
2646-
{
2647-
if (zend_string_equals_ci(CG(active_class_entry)->name, type_name)) {
2648-
return true;
2649-
}
2650-
if (zend_string_equals_ci(type_name, ZSTR_KNOWN(ZEND_STR_SELF))) {
2651-
return true;
2652-
}
2653-
if (zend_string_equals_ci(type_name, ZSTR_KNOWN(ZEND_STR_PARENT))) {
2654-
return true;
2655-
}
2656-
2657-
ZEND_ASSERT((CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED) == 0);
2658-
if (CG(active_class_entry)->num_interfaces) {
2659-
for (uint32_t i = 0; i < CG(active_class_entry)->num_interfaces; i++) {
2660-
if (zend_string_equals_ci(CG(active_class_entry)->interface_names[i].lc_name, type_name)) {
2661-
return true;
2662-
}
2663-
}
2664-
}
2665-
const zend_string *parent_name = CG(active_class_entry)->parent_name;
2666-
if (parent_name && zend_string_equals_ci(parent_name, type_name)) {
2667-
return true;
2668-
}
2669-
2670-
return false;
2671-
}
2672-
2673-
static bool zend_is_this_valid_for_return_type(zend_type type)
2674-
{
2675-
/* Closures can be bound to a class scope, however it might not and this must type error */
2676-
if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
2677-
return false;
2678-
}
2679-
2680-
if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_OBJECT|MAY_BE_STATIC)) {
2681-
return true;
2682-
}
2683-
2684-
const zend_type *single_type;
2685-
ZEND_TYPE_FOREACH(type, single_type) {
2686-
if (ZEND_TYPE_HAS_NAME(*single_type)) {
2687-
const zend_string *name = ZEND_TYPE_NAME(*single_type);
2688-
if (zend_is_this_instance_of_name(name)) {
2689-
return true;
2690-
}
2691-
}
2692-
} ZEND_TYPE_FOREACH_END();
2693-
2694-
return false;
2695-
}
2696-
26972645
static void zend_emit_return_type_check(
26982646
znode *expr, const zend_arg_info *return_info, bool implicit) /* {{{ */
26992647
{
@@ -2749,17 +2697,6 @@ static void zend_emit_return_type_check(
27492697
return;
27502698
}
27512699

2752-
/* If return type contains static and we are returning $this
2753-
* (determined by checking if the previous opcode is ZEND_FETCH_THIS)
2754-
* then we don't need to check the return type */
2755-
const zend_op_array *op_array = CG(active_op_array);
2756-
if (expr && op_array->last >= 1
2757-
&& op_array->opcodes[op_array->last-1].opcode == ZEND_FETCH_THIS
2758-
&& zend_is_this_valid_for_return_type(type)) {
2759-
ZEND_ASSERT((expr->op_type & (IS_VAR|IS_TMP_VAR)) && expr->u.op.var == op_array->opcodes[op_array->last-1].result.var);
2760-
return;
2761-
}
2762-
27632700
opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
27642701
if (expr && expr->op_type == IS_CONST) {
27652702
opline->result_type = expr->op_type = IS_TMP_VAR;

ext/opcache/tests/opt/verify_return_type/direct_extended_interface_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ $_main:
3131
0002 RETURN int(1)
3232

3333
C::foo:
34-
; (lines=4, args=0, vars=0, tmps=1)
34+
; (lines=5, args=0, vars=0, tmps=1)
3535
; (before optimizer)
3636
; %s:7-9
3737
; return [] RANGE[0..0]
3838
0000 T0 = FETCH_THIS
39-
0001 RETURN T0
40-
0002 VERIFY_RETURN_TYPE
41-
0003 RETURN null
39+
0001 VERIFY_RETURN_TYPE T0
40+
0002 RETURN T0
41+
0003 VERIFY_RETURN_TYPE
42+
0004 RETURN null
43+
LIVE RANGES:
44+
0: 0001 - 0002 (tmp/var)
4245

4346
$_main:
4447
; (lines=3, args=0, vars=0, tmps=0)
@@ -53,4 +56,4 @@ C::foo:
5356
; (after optimizer)
5457
; %s:7-9
5558
0000 T0 = FETCH_THIS
56-
0001 RETURN T0
59+
0001 RETURN T0

ext/opcache/tests/opt/verify_return_type/direct_interface_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@ $_main:
2929
0001 RETURN int(1)
3030

3131
C::foo:
32-
; (lines=4, args=0, vars=0, tmps=1)
32+
; (lines=5, args=0, vars=0, tmps=1)
3333
; (before optimizer)
3434
; %s:6-8
3535
; return [] RANGE[0..0]
3636
0000 T0 = FETCH_THIS
37-
0001 RETURN T0
38-
0002 VERIFY_RETURN_TYPE
39-
0003 RETURN null
37+
0001 VERIFY_RETURN_TYPE T0
38+
0002 RETURN T0
39+
0003 VERIFY_RETURN_TYPE
40+
0004 RETURN null
41+
LIVE RANGES:
42+
0: 0001 - 0002 (tmp/var)
4043

4144
$_main:
4245
; (lines=2, args=0, vars=0, tmps=0)
@@ -50,4 +53,4 @@ C::foo:
5053
; (after optimizer)
5154
; %s:6-8
5255
0000 T0 = FETCH_THIS
53-
0001 RETURN T0
56+
0001 RETURN T0

ext/opcache/tests/opt/verify_return_type/parent_explicit_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ $_main:
2828
0000 RETURN int(1)
2929

3030
C2::foo:
31-
; (lines=4, args=0, vars=0, tmps=1)
31+
; (lines=5, args=0, vars=0, tmps=1)
3232
; (before optimizer)
3333
; %s:6-8
3434
; return [] RANGE[0..0]
3535
0000 T0 = FETCH_THIS
36-
0001 RETURN T0
37-
0002 VERIFY_RETURN_TYPE
38-
0003 RETURN null
36+
0001 VERIFY_RETURN_TYPE T0
37+
0002 RETURN T0
38+
0003 VERIFY_RETURN_TYPE
39+
0004 RETURN null
40+
LIVE RANGES:
41+
0: 0001 - 0002 (tmp/var)
3942

4043
$_main:
4144
; (lines=1, args=0, vars=0, tmps=0)
@@ -48,4 +51,4 @@ C2::foo:
4851
; (after optimizer)
4952
; %s:6-8
5053
0000 T0 = FETCH_THIS
51-
0001 RETURN T0
54+
0001 RETURN T0

ext/opcache/tests/opt/verify_return_type/parent_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ $_main:
2828
0000 RETURN int(1)
2929

3030
C2::foo:
31-
; (lines=4, args=0, vars=0, tmps=1)
31+
; (lines=5, args=0, vars=0, tmps=1)
3232
; (before optimizer)
3333
; %s:6-8
3434
; return [] RANGE[0..0]
3535
0000 T0 = FETCH_THIS
36-
0001 RETURN T0
37-
0002 VERIFY_RETURN_TYPE
38-
0003 RETURN null
36+
0001 VERIFY_RETURN_TYPE T0
37+
0002 RETURN T0
38+
0003 VERIFY_RETURN_TYPE
39+
0004 RETURN null
40+
LIVE RANGES:
41+
0: 0001 - 0002 (tmp/var)
3942

4043
$_main:
4144
; (lines=1, args=0, vars=0, tmps=0)
@@ -48,4 +51,4 @@ C2::foo:
4851
; (after optimizer)
4952
; %s:6-8
5053
0000 T0 = FETCH_THIS
51-
0001 RETURN T0
54+
0001 RETURN T0

ext/opcache/tests/opt/verify_return_type/self_explicit_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ $_main:
2626
0000 RETURN int(1)
2727

2828
C::foo:
29-
; (lines=4, args=0, vars=0, tmps=1)
29+
; (lines=5, args=0, vars=0, tmps=1)
3030
; (before optimizer)
3131
; %s:4-6
3232
; return [] RANGE[0..0]
3333
0000 T0 = FETCH_THIS
34-
0001 RETURN T0
35-
0002 VERIFY_RETURN_TYPE
36-
0003 RETURN null
34+
0001 VERIFY_RETURN_TYPE T0
35+
0002 RETURN T0
36+
0003 VERIFY_RETURN_TYPE
37+
0004 RETURN null
38+
LIVE RANGES:
39+
0: 0001 - 0002 (tmp/var)
3740

3841
$_main:
3942
; (lines=1, args=0, vars=0, tmps=0)
@@ -46,4 +49,4 @@ C::foo:
4649
; (after optimizer)
4750
; %s:4-6
4851
0000 T0 = FETCH_THIS
49-
0001 RETURN T0
52+
0001 RETURN T0

ext/opcache/tests/opt/verify_return_type/self_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ $_main:
2626
0000 RETURN int(1)
2727

2828
C::foo:
29-
; (lines=4, args=0, vars=0, tmps=1)
29+
; (lines=5, args=0, vars=0, tmps=1)
3030
; (before optimizer)
3131
; %s:4-6
3232
; return [] RANGE[0..0]
3333
0000 T0 = FETCH_THIS
34-
0001 RETURN T0
35-
0002 VERIFY_RETURN_TYPE
36-
0003 RETURN null
34+
0001 VERIFY_RETURN_TYPE T0
35+
0002 RETURN T0
36+
0003 VERIFY_RETURN_TYPE
37+
0004 RETURN null
38+
LIVE RANGES:
39+
0: 0001 - 0002 (tmp/var)
3740

3841
$_main:
3942
; (lines=1, args=0, vars=0, tmps=0)
@@ -46,4 +49,4 @@ C::foo:
4649
; (after optimizer)
4750
; %s:4-6
4851
0000 T0 = FETCH_THIS
49-
0001 RETURN T0
52+
0001 RETURN T0

ext/opcache/tests/opt/verify_return_type/self_verify_return_type_for_this_trait.phpt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ $_main:
2626
0000 RETURN int(1)
2727

2828
T::foo:
29-
; (lines=4, args=0, vars=0, tmps=1)
29+
; (lines=5, args=0, vars=0, tmps=1)
3030
; (before optimizer)
3131
; %s:4-6
3232
; return [] RANGE[0..0]
3333
0000 T0 = FETCH_THIS
34-
0001 RETURN T0
35-
0002 VERIFY_RETURN_TYPE
36-
0003 RETURN null
34+
0001 VERIFY_RETURN_TYPE T0
35+
0002 RETURN T0
36+
0003 VERIFY_RETURN_TYPE
37+
0004 RETURN null
38+
LIVE RANGES:
39+
0: 0001 - 0002 (tmp/var)
3740

3841
$_main:
3942
; (lines=1, args=0, vars=0, tmps=0)
@@ -42,8 +45,11 @@ $_main:
4245
0000 RETURN int(1)
4346

4447
T::foo:
45-
; (lines=2, args=0, vars=0, tmps=1)
48+
; (lines=3, args=0, vars=0, tmps=1)
4649
; (after optimizer)
4750
; %s:4-6
4851
0000 T0 = FETCH_THIS
49-
0001 RETURN T0
52+
0001 VERIFY_RETURN_TYPE T0
53+
0002 RETURN T0
54+
LIVE RANGES:
55+
0: 0001 - 0002 (tmp/var)

ext/opcache/tests/opt/verify_return_type/static_verify_return_type_for_this_class.phpt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@ $_main:
2626
0000 RETURN int(1)
2727

2828
C::returnStatic:
29-
; (lines=4, args=0, vars=0, tmps=1)
29+
; (lines=5, args=0, vars=0, tmps=1)
3030
; (before optimizer)
3131
; %s:4-6
3232
; return [] RANGE[0..0]
3333
0000 T0 = FETCH_THIS
34-
0001 RETURN T0
35-
0002 VERIFY_RETURN_TYPE
36-
0003 RETURN null
34+
0001 VERIFY_RETURN_TYPE T0
35+
0002 RETURN T0
36+
0003 VERIFY_RETURN_TYPE
37+
0004 RETURN null
38+
LIVE RANGES:
39+
0: 0001 - 0002 (tmp/var)
3740

3841
$_main:
3942
; (lines=1, args=0, vars=0, tmps=0)
@@ -46,4 +49,4 @@ C::returnStatic:
4649
; (after optimizer)
4750
; %s:4-6
4851
0000 T0 = FETCH_THIS
49-
0001 RETURN T0
52+
0001 RETURN T0

0 commit comments

Comments
 (0)