diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 916d8eebd8960..1ce921d4fec2f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5054,25 +5054,23 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg /* Bail out if the callback is assert() due to the AST stringification logic * breaking for the generated call. */ - if (callback->kind == ZEND_AST_CALL && zend_string_equals_literal_ci(zend_ast_get_str(callback->child[0]), "assert")) { + if (callback->kind == ZEND_AST_CALL + && callback->child[0]->kind == ZEND_AST_ZVAL + && Z_TYPE_P(zend_ast_get_zval(callback->child[0])) == IS_STRING + && zend_string_equals_literal_ci(zend_ast_get_str(callback->child[0]), "assert")) { + return FAILURE; + } + + zend_ast_list *callback_args = zend_ast_get_list(((zend_ast_fcc*)args_ast)->args); + if (callback_args->children != 1 || callback_args->child[0]->attr != ZEND_PLACEHOLDER_VARIADIC) { + /* Full PFA is not yet implemented, will fail in zend_compile_call_common(). */ return FAILURE; } znode value; value.op_type = IS_TMP_VAR; value.u.op.var = get_temporary_variable(); - - zend_ast_list *callback_args = zend_ast_get_list(((zend_ast_fcc*)args_ast)->args); - zend_ast *call_args = zend_ast_create_list(0, ZEND_AST_ARG_LIST); - for (uint32_t i = 0; i < callback_args->children; i++) { - zend_ast *child = callback_args->child[i]; - if (child->kind == ZEND_AST_PLACEHOLDER_ARG) { - call_args = zend_ast_list_add(call_args, zend_ast_create_znode(&value)); - } else { - ZEND_ASSERT(0 && "not implemented"); - call_args = zend_ast_list_add(call_args, child); - } - } + zend_ast *call_args = zend_ast_create_list(1, ZEND_AST_ARG_LIST, zend_ast_create_znode(&value)); zend_op *opline; diff --git a/ext/opcache/tests/array_map_foreach_optimization_006.phpt b/ext/opcache/tests/array_map_foreach_optimization_006.phpt new file mode 100644 index 0000000000000..a3b1c534e3410 --- /dev/null +++ b/ext/opcache/tests/array_map_foreach_optimization_006.phpt @@ -0,0 +1,84 @@ +--TEST-- +array_map(): foreach optimization - dynamic name +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.opt_debug_level=0x20000 +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 INIT_FCALL 2 %d string("range") +0001 SEND_VAL int(1) 1 +0002 SEND_VAL int(10) 2 +0003 V3 = DO_ICALL +0004 ASSIGN CV0($array) V3 +0005 ASSIGN CV1($plus1) string("plus1") +0006 TYPE_ASSERT 131079 string("array_map") CV0($array) +0007 T3 = INIT_ARRAY 0 (packed) NEXT +0008 V4 = FE_RESET_R CV0($array) 0015 +0009 T6 = FE_FETCH_R V4 T5 0015 +0010 INIT_DYNAMIC_CALL 1 CV1($plus1) +0011 SEND_VAL_EX T5 1 +0012 V5 = DO_FCALL +0013 T3 = ADD_ARRAY_ELEMENT V5 T6 +0014 JMP 0009 +0015 FE_FREE V4 +0016 ASSIGN CV2($foo) T3 +0017 INIT_FCALL 1 %d string("var_dump") +0018 SEND_VAR CV2($foo) 1 +0019 DO_ICALL +0020 RETURN int(1) +LIVE RANGES: + 3: 0008 - 0016 (tmp/var) + 4: 0009 - 0015 (loop) + 5: 0010 - 0011 (tmp/var) + 6: 0010 - 0013 (tmp/var) + +plus1: + ; (lines=3, args=1, vars=1, tmps=%d) + ; (after optimizer) + ; %s +0000 CV0($x) = RECV 1 +0001 T1 = ADD CV0($x) int(1) +0002 RETURN T1 +array(10) { + [0]=> + int(2) + [1]=> + int(3) + [2]=> + int(4) + [3]=> + int(5) + [4]=> + int(6) + [5]=> + int(7) + [6]=> + int(8) + [7]=> + int(9) + [8]=> + int(10) + [9]=> + int(11) +}