Skip to content

Commit 56e1803

Browse files
committed
Ignore scope when compiling closure in non-tracing jit
1 parent 2d8a93c commit 56e1803

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
12861286
bool ce_is_instanceof;
12871287
bool on_this;
12881288

1289+
ZEND_ASSERT(!(op_array->fn_flags & ZEND_ACC_CLOSURE) || !(op_array->scope));
1290+
12891291
if (JIT_G(bisect_limit)) {
12901292
jit_bisect_pos++;
12911293
if (jit_bisect_pos >= JIT_G(bisect_limit)) {
@@ -2834,6 +2836,17 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons
28342836
/* Build SSA */
28352837
memset(&ssa, 0, sizeof(zend_ssa));
28362838

2839+
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
2840+
if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC ||
2841+
JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST ||
2842+
JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS) {
2843+
zend_jit_op_array_extension_common *jit_extension = (zend_jit_op_array_extension_common*)ZEND_FUNC_INFO(op_array);
2844+
op_array = (zend_op_array*) jit_extension->op_array;
2845+
} else {
2846+
ZEND_ASSERT(!op_array->scope);
2847+
}
2848+
}
2849+
28372850
if (zend_jit_op_array_analyze1(op_array, script, &ssa) != SUCCESS) {
28382851
goto jit_failure;
28392852
}
@@ -3051,6 +3064,7 @@ static int zend_jit_setup_hot_counters(zend_op_array *op_array)
30513064
}
30523065
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
30533066
jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_HOT_COUNTERS;
3067+
jit_extension->op_array = op_array;
30543068
jit_extension->counter = &zend_jit_hot_counters[zend_jit_op_array_hash(op_array) & (ZEND_HOT_COUNTERS_COUNT - 1)];
30553069
for (i = 0; i < op_array->last; i++) {
30563070
jit_extension->orig_handlers[i] = op_array->opcodes[i].handler;
@@ -3095,6 +3109,7 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
30953109
}
30963110
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
30973111
jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_FIRST_EXEC;
3112+
jit_extension->op_array = op_array;
30983113
jit_extension->orig_handler = (void*)opline->handler;
30993114
ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
31003115
opline->handler = (const void*)zend_jit_runtime_jit_handler;
@@ -3124,6 +3139,7 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
31243139
}
31253140
memset(&jit_extension->func_info, 0, sizeof(zend_func_info));
31263141
jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_PROF_REQUEST;
3142+
jit_extension->op_array = op_array;
31273143
jit_extension->orig_handler = (void*)opline->handler;
31283144
ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension);
31293145
opline->handler = (const void*)zend_jit_profile_jit_handler;

ext/opcache/jit/zend_jit_internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,15 @@ static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_
121121
return 0;
122122
}
123123

124+
typedef struct _zend_jit_op_array_extension_common {
125+
zend_func_info func_info;
126+
const zend_op_array *op_array;
127+
} zend_jit_op_array_extension_common;
128+
124129
typedef struct _zend_jit_op_array_extension {
130+
/* zend_jit_op_array_extension_common */
125131
zend_func_info func_info;
132+
const zend_op_array *op_array;
126133
const void *orig_handler;
127134
} zend_jit_op_array_extension;
128135

@@ -159,7 +166,9 @@ static zend_always_inline zend_long zend_jit_hash(const void *ptr)
159166
void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend_op *opline);
160167

161168
typedef struct _zend_jit_op_array_hot_extension {
169+
/* zend_jit_op_array_extension_common */
162170
zend_func_info func_info;
171+
const zend_op_array *op_array;
163172
int16_t *counter;
164173
const void *orig_handlers[1];
165174
} zend_jit_op_array_hot_extension;
@@ -333,6 +342,7 @@ typedef union _zend_op_trace_info {
333342
} zend_op_trace_info;
334343

335344
typedef struct _zend_jit_op_array_trace_extension {
345+
/* zend_jit_op_array_extension_common */
336346
zend_func_info func_info;
337347
const zend_op_array *op_array;
338348
size_t offset; /* offset from "zend_op" to corresponding "op_info" */

ext/opcache/tests/gh16186.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
GH-16186 (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+
}

0 commit comments

Comments
 (0)