diff options
author | Nikita Popov <nikic@php.net> | 2014-08-25 21:59:30 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2014-08-25 22:04:33 +0200 |
commit | 899a1ed59a2f7133367dc39f95b143c019822520 (patch) | |
tree | a8fc518673cf0c94ad363d04bc3474eb3f3bfa66 /Zend/zend_ast.c | |
parent | af59e92b24c8f624672720d47ef65bd8457728b9 (diff) | |
parent | 6db293d5e043d35c281a6b11cb68460f5d7188a9 (diff) | |
download | php-git-POST_AST_MERGE.tar.gz |
Merge branch 'ast'POST_AST_MERGE
Conflicts:
Zend/zend_compile.c
Diffstat (limited to 'Zend/zend_ast.c')
-rw-r--r-- | Zend/zend_ast.c | 509 |
1 files changed, 268 insertions, 241 deletions
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 810b9b1fe8..2532018274 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -23,82 +23,146 @@ #include "zend_API.h" #include "zend_operators.h" -ZEND_API zend_ast *zend_ast_create_constant(zval *zv) -{ - zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zval)); - ast->kind = ZEND_CONST; - ast->children = 0; - ZVAL_COPY_VALUE(&ast->u.val, zv); - return ast; +static inline void *zend_ast_alloc(size_t size TSRMLS_DC) { + return zend_arena_alloc(&CG(ast_arena), size); } -ZEND_API zend_ast* zend_ast_create_unary(uint kind, zend_ast *op0) -{ - zend_ast *ast = emalloc(sizeof(zend_ast)); +static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size TSRMLS_DC) { + void *new = zend_ast_alloc(new_size TSRMLS_CC); + memcpy(new, old, old_size); + return new; +} + +static inline size_t zend_ast_size(uint32_t children) { + return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children; +} + +static inline size_t zend_ast_list_size(uint32_t children) { + return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children; +} + +ZEND_API zend_ast *zend_ast_create_znode(znode *node) { + TSRMLS_FETCH(); + zend_ast_znode *ast = zend_ast_alloc(sizeof(zend_ast_znode) TSRMLS_CC); + ast->kind = ZEND_AST_ZNODE; + ast->attr = 0; + ast->lineno = CG(zend_lineno); + ast->node = *node; + return (zend_ast *) ast; +} + +ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) { + TSRMLS_FETCH(); + zend_ast_zval *ast = zend_ast_alloc(sizeof(zend_ast_zval) TSRMLS_CC); + ast->kind = ZEND_AST_ZVAL; + ast->attr = attr; + ZVAL_COPY_VALUE(&ast->val, zv); + ast->val.u2.lineno = CG(zend_lineno); + return (zend_ast *) ast; +} + +ZEND_API zend_ast *zend_ast_create_decl( + zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, + zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2 +) { + TSRMLS_FETCH(); + zend_ast_decl *ast = zend_ast_alloc(sizeof(zend_ast_decl) TSRMLS_CC); + ast->kind = kind; - ast->children = 1; - (&ast->u.child)[0] = op0; - return ast; + ast->attr = 0; + ast->start_lineno = start_lineno; + ast->end_lineno = CG(zend_lineno); + ast->flags = flags; + ast->lex_pos = LANG_SCNG(yy_text); + ast->doc_comment = doc_comment; + ast->name = name; + ast->child[0] = child0; + ast->child[1] = child1; + ast->child[2] = child2; + + return (zend_ast *) ast; } -ZEND_API zend_ast* zend_ast_create_binary(uint kind, zend_ast *op0, zend_ast *op1) -{ - zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*)); +static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) { + TSRMLS_FETCH(); + uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT; + zend_ast *ast = zend_ast_alloc(zend_ast_size(children) TSRMLS_CC); ast->kind = kind; - ast->children = 2; - (&ast->u.child)[0] = op0; - (&ast->u.child)[1] = op1; + ast->attr = attr; + ast->lineno = (uint32_t) -1; + + for (i = 0; i < children; ++i) { + ast->child[i] = va_arg(va, zend_ast *); + if (ast->child[i] != NULL) { + uint32_t lineno = zend_ast_get_lineno(ast->child[i]); + if (lineno < ast->lineno) { + ast->lineno = lineno; + } + } + } + + if (ast->lineno == UINT_MAX) { + ast->lineno = CG(zend_lineno); + } + return ast; } -ZEND_API zend_ast* zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *op1, zend_ast *op2) -{ - zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 2); - ast->kind = kind; - ast->children = 3; - (&ast->u.child)[0] = op0; - (&ast->u.child)[1] = op1; - (&ast->u.child)[2] = op2; +ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) { + va_list va; + zend_ast *ast; + + va_start(va, attr); + ast = zend_ast_create_from_va_list(kind, attr, va); + va_end(va); + return ast; } -ZEND_API zend_ast* zend_ast_create_dynamic(uint kind) -{ - zend_ast *ast = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * 3); /* use 4 children as deafult */ - ast->kind = kind; - ast->children = 0; +ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) { + va_list va; + zend_ast *ast; + + va_start(va, kind); + ast = zend_ast_create_from_va_list(kind, 0, va); + va_end(va); + return ast; } -ZEND_API void zend_ast_dynamic_add(zend_ast **ast, zend_ast *op) -{ - if ((*ast)->children >= 4 && (*ast)->children == ((*ast)->children & -(*ast)->children)) { - *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children * 2 + 1)); +ZEND_API zend_ast_list *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) { + TSRMLS_FETCH(); + zend_ast_list *list = zend_ast_alloc(zend_ast_list_size(4) TSRMLS_CC); + list->kind = kind; + list->attr = 0; + list->lineno = CG(zend_lineno); + list->children = 0; + + { + va_list va; + uint32_t i; + va_start(va, kind); + for (i = 0; i < init_children; ++i) { + list = zend_ast_list_add(list, va_arg(va, zend_ast *)); + } + va_end(va); } - (&(*ast)->u.child)[(*ast)->children++] = op; -} -ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast) -{ - *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast*) * ((*ast)->children - 1)); + return list; } -ZEND_API int zend_ast_is_ct_constant(zend_ast *ast) -{ - int i; +static inline zend_bool is_power_of_two(uint32_t n) { + return n == (n & -n); +} - if (ast->kind == ZEND_CONST) { - return !Z_CONSTANT(ast->u.val); - } else { - for (i = 0; i < ast->children; i++) { - if ((&ast->u.child)[i]) { - if (!zend_ast_is_ct_constant((&ast->u.child)[i])) { - return 0; - } - } - } - return 1; +ZEND_API zend_ast_list *zend_ast_list_add(zend_ast_list *list, zend_ast *op) { + if (list->children >= 4 && is_power_of_two(list->children)) { + TSRMLS_FETCH(); + list = zend_ast_realloc(list, + zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2) TSRMLS_CC); } + list->child[list->children++] = op; + return list; } static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TSRMLS_DC) @@ -137,167 +201,58 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s zval op1, op2; switch (ast->kind) { - case ZEND_ADD: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - add_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_SUB: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - sub_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_MUL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - mul_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_POW: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - pow_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_DIV: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - div_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_MOD: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - mod_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_SL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - shift_left_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_SR: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - shift_right_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_CONCAT: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - concat_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_BW_OR: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - bitwise_or_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_BW_AND: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - bitwise_and_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_BW_XOR: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - bitwise_xor_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_BW_NOT: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - bitwise_not_function(result, &op1 TSRMLS_CC); - zval_dtor(&op1); - break; - case ZEND_BOOL_NOT: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - boolean_not_function(result, &op1 TSRMLS_CC); - zval_dtor(&op1); - break; - case ZEND_BOOL_XOR: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - boolean_xor_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_IS_IDENTICAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - is_identical_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_IS_NOT_IDENTICAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - is_not_identical_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_IS_EQUAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - is_equal_function(result, &op1, &op2 TSRMLS_CC); - zval_dtor(&op1); - zval_dtor(&op2); - break; - case ZEND_IS_NOT_EQUAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - is_not_equal_function(result, &op1, &op2 TSRMLS_CC); + case ZEND_AST_BINARY_OP: + { + binary_op_type op = get_binary_op(ast->attr); + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC); + op(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; - case ZEND_IS_SMALLER: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - is_smaller_function(result, &op1, &op2 TSRMLS_CC); + } + case ZEND_AST_GREATER: + case ZEND_AST_GREATER_EQUAL: + { + /* op1 > op2 is the same as op2 < op1 */ + binary_op_type op = ast->kind == ZEND_AST_GREATER + ? is_smaller_function : is_smaller_or_equal_function; + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC); + op(result, &op2, &op1 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; - case ZEND_IS_SMALLER_OR_EQUAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); - is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC); + } + case ZEND_AST_UNARY_OP: + { + unary_op_type op = get_unary_op(ast->attr); + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); + op(result, &op1 TSRMLS_CC); zval_dtor(&op1); - zval_dtor(&op2); break; - case ZEND_CONST: - /* class constants may be updated in-place */ + } + case ZEND_AST_ZVAL: + { + zval *zv = zend_ast_get_zval(ast); if (scope) { - if (Z_OPT_CONSTANT(ast->u.val)) { - zval_update_constant_ex(&ast->u.val, 1, scope TSRMLS_CC); + /* class constants may be updated in-place */ + if (Z_OPT_CONSTANT_P(zv)) { + zval_update_constant_ex(zv, 1, scope TSRMLS_CC); } - ZVAL_DUP(result, &ast->u.val); + ZVAL_DUP(result, zv); } else { - ZVAL_DUP(result, &ast->u.val); + ZVAL_DUP(result, zv); if (Z_OPT_CONSTANT_P(result)) { zval_update_constant_ex(result, 1, scope TSRMLS_CC); } } break; - case ZEND_BOOL_AND: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + } + case ZEND_AST_AND: + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); if (zend_is_true(&op1 TSRMLS_CC)) { - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC); ZVAL_BOOL(result, zend_is_true(&op2 TSRMLS_CC)); zval_dtor(&op2); } else { @@ -305,61 +260,63 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s } zval_dtor(&op1); break; - case ZEND_BOOL_OR: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + case ZEND_AST_OR: + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); if (zend_is_true(&op1 TSRMLS_CC)) { ZVAL_BOOL(result, 1); } else { - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC); ZVAL_BOOL(result, zend_is_true(&op2 TSRMLS_CC)); zval_dtor(&op2); } zval_dtor(&op1); break; - case ZEND_SELECT: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + case ZEND_AST_CONDITIONAL: + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); if (zend_is_true(&op1 TSRMLS_CC)) { - if (!(&ast->u.child)[1]) { + if (!ast->child[1]) { *result = op1; } else { - zend_ast_evaluate(result, (&ast->u.child)[1], scope TSRMLS_CC); + zend_ast_evaluate(result, ast->child[1], scope TSRMLS_CC); zval_dtor(&op1); } } else { - zend_ast_evaluate(result, (&ast->u.child)[2], scope TSRMLS_CC); + zend_ast_evaluate(result, ast->child[2], scope TSRMLS_CC); zval_dtor(&op1); } break; - case ZEND_UNARY_PLUS: + case ZEND_AST_UNARY_PLUS: ZVAL_LONG(&op1, 0); - zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[0], scope TSRMLS_CC); add_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op2); break; - case ZEND_UNARY_MINUS: + case ZEND_AST_UNARY_MINUS: ZVAL_LONG(&op1, 0); - zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[0], scope TSRMLS_CC); sub_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op2); break; - case ZEND_INIT_ARRAY: + case ZEND_AST_ARRAY: array_init(result); { - int i; - for (i = 0; i < ast->children; i+=2) { - if ((&ast->u.child)[i]) { - zend_ast_evaluate(&op1, (&ast->u.child)[i], scope TSRMLS_CC); + uint32_t i; + zend_ast_list *list = zend_ast_get_list(ast); + for (i = 0; i < list->children; i++) { + zend_ast *elem = list->child[i]; + if (elem->child[1]) { + zend_ast_evaluate(&op1, elem->child[1], scope TSRMLS_CC); } else { ZVAL_UNDEF(&op1); } - zend_ast_evaluate(&op2, (&ast->u.child)[i+1], scope TSRMLS_CC); + zend_ast_evaluate(&op2, elem->child[0], scope TSRMLS_CC); zend_ast_add_array_element(result, &op1, &op2 TSRMLS_CC); } } break; - case ZEND_FETCH_DIM_R: - zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); + case ZEND_AST_DIM: + zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC); { zval tmp; zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC); @@ -377,35 +334,105 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast) { if (ast == NULL) { return NULL; - } else if (ast->kind == ZEND_CONST) { - zend_ast *copy = zend_ast_create_constant(&ast->u.val); - zval_copy_ctor(©->u.val); - return copy; - } else if (ast->children) { - zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast*) * (ast->children - 1)); - int i; + } else if (ast->kind == ZEND_AST_ZVAL) { + zend_ast_zval *new = emalloc(sizeof(zend_ast_zval)); + new->kind = ZEND_AST_ZVAL; + new->attr = ast->attr; + ZVAL_COPY(&new->val, zend_ast_get_zval(ast)); + return (zend_ast *) new; + } else if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + zend_ast_list *new = emalloc(zend_ast_list_size(list->children)); + uint32_t i; + new->kind = list->kind; + new->attr = list->attr; + new->children = list->children; + for (i = 0; i < list->children; i++) { + new->child[i] = zend_ast_copy(list->child[i]); + } + return (zend_ast *) new; + } else { + uint32_t i, children = zend_ast_get_num_children(ast); + zend_ast *new = emalloc(zend_ast_size(children)); new->kind = ast->kind; - new->children = ast->children; - for (i = 0; i < ast->children; i++) { - (&new->u.child)[i] = zend_ast_copy((&ast->u.child)[i]); + new->attr = ast->attr; + for (i = 0; i < children; i++) { + new->child[i] = zend_ast_copy(ast->child[i]); } return new; } - return zend_ast_create_dynamic(ast->kind); } -ZEND_API void zend_ast_destroy(zend_ast *ast) -{ - int i; +static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) { + if (!ast) { + return; + } - if (ast->kind == ZEND_CONST) { - zval_dtor(&ast->u.val); - } else { - for (i = 0; i < ast->children; i++) { - if ((&ast->u.child)[i]) { - zend_ast_destroy((&ast->u.child)[i]); + switch (ast->kind) { + case ZEND_AST_ZVAL: + { + /* Destroy value without using GC: When opcache moves arrays into SHM it will + * free the zend_array structure, so references to it from outside the op array + * become invalid. GC would cause such a reference in the root buffer. */ + zval *zv = zend_ast_get_zval(ast); + if (Z_REFCOUNTED_P(zv) && !Z_DELREF_P(zv)) { + _zval_dtor_func_for_ptr(Z_COUNTED_P(zv) ZEND_FILE_LINE_CC); + } + break; + } + case ZEND_AST_FUNC_DECL: + case ZEND_AST_CLOSURE: + case ZEND_AST_METHOD: + case ZEND_AST_CLASS: + { + zend_ast_decl *decl = (zend_ast_decl *) ast; + zend_string_release(decl->name); + if (decl->doc_comment) { + zend_string_release(decl->doc_comment); + } + zend_ast_destroy_ex(decl->child[0], free); + zend_ast_destroy_ex(decl->child[1], free); + zend_ast_destroy_ex(decl->child[2], free); + break; + } + default: + if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + uint32_t i; + for (i = 0; i < list->children; i++) { + zend_ast_destroy_ex(list->child[i], free); + } + } else { + uint32_t i, children = zend_ast_get_num_children(ast); + for (i = 0; i < children; i++) { + zend_ast_destroy_ex(ast->child[i], free); + } } + } + + if (free) { + efree(ast); + } +} + +ZEND_API void zend_ast_destroy(zend_ast *ast) { + zend_ast_destroy_ex(ast, 0); +} +ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) { + zend_ast_destroy_ex(ast, 1); +} + +ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC) { + if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + uint32_t i; + for (i = 0; i < list->children; ++i) { + fn(&list->child[i] TSRMLS_CC); + } + } else { + uint32_t i, children = zend_ast_get_num_children(ast); + for (i = 0; i < children; ++i) { + fn(&ast->child[i] TSRMLS_CC); } } - efree(ast); } |