Skip to content

Commit bfc535e

Browse files
committed
Merge branch 'PHP-8.6'
# Conflicts: # NEWS
2 parents 7141eef + 2290496 commit bfc535e

9 files changed

Lines changed: 231 additions & 3 deletions

File tree

‎Zend/Optimizer/zend_inference.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2470,7 +2470,7 @@ static const zend_property_info *zend_fetch_static_prop_info(const zend_script *
24702470
const zend_property_info *prop_info = NULL;
24712471
if (opline->op1_type == IS_CONST) {
24722472
const zend_class_entry *ce = NULL;
2473-
if (opline->op2_type == IS_UNUSED) {
2473+
if (opline->op2_type == IS_UNUSED && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
24742474
uint32_t fetch_type = opline->op2.num & ZEND_FETCH_CLASS_MASK;
24752475
switch (fetch_type) {
24762476
case ZEND_FETCH_CLASS_SELF:

‎Zend/Optimizer/zend_optimizer.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ zend_class_entry *zend_optimizer_get_class_entry_from_op1(
846846
return zend_optimizer_get_class_entry(script, op_array, Z_STR_P(op1 + 1));
847847
}
848848
} else if (opline->op1_type == IS_UNUSED && op_array->scope
849+
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)
849850
&& !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
850851
&& ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
851852
|| ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_STATIC

‎ext/opcache/jit/zend_jit.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,11 @@ static zend_class_entry* zend_get_known_class(const zend_op_array *op_array, con
581581
}
582582
} else {
583583
ZEND_ASSERT(op_type == IS_UNUSED);
584+
if ((op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)
585+
|| (op_array->scope && (op_array->scope->ce_flags & ZEND_ACC_TRAIT))) {
586+
/* self and parent depend on the class using the trait */
587+
return NULL;
588+
}
584589
if ((op.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
585590
ce = op_array->scope;
586591
} else {

‎ext/opcache/jit/zend_jit_ir.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9309,7 +9309,7 @@ static int zend_jit_init_static_method_call(zend_jit_ctx *jit,
93099309
}
93109310

93119311
ce = zend_get_known_class(op_array, opline, opline->op1_type, opline->op1);
9312-
if (!func && ce && (opline->op1_type == IS_CONST || !(ce->ce_flags & ZEND_ACC_TRAIT))) {
9312+
if (!func && ce) {
93139313
zval *zv = RT_CONSTANT(opline, opline->op2);
93149314
zend_string *method_name;
93159315

@@ -16333,7 +16333,7 @@ static int zend_jit_fetch_static_prop(zend_jit_ctx *jit, const zend_op *opline,
1633316333
zend_class_entry *ce;
1633416334

1633516335
ce = zend_get_known_class(op_array, opline, opline->op2_type, opline->op2);
16336-
if (ce && (opline->op2_type == IS_CONST || !(ce->ce_flags & ZEND_ACC_TRAIT))) {
16336+
if (ce) {
1633716337
zval *zv = RT_CONSTANT(opline, opline->op1);
1633816338
zend_string *prop_name;
1633916339

‎ext/opcache/tests/jit/gh23572.phpt‎

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
--TEST--
2+
GH-23572: Tracing JIT calls the wrong self/parent static method from trait clones
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit=tracing
9+
opcache.jit_buffer_size=16M
10+
opcache.jit_hot_func=2
11+
opcache.jit_hot_loop=255
12+
opcache.jit_hot_return=255
13+
opcache.jit_hot_side_exit=255
14+
--FILE--
15+
<?php
16+
class ParentA {
17+
public static function method() {
18+
return 'parent A';
19+
}
20+
}
21+
22+
class ParentB {
23+
public static function method() {
24+
return 'parent B';
25+
}
26+
}
27+
28+
trait T {
29+
public function callParent() {
30+
return parent::method();
31+
}
32+
33+
public function callSelf() {
34+
return self::method();
35+
}
36+
}
37+
38+
class A extends ParentA {
39+
use T;
40+
41+
public static function method() {
42+
return 'self A';
43+
}
44+
}
45+
46+
class B extends ParentB {
47+
use T;
48+
49+
public static function method() {
50+
return 'self B';
51+
}
52+
}
53+
54+
$a = new A;
55+
$b = new B;
56+
57+
for ($i = 0; $i < 4; $i++) {
58+
var_dump($a->callParent());
59+
}
60+
var_dump($b->callParent());
61+
var_dump($b->callParent());
62+
var_dump($a->callParent());
63+
64+
for ($i = 0; $i < 4; $i++) {
65+
var_dump($a->callSelf());
66+
}
67+
var_dump($b->callSelf());
68+
var_dump($b->callSelf());
69+
var_dump($a->callSelf());
70+
?>
71+
--EXPECT--
72+
string(8) "parent A"
73+
string(8) "parent A"
74+
string(8) "parent A"
75+
string(8) "parent A"
76+
string(8) "parent B"
77+
string(8) "parent B"
78+
string(8) "parent A"
79+
string(6) "self A"
80+
string(6) "self A"
81+
string(6) "self A"
82+
string(6) "self A"
83+
string(6) "self B"
84+
string(6) "self B"
85+
string(6) "self A"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
--TEST--
2+
GH-23572: Tracing JIT calls an instance method statically from trait clones
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit=tracing
9+
opcache.jit_buffer_size=16M
10+
opcache.jit_hot_func=2
11+
opcache.jit_max_polymorphic_calls=0
12+
--FILE--
13+
<?php
14+
trait T {
15+
public function callSelf() {
16+
return self::method();
17+
}
18+
}
19+
20+
class A {
21+
use T;
22+
23+
public static function method() {
24+
return 'A';
25+
}
26+
}
27+
28+
class B {
29+
use T;
30+
31+
public function method() {
32+
var_dump($this);
33+
return 'B';
34+
}
35+
}
36+
37+
$a = new A;
38+
$b = new B;
39+
40+
for ($i = 0; $i < 4; $i++) var_dump($a->callSelf());
41+
for ($i = 0; $i < 4; $i++) var_dump($b->callSelf());
42+
var_dump($a->callSelf());
43+
?>
44+
--EXPECTF--
45+
string(1) "A"
46+
string(1) "A"
47+
string(1) "A"
48+
string(1) "A"
49+
object(B)#%d (0) {
50+
}
51+
string(1) "B"
52+
object(B)#%d (0) {
53+
}
54+
string(1) "B"
55+
object(B)#%d (0) {
56+
}
57+
string(1) "B"
58+
object(B)#%d (0) {
59+
}
60+
string(1) "B"
61+
string(1) "A"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
GH-23572: Function JIT resolves self:: in trait methods to the trait
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.file_update_protection=0
9+
opcache.jit=1205
10+
opcache.jit_buffer_size=16M
11+
--FILE--
12+
<?php
13+
trait T {
14+
public function outer() { return self::inner(); }
15+
public function inner() { return static::class; }
16+
}
17+
class B { use T; }
18+
var_dump((new B)->outer(), (new B)->outer());
19+
?>
20+
--EXPECT--
21+
string(1) "B"
22+
string(1) "B"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
GH-23572: Function JIT calls a class override of a static trait method via self::
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.file_update_protection=0
9+
opcache.jit=1205
10+
opcache.jit_buffer_size=16M
11+
--FILE--
12+
<?php
13+
trait T {
14+
public function callMethod() { return self::method(); }
15+
public static function method() { return 'T'; }
16+
}
17+
class A {
18+
use T;
19+
public function method() {
20+
$a = 1; $b = 2; $c = 3; $d = 4; $e = 5; $f = 6; $g = 7; $h = 8;
21+
return get_class($this) . ($a + $b + $c + $d + $e + $f + $g + $h);
22+
}
23+
}
24+
var_dump((new A)->callMethod(), (new A)->callMethod());
25+
?>
26+
--EXPECT--
27+
string(3) "A36"
28+
string(3) "A36"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
GH-23572: Tracing JIT infers parent:: static property type from the wrong trait clone
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.file_update_protection=0
9+
opcache.jit=tracing
10+
opcache.jit_buffer_size=16M
11+
opcache.jit_hot_func=2
12+
--FILE--
13+
<?php
14+
class ParentA { public static int $x = 42; }
15+
class ParentB { public static string $x = "str"; }
16+
trait T {
17+
public function get() { return parent::$x; }
18+
}
19+
class A extends ParentA { use T; }
20+
class B extends ParentB { use T; }
21+
var_dump((new A)->get(), (new A)->get(), (new B)->get());
22+
?>
23+
--EXPECT--
24+
int(42)
25+
int(42)
26+
string(3) "str"

0 commit comments

Comments
 (0)