Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dedicated zend_ast_op_array struct #17391

Merged
merged 2 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions Zend/zend_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, ze
return (zend_ast *) ast;
}

ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_op_array(zend_op_array *op_array) {
zend_ast_op_array *ast;

ast = zend_ast_alloc(sizeof(zend_ast_op_array));
ast->kind = ZEND_AST_OP_ARRAY;
ast->attr = 0;
ast->lineno = CG(zend_lineno);
ast->op_array = op_array;

return (zend_ast *) ast;
}

ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
zend_string *name_str = zend_ast_get_str(name);
if (zend_string_equals_ci(name_str, ZSTR_KNOWN(ZEND_STR_CLASS))) {
Expand Down Expand Up @@ -992,7 +1004,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
}
case ZEND_AST_OP_ARRAY:
{
zend_function *func = Z_PTR_P(&((zend_ast_zval*)(ast))->val);
zend_function *func = (zend_function *)zend_ast_get_op_array(ast)->op_array;

zend_create_closure(result, func, scope, scope, NULL);
return SUCCESS;
Expand Down Expand Up @@ -1076,8 +1088,10 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
{
size_t size;

if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT || ast->kind == ZEND_AST_OP_ARRAY) {
if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
size = sizeof(zend_ast_zval);
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
size = sizeof(zend_ast_op_array);
} else if (zend_ast_is_list(ast)) {
uint32_t i;
zend_ast_list *list = zend_ast_get_list(ast);
Expand Down Expand Up @@ -1138,12 +1152,13 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
}
}
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
zend_ast_zval *new = (zend_ast_zval*)buf;
new->kind = ZEND_AST_OP_ARRAY;
new->attr = ast->attr;
ZVAL_COPY(&new->val, &((zend_ast_zval *) ast)->val);
Z_LINENO(new->val) = zend_ast_get_lineno(ast);
buf = (void*)((char*)buf + sizeof(zend_ast_zval));
zend_ast_op_array *old = zend_ast_get_op_array(ast);
zend_ast_op_array *new = (zend_ast_op_array*)buf;
new->kind = old->kind;
new->attr = old->attr;
new->lineno = old->lineno;
new->op_array = old->op_array;
buf = (void*)((char*)buf + sizeof(zend_ast_op_array));
} else if (zend_ast_is_decl(ast)) {
/* Not implemented. */
ZEND_UNREACHABLE();
Expand Down Expand Up @@ -1211,7 +1226,7 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
} else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
} else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) {
ZEND_ASSERT(!Z_REFCOUNTED(((zend_ast_zval*)(ast))->val));
/* Nothing to do. */
} else if (EXPECTED(zend_ast_is_decl(ast))) {
zend_ast_decl *decl = (zend_ast_decl *) ast;

Expand Down
18 changes: 17 additions & 1 deletion Zend/zend_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ typedef struct _zend_ast_zval {
zval val;
} zend_ast_zval;

typedef struct _zend_op_array zend_op_array;

typedef struct _zend_ast_op_array {
zend_ast_kind kind;
zend_ast_attr attr;
uint32_t lineno;
zend_op_array *op_array;
} zend_ast_op_array;

/* Separate structure for function and class declaration, as they need extra information. */
typedef struct _zend_ast_decl {
zend_ast_kind kind;
Expand All @@ -231,6 +240,8 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval)
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr);
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name);

ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_op_array(zend_op_array *op_array);

#if ZEND_AST_SPEC
# define ZEND_AST_SPEC_CALL(name, ...) \
ZEND_EXPAND_VA(ZEND_AST_SPEC_CALL_(name, __VA_ARGS__, _n, _5, _4, _3, _2, _1, _0)(__VA_ARGS__))
Expand Down Expand Up @@ -353,6 +364,11 @@ static zend_always_inline zend_string *zend_ast_get_str(zend_ast *ast) {
return Z_STR_P(zv);
}

static zend_always_inline zend_ast_op_array *zend_ast_get_op_array(zend_ast *ast) {
ZEND_ASSERT(ast->kind == ZEND_AST_OP_ARRAY);
return (zend_ast_op_array *) ast;
}

static zend_always_inline zend_string *zend_ast_get_constant_name(zend_ast *ast) {
ZEND_ASSERT(ast->kind == ZEND_AST_CONSTANT);
ZEND_ASSERT(Z_TYPE(((zend_ast_zval *) ast)->val) == IS_STRING);
Expand All @@ -369,7 +385,7 @@ static zend_always_inline uint32_t zend_ast_get_lineno(zend_ast *ast) {
if (ast->kind == ZEND_AST_ZVAL) {
zval *zv = zend_ast_get_zval(ast);
return Z_LINENO_P(zv);
} else if (ast->kind == ZEND_AST_CONSTANT || ast->kind == ZEND_AST_OP_ARRAY) {
} else if (ast->kind == ZEND_AST_CONSTANT) {
zval *zv = &((zend_ast_zval *) ast)->val;
return Z_LINENO_P(zv);
} else {
Expand Down
7 changes: 2 additions & 5 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -11220,13 +11220,10 @@ static void zend_compile_const_expr_closure(zend_ast **ast_ptr)
}

znode node;
zend_op_array *op = zend_compile_func_decl(&node, *ast_ptr, FUNC_DECL_LEVEL_CONSTEXPR);
zend_op_array *op = zend_compile_func_decl(&node, (zend_ast*)closure_ast, FUNC_DECL_LEVEL_CONSTEXPR);

zend_ast_destroy(*ast_ptr);
zval z;
ZVAL_PTR(&z, op);
*ast_ptr = zend_ast_create_zval(&z);
(*ast_ptr)->kind = ZEND_AST_OP_ARRAY;
*ast_ptr = zend_ast_create_op_array(op);
}

static void zend_compile_const_expr_args(zend_ast **ast_ptr)
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/zend_file_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ static void zend_file_cache_serialize_ast(zend_ast *ast,
}
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
/* The op_array itself will be serialized as part of the dynamic_func_defs. */
SERIALIZE_PTR(Z_PTR(((zend_ast_zval*)ast)->val));
SERIALIZE_PTR(zend_ast_get_op_array(ast)->op_array);
} else if (zend_ast_is_decl(ast)) {
/* Not implemented. */
ZEND_UNREACHABLE();
Expand Down Expand Up @@ -1250,7 +1250,7 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast,
}
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
/* The op_array itself will be unserialized as part of the dynamic_func_defs. */
UNSERIALIZE_PTR(Z_PTR(((zend_ast_zval*)ast)->val));
UNSERIALIZE_PTR(zend_ast_get_op_array(ast)->op_array);
} else if (zend_ast_is_decl(ast)) {
/* Not implemented. */
ZEND_UNREACHABLE();
Expand Down
7 changes: 5 additions & 2 deletions ext/opcache/zend_persist.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,11 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
}
node = (zend_ast *) copy;
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
zend_ast_zval *copy = zend_shared_memdup(ast, sizeof(zend_ast_zval));
zend_persist_op_array(&copy->val);
zend_ast_op_array *copy = zend_shared_memdup(ast, sizeof(zend_ast_op_array));
zval z;
ZVAL_PTR(&z, copy->op_array);
zend_persist_op_array(&z);
copy->op_array = Z_PTR(z);
node = (zend_ast *) copy;
} else if (zend_ast_is_decl(ast)) {
/* Not implemented. */
Expand Down
6 changes: 4 additions & 2 deletions ext/opcache/zend_persist_calc.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ static void zend_persist_ast_calc(zend_ast *ast)
}
}
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
ADD_SIZE(sizeof(zend_ast_zval));
zend_persist_op_array_calc(&((zend_ast_zval*)(ast))->val);
ADD_SIZE(sizeof(zend_ast_op_array));
zval z;
ZVAL_PTR(&z, zend_ast_get_op_array(ast)->op_array);
zend_persist_op_array_calc(&z);
} else if (zend_ast_is_decl(ast)) {
/* Not implemented. */
ZEND_UNREACHABLE();
Expand Down
2 changes: 2 additions & 0 deletions main/debug_gdb_scripts.c
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,8 @@ asm(
".ascii \"\\n\"\n"
".ascii \" if kind == enum_value('ZEND_AST_ZVAL') or kind == enum_value('ZEND_AST_CONSTANT'):\\n\"\n"
".ascii \" return self.val.cast(gdb.lookup_type('zend_ast_zval'))\\n\"\n"
".ascii \" if kind == enum_value('ZEND_AST_OP_ARRAY'):\\n\"\n"
".ascii \" return self.val.cast(gdb.lookup_type('zend_ast_op_array'))\\n\"\n"
".ascii \" if kind == enum_value('ZEND_AST_ZNODE'):\\n\"\n"
".ascii \" return self.val.cast(gdb.lookup_type('zend_ast_znode'))\\n\"\n"
".ascii \" if self.is_decl():\\n\"\n"
Expand Down
2 changes: 2 additions & 0 deletions scripts/gdb/php_gdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ def cast(self):

if kind == enum_value('ZEND_AST_ZVAL') or kind == enum_value('ZEND_AST_CONSTANT'):
return self.val.cast(gdb.lookup_type('zend_ast_zval'))
if kind == enum_value('ZEND_AST_OP_ARRAY'):
return self.val.cast(gdb.lookup_type('zend_ast_op_array'))
if kind == enum_value('ZEND_AST_ZNODE'):
return self.val.cast(gdb.lookup_type('zend_ast_znode'))
if self.is_decl():
Expand Down
Loading