diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index a278f435fc848..c1d973f67c85c 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -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))) { @@ -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; @@ -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); @@ -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(); @@ -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; diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 363679dda3ff6..db41802b16f16 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -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; @@ -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__)) @@ -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); @@ -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 { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f426f350e264c..23dfd4577812a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 41165270598ee..74e0d19d1b6de 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -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(); @@ -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(); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 1aedbeb3ddb6b..9e89980b67e14 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -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(©->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. */ diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index d4082365dbcd7..0c53923354c42 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -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(); diff --git a/main/debug_gdb_scripts.c b/main/debug_gdb_scripts.c index 13288fc9adc8d..590a4f42abb97 100644 --- a/main/debug_gdb_scripts.c +++ b/main/debug_gdb_scripts.c @@ -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" diff --git a/scripts/gdb/php_gdb.py b/scripts/gdb/php_gdb.py index b7258fb78f1a9..97f7e976b75c0 100644 --- a/scripts/gdb/php_gdb.py +++ b/scripts/gdb/php_gdb.py @@ -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():