PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_ast.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 232 233 99.6 %
Date: 2014-10-30 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Bob Weinand <bwoebi@php.net>                                |
      16             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      17             :    +----------------------------------------------------------------------+
      18             : */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : #include "zend_ast.h"
      23             : #include "zend_API.h"
      24             : #include "zend_operators.h"
      25             : 
      26     4421799 : static inline void *zend_ast_alloc(size_t size TSRMLS_DC) {
      27     4421799 :         return zend_arena_alloc(&CG(ast_arena), size);
      28             : }
      29             : 
      30       67445 : static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size TSRMLS_DC) {
      31       67445 :         void *new = zend_ast_alloc(new_size TSRMLS_CC);
      32       67445 :         memcpy(new, old, old_size);
      33       67445 :         return new;
      34             : }
      35             : 
      36     1898601 : static inline size_t zend_ast_size(uint32_t children) {
      37     1898601 :         return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
      38             : }
      39             : 
      40      786363 : static inline size_t zend_ast_list_size(uint32_t children) {
      41      786363 :         return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
      42             : }
      43             : 
      44       16737 : ZEND_API zend_ast *zend_ast_create_znode(znode *node) {
      45             :         zend_ast_znode *ast;
      46             :         TSRMLS_FETCH();
      47             : 
      48       16737 :         ast = zend_ast_alloc(sizeof(zend_ast_znode) TSRMLS_CC);
      49       16737 :         ast->kind = ZEND_AST_ZNODE;
      50       16737 :         ast->attr = 0;
      51       16737 :         ast->lineno = CG(zend_lineno);
      52       16737 :         ast->node = *node;
      53       16737 :         return (zend_ast *) ast;
      54             : }
      55             : 
      56     1745333 : ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
      57             :         zend_ast_zval *ast;
      58             :         TSRMLS_FETCH();
      59             : 
      60     1745333 :         ast = zend_ast_alloc(sizeof(zend_ast_zval) TSRMLS_CC);
      61     1745333 :         ast->kind = ZEND_AST_ZVAL;
      62     1745333 :         ast->attr = attr;
      63     1745333 :         ZVAL_COPY_VALUE(&ast->val, zv);
      64     1745333 :         ast->val.u2.lineno = CG(zend_lineno);
      65     1745333 :         return (zend_ast *) ast;
      66             : }
      67             : 
      68       42490 : ZEND_API zend_ast *zend_ast_create_decl(
      69             :         zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
      70             :         zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2
      71             : ) {
      72             :         zend_ast_decl *ast;
      73             :         TSRMLS_FETCH();
      74             : 
      75       42490 :         ast = zend_ast_alloc(sizeof(zend_ast_decl) TSRMLS_CC);
      76       42490 :         ast->kind = kind;
      77       42490 :         ast->attr = 0;
      78       42490 :         ast->start_lineno = start_lineno;
      79       42490 :         ast->end_lineno = CG(zend_lineno);
      80       42490 :         ast->flags = flags;
      81       42490 :         ast->lex_pos = LANG_SCNG(yy_text);
      82       42490 :         ast->doc_comment = doc_comment;
      83       42490 :         ast->name = name;
      84       42490 :         ast->child[0] = child0;
      85       42490 :         ast->child[1] = child1;
      86       42490 :         ast->child[2] = child2;
      87             : 
      88       42490 :         return (zend_ast *) ast;
      89             : }
      90             : 
      91     1898420 : static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
      92     1898420 :         uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
      93             :         zend_ast *ast;
      94             :         TSRMLS_FETCH();
      95             : 
      96     1898420 :         ast = zend_ast_alloc(zend_ast_size(children) TSRMLS_CC);
      97     1898420 :         ast->kind = kind;
      98     1898420 :         ast->attr = attr;
      99     1898420 :         ast->lineno = (uint32_t) -1;
     100             : 
     101     4985536 :         for (i = 0; i < children; ++i) {
     102     3087116 :                 ast->child[i] = va_arg(va, zend_ast *);
     103     3087116 :                 if (ast->child[i] != NULL) {
     104     5675608 :                         uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
     105     2837804 :                         if (lineno < ast->lineno) {
     106     1887360 :                                 ast->lineno = lineno;
     107             :                         }
     108             :                 }
     109             :         }
     110             : 
     111     1898420 :         if (ast->lineno == UINT_MAX) {
     112       11705 :                 ast->lineno = CG(zend_lineno);
     113             :         }
     114             : 
     115     1898420 :         return ast;
     116             : }
     117             : 
     118      218197 : ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
     119             :         va_list va;
     120             :         zend_ast *ast;
     121             : 
     122      218197 :         va_start(va, attr);
     123      218197 :         ast = zend_ast_create_from_va_list(kind, attr, va);
     124      218197 :         va_end(va);
     125             : 
     126      218197 :         return ast;
     127             : }
     128             : 
     129     1680223 : ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
     130             :         va_list va;
     131             :         zend_ast *ast;
     132             : 
     133     1680223 :         va_start(va, kind);
     134     1680223 :         ast = zend_ast_create_from_va_list(kind, 0, va);
     135     1680223 :         va_end(va);
     136             : 
     137     1680223 :         return ast;
     138             : }
     139             : 
     140      651374 : ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
     141             :         zend_ast *ast;
     142             :         zend_ast_list *list;
     143             :         TSRMLS_FETCH();
     144             : 
     145      651374 :         ast = zend_ast_alloc(zend_ast_list_size(4) TSRMLS_CC);
     146      651374 :         list = (zend_ast_list *) ast;
     147      651374 :         list->kind = kind;
     148      651374 :         list->attr = 0;
     149      651374 :         list->lineno = CG(zend_lineno);
     150      651374 :         list->children = 0;
     151             : 
     152             :         {
     153             :                 va_list va;
     154             :                 uint32_t i;
     155      651374 :                 va_start(va, kind);
     156     1109570 :                 for (i = 0; i < init_children; ++i) {
     157      458196 :                         ast = zend_ast_list_add(ast, va_arg(va, zend_ast *));
     158             :                 }
     159      651374 :                 va_end(va);
     160             :         }
     161             : 
     162      651374 :         return ast;
     163             : }
     164             : 
     165      354175 : static inline zend_bool is_power_of_two(uint32_t n) {
     166      354175 :         return ((n != 0) && (n == (n & (~n + 1))));
     167             : }
     168             : 
     169     1364970 : ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
     170     1364970 :         zend_ast_list *list = zend_ast_get_list(ast);
     171     1364970 :         if (list->children >= 4 && is_power_of_two(list->children)) {
     172             :                 TSRMLS_FETCH();
     173       67445 :                 list = zend_ast_realloc(list,
     174             :                         zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2) TSRMLS_CC);
     175             :         }
     176     1364970 :         list->child[list->children++] = op;
     177     1364970 :         return (zend_ast *) list;
     178             : }
     179             : 
     180         117 : static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TSRMLS_DC)
     181             : {
     182         117 :         switch (Z_TYPE_P(offset)) {
     183             :                 case IS_UNDEF:
     184          17 :                         zend_hash_next_index_insert(Z_ARRVAL_P(result), expr);
     185          17 :                         break;
     186             :                 case IS_STRING:
     187          34 :                         zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
     188             :                         zval_dtor(offset);
     189          34 :                         break;
     190             :                 case IS_NULL:
     191           1 :                         zend_symtable_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), expr);
     192           1 :                         break;
     193             :                 case IS_LONG:
     194          61 :                         zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), expr);
     195          61 :                         break;
     196             :                 case IS_FALSE:
     197           1 :                         zend_hash_index_update(Z_ARRVAL_P(result), 0, expr);
     198           1 :                         break;
     199             :                 case IS_TRUE:
     200           1 :                         zend_hash_index_update(Z_ARRVAL_P(result), 1, expr);
     201           1 :                         break;
     202             :                 case IS_DOUBLE:
     203           2 :                         zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
     204           1 :                         break;
     205             :                 default:
     206           1 :                         zend_error(E_ERROR, "Illegal offset type");
     207             :                         break;
     208             :         }
     209         116 : }
     210             : 
     211         459 : ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC)
     212             : {
     213             :         zval op1, op2;
     214             : 
     215         459 :         switch (ast->kind) {
     216             :                 case ZEND_AST_BINARY_OP:
     217             :                 {
     218          13 :                         binary_op_type op = get_binary_op(ast->attr);
     219          13 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     220          13 :                         zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
     221          13 :                         op(result, &op1, &op2 TSRMLS_CC);
     222             :                         zval_dtor(&op1);
     223             :                         zval_dtor(&op2);
     224          13 :                         break;
     225             :                 }
     226             :                 case ZEND_AST_GREATER:
     227             :                 case ZEND_AST_GREATER_EQUAL:
     228             :                 {
     229             :                         /* op1 > op2 is the same as op2 < op1 */
     230           2 :                         binary_op_type op = ast->kind == ZEND_AST_GREATER
     231           2 :                                 ? is_smaller_function : is_smaller_or_equal_function;
     232           2 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     233           2 :                         zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
     234           2 :                         op(result, &op2, &op1 TSRMLS_CC);
     235             :                         zval_dtor(&op1);
     236             :                         zval_dtor(&op2);
     237           2 :                         break;
     238             :                 }
     239             :                 case ZEND_AST_UNARY_OP:
     240             :                 {
     241           2 :                         unary_op_type op = get_unary_op(ast->attr);
     242           2 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     243           2 :                         op(result, &op1 TSRMLS_CC);
     244             :                         zval_dtor(&op1);
     245           2 :                         break;
     246             :                 }
     247             :                 case ZEND_AST_ZVAL:
     248             :                 {
     249         310 :                         zval *zv = zend_ast_get_zval(ast);
     250         310 :                         if (scope) {
     251             :                                 /* class constants may be updated in-place */
     252           9 :                                 if (Z_OPT_CONSTANT_P(zv)) {
     253           6 :                                         zval_update_constant_ex(zv, 1, scope TSRMLS_CC);
     254             :                                 }
     255           6 :                                 ZVAL_DUP(result, zv);
     256             :                         } else {
     257         301 :                                 ZVAL_DUP(result, zv);
     258         301 :                                 if (Z_OPT_CONSTANT_P(result)) {
     259         183 :                                         zval_update_constant_ex(result, 1, scope TSRMLS_CC);
     260             :                                 }
     261             :                         }
     262         291 :                         break;
     263             :                 }
     264             :                 case ZEND_AST_AND:
     265           4 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     266           4 :                         if (zend_is_true(&op1 TSRMLS_CC)) {
     267           3 :                                 zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
     268           3 :                                 ZVAL_BOOL(result, zend_is_true(&op2 TSRMLS_CC));
     269             :                                 zval_dtor(&op2);
     270             :                         } else {
     271           1 :                                 ZVAL_BOOL(result, 0);
     272             :                         }
     273             :                         zval_dtor(&op1);
     274           4 :                         break;
     275             :                 case ZEND_AST_OR:
     276           4 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     277           4 :                         if (zend_is_true(&op1 TSRMLS_CC)) {
     278           2 :                                 ZVAL_BOOL(result, 1);
     279             :                         } else {
     280           2 :                                 zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
     281           2 :                                 ZVAL_BOOL(result, zend_is_true(&op2 TSRMLS_CC));
     282             :                                 zval_dtor(&op2);
     283             :                         }
     284             :                         zval_dtor(&op1);
     285           4 :                         break;
     286             :                 case ZEND_AST_CONDITIONAL:
     287           6 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     288           6 :                         if (zend_is_true(&op1 TSRMLS_CC)) {
     289           3 :                                 if (!ast->child[1]) {
     290           2 :                                         *result = op1;
     291             :                                 } else {
     292           1 :                                         zend_ast_evaluate(result, ast->child[1], scope TSRMLS_CC);
     293             :                                         zval_dtor(&op1);
     294             :                                 }
     295             :                         } else {
     296           3 :                                 zend_ast_evaluate(result, ast->child[2], scope TSRMLS_CC);
     297             :                                 zval_dtor(&op1);
     298             :                         }
     299           6 :                         break;
     300             :                 case ZEND_AST_UNARY_PLUS:
     301           2 :                         ZVAL_LONG(&op1, 0);
     302           2 :                         zend_ast_evaluate(&op2, ast->child[0], scope TSRMLS_CC);
     303           2 :                         add_function(result, &op1, &op2 TSRMLS_CC);
     304             :                         zval_dtor(&op2);
     305           2 :                         break;
     306             :                 case ZEND_AST_UNARY_MINUS:
     307           3 :                         ZVAL_LONG(&op1, 0);
     308           3 :                         zend_ast_evaluate(&op2, ast->child[0], scope TSRMLS_CC);
     309           3 :                         sub_function(result, &op1, &op2 TSRMLS_CC);
     310             :                         zval_dtor(&op2);
     311           3 :                         break;
     312             :                 case ZEND_AST_ARRAY:
     313         102 :                         array_init(result);
     314             :                         {
     315             :                                 uint32_t i;
     316         102 :                                 zend_ast_list *list = zend_ast_get_list(ast);
     317         218 :                                 for (i = 0; i < list->children; i++) {
     318         136 :                                         zend_ast *elem = list->child[i];
     319         136 :                                         if (elem->child[1]) {
     320         111 :                                                 zend_ast_evaluate(&op1, elem->child[1], scope TSRMLS_CC);
     321             :                                         } else {
     322          25 :                                                 ZVAL_UNDEF(&op1);
     323             :                                         }
     324         130 :                                         zend_ast_evaluate(&op2, elem->child[0], scope TSRMLS_CC);
     325         117 :                                         zend_ast_add_array_element(result, &op1, &op2 TSRMLS_CC);
     326             :                                 }
     327             :                         }
     328          82 :                         break;
     329             :                 case ZEND_AST_DIM:
     330          11 :                         zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC);
     331          11 :                         zend_ast_evaluate(&op2, ast->child[1], scope TSRMLS_CC);
     332             :                         {
     333             :                                 zval tmp;
     334          11 :                                 zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
     335          33 :                                 ZVAL_ZVAL(result, &tmp, 1, 1);
     336             :                         }
     337             :                         zval_dtor(&op1);
     338             :                         zval_dtor(&op2);
     339          11 :                         break;
     340             :                 default:
     341           0 :                         zend_error(E_ERROR, "Unsupported constant expression");
     342             :         }
     343         420 : }
     344             : 
     345         627 : ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
     346             : {
     347         627 :         if (ast == NULL) {
     348          26 :                 return NULL;
     349         601 :         } else if (ast->kind == ZEND_AST_ZVAL) {
     350         321 :                 zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
     351         321 :                 new->kind = ZEND_AST_ZVAL;
     352         321 :                 new->attr = ast->attr;
     353         642 :                 ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
     354         321 :                 return (zend_ast *) new;
     355         280 :         } else if (zend_ast_is_list(ast)) {
     356          99 :                 zend_ast_list *list = zend_ast_get_list(ast);
     357          99 :                 zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
     358             :                 uint32_t i;
     359          99 :                 new->kind = list->kind;
     360          99 :                 new->attr = list->attr;
     361          99 :                 new->children = list->children;
     362         232 :                 for (i = 0; i < list->children; i++) {
     363         133 :                         new->child[i] = zend_ast_copy(list->child[i]);
     364             :                 }
     365          99 :                 return (zend_ast *) new;
     366             :         } else {
     367         181 :                 uint32_t i, children = zend_ast_get_num_children(ast);
     368         181 :                 zend_ast *new = emalloc(zend_ast_size(children));
     369         181 :                 new->kind = ast->kind;
     370         181 :                 new->attr = ast->attr;
     371         542 :                 for (i = 0; i < children; i++) {
     372         361 :                         new->child[i] = zend_ast_copy(ast->child[i]);
     373             :                 }
     374         181 :                 return new;
     375             :         }
     376             : }
     377             : 
     378     4595409 : static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
     379     4595409 :         if (!ast) {
     380      322931 :                 return;
     381             :         }
     382             : 
     383     4272478 :         switch (ast->kind) {
     384             :                 case ZEND_AST_ZVAL:
     385             :                         /* Destroy value without using GC: When opcache moves arrays into SHM it will
     386             :                          * free the zend_array structure, so references to it from outside the op array
     387             :                          * become invalid. GC would cause such a reference in the root buffer. */
     388             :                         zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
     389     1684466 :                         break;
     390             :                 case ZEND_AST_FUNC_DECL:
     391             :                 case ZEND_AST_CLOSURE:
     392             :                 case ZEND_AST_METHOD:
     393             :                 case ZEND_AST_CLASS:
     394             :                 {
     395       42055 :                         zend_ast_decl *decl = (zend_ast_decl *) ast;
     396       42055 :                         zend_string_release(decl->name);
     397       42055 :                         if (decl->doc_comment) {
     398        2064 :                                 zend_string_release(decl->doc_comment);
     399             :                         }
     400       42055 :                         zend_ast_destroy_ex(decl->child[0], free);
     401       42055 :                         zend_ast_destroy_ex(decl->child[1], free);
     402       42055 :                         zend_ast_destroy_ex(decl->child[2], free);
     403       42055 :                         break;
     404             :                 }
     405             :                 default:
     406     2545957 :                         if (zend_ast_is_list(ast)) {
     407      649957 :                                 zend_ast_list *list = zend_ast_get_list(ast);
     408             :                                 uint32_t i;
     409     2013374 :                                 for (i = 0; i < list->children; i++) {
     410     1363417 :                                         zend_ast_destroy_ex(list->child[i], free);
     411             :                                 }
     412             :                         } else {
     413     1896000 :                                 uint32_t i, children = zend_ast_get_num_children(ast);
     414     4945734 :                                 for (i = 0; i < children; i++) {
     415     3049734 :                                         zend_ast_destroy_ex(ast->child[i], free);
     416             :                                 }
     417             :                         }
     418             :         }
     419             : 
     420     4272478 :         if (free) {
     421         595 :                 efree(ast);
     422             :         }
     423             : }
     424             : 
     425       55961 : ZEND_API void zend_ast_destroy(zend_ast *ast) {
     426       55961 :         zend_ast_destroy_ex(ast, 0);
     427       55961 : }
     428         132 : ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
     429         132 :         zend_ast_destroy_ex(ast, 1);
     430         132 : }
     431             : 
     432         275 : ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC) {
     433         275 :         if (zend_ast_is_list(ast)) {
     434          97 :                 zend_ast_list *list = zend_ast_get_list(ast);
     435             :                 uint32_t i;
     436         227 :                 for (i = 0; i < list->children; ++i) {
     437         130 :                         fn(&list->child[i] TSRMLS_CC);
     438             :                 }
     439             :         } else {
     440         178 :                 uint32_t i, children = zend_ast_get_num_children(ast);
     441         533 :                 for (i = 0; i < children; ++i) {
     442         355 :                         fn(&ast->child[i] TSRMLS_CC);
     443             :                 }
     444             :         }
     445         275 : }

Generated by: LCOV version 1.10

Generated at Thu, 30 Oct 2014 07:41:26 +0000 (10 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.