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 - pass2.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 54 89 60.7 %
Date: 2018-03-13 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       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: 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             : /* pass 2:
      23             :  * - convert non-numeric constants to numeric constants in numeric operators
      24             :  * - optimize constant conditional JMPs
      25             :  */
      26             : 
      27             : #include "php.h"
      28             : #include "Optimizer/zend_optimizer.h"
      29             : #include "Optimizer/zend_optimizer_internal.h"
      30             : #include "zend_API.h"
      31             : #include "zend_constants.h"
      32             : #include "zend_execute.h"
      33             : #include "zend_vm.h"
      34             : 
      35         727 : void zend_optimizer_pass2(zend_op_array *op_array)
      36             : {
      37             :         zend_op *opline;
      38         727 :         zend_op *end = op_array->opcodes + op_array->last;
      39             : 
      40         727 :         opline = op_array->opcodes;
      41       11896 :         while (opline < end) {
      42       10442 :                 switch (opline->opcode) {
      43          14 :                         case ZEND_ADD:
      44             :                         case ZEND_SUB:
      45             :                         case ZEND_MUL:
      46             :                         case ZEND_DIV:
      47             :                         case ZEND_POW:
      48          14 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
      49           6 :                                         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
      50             :                                                 /* don't optimise if it should produce a runtime numeric string error */
      51           0 :                                                 if (is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0)) {
      52           0 :                                                         convert_scalar_to_number(&ZEND_OP1_LITERAL(opline));
      53             :                                                 }
      54             :                                         }
      55             :                                 }
      56             :                                 /* break missing *intentionally* - the assign_op's may only optimize op2 */
      57             :                         case ZEND_ASSIGN_ADD:
      58             :                         case ZEND_ASSIGN_SUB:
      59             :                         case ZEND_ASSIGN_MUL:
      60             :                         case ZEND_ASSIGN_DIV:
      61             :                         case ZEND_ASSIGN_POW:
      62          20 :                                 if (opline->extended_value != 0) {
      63             :                                         /* object tristate op - don't attempt to optimize it! */
      64           0 :                                         break;
      65             :                                 }
      66          20 :                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
      67          14 :                                         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
      68             :                                                 /* don't optimise if it should produce a runtime numeric string error */
      69           0 :                                                 if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) {
      70           0 :                                                         convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
      71             :                                                 }
      72             :                                         }
      73             :                                 }
      74          20 :                                 break;
      75             : 
      76           0 :                         case ZEND_MOD:
      77             :                         case ZEND_SL:
      78             :                         case ZEND_SR:
      79           0 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
      80           0 :                                         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_LONG) {
      81             :                                                 /* don't optimise if it should produce a runtime numeric string error */
      82           0 :                                                 if (!(Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING
      83           0 :                                                         && !is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0))) {
      84           0 :                                                         convert_to_long(&ZEND_OP1_LITERAL(opline));
      85             :                                                 }
      86             :                                         }
      87             :                                 }
      88             :                                 /* break missing *intentionally - the assign_op's may only optimize op2 */
      89             :                         case ZEND_ASSIGN_MOD:
      90             :                         case ZEND_ASSIGN_SL:
      91             :                         case ZEND_ASSIGN_SR:
      92           0 :                                 if (opline->extended_value != 0) {
      93             :                                         /* object tristate op - don't attempt to optimize it! */
      94           0 :                                         break;
      95             :                                 }
      96           0 :                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
      97           0 :                                         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
      98             :                                                 /* don't optimise if it should produce a runtime numeric string error */
      99           0 :                                                 if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING
     100           0 :                                                         && !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) {
     101           0 :                                                         convert_to_long(&ZEND_OP2_LITERAL(opline));
     102             :                                                 }
     103             :                                         }
     104             :                                 }
     105           0 :                                 break;
     106             : 
     107         153 :                         case ZEND_CONCAT:
     108             :                         case ZEND_FAST_CONCAT:
     109         153 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     110         118 :                                         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
     111           0 :                                                 convert_to_string(&ZEND_OP1_LITERAL(opline));
     112             :                                         }
     113             :                                 }
     114             :                                 /* break missing *intentionally - the assign_op's may only optimize op2 */
     115             :                         case ZEND_ASSIGN_CONCAT:
     116         157 :                                 if (opline->extended_value != 0) {
     117             :                                         /* object tristate op - don't attempt to optimize it! */
     118           0 :                                         break;
     119             :                                 }
     120         157 :                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
     121         144 :                                         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
     122           0 :                                                 convert_to_string(&ZEND_OP2_LITERAL(opline));
     123             :                                         }
     124             :                                 }
     125         157 :                                 break;
     126             : 
     127          61 :                         case ZEND_JMPZ_EX:
     128             :                         case ZEND_JMPNZ_EX:
     129             :                                 /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */
     130             : #if 0
     131             :                                 /* Disabled unsafe pattern: in conjunction with
     132             :                                  * ZEND_VM_SMART_BRANCH() this may improperly eliminate
     133             :                                  * assignment to Ti.
     134             :                                  */
     135             :                                 if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
     136             :                                     ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
     137             :                                     ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
     138             :                                         opline->opcode -= 3;
     139             :                                         SET_UNUSED(opline->result);
     140             :                                 } else
     141             : #endif
     142             :                                 /* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
     143             :                                    in case we know it wouldn't jump */
     144          61 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     145          25 :                                         int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
     146          25 :                                         if (opline->opcode == ZEND_JMPZ_EX) {
     147          15 :                                                 should_jmp = !should_jmp;
     148             :                                         }
     149          25 :                                         if (!should_jmp) {
     150           3 :                                                 opline->opcode = ZEND_QM_ASSIGN;
     151           3 :                                                 SET_UNUSED(opline->op2);
     152             :                                         }
     153             :                                 }
     154          61 :                                 break;
     155             : 
     156         497 :                         case ZEND_JMPZ:
     157             :                         case ZEND_JMPNZ:
     158         497 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     159         233 :                                         int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
     160             : 
     161         233 :                                         if (opline->opcode == ZEND_JMPZ) {
     162         232 :                                                 should_jmp = !should_jmp;
     163             :                                         }
     164         466 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     165         233 :                                         ZEND_OP1_TYPE(opline) = IS_UNUSED;
     166         233 :                                         if (should_jmp) {
     167         223 :                                                 opline->opcode = ZEND_JMP;
     168         223 :                                                 COPY_NODE(opline->op1, opline->op2);
     169             :                                         } else {
     170          10 :                                                 MAKE_NOP(opline);
     171             :                                         }
     172         233 :                                         break;
     173             :                                 }
     174         264 :                                 if ((opline + 1)->opcode == ZEND_JMP) {
     175             :                                         /* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
     176             :                                         /* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
     177          17 :                                         if (ZEND_OP2_JMP_ADDR(opline) == ZEND_OP1_JMP_ADDR(opline + 1)) {
     178             :                                                 /* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
     179           1 :                                                 if (opline->op1_type == IS_CV) {
     180           0 :                                                         opline->opcode = ZEND_CHECK_VAR;
     181           0 :                                                         opline->op2.num = 0;
     182           1 :                                                 } else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
     183           1 :                                                         opline->opcode = ZEND_FREE;
     184           1 :                                                         opline->op2.num = 0;
     185             :                                                 } else {
     186           0 :                                                         MAKE_NOP(opline);
     187             :                                                 }
     188             :                                         } else {
     189          16 :                                                 if (opline->opcode == ZEND_JMPZ) {
     190           6 :                                                         opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(opline + 1));
     191             :                                                 } else {
     192          10 :                                                         opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP2_JMP_ADDR(opline));
     193          10 :                                                         ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(opline + 1));
     194             :                                                 }
     195          16 :                                                 opline->opcode = ZEND_JMPZNZ;
     196             :                                         }
     197             :                                 }
     198         264 :                                 break;
     199             : 
     200           0 :                         case ZEND_JMPZNZ:
     201           0 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     202             :                                         zend_op *target_opline;
     203             : 
     204           0 :                                         if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
     205           0 :                                                 target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); /* JMPNZ */
     206             :                                         } else {
     207           0 :                                                 target_opline = ZEND_OP2_JMP_ADDR(opline); /* JMPZ */
     208             :                                         }
     209           0 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     210           0 :                                         ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
     211           0 :                                         ZEND_OP1_TYPE(opline) = IS_UNUSED;
     212           0 :                                         opline->opcode = ZEND_JMP;
     213             :                                 }
     214           0 :                                 break;
     215             :                 }
     216       10442 :                 opline++;
     217             :         }
     218         727 : }

Generated by: LCOV version 1.10

Generated at Tue, 13 Mar 2018 05:00:39 +0000 (68 days ago)

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