Skip to content

Commit cee64ed

Browse files
authored
Add dedicated zend_ast_op_array struct (#17391)
Given that the `ZEND_AST_OP_ARRAY` type already needed special handling in various places, it makes sense to give it its own struct to avoid some of the casts. As a side benefit, it is a little smaller than the `zend_ast_zval` struct.
1 parent fd1eacc commit cee64ed

File tree

8 files changed

+58
-21
lines changed

8 files changed

+58
-21
lines changed

Zend/zend_ast.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,18 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, ze
100100
return (zend_ast *) ast;
101101
}
102102

103+
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_op_array(zend_op_array *op_array) {
104+
zend_ast_op_array *ast;
105+
106+
ast = zend_ast_alloc(sizeof(zend_ast_op_array));
107+
ast->kind = ZEND_AST_OP_ARRAY;
108+
ast->attr = 0;
109+
ast->lineno = CG(zend_lineno);
110+
ast->op_array = op_array;
111+
112+
return (zend_ast *) ast;
113+
}
114+
103115
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
104116
zend_string *name_str = zend_ast_get_str(name);
105117
if (zend_string_equals_ci(name_str, ZSTR_KNOWN(ZEND_STR_CLASS))) {
@@ -992,7 +1004,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
9921004
}
9931005
case ZEND_AST_OP_ARRAY:
9941006
{
995-
zend_function *func = Z_PTR_P(&((zend_ast_zval*)(ast))->val);
1007+
zend_function *func = (zend_function *)zend_ast_get_op_array(ast)->op_array;
9961008

9971009
zend_create_closure(result, func, scope, scope, NULL);
9981010
return SUCCESS;
@@ -1076,8 +1088,10 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
10761088
{
10771089
size_t size;
10781090

1079-
if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT || ast->kind == ZEND_AST_OP_ARRAY) {
1091+
if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
10801092
size = sizeof(zend_ast_zval);
1093+
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
1094+
size = sizeof(zend_ast_op_array);
10811095
} else if (zend_ast_is_list(ast)) {
10821096
uint32_t i;
10831097
zend_ast_list *list = zend_ast_get_list(ast);
@@ -1138,12 +1152,13 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
11381152
}
11391153
}
11401154
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
1141-
zend_ast_zval *new = (zend_ast_zval*)buf;
1142-
new->kind = ZEND_AST_OP_ARRAY;
1143-
new->attr = ast->attr;
1144-
ZVAL_COPY(&new->val, &((zend_ast_zval *) ast)->val);
1145-
Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1146-
buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1155+
zend_ast_op_array *old = zend_ast_get_op_array(ast);
1156+
zend_ast_op_array *new = (zend_ast_op_array*)buf;
1157+
new->kind = old->kind;
1158+
new->attr = old->attr;
1159+
new->lineno = old->lineno;
1160+
new->op_array = old->op_array;
1161+
buf = (void*)((char*)buf + sizeof(zend_ast_op_array));
11471162
} else if (zend_ast_is_decl(ast)) {
11481163
/* Not implemented. */
11491164
ZEND_UNREACHABLE();
@@ -1211,7 +1226,7 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
12111226
} else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
12121227
zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
12131228
} else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) {
1214-
ZEND_ASSERT(!Z_REFCOUNTED(((zend_ast_zval*)(ast))->val));
1229+
/* Nothing to do. */
12151230
} else if (EXPECTED(zend_ast_is_decl(ast))) {
12161231
zend_ast_decl *decl = (zend_ast_decl *) ast;
12171232

Zend/zend_ast.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,15 @@ typedef struct _zend_ast_zval {
207207
zval val;
208208
} zend_ast_zval;
209209

210+
typedef struct _zend_op_array zend_op_array;
211+
212+
typedef struct _zend_ast_op_array {
213+
zend_ast_kind kind;
214+
zend_ast_attr attr;
215+
uint32_t lineno;
216+
zend_op_array *op_array;
217+
} zend_ast_op_array;
218+
210219
/* Separate structure for function and class declaration, as they need extra information. */
211220
typedef struct _zend_ast_decl {
212221
zend_ast_kind kind;
@@ -231,6 +240,8 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval)
231240
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr);
232241
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name);
233242

243+
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_op_array(zend_op_array *op_array);
244+
234245
#if ZEND_AST_SPEC
235246
# define ZEND_AST_SPEC_CALL(name, ...) \
236247
ZEND_EXPAND_VA(ZEND_AST_SPEC_CALL_(name, __VA_ARGS__, _n, _5, _4, _3, _2, _1, _0)(__VA_ARGS__))
@@ -353,6 +364,11 @@ static zend_always_inline zend_string *zend_ast_get_str(zend_ast *ast) {
353364
return Z_STR_P(zv);
354365
}
355366

367+
static zend_always_inline zend_ast_op_array *zend_ast_get_op_array(zend_ast *ast) {
368+
ZEND_ASSERT(ast->kind == ZEND_AST_OP_ARRAY);
369+
return (zend_ast_op_array *) ast;
370+
}
371+
356372
static zend_always_inline zend_string *zend_ast_get_constant_name(zend_ast *ast) {
357373
ZEND_ASSERT(ast->kind == ZEND_AST_CONSTANT);
358374
ZEND_ASSERT(Z_TYPE(((zend_ast_zval *) ast)->val) == IS_STRING);
@@ -369,7 +385,7 @@ static zend_always_inline uint32_t zend_ast_get_lineno(zend_ast *ast) {
369385
if (ast->kind == ZEND_AST_ZVAL) {
370386
zval *zv = zend_ast_get_zval(ast);
371387
return Z_LINENO_P(zv);
372-
} else if (ast->kind == ZEND_AST_CONSTANT || ast->kind == ZEND_AST_OP_ARRAY) {
388+
} else if (ast->kind == ZEND_AST_CONSTANT) {
373389
zval *zv = &((zend_ast_zval *) ast)->val;
374390
return Z_LINENO_P(zv);
375391
} else {

Zend/zend_compile.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11220,13 +11220,10 @@ static void zend_compile_const_expr_closure(zend_ast **ast_ptr)
1122011220
}
1122111221

1122211222
znode node;
11223-
zend_op_array *op = zend_compile_func_decl(&node, *ast_ptr, FUNC_DECL_LEVEL_CONSTEXPR);
11223+
zend_op_array *op = zend_compile_func_decl(&node, (zend_ast*)closure_ast, FUNC_DECL_LEVEL_CONSTEXPR);
1122411224

1122511225
zend_ast_destroy(*ast_ptr);
11226-
zval z;
11227-
ZVAL_PTR(&z, op);
11228-
*ast_ptr = zend_ast_create_zval(&z);
11229-
(*ast_ptr)->kind = ZEND_AST_OP_ARRAY;
11226+
*ast_ptr = zend_ast_create_op_array(op);
1123011227
}
1123111228

1123211229
static void zend_compile_const_expr_args(zend_ast **ast_ptr)

ext/opcache/zend_file_cache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static void zend_file_cache_serialize_ast(zend_ast *ast,
365365
}
366366
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
367367
/* The op_array itself will be serialized as part of the dynamic_func_defs. */
368-
SERIALIZE_PTR(Z_PTR(((zend_ast_zval*)ast)->val));
368+
SERIALIZE_PTR(zend_ast_get_op_array(ast)->op_array);
369369
} else if (zend_ast_is_decl(ast)) {
370370
/* Not implemented. */
371371
ZEND_UNREACHABLE();
@@ -1250,7 +1250,7 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast,
12501250
}
12511251
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
12521252
/* The op_array itself will be unserialized as part of the dynamic_func_defs. */
1253-
UNSERIALIZE_PTR(Z_PTR(((zend_ast_zval*)ast)->val));
1253+
UNSERIALIZE_PTR(zend_ast_get_op_array(ast)->op_array);
12541254
} else if (zend_ast_is_decl(ast)) {
12551255
/* Not implemented. */
12561256
ZEND_UNREACHABLE();

ext/opcache/zend_persist.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,11 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
189189
}
190190
node = (zend_ast *) copy;
191191
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
192-
zend_ast_zval *copy = zend_shared_memdup(ast, sizeof(zend_ast_zval));
193-
zend_persist_op_array(&copy->val);
192+
zend_ast_op_array *copy = zend_shared_memdup(ast, sizeof(zend_ast_op_array));
193+
zval z;
194+
ZVAL_PTR(&z, copy->op_array);
195+
zend_persist_op_array(&z);
196+
copy->op_array = Z_PTR(z);
194197
node = (zend_ast *) copy;
195198
} else if (zend_ast_is_decl(ast)) {
196199
/* Not implemented. */

ext/opcache/zend_persist_calc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ static void zend_persist_ast_calc(zend_ast *ast)
8787
}
8888
}
8989
} else if (ast->kind == ZEND_AST_OP_ARRAY) {
90-
ADD_SIZE(sizeof(zend_ast_zval));
91-
zend_persist_op_array_calc(&((zend_ast_zval*)(ast))->val);
90+
ADD_SIZE(sizeof(zend_ast_op_array));
91+
zval z;
92+
ZVAL_PTR(&z, zend_ast_get_op_array(ast)->op_array);
93+
zend_persist_op_array_calc(&z);
9294
} else if (zend_ast_is_decl(ast)) {
9395
/* Not implemented. */
9496
ZEND_UNREACHABLE();

main/debug_gdb_scripts.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,8 @@ asm(
860860
".ascii \"\\n\"\n"
861861
".ascii \" if kind == enum_value('ZEND_AST_ZVAL') or kind == enum_value('ZEND_AST_CONSTANT'):\\n\"\n"
862862
".ascii \" return self.val.cast(gdb.lookup_type('zend_ast_zval'))\\n\"\n"
863+
".ascii \" if kind == enum_value('ZEND_AST_OP_ARRAY'):\\n\"\n"
864+
".ascii \" return self.val.cast(gdb.lookup_type('zend_ast_op_array'))\\n\"\n"
863865
".ascii \" if kind == enum_value('ZEND_AST_ZNODE'):\\n\"\n"
864866
".ascii \" return self.val.cast(gdb.lookup_type('zend_ast_znode'))\\n\"\n"
865867
".ascii \" if self.is_decl():\\n\"\n"

scripts/gdb/php_gdb.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ def cast(self):
190190

191191
if kind == enum_value('ZEND_AST_ZVAL') or kind == enum_value('ZEND_AST_CONSTANT'):
192192
return self.val.cast(gdb.lookup_type('zend_ast_zval'))
193+
if kind == enum_value('ZEND_AST_OP_ARRAY'):
194+
return self.val.cast(gdb.lookup_type('zend_ast_op_array'))
193195
if kind == enum_value('ZEND_AST_ZNODE'):
194196
return self.val.cast(gdb.lookup_type('zend_ast_znode'))
195197
if self.is_decl():

0 commit comments

Comments
 (0)