Skip to content

Commit

Permalink
Clean up hack to avoid opcode emission for closures in const-expr
Browse files Browse the repository at this point in the history
  • Loading branch information
TimWolla committed Dec 2, 2024
1 parent 94f42ef commit 469df0e
Showing 1 changed file with 22 additions and 20 deletions.
42 changes: 22 additions & 20 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -8138,7 +8138,13 @@ static uint32_t zend_add_dynamic_func_def(zend_op_array *def) {
return def_offset;
}

static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, bool toplevel) /* {{{ */
enum func_decl_level {
FUNC_DECL_LEVEL_TOPLEVEL,
FUNC_DECL_LEVEL_NESTED,
FUNC_DECL_LEVEL_CONSTEXPR,
};

static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, enum func_decl_level level) /* {{{ */
{
zend_string *unqualified_name, *name, *lcname;
zend_op *opline;
Expand Down Expand Up @@ -8208,9 +8214,9 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array,
}

zend_register_seen_symbol(lcname, ZEND_SYMBOL_FUNCTION);
if (!toplevel) {
if (level != FUNC_DECL_LEVEL_TOPLEVEL) {
uint32_t func_ref = zend_add_dynamic_func_def(op_array);
if (decl->kind != ZEND_AST_OP_ARRAY) {
if (level != FUNC_DECL_LEVEL_CONSTEXPR) {
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
opline->op2.num = func_ref;
Expand All @@ -8228,7 +8234,7 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array,
/* }}} */

static zend_op_array *zend_compile_func_decl_ex(
znode *result, zend_ast *ast, bool toplevel,
znode *result, zend_ast *ast, enum func_decl_level level,
const zend_property_info *property_info,
zend_property_hook_kind hook_kind
) {
Expand Down Expand Up @@ -8262,7 +8268,7 @@ static zend_op_array *zend_compile_func_decl_ex(
op_array->doc_comment = zend_string_copy(decl->doc_comment);
}

if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC || decl->kind == ZEND_AST_OP_ARRAY) {
if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC) {
op_array->fn_flags |= ZEND_ACC_CLOSURE;
}

Expand All @@ -8274,7 +8280,7 @@ static zend_op_array *zend_compile_func_decl_ex(
bool has_body = stmt_ast != NULL;
lcname = zend_begin_method_decl(op_array, decl->name, has_body);
} else {
lcname = zend_begin_func_decl(result, op_array, decl, toplevel);
lcname = zend_begin_func_decl(result, op_array, decl, level);
if (decl->kind == ZEND_AST_ARROW_FUNC) {
find_implicit_binds(&info, params_ast, stmt_ast);
compile_implicit_lexical_binds(&info, result, op_array);
Expand Down Expand Up @@ -8322,7 +8328,7 @@ static zend_op_array *zend_compile_func_decl_ex(
CG(active_class_entry) = NULL;
}

if (toplevel) {
if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
op_array->fn_flags |= ZEND_ACC_TOP_LEVEL;
}

Expand Down Expand Up @@ -8369,7 +8375,7 @@ static zend_op_array *zend_compile_func_decl_ex(
CG(zend_lineno) = decl->start_lineno;
zend_check_magic_method_implementation(
CG(active_class_entry), (zend_function *) op_array, lcname, E_COMPILE_ERROR);
} else if (toplevel) {
} else if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
/* Only register the function after a successful compile */
if (UNEXPECTED(zend_hash_add_ptr(CG(function_table), lcname, op_array) == NULL)) {
CG(zend_lineno) = decl->start_lineno;
Expand All @@ -8389,7 +8395,7 @@ static zend_op_array *zend_compile_func_decl_ex(
/* Pop the loop variable stack separator */
zend_stack_del_top(&CG(loop_var_stack));

if (toplevel) {
if (level == FUNC_DECL_LEVEL_TOPLEVEL) {
zend_observer_function_declared_notify(op_array, lcname);
}

Expand All @@ -8403,9 +8409,9 @@ static zend_op_array *zend_compile_func_decl_ex(
return op_array;
}

static zend_op_array *zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel)
static zend_op_array *zend_compile_func_decl(znode *result, zend_ast *ast, enum func_decl_level level)
{
return zend_compile_func_decl_ex(result, ast, toplevel, /* property_info */ NULL, (zend_property_hook_kind)-1);
return zend_compile_func_decl_ex(result, ast, level, /* property_info */ NULL, (zend_property_hook_kind)-1);
}

zend_property_hook_kind zend_get_property_hook_kind_from_name(zend_string *name) {
Expand Down Expand Up @@ -8544,7 +8550,7 @@ static void zend_compile_property_hooks(
hook->name = zend_strpprintf(0, "$%s::%s", ZSTR_VAL(prop_name), ZSTR_VAL(name));

zend_function *func = (zend_function *) zend_compile_func_decl_ex(
NULL, (zend_ast *) hook, /* toplevel */ false, prop_info, hook_kind);
NULL, (zend_ast *) hook, FUNC_DECL_LEVEL_NESTED, prop_info, hook_kind);

func->common.prop_info = prop_info;

Expand Down Expand Up @@ -11200,11 +11206,7 @@ static void zend_compile_const_expr_closure(zend_ast **ast_ptr)
}

znode node;
zend_ast *ast = *ast_ptr;
zend_ast_kind old_kind = ast->kind;
ast->kind = ZEND_AST_OP_ARRAY;
zend_op_array *op = zend_compile_func_decl(&node, ast, /* toplevel */ false);
ast->kind = old_kind;
zend_op_array *op = zend_compile_func_decl(&node, *ast_ptr, FUNC_DECL_LEVEL_CONSTEXPR);

zend_ast_destroy(*ast_ptr);
zval z;
Expand Down Expand Up @@ -11320,7 +11322,7 @@ void zend_compile_top_stmt(zend_ast *ast) /* {{{ */

if (ast->kind == ZEND_AST_FUNC_DECL) {
CG(zend_lineno) = ast->lineno;
zend_compile_func_decl(NULL, ast, 1);
zend_compile_func_decl(NULL, ast, FUNC_DECL_LEVEL_TOPLEVEL);
CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno;
} else if (ast->kind == ZEND_AST_CLASS) {
CG(zend_lineno) = ast->lineno;
Expand Down Expand Up @@ -11402,7 +11404,7 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
break;
case ZEND_AST_FUNC_DECL:
case ZEND_AST_METHOD:
zend_compile_func_decl(NULL, ast, 0);
zend_compile_func_decl(NULL, ast, FUNC_DECL_LEVEL_NESTED);
break;
case ZEND_AST_ENUM_CASE:
zend_compile_enum_case(ast);
Expand Down Expand Up @@ -11579,7 +11581,7 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
return;
case ZEND_AST_CLOSURE:
case ZEND_AST_ARROW_FUNC:
zend_compile_func_decl(result, ast, 0);
zend_compile_func_decl(result, ast, FUNC_DECL_LEVEL_NESTED);
return;
case ZEND_AST_THROW:
zend_compile_throw(result, ast);
Expand Down

0 comments on commit 469df0e

Please # to comment.