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 - optimize_temp_vars_5.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 85 99 85.9 %
Date: 2017-10-15 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2017 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: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Stanislav Malyshev <stas@zend.com>                          |
      18             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : #include "php.h"
      23             : #include "Optimizer/zend_optimizer.h"
      24             : #include "Optimizer/zend_optimizer_internal.h"
      25             : #include "zend_API.h"
      26             : #include "zend_constants.h"
      27             : #include "zend_execute.h"
      28             : #include "zend_vm.h"
      29             : #include "zend_bitset.h"
      30             : 
      31             : #define GET_AVAILABLE_T()                                       \
      32             :         for (i = 0; i < T; i++) {                            \
      33             :                 if (!zend_bitset_in(taken_T, i)) {      \
      34             :                         break;                                                  \
      35             :                 }                                                                       \
      36             :         }                                                                               \
      37             :         zend_bitset_incl(taken_T, i);                   \
      38             :         if (i > max) {                                                       \
      39             :                 max = i;                                                        \
      40             :         }
      41             : 
      42         721 : void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx)
      43             : {
      44         721 :         int T = op_array->T;
      45         721 :         int offset = op_array->last_var;
      46             :         uint32_t bitset_len;
      47             :         zend_bitset taken_T;    /* T index in use */
      48             :         zend_op **start_of_T;   /* opline where T is first used */
      49             :         zend_bitset valid_T;    /* Is the map_T valid */
      50             :         int *map_T;                             /* Map's the T to its new index */
      51             :         zend_op *opline, *end;
      52             :         int currT;
      53             :         int i;
      54         721 :         int max = -1;
      55         721 :         int var_to_free = -1;
      56        1442 :         void *checkpoint = zend_arena_checkpoint(ctx->arena);
      57             : 
      58         721 :         bitset_len = zend_bitset_len(T);
      59        1442 :         taken_T = (zend_bitset) zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
      60        1442 :         start_of_T = (zend_op **) zend_arena_alloc(&ctx->arena, T * sizeof(zend_op *));
      61        1442 :         valid_T = (zend_bitset) zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
      62        1442 :         map_T = (int *) zend_arena_alloc(&ctx->arena, T * sizeof(int));
      63             : 
      64         721 :     end = op_array->opcodes;
      65         721 :     opline = &op_array->opcodes[op_array->last - 1];
      66             : 
      67             :     /* Find T definition points */
      68        9525 :     while (opline >= end) {
      69        8083 :         if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
      70        1980 :                         start_of_T[VAR_NUM(ZEND_RESULT(opline).var) - offset] = opline;
      71             :                 }
      72        8083 :                 opline--;
      73             :         }
      74             : 
      75         721 :         zend_bitset_clear(valid_T, bitset_len);
      76         721 :         zend_bitset_clear(taken_T, bitset_len);
      77             : 
      78         721 :     end = op_array->opcodes;
      79         721 :     opline = &op_array->opcodes[op_array->last - 1];
      80             : 
      81        9525 :     while (opline >= end) {
      82        8083 :                 if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_TMP_VAR))) {
      83        1578 :                         currT = VAR_NUM(ZEND_OP1(opline).var) - offset;
      84        1578 :                         if (opline->opcode == ZEND_ROPE_END) {
      85          28 :                                 int num = (((opline->extended_value + 1) * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
      86             :                                 int var;
      87             : 
      88          28 :                                 var = max;
      89          74 :                                 while (var >= 0 && !zend_bitset_in(taken_T, var)) {
      90          18 :                                         var--;
      91             :                                 }
      92          28 :                                 max = MAX(max, var + num);
      93          28 :                                 var = var + 1;
      94          28 :                                 map_T[currT] = var;
      95          28 :                                 zend_bitset_incl(valid_T, currT);
      96          28 :                                 zend_bitset_incl(taken_T, var);
      97          28 :                                 ZEND_OP1(opline).var = NUM_VAR(var + offset);
      98          96 :                                 while (num > 1) {
      99          40 :                                         num--;
     100          40 :                                         zend_bitset_incl(taken_T, var + num);
     101             :                                 }
     102             :                         } else {
     103        1550 :                                 if (!zend_bitset_in(valid_T, currT)) {
     104        1457 :                                         int use_new_var = 0;
     105             : 
     106             :                                         /* Code in "finally" blocks may modify temorary variables.
     107             :                                          * We allocate new temporaries for values that need to
     108             :                                          * relive FAST_CALLs.
     109             :                                          */
     110        1467 :                                         if ((op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) &&
     111           2 :                                             (opline->opcode == ZEND_RETURN ||
     112           2 :                                              opline->opcode == ZEND_GENERATOR_RETURN ||
     113           2 :                                              opline->opcode == ZEND_RETURN_BY_REF ||
     114           2 :                                              opline->opcode == ZEND_FREE ||
     115           2 :                                              opline->opcode == ZEND_FE_FREE)) {
     116           0 :                                                 zend_op *curr = opline;
     117             : 
     118           0 :                                                 while (--curr >= end) {
     119           0 :                                                         if (curr->opcode == ZEND_FAST_CALL) {
     120           0 :                                                                 use_new_var = 1;
     121           0 :                                                                 break;
     122           0 :                                                         } else if (curr->opcode != ZEND_FREE &&
     123           0 :                                                                    curr->opcode != ZEND_FE_FREE &&
     124           0 :                                                                    curr->opcode != ZEND_VERIFY_RETURN_TYPE &&
     125           0 :                                                                    curr->opcode != ZEND_DISCARD_EXCEPTION) {
     126           0 :                                                                 break;
     127             :                                                         }
     128             :                                                 }
     129             :                                         }
     130        1457 :                                         if (use_new_var) {
     131           0 :                                                 i = ++max;
     132           0 :                                                 zend_bitset_incl(taken_T, i);
     133             :                                         } else {
     134        1457 :                                                 GET_AVAILABLE_T();
     135             :                                         }
     136        1457 :                                         map_T[currT] = i;
     137        1457 :                                         zend_bitset_incl(valid_T, currT);
     138             :                                 }
     139        1550 :                                 ZEND_OP1(opline).var = NUM_VAR(map_T[currT] + offset);
     140             :                         }
     141             :                 }
     142             : 
     143        8083 :                 if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))) {
     144         342 :                         currT = VAR_NUM(ZEND_OP2(opline).var) - offset;
     145         342 :                         if (!zend_bitset_in(valid_T, currT)) {
     146         342 :                                 GET_AVAILABLE_T();
     147         342 :                                 map_T[currT] = i;
     148         342 :                                 zend_bitset_incl(valid_T, currT);
     149             :                         }
     150         342 :                         ZEND_OP2(opline).var = NUM_VAR(map_T[currT] + offset);
     151             :                 }
     152             : 
     153        8083 :                 if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) {
     154        1980 :                         currT = VAR_NUM(ZEND_RESULT(opline).var) - offset;
     155        1980 :                         if (zend_bitset_in(valid_T, currT)) {
     156        1978 :                                 if (start_of_T[currT] == opline) {
     157             :                                         /* ZEND_FAST_CALL can not share temporary var with others
     158             :                                          * since the fast_var could also be set by ZEND_HANDLE_EXCEPTION
     159             :                                          * which could be ahead of it */
     160        1826 :                                         if (opline->opcode != ZEND_FAST_CALL) {
     161        1825 :                                                 zend_bitset_excl(taken_T, map_T[currT]);
     162             :                                         }
     163             :                                 }
     164        1978 :                                 ZEND_RESULT(opline).var = NUM_VAR(map_T[currT] + offset);
     165        1978 :                                 if (opline->opcode == ZEND_ROPE_INIT) {
     166          28 :                                         if (start_of_T[currT] == opline) {
     167          28 :                                                 uint32_t num = ((opline->extended_value * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
     168          96 :                                                 while (num > 1) {
     169          40 :                                                         num--;
     170          40 :                                                         zend_bitset_excl(taken_T, map_T[currT]+num);
     171             :                                                 }
     172             :                                         }
     173             :                                 }
     174             :                         } else {
     175             :                                 /* Code which gets here is using a wrongly built opcode such as RECV() */
     176           2 :                                 GET_AVAILABLE_T();
     177           2 :                                 map_T[currT] = i;
     178           2 :                                 zend_bitset_incl(valid_T, currT);
     179           2 :                                 ZEND_RESULT(opline).var = NUM_VAR(i + offset);
     180             :                         }
     181             :                 }
     182             : 
     183        8083 :                 if (var_to_free >= 0) {
     184           0 :                         zend_bitset_excl(taken_T, var_to_free);
     185           0 :                         var_to_free = -1;
     186             :                 }
     187             : 
     188        8083 :                 opline--;
     189             :         }
     190             : 
     191         721 :         if (op_array->live_range) {
     192         297 :                 for (i = 0; i < op_array->last_live_range; i++) {
     193         410 :                         op_array->live_range[i].var =
     194         410 :                                 NUM_VAR(map_T[VAR_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK) - offset] + offset) |
     195         205 :                                 (op_array->live_range[i].var & ZEND_LIVE_MASK);
     196             :                 }
     197             :         }
     198             : 
     199         721 :         zend_arena_release(&ctx->arena, checkpoint);
     200         721 :         op_array->T = max + 1;
     201         721 : }

Generated by: LCOV version 1.10

Generated at Sun, 15 Oct 2017 12:26:23 +0000 (8 days ago)

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