Skip to content

Commit f8796aa

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: NEWS for phpGH-16200 Use original op_array when JIT compiling a Closure
2 parents 1e6e7bf + 6f70cd3 commit f8796aa

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

ext/opcache/jit/zend_jit.c

+17
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
13231323
bool ce_is_instanceof;
13241324
bool on_this;
13251325

1326+
ZEND_ASSERT(!(op_array->fn_flags & ZEND_ACC_CLOSURE) || !(op_array->scope));
1327+
13261328
if (JIT_G(bisect_limit)) {
13271329
jit_bisect_pos++;
13281330
if (jit_bisect_pos >= JIT_G(bisect_limit)) {
@@ -2884,6 +2886,18 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons
28842886
/* Build SSA */
28852887
memset(&ssa, 0, sizeof(zend_ssa));
28862888

2889+
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
2890+
if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC) {
2891+
zend_jit_op_array_extension *jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
2892+
op_array = (zend_op_array*) jit_extension->op_array;
2893+
} else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
2894+
zend_jit_op_array_hot_extension *jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(op_array);
2895+
op_array = (zend_op_array*) jit_extension->op_array;
2896+
} else {
2897+
ZEND_ASSERT(!op_array->scope);
2898+
}
2899+
}
2900+
28872901
if (zend_jit_op_array_analyze1(op_array, script, &ssa) != SUCCESS) {
28882902
goto jit_failure;
28892903
}
@@ -3101,6 +3115,7 @@ static int zend_jit_setup_hot_counters(zend_op_array *op_array)
31013115
}
31023116
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
31033117
jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_HOT_COUNTERS;
3118+
jit_extension->op_array = op_array;
31043119
jit_extension->counter = &zend_jit_hot_counters[zend_jit_op_array_hash(op_array) & (ZEND_HOT_COUNTERS_COUNT - 1)];
31053120
for (i = 0; i < op_array->last; i++) {
31063121
jit_extension->orig_handlers[i] = op_array->opcodes[i].handler;
@@ -3145,6 +3160,7 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
31453160
}
31463161
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
31473162
jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_FIRST_EXEC;
3163+
jit_extension->op_array = op_array;
31483164
jit_extension->orig_handler = (void*)opline->handler;
31493165
ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
31503166
opline->handler = (const void*)zend_jit_runtime_jit_handler;
@@ -3174,6 +3190,7 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
31743190
}
31753191
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
31763192
jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_PROF_REQUEST;
3193+
jit_extension->op_array = op_array;
31773194
jit_extension->orig_handler = (void*)opline->handler;
31783195
ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
31793196
opline->handler = (const void*)zend_jit_profile_jit_handler;

ext/opcache/jit/zend_jit_internal.h

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_
123123

124124
typedef struct _zend_jit_op_array_extension {
125125
zend_func_info func_info;
126+
const zend_op_array *op_array;
126127
const void *orig_handler;
127128
} zend_jit_op_array_extension;
128129

@@ -160,6 +161,7 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend
160161

161162
typedef struct _zend_jit_op_array_hot_extension {
162163
zend_func_info func_info;
164+
const zend_op_array *op_array;
163165
int16_t *counter;
164166
const void *orig_handlers[1];
165167
} zend_jit_op_array_hot_extension;

ext/opcache/tests/gh16186_001.phpt

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
GH-16186 001 (Non-tracing JIT uses Closure scope)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=64M
9+
opcache.jit=0234
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
class A {
17+
private $x;
18+
public function getIncrementor() {
19+
return function() { $this->x++; };
20+
}
21+
}
22+
$a = new A();
23+
$f = $a->getIncrementor();
24+
$c = new stdClass();
25+
$f();
26+
$f2 = Closure::bind($f, $c);
27+
$f2();
28+
$f2();
29+
30+
var_dump($c);
31+
32+
?>
33+
--EXPECTF--
34+
Warning: Undefined property: stdClass::$x in %s on line %d
35+
object(stdClass)#%d (1) {
36+
["x"]=>
37+
int(2)
38+
}

ext/opcache/tests/gh16186_002.phpt

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
GH-16186 002 (Non-tracing JIT uses Closure scope)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit_buffer_size=64M
9+
opcache.jit=0214
10+
opcache.file_update_protection=0
11+
opcache.revalidate_freq=0
12+
opcache.protect_memory=1
13+
--FILE--
14+
<?php
15+
16+
class A {
17+
private $x;
18+
public function getIncrementor() {
19+
return function() { $this->x++; };
20+
}
21+
}
22+
$a = new A();
23+
$f = $a->getIncrementor();
24+
$c = new stdClass();
25+
$f();
26+
$f2 = Closure::bind($f, $c);
27+
$f2();
28+
$f2();
29+
30+
var_dump($c);
31+
32+
?>
33+
--EXPECTF--
34+
Warning: Undefined property: stdClass::$x in %s on line %d
35+
object(stdClass)#%d (1) {
36+
["x"]=>
37+
int(2)
38+
}

0 commit comments

Comments
 (0)