mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Optimizer cleanup
- all rules from pass2 moved to pass1 - all JMP unrelated rules from pass3 moved to pass1 - pass3 keeps only JMP optimization rules - pass2.c is removed - pass1_5.c remaned to pass1.c ("_5" was related to PHP 5)
This commit is contained in:
parent
a0eef7067b
commit
6cac8d5b3b
@ -19,12 +19,15 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* pass 1
|
||||
* - substitute persistent constants (true, false, null, etc)
|
||||
* - perform compile-time evaluation of constant binary and unary operations
|
||||
/* pass 1 (Simple local optimizations)
|
||||
* - persistent constant substitution (true, false, null, etc)
|
||||
* - constant casting (ADD expects numbers, CONCAT strings, etc)
|
||||
* - simlple constant subexpression elimination
|
||||
* - optimize constant conditional JMPs
|
||||
* - convert CAST(IS_BOOL,x) into BOOL(x)
|
||||
* - pre-evaluate constant function calls
|
||||
* - eliminate FETCH $GLOBALS followed by FETCH_DIM/UNSET_DIM/ISSET_ISEMPTY_DIM
|
||||
* - change $i++ to ++$i where possible
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
@ -37,7 +40,6 @@
|
||||
|
||||
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
{
|
||||
int i = 0;
|
||||
zend_op *opline = op_array->opcodes;
|
||||
zend_op *end = opline + op_array->last;
|
||||
zend_bool collect_constants = (ZEND_OPTIMIZER_PASS_15 & ctx->optimization_level)?
|
||||
@ -49,21 +51,133 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
case ZEND_SUB:
|
||||
case ZEND_MUL:
|
||||
case ZEND_DIV:
|
||||
case ZEND_MOD:
|
||||
case ZEND_POW:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0)) {
|
||||
convert_scalar_to_number(&ZEND_OP1_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) {
|
||||
convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
goto constant_binary_op;
|
||||
}
|
||||
}
|
||||
goto try_compound_assignment;
|
||||
|
||||
case ZEND_MOD:
|
||||
case ZEND_SL:
|
||||
case ZEND_SR:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_LONG) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (!(Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING
|
||||
&& !is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0))) {
|
||||
convert_to_long(&ZEND_OP1_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING
|
||||
&& !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) {
|
||||
convert_to_long(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
goto constant_binary_op;
|
||||
}
|
||||
}
|
||||
goto try_compound_assignment;
|
||||
|
||||
case ZEND_CONCAT:
|
||||
case ZEND_FAST_CONCAT:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
|
||||
convert_to_string(&ZEND_OP1_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
|
||||
convert_to_string(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
goto constant_binary_op;
|
||||
}
|
||||
}
|
||||
goto try_compound_assignment;
|
||||
|
||||
case ZEND_BW_OR:
|
||||
case ZEND_BW_AND:
|
||||
case ZEND_BW_XOR:
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
opline->op2_type == IS_CONST) {
|
||||
|
||||
goto constant_binary_op;
|
||||
} else {
|
||||
zend_op *next_opline;
|
||||
|
||||
try_compound_assignment:
|
||||
next_opline = opline + 1;;
|
||||
while (next_opline < end && next_opline->opcode == ZEND_NOP) {
|
||||
++next_opline;
|
||||
}
|
||||
|
||||
if (next_opline >= end || next_opline->opcode != ZEND_ASSIGN) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* change $i=expr+$i to $i=$i+expr so that the following optimization
|
||||
* works on it. Only do this if we are ignoring operator overloading,
|
||||
* as operand order might be significant otherwise. */
|
||||
if ((ctx->optimization_level & ZEND_OPTIMIZER_IGNORE_OVERLOADING)
|
||||
&& (opline->op2_type & (IS_VAR | IS_CV))
|
||||
&& opline->op2.var == next_opline->op1.var &&
|
||||
(opline->opcode == ZEND_ADD ||
|
||||
opline->opcode == ZEND_MUL ||
|
||||
opline->opcode == ZEND_BW_OR ||
|
||||
opline->opcode == ZEND_BW_AND ||
|
||||
opline->opcode == ZEND_BW_XOR)) {
|
||||
zend_uchar tmp_type = opline->op1_type;
|
||||
znode_op tmp = opline->op1;
|
||||
|
||||
if (opline->opcode != ZEND_ADD
|
||||
|| (opline->op1_type == IS_CONST
|
||||
&& Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_ARRAY)) {
|
||||
/* protection from array add: $a = array + $a is not commutative! */
|
||||
COPY_NODE(opline->op1, opline->op2);
|
||||
COPY_NODE(opline->op2, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (ZEND_IS_BINARY_ASSIGN_OP_OPCODE(opline->opcode)
|
||||
&& (opline->op1_type & (IS_VAR | IS_CV))
|
||||
&& opline->op1.var == next_opline->op1.var
|
||||
&& opline->op1_type == next_opline->op1_type) {
|
||||
opline->extended_value = opline->opcode;
|
||||
opline->opcode = ZEND_ASSIGN_OP;
|
||||
COPY_NODE(opline->result, next_opline->result);
|
||||
MAKE_NOP(next_opline);
|
||||
opline++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_IS_EQUAL:
|
||||
case ZEND_IS_NOT_EQUAL:
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
case ZEND_IS_IDENTICAL:
|
||||
case ZEND_IS_NOT_IDENTICAL:
|
||||
case ZEND_BW_OR:
|
||||
case ZEND_BW_AND:
|
||||
case ZEND_BW_XOR:
|
||||
case ZEND_BOOL_XOR:
|
||||
case ZEND_SPACESHIP:
|
||||
case ZEND_CASE:
|
||||
@ -72,6 +186,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
/* binary operation with constant operands */
|
||||
zval result;
|
||||
|
||||
constant_binary_op:
|
||||
if (zend_optimizer_eval_binary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
literal_dtor(&ZEND_OP2_LITERAL(opline));
|
||||
@ -86,6 +201,37 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_ASSIGN_OP:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (opline->extended_value == ZEND_ADD
|
||||
|| opline->extended_value == ZEND_SUB
|
||||
|| opline->extended_value == ZEND_MUL
|
||||
|| opline->extended_value == ZEND_DIV
|
||||
|| opline->extended_value == ZEND_POW) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) {
|
||||
convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
} else if (opline->extended_value == ZEND_MOD
|
||||
|| opline->extended_value == ZEND_SL
|
||||
|| opline->extended_value == ZEND_SR) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING
|
||||
&& !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) {
|
||||
convert_to_long(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
} else if (opline->extended_value == ZEND_CONCAT) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
|
||||
convert_to_string(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_CAST:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
/* cast of constant operand */
|
||||
@ -559,6 +705,114 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_POST_INC_STATIC_PROP:
|
||||
case ZEND_POST_DEC_STATIC_PROP:
|
||||
case ZEND_POST_INC_OBJ:
|
||||
case ZEND_POST_DEC_OBJ:
|
||||
case ZEND_POST_INC:
|
||||
case ZEND_POST_DEC: {
|
||||
/* POST_INC, FREE => PRE_INC */
|
||||
zend_op *next_op = opline + 1;
|
||||
|
||||
if (next_op >= end) {
|
||||
break;
|
||||
}
|
||||
if (next_op->opcode == ZEND_FREE &&
|
||||
next_op->op1.var == opline->result.var) {
|
||||
MAKE_NOP(next_op);
|
||||
opline->opcode -= 2;
|
||||
opline->result_type = IS_UNUSED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMPZ_EX:
|
||||
case ZEND_JMPNZ_EX:
|
||||
/* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
|
||||
in case we know it wouldn't jump */
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
|
||||
if (opline->opcode == ZEND_JMPZ_EX) {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zval_ptr_dtor_nogc(&ZEND_OP1_LITERAL(opline));
|
||||
ZVAL_TRUE(&ZEND_OP1_LITERAL(opline));
|
||||
opline->op2.num = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (opline->opcode == ZEND_JMPNZ_EX) {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
zval_ptr_dtor_nogc(&ZEND_OP1_LITERAL(opline));
|
||||
ZVAL_FALSE(&ZEND_OP1_LITERAL(opline));
|
||||
opline->op2.num = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
collect_constants = 0;
|
||||
break;
|
||||
|
||||
case ZEND_JMPZ:
|
||||
case ZEND_JMPNZ:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
|
||||
|
||||
if (opline->opcode == ZEND_JMPZ) {
|
||||
should_jmp = !should_jmp;
|
||||
}
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
opline->op1_type = IS_UNUSED;
|
||||
if (should_jmp) {
|
||||
opline->opcode = ZEND_JMP;
|
||||
COPY_NODE(opline->op1, opline->op2);
|
||||
opline->op2.num = 0;
|
||||
} else {
|
||||
MAKE_NOP(opline);
|
||||
break;
|
||||
}
|
||||
} else if ((opline + 1)->opcode == ZEND_JMP) {
|
||||
if (ZEND_OP2_JMP_ADDR(opline) == ZEND_OP1_JMP_ADDR(opline + 1)) {
|
||||
/* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
|
||||
if (opline->op1_type == IS_CV) {
|
||||
opline->opcode = ZEND_CHECK_VAR;
|
||||
opline->op2.num = 0;
|
||||
} else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
|
||||
opline->opcode = ZEND_FREE;
|
||||
opline->op2.num = 0;
|
||||
} else {
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if (opline->opcode == ZEND_JMPZ) {
|
||||
opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(opline + 1));
|
||||
} else {
|
||||
opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP2_JMP_ADDR(opline));
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(opline + 1));
|
||||
}
|
||||
opline->opcode = ZEND_JMPZNZ;
|
||||
}
|
||||
}
|
||||
collect_constants = 0;
|
||||
break;
|
||||
|
||||
case ZEND_JMPZNZ:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zend_op *target_opline;
|
||||
|
||||
if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
|
||||
target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); /* JMPNZ */
|
||||
} else {
|
||||
target_opline = ZEND_OP2_JMP_ADDR(opline); /* JMPZ */
|
||||
}
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
|
||||
opline->op1_type = IS_UNUSED;
|
||||
opline->opcode = ZEND_JMP;
|
||||
}
|
||||
collect_constants = 0;
|
||||
break;
|
||||
|
||||
case ZEND_RETURN:
|
||||
case ZEND_RETURN_BY_REF:
|
||||
case ZEND_GENERATOR_RETURN:
|
||||
@ -568,11 +822,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
case ZEND_FAST_CALL:
|
||||
case ZEND_FAST_RET:
|
||||
case ZEND_JMP:
|
||||
case ZEND_JMPZNZ:
|
||||
case ZEND_JMPZ:
|
||||
case ZEND_JMPNZ:
|
||||
case ZEND_JMPZ_EX:
|
||||
case ZEND_JMPNZ_EX:
|
||||
case ZEND_FE_RESET_R:
|
||||
case ZEND_FE_RESET_RW:
|
||||
case ZEND_FE_FETCH_R:
|
||||
@ -584,6 +833,5 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
opline++;
|
||||
i++;
|
||||
}
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend OPcache |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Andi Gutmans <andi@php.net> |
|
||||
| Zeev Suraski <zeev@php.net> |
|
||||
| Stanislav Malyshev <stas@zend.com> |
|
||||
| Dmitry Stogov <dmitry@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* pass 2:
|
||||
* - convert non-numeric constants to numeric constants in numeric operators
|
||||
* - optimize constant conditional JMPs
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
#include "Optimizer/zend_optimizer.h"
|
||||
#include "Optimizer/zend_optimizer_internal.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_constants.h"
|
||||
#include "zend_execute.h"
|
||||
#include "zend_vm.h"
|
||||
|
||||
void zend_optimizer_pass2(zend_op_array *op_array)
|
||||
{
|
||||
zend_op *opline;
|
||||
zend_op *end = op_array->opcodes + op_array->last;
|
||||
|
||||
opline = op_array->opcodes;
|
||||
while (opline < end) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ADD:
|
||||
case ZEND_SUB:
|
||||
case ZEND_MUL:
|
||||
case ZEND_DIV:
|
||||
case ZEND_POW:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0)) {
|
||||
convert_scalar_to_number(&ZEND_OP1_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) {
|
||||
convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_MOD:
|
||||
case ZEND_SL:
|
||||
case ZEND_SR:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_LONG) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (!(Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING
|
||||
&& !is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0))) {
|
||||
convert_to_long(&ZEND_OP1_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING
|
||||
&& !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) {
|
||||
convert_to_long(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_CONCAT:
|
||||
case ZEND_FAST_CONCAT:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
|
||||
convert_to_string(&ZEND_OP1_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
|
||||
convert_to_string(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_ASSIGN_OP:
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
if (opline->extended_value == ZEND_ADD
|
||||
|| opline->extended_value == ZEND_SUB
|
||||
|| opline->extended_value == ZEND_MUL
|
||||
|| opline->extended_value == ZEND_DIV
|
||||
|| opline->extended_value == ZEND_POW) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) {
|
||||
convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
} else if (opline->extended_value == ZEND_MOD
|
||||
|| opline->extended_value == ZEND_SL
|
||||
|| opline->extended_value == ZEND_SR) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
|
||||
/* don't optimise if it should produce a runtime numeric string error */
|
||||
if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING
|
||||
&& !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) {
|
||||
convert_to_long(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
} else if (opline->extended_value == ZEND_CONCAT) {
|
||||
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
|
||||
convert_to_string(&ZEND_OP2_LITERAL(opline));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMPZ_EX:
|
||||
case ZEND_JMPNZ_EX:
|
||||
/* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */
|
||||
#if 0
|
||||
/* Disabled unsafe pattern: in conjunction with
|
||||
* ZEND_VM_SMART_BRANCH() this may improperly eliminate
|
||||
* assignment to Ti.
|
||||
*/
|
||||
if (opline->op1_type == IS_TMP_VAR &&
|
||||
opline->result_type == IS_TMP_VAR &&
|
||||
opline->op1.var == opline->result.var) {
|
||||
opline->opcode -= 3;
|
||||
SET_UNUSED(opline->result);
|
||||
} else
|
||||
#endif
|
||||
/* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
|
||||
in case we know it wouldn't jump */
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
|
||||
if (opline->opcode == ZEND_JMPZ_EX) {
|
||||
should_jmp = !should_jmp;
|
||||
}
|
||||
if (!should_jmp) {
|
||||
opline->opcode = ZEND_QM_ASSIGN;
|
||||
SET_UNUSED(opline->op2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMPZ:
|
||||
case ZEND_JMPNZ:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
|
||||
|
||||
if (opline->opcode == ZEND_JMPZ) {
|
||||
should_jmp = !should_jmp;
|
||||
}
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
opline->op1_type = IS_UNUSED;
|
||||
if (should_jmp) {
|
||||
opline->opcode = ZEND_JMP;
|
||||
COPY_NODE(opline->op1, opline->op2);
|
||||
} else {
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((opline + 1)->opcode == ZEND_JMP) {
|
||||
/* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
|
||||
/* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
|
||||
if (ZEND_OP2_JMP_ADDR(opline) == ZEND_OP1_JMP_ADDR(opline + 1)) {
|
||||
/* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
|
||||
if (opline->op1_type == IS_CV) {
|
||||
opline->opcode = ZEND_CHECK_VAR;
|
||||
opline->op2.num = 0;
|
||||
} else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
|
||||
opline->opcode = ZEND_FREE;
|
||||
opline->op2.num = 0;
|
||||
} else {
|
||||
MAKE_NOP(opline);
|
||||
}
|
||||
} else {
|
||||
if (opline->opcode == ZEND_JMPZ) {
|
||||
opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(opline + 1));
|
||||
} else {
|
||||
opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP2_JMP_ADDR(opline));
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(opline + 1));
|
||||
}
|
||||
opline->opcode = ZEND_JMPZNZ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMPZNZ:
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zend_op *target_opline;
|
||||
|
||||
if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
|
||||
target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); /* JMPNZ */
|
||||
} else {
|
||||
target_opline = ZEND_OP2_JMP_ADDR(opline); /* JMPZ */
|
||||
}
|
||||
literal_dtor(&ZEND_OP1_LITERAL(opline));
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
|
||||
opline->op1_type = IS_UNUSED;
|
||||
opline->opcode = ZEND_JMP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
opline++;
|
||||
}
|
||||
}
|
@ -19,10 +19,8 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* pass 3:
|
||||
* - optimize $i = $i+expr to $i+=expr
|
||||
/* pass 3: (Jump optimization)
|
||||
* - optimize series of JMPs
|
||||
* - change $i++ to ++$i where possible
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
@ -53,89 +51,29 @@
|
||||
void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
{
|
||||
zend_op *opline;
|
||||
zend_op *end = op_array->opcodes + op_array->last;
|
||||
zend_op *end;
|
||||
zend_op **jmp_hitlist;
|
||||
int jmp_hitlist_count;
|
||||
int i;
|
||||
uint32_t opline_num = 0;
|
||||
ALLOCA_FLAG(use_heap);
|
||||
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
|
||||
return;
|
||||
}
|
||||
|
||||
jmp_hitlist = (zend_op**)do_alloca(sizeof(zend_op*)*op_array->last, use_heap);
|
||||
opline = op_array->opcodes;
|
||||
end = opline + op_array->last;
|
||||
|
||||
while (opline < end) {
|
||||
jmp_hitlist_count = 0;
|
||||
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ADD:
|
||||
case ZEND_SUB:
|
||||
case ZEND_MUL:
|
||||
case ZEND_DIV:
|
||||
case ZEND_MOD:
|
||||
case ZEND_POW:
|
||||
case ZEND_CONCAT:
|
||||
case ZEND_SL:
|
||||
case ZEND_SR:
|
||||
case ZEND_BW_OR:
|
||||
case ZEND_BW_AND:
|
||||
case ZEND_BW_XOR:
|
||||
{
|
||||
zend_op *next_opline = opline + 1;
|
||||
|
||||
while (next_opline < end && next_opline->opcode == ZEND_NOP) {
|
||||
++next_opline;
|
||||
}
|
||||
|
||||
if (next_opline >= end || next_opline->opcode != ZEND_ASSIGN) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* change $i=expr+$i to $i=$i+expr so that the following optimization
|
||||
* works on it. Only do this if we are ignoring operator overloading,
|
||||
* as operand order might be significant otherwise. */
|
||||
if ((ctx->optimization_level & ZEND_OPTIMIZER_IGNORE_OVERLOADING)
|
||||
&& (opline->op2_type & (IS_VAR | IS_CV))
|
||||
&& opline->op2.var == next_opline->op1.var &&
|
||||
(opline->opcode == ZEND_ADD ||
|
||||
opline->opcode == ZEND_MUL ||
|
||||
opline->opcode == ZEND_BW_OR ||
|
||||
opline->opcode == ZEND_BW_AND ||
|
||||
opline->opcode == ZEND_BW_XOR)) {
|
||||
zend_uchar tmp_type = opline->op1_type;
|
||||
znode_op tmp = opline->op1;
|
||||
|
||||
if (opline->opcode != ZEND_ADD
|
||||
|| (opline->op1_type == IS_CONST
|
||||
&& Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_ARRAY)) {
|
||||
/* protection from array add: $a = array + $a is not commutative! */
|
||||
COPY_NODE(opline->op1, opline->op2);
|
||||
COPY_NODE(opline->op2, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (ZEND_IS_BINARY_ASSIGN_OP_OPCODE(opline->opcode)
|
||||
&& (opline->op1_type & (IS_VAR | IS_CV))
|
||||
&& opline->op1.var == next_opline->op1.var
|
||||
&& opline->op1_type == next_opline->op1_type) {
|
||||
opline->extended_value = opline->opcode;
|
||||
opline->opcode = ZEND_ASSIGN_OP;
|
||||
COPY_NODE(opline->result, next_opline->result);
|
||||
MAKE_NOP(next_opline);
|
||||
opline++;
|
||||
opline_num++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMP:
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* convert L: JMP L+1 to NOP */
|
||||
if (ZEND_OP1_JMP_ADDR(opline) == opline + 1) {
|
||||
MAKE_NOP(opline);
|
||||
goto done_jmp_optimization;
|
||||
break;
|
||||
}
|
||||
|
||||
/* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */
|
||||
@ -149,10 +87,6 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
|
||||
case ZEND_JMP_SET:
|
||||
case ZEND_COALESCE:
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (ZEND_OP2_JMP_ADDR(opline) < end) {
|
||||
zend_op *target = ZEND_OP2_JMP_ADDR(opline);
|
||||
if (target->opcode == ZEND_JMP) {
|
||||
@ -162,12 +96,9 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMPZ:
|
||||
case ZEND_JMPNZ:
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (ZEND_OP2_JMP_ADDR(opline) < end) {
|
||||
zend_op *target = ZEND_OP2_JMP_ADDR(opline);
|
||||
|
||||
@ -215,20 +146,12 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zend_uchar T_type = opline->result_type;
|
||||
znode_op T = opline->result;
|
||||
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
|
||||
/* convert L: T = JMPZ_EX T,L+1 to NOP */
|
||||
if (ZEND_OP2_JMP_ADDR(opline) == opline + 1) {
|
||||
if (opline->op1.var == opline->result.var) {
|
||||
MAKE_NOP(opline);
|
||||
} else {
|
||||
opline->opcode = ZEND_BOOL;
|
||||
SET_UNUSED(opline->op2);
|
||||
}
|
||||
goto done_jmp_optimization;
|
||||
opline->opcode = ZEND_BOOL;
|
||||
opline->op2.num = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
while (ZEND_OP2_JMP_ADDR(opline) < end) {
|
||||
@ -238,21 +161,21 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
SAME_VAR(target->op1, T)) {
|
||||
/* convert T=JMPZ_EX(X,L1), L1: JMPZ(T,L2) to
|
||||
JMPZ_EX(X,L2) */
|
||||
CHECK_JMP2(target, continue_jmp_ex_optimization);
|
||||
CHECK_JMP2(target, done_jmp_optimization);
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
|
||||
} else if (target->opcode == opline->opcode &&
|
||||
SAME_VAR(target->op1, T) &&
|
||||
SAME_VAR(target->result, T)) {
|
||||
/* convert T=JMPZ_EX(X,L1), L1: T=JMPZ_EX(T,L2) to
|
||||
JMPZ_EX(X,L2) */
|
||||
CHECK_JMP2(target, continue_jmp_ex_optimization);
|
||||
CHECK_JMP2(target, done_jmp_optimization);
|
||||
ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
|
||||
} else if (target->opcode == ZEND_JMPZNZ &&
|
||||
SAME_VAR(target->op1, T)) {
|
||||
/* Check for JMPZNZ with same cond variable */
|
||||
zend_op *new_target;
|
||||
|
||||
CHECK_JMP2(target, continue_jmp_ex_optimization);
|
||||
CHECK_JMP2(target, done_jmp_optimization);
|
||||
if (opline->opcode == ZEND_JMPZ_EX) {
|
||||
new_target = ZEND_OP2_JMP_ADDR(target);
|
||||
} else {
|
||||
@ -291,92 +214,10 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
} /* while */
|
||||
continue_jmp_ex_optimization:
|
||||
break;
|
||||
#if 0
|
||||
/* If Ti = JMPZ_EX(X, L) and Ti is not used, convert to JMPZ(X, L) */
|
||||
{
|
||||
zend_op *op;
|
||||
for(op = opline+1; op<end; op++) {
|
||||
if(op->result_type == IS_TMP_VAR &&
|
||||
op->result.var == opline->result.var) {
|
||||
break; /* can pass to part 2 */
|
||||
}
|
||||
|
||||
if(op->opcode == ZEND_JMP ||
|
||||
op->opcode == ZEND_JMPZ ||
|
||||
op->opcode == ZEND_JMPZ_EX ||
|
||||
op->opcode == ZEND_JMPNZ ||
|
||||
op->opcode == ZEND_JMPNZ_EX ||
|
||||
op->opcode == ZEND_JMPZNZ ||
|
||||
op->opcode == ZEND_CASE ||
|
||||
op->opcode == ZEND_RETURN ||
|
||||
op->opcode == ZEND_RETURN_BY_REF ||
|
||||
op->opcode == ZEND_FAST_RET ||
|
||||
op->opcode == ZEND_FE_FETCH_R ||
|
||||
op->opcode == ZEND_FE_FETCH_RW ||
|
||||
op->opcode == ZEND_EXIT) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(op->op1_type == IS_TMP_VAR &&
|
||||
op->op1.var == opline->result.var) {
|
||||
goto done_jmp_optimization;
|
||||
}
|
||||
|
||||
if(op->op2_type == IS_TMP_VAR &&
|
||||
op->op2.var == opline->result.var) {
|
||||
goto done_jmp_optimization;
|
||||
}
|
||||
} /* for */
|
||||
|
||||
for(op = &op_array->opcodes[opline->op2.opline_num]; op<end; op++) {
|
||||
|
||||
if(op->result_type == IS_TMP_VAR &&
|
||||
op->result.var == opline->result.var) {
|
||||
break; /* can pass to optimization */
|
||||
}
|
||||
|
||||
if(op->opcode == ZEND_JMP ||
|
||||
op->opcode == ZEND_JMPZ ||
|
||||
op->opcode == ZEND_JMPZ_EX ||
|
||||
op->opcode == ZEND_JMPNZ ||
|
||||
op->opcode == ZEND_JMPNZ_EX ||
|
||||
op->opcode == ZEND_JMPZNZ ||
|
||||
op->opcode == ZEND_CASE ||
|
||||
op->opcode == ZEND_RETURN ||
|
||||
op->opcode == ZEND_RETURN_BY_REF ||
|
||||
op->opcode == ZEND_FAST_RET ||
|
||||
op->opcode == ZEND_FE_FETCH_R ||
|
||||
op->opcode == ZEND_FE_FETCH_RW ||
|
||||
op->opcode == ZEND_EXIT) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(op->op1_type == IS_TMP_VAR &&
|
||||
op->op1.var == opline->result.var) {
|
||||
goto done_jmp_optimization;
|
||||
}
|
||||
|
||||
if(op->op2_type == IS_TMP_VAR &&
|
||||
op->op2.var == opline->result.var) {
|
||||
goto done_jmp_optimization;
|
||||
}
|
||||
}
|
||||
|
||||
opline->opcode = opline->opcode-3; /* JMP_EX -> JMP */
|
||||
SET_UNUSED(opline->result);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_JMPZNZ:
|
||||
if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
|
||||
while (ZEND_OP2_JMP_ADDR(opline) < end
|
||||
&& ZEND_OP2_JMP_ADDR(opline)->opcode == ZEND_JMP) {
|
||||
@ -393,29 +234,9 @@ continue_jmpznz_optimization:
|
||||
opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(target));
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_POST_INC_OBJ:
|
||||
case ZEND_POST_DEC_OBJ:
|
||||
case ZEND_POST_INC:
|
||||
case ZEND_POST_DEC: {
|
||||
/* POST_INC, FREE => PRE_INC */
|
||||
zend_op *next_op = opline + 1;
|
||||
|
||||
if (next_op >= end) {
|
||||
break;
|
||||
}
|
||||
if (next_op->opcode == ZEND_FREE &&
|
||||
next_op->op1.var == opline->result.var) {
|
||||
MAKE_NOP(next_op);
|
||||
opline->opcode -= 2;
|
||||
opline->result_type = IS_UNUSED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
done_jmp_optimization:
|
||||
opline++;
|
||||
opline_num++;
|
||||
}
|
||||
free_alloca(jmp_hitlist, use_heap);
|
||||
}
|
||||
|
@ -934,12 +934,15 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_LIVE_RANGES, "before optimizer", NULL);
|
||||
}
|
||||
|
||||
/* pass 1
|
||||
* - substitute persistent constants (true, false, null, etc)
|
||||
* - perform compile-time evaluation of constant binary and unary operations
|
||||
* - optimize series of ADD_STRING and/or ADD_CHAR
|
||||
/* pass 1 (Simple local optimizations)
|
||||
* - persistent constant substitution (true, false, null, etc)
|
||||
* - constant casting (ADD expects numbers, CONCAT strings, etc)
|
||||
* - simlple constant subexpression elimination
|
||||
* - optimize constant conditional JMPs
|
||||
* - convert CAST(IS_BOOL,x) into BOOL(x)
|
||||
* - pre-evaluate constant function calls
|
||||
* - pre-evaluate constant function calls
|
||||
* - eliminate FETCH $GLOBALS followed by FETCH_DIM/UNSET_DIM/ISSET_ISEMPTY_DIM
|
||||
* - change $i++ to ++$i where possible
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_1 & ctx->optimization_level) {
|
||||
zend_optimizer_pass1(op_array, ctx);
|
||||
@ -948,21 +951,8 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 2:
|
||||
* - convert non-numeric constants to numeric constants in numeric operators
|
||||
* - optimize constant conditional JMPs
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_2 & ctx->optimization_level) {
|
||||
zend_optimizer_pass2(op_array);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_2) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 2", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 3:
|
||||
* - optimize $i = $i+expr to $i+=expr
|
||||
/* pass 3: (Jump optimization)
|
||||
* - optimize series of JMPs
|
||||
* - change $i++ to ++$i where possible
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_3 & ctx->optimization_level) {
|
||||
zend_optimizer_pass3(op_array, ctx);
|
||||
|
@ -25,9 +25,9 @@
|
||||
#include "zend.h"
|
||||
#include "zend_compile.h"
|
||||
|
||||
#define ZEND_OPTIMIZER_PASS_1 (1<<0) /* CSE, STRING construction */
|
||||
#define ZEND_OPTIMIZER_PASS_2 (1<<1) /* Constant conversion and jumps */
|
||||
#define ZEND_OPTIMIZER_PASS_3 (1<<2) /* ++, +=, series of jumps */
|
||||
#define ZEND_OPTIMIZER_PASS_1 (1<<0) /* Simple local optimizations */
|
||||
#define ZEND_OPTIMIZER_PASS_2 (1<<1) /* */
|
||||
#define ZEND_OPTIMIZER_PASS_3 (1<<2) /* Jump optimization */
|
||||
#define ZEND_OPTIMIZER_PASS_4 (1<<3) /* INIT_FCALL_BY_NAME -> DO_FCALL */
|
||||
#define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */
|
||||
#define ZEND_OPTIMIZER_PASS_6 (1<<5) /* DFA based optimization */
|
||||
|
@ -93,7 +93,6 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
|
||||
zend_op *zend_optimizer_get_loop_var_def(const zend_op_array *op_array, zend_op *free_opline);
|
||||
|
||||
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void zend_optimizer_pass2(zend_op_array *op_array);
|
||||
void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
|
@ -296,8 +296,7 @@ int main() {
|
||||
shared_alloc_mmap.c \
|
||||
shared_alloc_posix.c \
|
||||
Optimizer/zend_optimizer.c \
|
||||
Optimizer/pass1_5.c \
|
||||
Optimizer/pass2.c \
|
||||
Optimizer/pass1.c \
|
||||
Optimizer/pass3.c \
|
||||
Optimizer/optimize_func_calls.c \
|
||||
Optimizer/block_pass.c \
|
||||
|
@ -38,7 +38,7 @@ if (PHP_OPCACHE != "no") {
|
||||
}
|
||||
}
|
||||
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c", "opcache", "OptimizerObj");
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c", "opcache", "OptimizerObj");
|
||||
|
||||
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user