Skip to content

Commit 3497dbb

Browse files
committed
zend_compile: Fix array_map() optimization for dynamic function names
Fixes #20990.
1 parent bafd299 commit 3497dbb

2 files changed

Lines changed: 90 additions & 1 deletion

File tree

Zend/zend_compile.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5054,7 +5054,12 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg
50545054
/* Bail out if the callback is assert() due to the AST stringification logic
50555055
* breaking for the generated call.
50565056
*/
5057-
if (callback->kind == ZEND_AST_CALL && zend_string_equals_literal_ci(zend_ast_get_str(callback->child[0]), "assert")) {
5057+
if (
5058+
callback->kind == ZEND_AST_CALL
5059+
&& callback->child[0]->kind == ZEND_AST_ZVAL
5060+
&& Z_TYPE_P(zend_ast_get_zval(callback->child[0])) == IS_STRING
5061+
&& zend_string_equals_literal_ci(zend_ast_get_str(callback->child[0]), "assert")
5062+
) {
50585063
return FAILURE;
50595064
}
50605065

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
--TEST--
2+
array_map(): foreach optimization - dynamic name
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.opt_debug_level=0x20000
9+
--FILE--
10+
<?php
11+
12+
function plus1($x) {
13+
return $x + 1;
14+
}
15+
16+
$array = range(1, 10);
17+
18+
$plus1 = 'plus1';
19+
$foo = array_map($plus1(...), $array);
20+
21+
var_dump($foo);
22+
23+
?>
24+
--EXPECTF--
25+
$_main:
26+
; (lines=%d, args=0, vars=%d, tmps=%d)
27+
; (after optimizer)
28+
; %s
29+
0000 INIT_FCALL 2 %d string("range")
30+
0001 SEND_VAL int(1) 1
31+
0002 SEND_VAL int(10) 2
32+
0003 V3 = DO_ICALL
33+
0004 ASSIGN CV0($array) V3
34+
0005 ASSIGN CV1($plus1) string("plus1")
35+
0006 TYPE_ASSERT 131079 string("array_map") CV0($array)
36+
0007 T3 = INIT_ARRAY 0 (packed) NEXT
37+
0008 V4 = FE_RESET_R CV0($array) 0015
38+
0009 T6 = FE_FETCH_R V4 T5 0015
39+
0010 INIT_DYNAMIC_CALL 1 CV1($plus1)
40+
0011 SEND_VAL_EX T5 1
41+
0012 V5 = DO_FCALL
42+
0013 T3 = ADD_ARRAY_ELEMENT V5 T6
43+
0014 JMP 0009
44+
0015 FE_FREE V4
45+
0016 ASSIGN CV2($foo) T3
46+
0017 INIT_FCALL 1 %d string("var_dump")
47+
0018 SEND_VAR CV2($foo) 1
48+
0019 DO_ICALL
49+
0020 RETURN int(1)
50+
LIVE RANGES:
51+
3: 0008 - 0016 (tmp/var)
52+
4: 0009 - 0015 (loop)
53+
5: 0010 - 0011 (tmp/var)
54+
6: 0010 - 0013 (tmp/var)
55+
56+
plus1:
57+
; (lines=3, args=1, vars=1, tmps=%d)
58+
; (after optimizer)
59+
; %s
60+
0000 CV0($x) = RECV 1
61+
0001 T1 = ADD CV0($x) int(1)
62+
0002 RETURN T1
63+
array(10) {
64+
[0]=>
65+
int(2)
66+
[1]=>
67+
int(3)
68+
[2]=>
69+
int(4)
70+
[3]=>
71+
int(5)
72+
[4]=>
73+
int(6)
74+
[5]=>
75+
int(7)
76+
[6]=>
77+
int(8)
78+
[7]=>
79+
int(9)
80+
[8]=>
81+
int(10)
82+
[9]=>
83+
int(11)
84+
}

0 commit comments

Comments
 (0)