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 - ext/opcache/Optimizer - zend_dfg.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 88 106 83.0 %
Date: 2018-09-10 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine, DFG - Data Flow Graph                                   |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2018 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Dmitry Stogov <dmitry@zend.com>                             |
      16             :    +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : #include "php.h"
      20             : #include "zend_compile.h"
      21             : #include "zend_dfg.h"
      22             : 
      23         440 : int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags) /* {{{ */
      24             : {
      25             :         int set_size;
      26         440 :         zend_basic_block *blocks = cfg->blocks;
      27         440 :         int blocks_count = cfg->blocks_count;
      28             :         zend_bitset tmp, def, use, in, out;
      29             :         int k;
      30             :         uint32_t var_num;
      31             :         int j;
      32             : 
      33         440 :         set_size = dfg->size;
      34         440 :         tmp = dfg->tmp;
      35         440 :         def = dfg->def;
      36         440 :         use = dfg->use;
      37         440 :         in  = dfg->in;
      38         440 :         out = dfg->out;
      39             : 
      40             :         /* Collect "def" and "use" sets */
      41        1233 :         for (j = 0; j < blocks_count; j++) {
      42             :                 zend_op *opline, *end;
      43         793 :                 if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
      44           0 :                         continue;
      45             :                 }
      46             : 
      47         793 :                 opline = op_array->opcodes + blocks[j].start;
      48         793 :                 end = opline + blocks[j].len;
      49        4683 :                 for (; opline < end; opline++) {
      50        3890 :                         if (opline->opcode != ZEND_OP_DATA) {
      51        3881 :                                 zend_op *next = opline + 1;
      52        3881 :                                 if (next < end && next->opcode == ZEND_OP_DATA) {
      53           9 :                                         if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
      54           4 :                                                 var_num = EX_VAR_TO_NUM(next->op1.var);
      55           4 :                                                 if (!DFG_ISSET(def, set_size, j, var_num)) {
      56           1 :                                                         DFG_SET(use, set_size, j, var_num);
      57             :                                                 }
      58             :                                         }
      59           9 :                                         if (next->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
      60           0 :                                                 var_num = EX_VAR_TO_NUM(next->op2.var);
      61           0 :                                                 if (!DFG_ISSET(def, set_size, j, var_num)) {
      62           0 :                                                         DFG_SET(use, set_size, j, var_num);
      63             :                                                 }
      64             :                                         }
      65             :                                 }
      66        3881 :                                 if (opline->op1_type == IS_CV) {
      67         667 :                                         var_num = EX_VAR_TO_NUM(opline->op1.var);
      68         667 :                                         switch (opline->opcode) {
      69           3 :                                         case ZEND_ADD_ARRAY_ELEMENT:
      70             :                                         case ZEND_INIT_ARRAY:
      71           3 :                                                 if ((build_flags & ZEND_SSA_RC_INFERENCE)
      72           3 :                                                                 || (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
      73             :                                                         goto op1_def;
      74             :                                                 }
      75           3 :                                                 goto op1_use;
      76         184 :                                         case ZEND_FE_RESET_R:
      77             :                                         case ZEND_SEND_VAR:
      78             :                                         case ZEND_CAST:
      79             :                                         case ZEND_QM_ASSIGN:
      80             :                                         case ZEND_JMP_SET:
      81             :                                         case ZEND_COALESCE:
      82         184 :                                                 if (build_flags & ZEND_SSA_RC_INFERENCE) {
      83           0 :                                                         goto op1_def;
      84             :                                                 }
      85         184 :                                                 goto op1_use;
      86           0 :                                         case ZEND_YIELD:
      87           0 :                                                 if ((build_flags & ZEND_SSA_RC_INFERENCE)
      88           0 :                                                                 || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
      89             :                                                         goto op1_def;
      90             :                                                 }
      91           0 :                                                 goto op1_use;
      92           0 :                                         case ZEND_UNSET_VAR:
      93           0 :                                                 ZEND_ASSERT(opline->extended_value & ZEND_QUICK_SET);
      94             :                                                 /* break missing intentionally */
      95             :                                         case ZEND_ASSIGN:
      96             :                                         case ZEND_ASSIGN_REF:
      97             :                                         case ZEND_BIND_GLOBAL:
      98             :                                         case ZEND_BIND_STATIC:
      99             :                                         case ZEND_SEND_VAR_EX:
     100             :                                         case ZEND_SEND_REF:
     101             :                                         case ZEND_SEND_VAR_NO_REF:
     102             :                                         case ZEND_SEND_VAR_NO_REF_EX:
     103             :                                         case ZEND_FE_RESET_RW:
     104             :                                         case ZEND_ASSIGN_ADD:
     105             :                                         case ZEND_ASSIGN_SUB:
     106             :                                         case ZEND_ASSIGN_MUL:
     107             :                                         case ZEND_ASSIGN_DIV:
     108             :                                         case ZEND_ASSIGN_MOD:
     109             :                                         case ZEND_ASSIGN_SL:
     110             :                                         case ZEND_ASSIGN_SR:
     111             :                                         case ZEND_ASSIGN_CONCAT:
     112             :                                         case ZEND_ASSIGN_BW_OR:
     113             :                                         case ZEND_ASSIGN_BW_AND:
     114             :                                         case ZEND_ASSIGN_BW_XOR:
     115             :                                         case ZEND_ASSIGN_POW:
     116             :                                         case ZEND_PRE_INC:
     117             :                                         case ZEND_PRE_DEC:
     118             :                                         case ZEND_POST_INC:
     119             :                                         case ZEND_POST_DEC:
     120             :                                         case ZEND_ASSIGN_DIM:
     121             :                                         case ZEND_ASSIGN_OBJ:
     122             :                                         case ZEND_UNSET_DIM:
     123             :                                         case ZEND_UNSET_OBJ:
     124             :                                         case ZEND_FETCH_DIM_W:
     125             :                                         case ZEND_FETCH_DIM_RW:
     126             :                                         case ZEND_FETCH_DIM_FUNC_ARG:
     127             :                                         case ZEND_FETCH_DIM_UNSET:
     128             :                                         case ZEND_FETCH_OBJ_W:
     129             :                                         case ZEND_FETCH_OBJ_RW:
     130             :                                         case ZEND_FETCH_OBJ_FUNC_ARG:
     131             :                                         case ZEND_FETCH_OBJ_UNSET:
     132             :                                         case ZEND_VERIFY_RETURN_TYPE:
     133           0 : op1_def:
     134             :                                                 /* `def` always come along with dtor or separation,
     135             :                                                  * thus the origin var info might be also `use`d in the feature(CG) */
     136         295 :                                                 DFG_SET(use, set_size, j, var_num);
     137         295 :                                                 DFG_SET(def, set_size, j, var_num);
     138         295 :                                                 break;
     139             :                                         default:
     140         372 : op1_use:
     141         372 :                                                 if (!DFG_ISSET(def, set_size, j, var_num)) {
     142         217 :                                                         DFG_SET(use, set_size, j, var_num);
     143             :                                                 }
     144             :                                         }
     145        3214 :                                 } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
     146         656 :                                         var_num = EX_VAR_TO_NUM(opline->op1.var);
     147         656 :                                         if (!DFG_ISSET(def, set_size, j, var_num)) {
     148          11 :                                                 DFG_SET(use, set_size, j, var_num);
     149             :                                         }
     150         656 :                                         if (opline->opcode == ZEND_VERIFY_RETURN_TYPE) {
     151           4 :                                                 DFG_SET(def, set_size, j, var_num);
     152             :                                         }
     153             :                                 }
     154        3881 :                                 if (opline->op2_type == IS_CV) {
     155         110 :                                         var_num = EX_VAR_TO_NUM(opline->op2.var);
     156         110 :                                         switch (opline->opcode) {
     157           0 :                                                 case ZEND_ASSIGN:
     158           0 :                                                         if (build_flags & ZEND_SSA_RC_INFERENCE) {
     159           0 :                                                                 goto op2_def;
     160             :                                                         }
     161           0 :                                                         goto op2_use;
     162           9 :                                                 case ZEND_BIND_LEXICAL:
     163           9 :                                                         if ((build_flags & ZEND_SSA_RC_INFERENCE) || opline->extended_value) {
     164             :                                                                 goto op2_def;
     165             :                                                         }
     166           5 :                                                         goto op2_use;
     167             :                                                 case ZEND_ASSIGN_REF:
     168             :                                                 case ZEND_FE_FETCH_R:
     169             :                                                 case ZEND_FE_FETCH_RW:
     170           4 : op2_def:
     171             :                                                         // FIXME: include into "use" too ...?
     172           8 :                                                         DFG_SET(use, set_size, j, var_num);
     173           8 :                                                         DFG_SET(def, set_size, j, var_num);
     174           8 :                                                         break;
     175             :                                                 default:
     176         102 : op2_use:
     177         102 :                                                         if (!DFG_ISSET(def, set_size, j, var_num)) {
     178          46 :                                                                 DFG_SET(use, set_size, j, var_num);
     179             :                                                         }
     180         102 :                                                         break;
     181             :                                         }
     182        3771 :                                 } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
     183         200 :                                         var_num = EX_VAR_TO_NUM(opline->op2.var);
     184         200 :                                         if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
     185           0 :                                                 DFG_SET(def, set_size, j, var_num);
     186             :                                         } else {
     187         200 :                                                 if (!DFG_ISSET(def, set_size, j, var_num)) {
     188           2 :                                                         DFG_SET(use, set_size, j, var_num);
     189             :                                                 }
     190             :                                         }
     191             :                                 }
     192        3881 :                                 if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
     193         917 :                                         var_num = EX_VAR_TO_NUM(opline->result.var);
     194         917 :                                         DFG_SET(def, set_size, j, var_num);
     195             :                                 }
     196             :                         }
     197             :                 }
     198             :         }
     199             : 
     200             :         /* Calculate "in" and "out" sets */
     201             :         {
     202         440 :                 uint32_t worklist_len = zend_bitset_len(blocks_count);
     203             :                 zend_bitset worklist;
     204             :                 ALLOCA_FLAG(use_heap);
     205         440 :                 worklist = ZEND_BITSET_ALLOCA(worklist_len, use_heap);
     206         440 :                 memset(worklist, 0, worklist_len * ZEND_BITSET_ELM_SIZE);
     207        1233 :                 for (j = 0; j < blocks_count; j++) {
     208         793 :                         zend_bitset_incl(worklist, j);
     209             :                 }
     210        1729 :                 while (!zend_bitset_empty(worklist, worklist_len)) {
     211             :                         /* We use the last block on the worklist, because predecessors tend to be located
     212             :                          * before the succeeding block, so this converges faster. */
     213         849 :                         j = zend_bitset_last(worklist, worklist_len);
     214         849 :                         zend_bitset_excl(worklist, j);
     215             : 
     216         849 :                         if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
     217           0 :                                 continue;
     218             :                         }
     219         849 :                         if (blocks[j].successors[0] >= 0) {
     220         335 :                                 zend_bitset_copy(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[0]), set_size);
     221         335 :                                 if (blocks[j].successors[1] >= 0) {
     222         244 :                                         zend_bitset_union(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[1]), set_size);
     223             :                                 }
     224             :                         } else {
     225         514 :                                 zend_bitset_clear(DFG_BITSET(out, set_size, j), set_size);
     226             :                         }
     227         849 :                         zend_bitset_union_with_difference(tmp, DFG_BITSET(use, set_size, j), DFG_BITSET(out, set_size, j), DFG_BITSET(def, set_size, j), set_size);
     228         849 :                         if (!zend_bitset_equal(DFG_BITSET(in, set_size, j), tmp, set_size)) {
     229         392 :                                 zend_bitset_copy(DFG_BITSET(in, set_size, j), tmp, set_size);
     230             : 
     231             :                                 /* Add predecessors of changed block to worklist */
     232             :                                 {
     233         392 :                                         int *predecessors = &cfg->predecessors[blocks[j].predecessor_offset];
     234         769 :                                         for (k = 0; k < blocks[j].predecessors_count; k++) {
     235         377 :                                                 zend_bitset_incl(worklist, predecessors[k]);
     236             :                                         }
     237             :                                 }
     238             :                         }
     239             :                 }
     240             : 
     241         440 :                 free_alloca(worklist, use_heap);
     242             :         }
     243             : 
     244         440 :         return SUCCESS;
     245             : }
     246             : /* }}} */
     247             : 
     248             : /*
     249             :  * Local variables:
     250             :  * tab-width: 4
     251             :  * c-basic-offset: 4
     252             :  * indent-tabs-mode: t
     253             :  * End:
     254             :  */

Generated by: LCOV version 1.10

Generated at Mon, 10 Sep 2018 14:11:41 +0000 (10 days ago)

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