Skip to content

Commit 2f78af3

Browse files
committed
Merge branch 'PHP-8.1'
* PHP-8.1: [ci skip] NEWS Add JIT guards for INIT_METHOD_CALL when the method may be modified (#8600)
2 parents 8685a7f + badda52 commit 2f78af3

15 files changed

+345
-24
lines changed

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8896,15 +8896,15 @@ static int zend_jit_init_method_call(dasm_State **Dst,
88968896
|2:
88978897
}
88988898

8899-
if (!func
8899+
if ((!func || zend_jit_may_be_modified(func, op_array))
89008900
&& trace
89018901
&& trace->op == ZEND_JIT_TRACE_INIT_CALL
89028902
&& trace->func
89038903
) {
89048904
int32_t exit_point;
89058905
const void *exit_addr;
89068906

8907-
exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_METHOD_CALL);
8907+
exit_point = zend_jit_trace_get_exit_point(opline, func ? ZEND_JIT_EXIT_INVALIDATE : ZEND_JIT_EXIT_METHOD_CALL);
89088908
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
89098909
if (!exit_addr) {
89108910
return 0;

ext/opcache/jit/zend_jit_internal.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,26 @@ static zend_always_inline const zend_op* zend_jit_trace_get_exit_opline(zend_jit
731731
return NULL;
732732
}
733733

734+
static inline bool zend_jit_may_be_modified(const zend_function *func, const zend_op_array *called_from)
735+
{
736+
if (func->type == ZEND_INTERNAL_FUNCTION) {
737+
#ifdef _WIN32
738+
/* ASLR */
739+
return 1;
740+
#else
741+
return 0;
742+
#endif
743+
} else if (func->type == ZEND_USER_FUNCTION) {
744+
if (func->common.fn_flags & ZEND_ACC_PRELOADED) {
745+
return 0;
746+
}
747+
if (func->op_array.filename == called_from->filename && !func->op_array.scope) {
748+
return 0;
749+
}
750+
}
751+
return 1;
752+
}
753+
734754
static zend_always_inline bool zend_jit_may_be_polymorphic_call(const zend_op *opline)
735755
{
736756
if (opline->opcode == ZEND_INIT_FCALL

ext/opcache/jit/zend_jit_trace.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -365,26 +365,6 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
365365
return 0;
366366
}
367367

368-
static bool zend_jit_may_be_modified(const zend_function *func, const zend_op_array *called_from)
369-
{
370-
if (func->type == ZEND_INTERNAL_FUNCTION) {
371-
#ifdef _WIN32
372-
/* ASLR */
373-
return 1;
374-
#else
375-
return 0;
376-
#endif
377-
} else if (func->type == ZEND_USER_FUNCTION) {
378-
if (func->common.fn_flags & ZEND_ACC_PRELOADED) {
379-
return 0;
380-
}
381-
if (func->op_array.filename == called_from->filename && !func->op_array.scope) {
382-
return 0;
383-
}
384-
}
385-
return 1;
386-
}
387-
388368
static zend_always_inline uint32_t zend_jit_trace_type_to_info_ex(zend_uchar type, uint32_t info)
389369
{
390370
if (type == IS_UNKNOWN) {

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9527,7 +9527,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
95279527
|2:
95289528
}
95299529

9530-
if (!func
9530+
if ((!func || zend_jit_may_be_modified(func, op_array))
95319531
&& trace
95329532
&& trace->op == ZEND_JIT_TRACE_INIT_CALL
95339533
&& trace->func
@@ -9538,7 +9538,7 @@ static int zend_jit_init_method_call(dasm_State **Dst,
95389538
int32_t exit_point;
95399539
const void *exit_addr;
95409540

9541-
exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_METHOD_CALL);
9541+
exit_point = zend_jit_trace_get_exit_point(opline, func ? ZEND_JIT_EXIT_INVALIDATE : ZEND_JIT_EXIT_METHOD_CALL);
95429542
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
95439543
if (!exit_addr) {
95449544
return 0;

ext/opcache/tests/jit/gh8591-001.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
interface ModelInterface
6+
{
7+
}

ext/opcache/tests/jit/gh8591-001.phpt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
Bug GH-8591 001 (JIT does not account for class re-compile)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=1M
9+
opcache.jit=1255
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
// Checks that JITed code does not crash in --repeat 2 after the ModelInterface
17+
// interface is recompiled and Model is re-linked.
18+
19+
require __DIR__ . '/gh8591-001.inc';
20+
21+
class Model implements ModelInterface
22+
{
23+
protected static int $field = 1;
24+
25+
public function __construct()
26+
{
27+
for ($i = 0; $i < 10; $i++) {
28+
$this->cast();
29+
}
30+
}
31+
32+
private function cast()
33+
{
34+
global $x;
35+
$x = static::$field;
36+
}
37+
}
38+
39+
new Model();
40+
41+
// mark the file as changed (important)
42+
touch(__DIR__ . '/gh8591-001.inc');
43+
44+
var_dump($x);
45+
46+
print "OK";
47+
--EXPECT--
48+
int(1)
49+
OK

ext/opcache/tests/jit/gh8591-002.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
interface ModelInterface
6+
{
7+
}

ext/opcache/tests/jit/gh8591-002.phpt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
Bug GH-8591 002 (JIT does not account for class re-compile)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=1M
9+
opcache.jit=1255
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
// Checks that JITed code does not crash in --repeat 2 after the ModelInterface
17+
// interface changes and Model is re-linked.
18+
19+
if (!isset(opcache_get_status()['scripts'][__DIR__ . '/gh8591-002.inc'])) {
20+
require __DIR__ . '/gh8591-001.inc';
21+
} else {
22+
interface ModelInterace
23+
{
24+
}
25+
}
26+
27+
class Model implements ModelInterface
28+
{
29+
protected static int $field = 1;
30+
31+
public function __construct()
32+
{
33+
for ($i = 0; $i < 10; $i++) {
34+
$this->cast();
35+
}
36+
}
37+
38+
private function cast()
39+
{
40+
global $x;
41+
$x = static::$field;
42+
}
43+
}
44+
45+
new Model();
46+
47+
var_dump($x);
48+
49+
print "OK";
50+
--EXPECT--
51+
int(1)
52+
OK

ext/opcache/tests/jit/gh8591-003.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Bug GH-8591 003 (JIT does not account for class re-compile)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=1M
9+
opcache.jit=1255
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
interface ModelInterface
17+
{
18+
}
19+
20+
class Model implements ModelInterface
21+
{
22+
protected static int $field = 1;
23+
24+
public function __construct()
25+
{
26+
for ($i = 0; $i < 10; $i++) {
27+
$this->cast();
28+
}
29+
}
30+
31+
private function cast()
32+
{
33+
global $x;
34+
$x = static::$field;
35+
}
36+
}
37+
38+
new Model();
39+
40+
var_dump($x);
41+
42+
print "OK";
43+
--EXPECT--
44+
int(1)
45+
OK

ext/opcache/tests/jit/gh8591-004.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
trait ModelTrait
6+
{
7+
}

ext/opcache/tests/jit/gh8591-004.phpt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
Bug GH-8591 004 (JIT does not account for class re-compile)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=1M
9+
opcache.jit=1255
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
// Checks that JITed code does not crash in --repeat 2 after the ModelTrait
17+
// trait is recompiled and Model is re-linked.
18+
19+
require __DIR__ . '/gh8591-004.inc';
20+
21+
class Model
22+
{
23+
use ModelTrait;
24+
25+
protected static int $field = 1;
26+
27+
public function __construct()
28+
{
29+
for ($i = 0; $i < 10; $i++) {
30+
$this->cast();
31+
}
32+
}
33+
34+
private function cast()
35+
{
36+
global $x;
37+
$x = static::$field;
38+
}
39+
}
40+
41+
new Model();
42+
43+
// mark the file as changed (important)
44+
touch(__DIR__ . '/gh8591-004.inc');
45+
46+
var_dump($x);
47+
48+
print "OK";
49+
--EXPECT--
50+
int(1)
51+
OK

ext/opcache/tests/jit/gh8591-005.inc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
class AbstractModel
4+
{
5+
protected static int $field = 1;
6+
7+
final protected function cast()
8+
{
9+
global $x;
10+
$x = static::$field;
11+
}
12+
}

ext/opcache/tests/jit/gh8591-005.phpt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Bug GH-8591 001 (JIT does not account for class re-compile)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=1M
9+
opcache.jit=1255
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
// Checks that JITed code does not crash in --repeat 2 after the AbstractModel
17+
// class is recompiled and Model is re-linked.
18+
19+
require __DIR__ . '/gh8591-005.inc';
20+
21+
class Model extends AbstractModel
22+
{
23+
public function __construct()
24+
{
25+
for ($i = 0; $i < 10; $i++) {
26+
$this->cast();
27+
}
28+
}
29+
}
30+
31+
new Model();
32+
33+
// mark the file as changed (important)
34+
touch(__DIR__ . '/gh8591-005.inc');
35+
36+
var_dump($x);
37+
38+
print "OK";
39+
--EXPECT--
40+
int(1)
41+
OK

ext/opcache/tests/jit/gh8591-006.inc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
class AbstractModel
4+
{
5+
protected static int $field = 1;
6+
7+
final protected function cast()
8+
{
9+
global $x;
10+
$x = static::$field;
11+
}
12+
}

0 commit comments

Comments
 (0)