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: 234 235 99.6 %
Date: 2015-02-21 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 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             : ZEND_API zend_ast_process_t zend_ast_process = NULL;
      27             : 
      28     4521683 : static inline void *zend_ast_alloc(size_t size) {
      29     4521683 :         return zend_arena_alloc(&CG(ast_arena), size);
      30             : }
      31             : 
      32       68868 : static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
      33       68868 :         void *new = zend_ast_alloc(new_size);
      34       68868 :         memcpy(new, old, old_size);
      35       68868 :         return new;
      36             : }
      37             : 
      38     1943052 : static inline size_t zend_ast_size(uint32_t children) {
      39     1943052 :         return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
      40             : }
      41             : 
      42      803234 : static inline size_t zend_ast_list_size(uint32_t children) {
      43      803234 :         return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
      44             : }
      45             : 
      46       17186 : ZEND_API zend_ast *zend_ast_create_znode(znode *node) {
      47             :         zend_ast_znode *ast;
      48             : 
      49       17186 :         ast = zend_ast_alloc(sizeof(zend_ast_znode));
      50       17186 :         ast->kind = ZEND_AST_ZNODE;
      51       17186 :         ast->attr = 0;
      52       17186 :         ast->lineno = CG(zend_lineno);
      53       17186 :         ast->node = *node;
      54       17186 :         return (zend_ast *) ast;
      55             : }
      56             : 
      57     1784117 : ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
      58             :         zend_ast_zval *ast;
      59             : 
      60     1784117 :         ast = zend_ast_alloc(sizeof(zend_ast_zval));
      61     1784117 :         ast->kind = ZEND_AST_ZVAL;
      62     1784117 :         ast->attr = attr;
      63     1784117 :         ZVAL_COPY_VALUE(&ast->val, zv);
      64     1784117 :         ast->val.u2.lineno = CG(zend_lineno);
      65     1784117 :         return (zend_ast *) ast;
      66             : }
      67             : 
      68       43183 : 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, zend_ast *child3
      71             : ) {
      72             :         zend_ast_decl *ast;
      73             : 
      74       43183 :         ast = zend_ast_alloc(sizeof(zend_ast_decl));
      75       43183 :         ast->kind = kind;
      76       43183 :         ast->attr = 0;
      77       43183 :         ast->start_lineno = start_lineno;
      78       43183 :         ast->end_lineno = CG(zend_lineno);
      79       43183 :         ast->flags = flags;
      80       43183 :         ast->lex_pos = LANG_SCNG(yy_text);
      81       43183 :         ast->doc_comment = doc_comment;
      82       43183 :         ast->name = name;
      83       43183 :         ast->child[0] = child0;
      84       43183 :         ast->child[1] = child1;
      85       43183 :         ast->child[2] = child2;
      86       43183 :         ast->child[3] = child3;
      87             : 
      88       43183 :         return (zend_ast *) ast;
      89             : }
      90             : 
      91     1942909 : static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
      92     1942909 :         uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
      93             :         zend_ast *ast;
      94             : 
      95     1942909 :         ast = zend_ast_alloc(zend_ast_size(children));
      96     1942909 :         ast->kind = kind;
      97     1942909 :         ast->attr = attr;
      98     1942909 :         ast->lineno = (uint32_t) -1;
      99             : 
     100     5099730 :         for (i = 0; i < children; ++i) {
     101     3156821 :                 ast->child[i] = va_arg(va, zend_ast *);
     102     3156821 :                 if (ast->child[i] != NULL) {
     103     5805862 :                         uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
     104     2902931 :                         if (lineno < ast->lineno) {
     105     1931543 :                                 ast->lineno = lineno;
     106             :                         }
     107             :                 }
     108             :         }
     109             : 
     110     1942909 :         if (ast->lineno == UINT_MAX) {
     111       12013 :                 ast->lineno = CG(zend_lineno);
     112             :         }
     113             : 
     114     1942909 :         return ast;
     115             : }
     116             : 
     117      223171 : ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
     118             :         va_list va;
     119             :         zend_ast *ast;
     120             : 
     121      223171 :         va_start(va, attr);
     122      223171 :         ast = zend_ast_create_from_va_list(kind, attr, va);
     123      223171 :         va_end(va);
     124             : 
     125      223171 :         return ast;
     126             : }
     127             : 
     128     1719738 : ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
     129             :         va_list va;
     130             :         zend_ast *ast;
     131             : 
     132     1719738 :         va_start(va, kind);
     133     1719738 :         ast = zend_ast_create_from_va_list(kind, 0, va);
     134     1719738 :         va_end(va);
     135             : 
     136     1719738 :         return ast;
     137             : }
     138             : 
     139      665420 : ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
     140             :         zend_ast *ast;
     141             :         zend_ast_list *list;
     142             : 
     143      665420 :         ast = zend_ast_alloc(zend_ast_list_size(4));
     144      665420 :         list = (zend_ast_list *) ast;
     145      665420 :         list->kind = kind;
     146      665420 :         list->attr = 0;
     147      665420 :         list->lineno = CG(zend_lineno);
     148      665420 :         list->children = 0;
     149             : 
     150             :         {
     151             :                 va_list va;
     152             :                 uint32_t i;
     153      665420 :                 va_start(va, kind);
     154     1134303 :                 for (i = 0; i < init_children; ++i) {
     155      468883 :                         ast = zend_ast_list_add(ast, va_arg(va, zend_ast *));
     156             :                 }
     157      665420 :                 va_end(va);
     158             :         }
     159             : 
     160      665420 :         return ast;
     161             : }
     162             : 
     163      359764 : static inline zend_bool is_power_of_two(uint32_t n) {
     164      359764 :         return ((n != 0) && (n == (n & (~n + 1))));
     165             : }
     166             : 
     167     1395395 : ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
     168     1395395 :         zend_ast_list *list = zend_ast_get_list(ast);
     169     1395395 :         if (list->children >= 4 && is_power_of_two(list->children)) {
     170       68868 :                         list = zend_ast_realloc(list,
     171             :                         zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
     172             :         }
     173     1395395 :         list->child[list->children++] = op;
     174     1395395 :         return (zend_ast *) list;
     175             : }
     176             : 
     177          80 : static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
     178             : {
     179          80 :         switch (Z_TYPE_P(offset)) {
     180             :                 case IS_UNDEF:
     181           7 :                         zend_hash_next_index_insert(Z_ARRVAL_P(result), expr);
     182           7 :                         break;
     183             :                 case IS_STRING:
     184          24 :                         zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
     185             :                         zval_dtor(offset);
     186          24 :                         break;
     187             :                 case IS_NULL:
     188           1 :                         zend_symtable_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), expr);
     189           1 :                         break;
     190             :                 case IS_LONG:
     191          44 :                         zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), expr);
     192          44 :                         break;
     193             :                 case IS_FALSE:
     194           1 :                         zend_hash_index_update(Z_ARRVAL_P(result), 0, expr);
     195           1 :                         break;
     196             :                 case IS_TRUE:
     197           1 :                         zend_hash_index_update(Z_ARRVAL_P(result), 1, expr);
     198           1 :                         break;
     199             :                 case IS_DOUBLE:
     200           2 :                         zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
     201           1 :                         break;
     202             :                 default:
     203           1 :                         zend_error(E_ERROR, "Illegal offset type");
     204             :                         break;
     205             :         }
     206          79 : }
     207             : 
     208         371 : ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
     209             : {
     210             :         zval op1, op2;
     211             : 
     212         371 :         switch (ast->kind) {
     213             :                 case ZEND_AST_BINARY_OP:
     214             :                 {
     215          12 :                         binary_op_type op = get_binary_op(ast->attr);
     216          12 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     217          12 :                         zend_ast_evaluate(&op2, ast->child[1], scope);
     218          12 :                         op(result, &op1, &op2);
     219             :                         zval_dtor(&op1);
     220             :                         zval_dtor(&op2);
     221          12 :                         break;
     222             :                 }
     223             :                 case ZEND_AST_GREATER:
     224             :                 case ZEND_AST_GREATER_EQUAL:
     225             :                 {
     226             :                         /* op1 > op2 is the same as op2 < op1 */
     227           2 :                         binary_op_type op = ast->kind == ZEND_AST_GREATER
     228           2 :                                 ? is_smaller_function : is_smaller_or_equal_function;
     229           2 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     230           2 :                         zend_ast_evaluate(&op2, ast->child[1], scope);
     231           2 :                         op(result, &op2, &op1);
     232             :                         zval_dtor(&op1);
     233             :                         zval_dtor(&op2);
     234           2 :                         break;
     235             :                 }
     236             :                 case ZEND_AST_UNARY_OP:
     237             :                 {
     238           2 :                         unary_op_type op = get_unary_op(ast->attr);
     239           2 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     240           2 :                         op(result, &op1);
     241             :                         zval_dtor(&op1);
     242           2 :                         break;
     243             :                 }
     244             :                 case ZEND_AST_ZVAL:
     245             :                 {
     246         244 :                         zval *zv = zend_ast_get_zval(ast);
     247         244 :                         if (scope) {
     248             :                                 /* class constants may be updated in-place */
     249           7 :                                 if (Z_OPT_CONSTANT_P(zv)) {
     250           5 :                                         zval_update_constant_ex(zv, 1, scope);
     251             :                                 }
     252           4 :                                 ZVAL_DUP(result, zv);
     253             :                         } else {
     254         237 :                                 ZVAL_DUP(result, zv);
     255         237 :                                 if (Z_OPT_CONSTANT_P(result)) {
     256         133 :                                         zval_update_constant_ex(result, 1, scope);
     257             :                                 }
     258             :                         }
     259         225 :                         break;
     260             :                 }
     261             :                 case ZEND_AST_AND:
     262           4 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     263           4 :                         if (zend_is_true(&op1)) {
     264           3 :                                 zend_ast_evaluate(&op2, ast->child[1], scope);
     265           3 :                                 ZVAL_BOOL(result, zend_is_true(&op2));
     266             :                                 zval_dtor(&op2);
     267             :                         } else {
     268           1 :                                 ZVAL_FALSE(result);
     269             :                         }
     270             :                         zval_dtor(&op1);
     271           4 :                         break;
     272             :                 case ZEND_AST_OR:
     273           4 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     274           4 :                         if (zend_is_true(&op1)) {
     275           2 :                                 ZVAL_TRUE(result);
     276             :                         } else {
     277           2 :                                 zend_ast_evaluate(&op2, ast->child[1], scope);
     278           2 :                                 ZVAL_BOOL(result, zend_is_true(&op2));
     279             :                                 zval_dtor(&op2);
     280             :                         }
     281             :                         zval_dtor(&op1);
     282           4 :                         break;
     283             :                 case ZEND_AST_CONDITIONAL:
     284           6 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     285           6 :                         if (zend_is_true(&op1)) {
     286           3 :                                 if (!ast->child[1]) {
     287           2 :                                         *result = op1;
     288             :                                 } else {
     289           1 :                                         zend_ast_evaluate(result, ast->child[1], scope);
     290             :                                         zval_dtor(&op1);
     291             :                                 }
     292             :                         } else {
     293           3 :                                 zend_ast_evaluate(result, ast->child[2], scope);
     294             :                                 zval_dtor(&op1);
     295             :                         }
     296           6 :                         break;
     297             :                 case ZEND_AST_UNARY_PLUS:
     298           2 :                         ZVAL_LONG(&op1, 0);
     299           2 :                         zend_ast_evaluate(&op2, ast->child[0], scope);
     300           2 :                         add_function(result, &op1, &op2);
     301             :                         zval_dtor(&op2);
     302           2 :                         break;
     303             :                 case ZEND_AST_UNARY_MINUS:
     304           3 :                         ZVAL_LONG(&op1, 0);
     305           3 :                         zend_ast_evaluate(&op2, ast->child[0], scope);
     306           3 :                         sub_function(result, &op1, &op2);
     307             :                         zval_dtor(&op2);
     308           3 :                         break;
     309             :                 case ZEND_AST_ARRAY:
     310          81 :                         array_init(result);
     311             :                         {
     312             :                                 uint32_t i;
     313          81 :                                 zend_ast_list *list = zend_ast_get_list(ast);
     314         160 :                                 for (i = 0; i < list->children; i++) {
     315          99 :                                         zend_ast *elem = list->child[i];
     316          99 :                                         if (elem->child[1]) {
     317          84 :                                                 zend_ast_evaluate(&op1, elem->child[1], scope);
     318             :                                         } else {
     319          15 :                                                 ZVAL_UNDEF(&op1);
     320             :                                         }
     321          93 :                                         zend_ast_evaluate(&op2, elem->child[0], scope);
     322          80 :                                         zend_ast_add_array_element(result, &op1, &op2);
     323             :                                 }
     324             :                         }
     325          61 :                         break;
     326             :                 case ZEND_AST_DIM:
     327          11 :                         zend_ast_evaluate(&op1, ast->child[0], scope);
     328          11 :                         zend_ast_evaluate(&op2, ast->child[1], scope);
     329             :                         {
     330             :                                 zval tmp;
     331          11 :                                 zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
     332          33 :                                 ZVAL_ZVAL(result, &tmp, 1, 1);
     333             :                         }
     334             :                         zval_dtor(&op1);
     335             :                         zval_dtor(&op2);
     336          11 :                         break;
     337             :                 default:
     338           0 :                         zend_error(E_ERROR, "Unsupported constant expression");
     339             :         }
     340         332 : }
     341             : 
     342         492 : ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
     343             : {
     344         492 :         if (ast == NULL) {
     345          16 :                 return NULL;
     346         476 :         } else if (ast->kind == ZEND_AST_ZVAL) {
     347         255 :                 zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
     348         255 :                 new->kind = ZEND_AST_ZVAL;
     349         255 :                 new->attr = ast->attr;
     350         510 :                 ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
     351         255 :                 return (zend_ast *) new;
     352         221 :         } else if (zend_ast_is_list(ast)) {
     353          78 :                 zend_ast_list *list = zend_ast_get_list(ast);
     354          78 :                 zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
     355             :                 uint32_t i;
     356          78 :                 new->kind = list->kind;
     357          78 :                 new->attr = list->attr;
     358          78 :                 new->children = list->children;
     359         174 :                 for (i = 0; i < list->children; i++) {
     360          96 :                         new->child[i] = zend_ast_copy(list->child[i]);
     361             :                 }
     362          78 :                 return (zend_ast *) new;
     363             :         } else {
     364         143 :                 uint32_t i, children = zend_ast_get_num_children(ast);
     365         143 :                 zend_ast *new = emalloc(zend_ast_size(children));
     366         143 :                 new->kind = ast->kind;
     367         143 :                 new->attr = ast->attr;
     368         428 :                 for (i = 0; i < children; i++) {
     369         285 :                         new->child[i] = zend_ast_copy(ast->child[i]);
     370             :                 }
     371         143 :                 return new;
     372             :         }
     373             : }
     374             : 
     375     4740403 : static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
     376     4740403 :         if (!ast) {
     377      371421 :                 return;
     378             :         }
     379             : 
     380     4368982 :         switch (ast->kind) {
     381             :                 case ZEND_AST_ZVAL:
     382             :                         /* Destroy value without using GC: When opcache moves arrays into SHM it will
     383             :                          * free the zend_array structure, so references to it from outside the op array
     384             :                          * become invalid. GC would cause such a reference in the root buffer. */
     385             :                         zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
     386     1721834 :                         break;
     387             :                 case ZEND_AST_FUNC_DECL:
     388             :                 case ZEND_AST_CLOSURE:
     389             :                 case ZEND_AST_METHOD:
     390             :                 case ZEND_AST_CLASS:
     391             :                 {
     392       42722 :                         zend_ast_decl *decl = (zend_ast_decl *) ast;
     393       42722 :                         zend_string_release(decl->name);
     394       42722 :                         if (decl->doc_comment) {
     395        2455 :                                 zend_string_release(decl->doc_comment);
     396             :                         }
     397       42722 :                         zend_ast_destroy_ex(decl->child[0], free);
     398       42722 :                         zend_ast_destroy_ex(decl->child[1], free);
     399       42722 :                         zend_ast_destroy_ex(decl->child[2], free);
     400       42722 :                         zend_ast_destroy_ex(decl->child[3], free);
     401       42722 :                         break;
     402             :                 }
     403             :                 default:
     404     2604426 :                         if (zend_ast_is_list(ast)) {
     405      663904 :                                 zend_ast_list *list = zend_ast_get_list(ast);
     406             :                                 uint32_t i;
     407     2057652 :                                 for (i = 0; i < list->children; i++) {
     408     1393748 :                                         zend_ast_destroy_ex(list->child[i], free);
     409             :                                 }
     410             :                         } else {
     411     1940522 :                                 uint32_t i, children = zend_ast_get_num_children(ast);
     412     5058890 :                                 for (i = 0; i < children; i++) {
     413     3118368 :                                         zend_ast_destroy_ex(ast->child[i], free);
     414             :                                 }
     415             :                         }
     416             :         }
     417             : 
     418     4368982 :         if (free) {
     419         470 :                 efree(ast);
     420             :         }
     421             : }
     422             : 
     423       57289 : ZEND_API void zend_ast_destroy(zend_ast *ast) {
     424       57289 :         zend_ast_destroy_ex(ast, 0);
     425       57289 : }
     426         110 : ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
     427         110 :         zend_ast_destroy_ex(ast, 1);
     428         110 : }
     429             : 
     430         218 : ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
     431         218 :         if (zend_ast_is_list(ast)) {
     432          77 :                 zend_ast_list *list = zend_ast_get_list(ast);
     433             :                 uint32_t i;
     434         171 :                 for (i = 0; i < list->children; ++i) {
     435          94 :                         fn(&list->child[i]);
     436             :                 }
     437             :         } else {
     438         141 :                 uint32_t i, children = zend_ast_get_num_children(ast);
     439         422 :                 for (i = 0; i < children; ++i) {
     440         281 :                         fn(&ast->child[i]);
     441             :                 }
     442             :         }
     443         218 : }

Generated by: LCOV version 1.10

Generated at Sat, 21 Feb 2015 16:01:44 +0000 (6 days ago)

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