Browse Source

Refactored optimizer (compile different opimizer passes separately, instead of including *.c file)

pull/788/head
Dmitry Stogov 11 years ago
parent
commit
234af84c04
  1. 24
      ext/opcache/Optimizer/block_pass.c
  2. 11
      ext/opcache/Optimizer/compact_literals.c
  3. 10
      ext/opcache/Optimizer/nop_removal.c
  4. 11
      ext/opcache/Optimizer/optimize_func_calls.c
  5. 10
      ext/opcache/Optimizer/optimize_temp_vars_5.c
  6. 24
      ext/opcache/Optimizer/pass10.c
  7. 49
      ext/opcache/Optimizer/pass1_5.c
  8. 11
      ext/opcache/Optimizer/pass2.c
  9. 11
      ext/opcache/Optimizer/pass3.c
  10. 24
      ext/opcache/Optimizer/pass5.c
  11. 29
      ext/opcache/Optimizer/pass9.c
  12. 104
      ext/opcache/Optimizer/zend_optimizer.c
  13. 54
      ext/opcache/Optimizer/zend_optimizer_internal.h
  14. 10
      ext/opcache/config.m4
  15. 2
      ext/opcache/config.w32

24
ext/opcache/Optimizer/block_pass.c

@ -19,10 +19,18 @@
+----------------------------------------------------------------------+
*/
#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"
#define DEBUG_BLOCKPASS 0
/* Checks if a constant (like "true") may be replaced by its value */
static int zend_get_persistent_constant(zend_string *name, zval *result, int copy TSRMLS_DC ELS_DC)
int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy TSRMLS_DC)
{
zend_constant *c;
char *lookup_name;
@ -619,7 +627,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
zval c = ZEND_OP1_LITERAL(src);
VAR_UNSET(opline->op1);
zval_copy_ctor(&c);
update_op1_const(op_array, opline, &c TSRMLS_CC);
zend_optimizer_update_op1_const(op_array, opline, &c TSRMLS_CC);
literal_dtor(&ZEND_OP1_LITERAL(src));
MAKE_NOP(src);
}
@ -633,7 +641,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
zval c = ZEND_OP1_LITERAL(src);
VAR_UNSET(opline->op2);
zval_copy_ctor(&c);
update_op2_const(op_array, opline, &c TSRMLS_CC);
zend_optimizer_update_op2_const(op_array, opline, &c TSRMLS_CC);
literal_dtor(&ZEND_OP1_LITERAL(src));
MAKE_NOP(src);
}
@ -713,7 +721,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
int flen = FUNCTION_CACHE->funcs[Z_LVAL(ZEND_OP1_LITERAL(fcall))].name_len;
if(flen == sizeof("defined")-1 && zend_binary_strcasecmp(fname, flen, "defined", sizeof("defined")-1) == 0) {
zval c;
if(zend_get_persistent_constant(Z_STR_P(arg), &c, 0 TSRMLS_CC ELS_CC) != 0) {
if(zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, 0 TSRMLS_CC ELS_CC) != 0) {
literal_dtor(arg);
MAKE_NOP(sv);
MAKE_NOP(fcall);
@ -733,7 +741,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
} else if(flen == sizeof("constant")-1 && zend_binary_strcasecmp(fname, flen, "constant", sizeof("constant")-1) == 0) {
zval c;
if(zend_get_persistent_constant(Z_STR_P(arg), &c, 1 TSRMLS_CC ELS_CC) != 0) {
if(zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, 1 TSRMLS_CC ELS_CC) != 0) {
literal_dtor(arg);
MAKE_NOP(sv);
MAKE_NOP(fcall);
@ -1019,7 +1027,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
literal_dtor(&ZEND_OP2_LITERAL(opline));
opline->opcode = ZEND_QM_ASSIGN;
SET_UNUSED(opline->op2);
update_op1_const(op_array, opline, &result TSRMLS_CC);
zend_optimizer_update_op1_const(op_array, opline, &result TSRMLS_CC);
}
EG(error_reporting) = er;
} else if ((opline->opcode == ZEND_BOOL ||
@ -1039,7 +1047,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
ZVAL_NULL(&ZEND_OP1_LITERAL(opline));
}
opline->opcode = ZEND_QM_ASSIGN;
update_op1_const(op_array, opline, &result TSRMLS_CC);
zend_optimizer_update_op1_const(op_array, opline, &result TSRMLS_CC);
} else if ((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) &&
ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
VAR_SOURCE(opline->op1) &&
@ -1939,7 +1947,7 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
#define PASSES 3
static void zend_block_optimization(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
{
zend_cfg cfg;
zend_code_block *cur_block;

11
ext/opcache/Optimizer/compact_literals.c

@ -20,6 +20,15 @@
/* pass 11
* - compact literals table
*/
#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"
#define DEBUG_COMPACT_LITERALS 0
#define LITERAL_VALUE 0x0100
@ -104,7 +113,7 @@ static void optimizer_literal_class_info(literal_info *info,
}
}
static void optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
{
zend_op *opline, *end;
int i, j, n, *map, cache_slots;

10
ext/opcache/Optimizer/nop_removal.c

@ -23,7 +23,15 @@
* - remove NOPs
*/
static void nop_removal(zend_op_array *op_array)
#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_nop_removal(zend_op_array *op_array)
{
zend_op *end, *opline;
uint32_t new_count, i, shift;

11
ext/opcache/Optimizer/optimize_func_calls.c

@ -21,6 +21,14 @@
* - optimize INIT_FCALL_BY_NAME to DO_FCALL
*/
#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"
#define ZEND_OP2_IS_CONST_STRING(opline) \
(ZEND_OP2_TYPE(opline) == IS_CONST && \
Z_TYPE(op_array->literals[(opline)->op2.constant]) == IS_STRING)
@ -30,7 +38,8 @@ typedef struct _optimizer_call_info {
zend_op *opline;
} optimizer_call_info;
static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC) {
void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
{
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
int call = 0;

10
ext/opcache/Optimizer/optimize_temp_vars_5.c

@ -19,6 +19,14 @@
+----------------------------------------------------------------------+
*/
#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"
#define GET_AVAILABLE_T() \
for (i = 0; i < T; i++) { \
if (!taken_T[i]) { \
@ -30,7 +38,7 @@
max = i; \
}
static void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx)
void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
int T = op_array->T;
int offset = op_array->last_var;

24
ext/opcache/Optimizer/pass10.c

@ -1,24 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2014 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@zend.com> |
| Zeev Suraski <zeev@zend.com> |
| Stanislav Malyshev <stas@zend.com> |
| Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
nop_removal(op_array);
}

49
ext/opcache/Optimizer/pass1_5.c

@ -27,9 +27,18 @@
* - pre-evaluate constant function calls
*/
#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"
#define ZEND_IS_CONSTANT_TYPE(t) ((t) == IS_CONSTANT)
if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
{
int i = 0;
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
@ -82,7 +91,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
}
break;
@ -118,9 +127,9 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
MAKE_NOP(opline);
if (opline->result_type == IS_TMP_VAR) {
replace_tmp_by_const(op_array, opline + 1, tv, &res TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline + 1, tv, &res TSRMLS_CC);
} else /* if (opline->result_type == IS_VAR) */ {
replace_var_by_const(op_array, opline + 1, tv, &res TSRMLS_CC);
zend_optimizer_replace_var_by_const(op_array, opline + 1, tv, &res TSRMLS_CC);
}
} else if (opline->extended_value == _IS_BOOL) {
/* T = CAST(X, IS_BOOL) => T = BOOL(X) */
@ -148,7 +157,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
literal_dtor(&ZEND_OP1_LITERAL(opline));
MAKE_NOP(opline);
replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
}
break;
@ -242,7 +251,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
replace_tmp_by_const(op_array, opline, tv, offset TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline, tv, offset TSRMLS_CC);
}
EG(current_execute_data) = orig_execute_data;
break;
@ -255,14 +264,14 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
uint32_t tv = ZEND_RESULT(opline).var;
zval c;
if (!zend_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) {
break;
}
}
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC);
}
/* class constant */
@ -307,7 +316,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) {
ZVAL_DEREF(c);
if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) {
if (!zend_get_persistent_constant(Z_STR_P(c), &t, 1 TSRMLS_CC) ||
if (!zend_optimizer_get_persistent_constant(Z_STR_P(c), &t, 1 TSRMLS_CC) ||
ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
break;
}
@ -323,7 +332,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
}
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
replace_tmp_by_const(op_array, opline, tv, &t TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline, tv, &t TSRMLS_CC);
}
}
}
@ -379,7 +388,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
func->module->type == MODULE_PERSISTENT) {
zval t;
ZVAL_BOOL(&t, 1);
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
@ -412,7 +421,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
}
}
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
@ -424,10 +433,10 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
"defined", sizeof("defined")-1)) {
zval t;
if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 0 TSRMLS_CC)) {
if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 0 TSRMLS_CC)) {
ZVAL_BOOL(&t, 1);
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
@ -440,8 +449,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
"constant", sizeof("constant")-1)) {
zval t;
if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 1 TSRMLS_CC)) {
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 1 TSRMLS_CC)) {
if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
@ -456,7 +465,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
zval t;
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
if (zend_optimizer_replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
@ -472,7 +481,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
zval t;
ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline)));
replace_tmp_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC);
literal_dtor(&ZEND_OP1_LITERAL(opline));
MAKE_NOP(opline);
}
@ -481,11 +490,11 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
{
zval c;
uint32_t tv = ZEND_RESULT(opline).var;
if (!zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0 TSRMLS_CC)) {
if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0 TSRMLS_CC)) {
break;
}
ZVAL_TRUE(&c);
replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC);
zend_optimizer_replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC);
literal_dtor(&ZEND_OP1_LITERAL(opline));
MAKE_NOP(opline);
}

11
ext/opcache/Optimizer/pass2.c

@ -25,7 +25,16 @@
* - optimize static BRKs and CONTs
*/
if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
#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 TSRMLS_DC)
{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;

11
ext/opcache/Optimizer/pass3.c

@ -25,6 +25,14 @@
* - change $i++ to ++$i where possible
*/
#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"
/* compares opcodes with allowing oc1 be _EX of oc2 */
#define SAME_OPCODE_EX(oc1, oc2) ((oc1 == oc2) || (oc1 == ZEND_JMPZ_EX && oc2 == ZEND_JMPZ) || (oc1 == ZEND_JMPNZ_EX && oc2 == ZEND_JMPNZ))
@ -45,7 +53,8 @@
} \
jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num;
if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
void zend_optimizer_pass3(zend_op_array *op_array TSRMLS_DC)
{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
uint32_t *jmp_hitlist;

24
ext/opcache/Optimizer/pass5.c

@ -1,24 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2014 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@zend.com> |
| Zeev Suraski <zeev@zend.com> |
| Stanislav Malyshev <stas@zend.com> |
| Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
zend_block_optimization(op_array, ctx TSRMLS_CC);
}

29
ext/opcache/Optimizer/pass9.c

@ -1,29 +0,0 @@
/*
+----------------------------------------------------------------------+
| Zend OPcache |
+----------------------------------------------------------------------+
| Copyright (c) 1998-2014 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@zend.com> |
| Zeev Suraski <zeev@zend.com> |
| Stanislav Malyshev <stas@zend.com> |
| Dmitry Stogov <dmitry@zend.com> |
+----------------------------------------------------------------------+
*/
/* pass 9
*
* - optimize usage of temporary variables
*/
if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
optimize_temporary_variables(op_array, ctx);
}

104
ext/opcache/Optimizer/zend_optimizer.c

@ -27,15 +27,12 @@
#include "zend_execute.h"
#include "zend_vm.h"
#define OPTIMIZATION_LEVEL \
ZCG(accel_directives).optimization_level
static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
{
zval_dtor(zvalue);
}
static void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value)
void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value)
{
zval val;
@ -47,7 +44,7 @@ static void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name,
zend_hash_add(ctx->constants, Z_STR_P(name), &val);
}
static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
{
zval *val;
@ -58,7 +55,7 @@ static int zend_optimizer_get_collected_constant(HashTable *constants, zval *nam
return 0;
}
static int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name)
int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name)
{
int i = 0;
zend_ulong hash_value = zend_string_hash_val(name);
@ -114,32 +111,9 @@ int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC)
return i;
}
# define LITERAL_LONG(op, val) do { \
zval _c; \
ZVAL_LONG(&_c, val); \
op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
} while (0)
# define LITERAL_BOOL(op, val) do { \
zval _c; \
ZVAL_BOOL(&_c, val); \
op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
} while (0)
# define literal_dtor(zv) do { \
zval_dtor(zv); \
ZVAL_NULL(zv); \
} while (0)
#define COPY_NODE(target, src) do { \
target ## _type = src ## _type; \
target = src; \
} while (0)
static void update_op1_const(zend_op_array *op_array,
zend_op *opline,
zval *val TSRMLS_DC)
void zend_optimizer_update_op1_const(zend_op_array *op_array,
zend_op *opline,
zval *val TSRMLS_DC)
{
if (opline->opcode == ZEND_FREE) {
MAKE_NOP(opline);
@ -170,9 +144,9 @@ static void update_op1_const(zend_op_array *op_array,
}
}
static void update_op2_const(zend_op_array *op_array,
zend_op *opline,
zval *val TSRMLS_DC)
void zend_optimizer_update_op2_const(zend_op_array *op_array,
zend_op *opline,
zval *val TSRMLS_DC)
{
ZEND_OP2_TYPE(opline) = IS_CONST;
if (opline->opcode == ZEND_INIT_FCALL) {
@ -288,10 +262,10 @@ check_numeric:
}
}
static int replace_var_by_const(zend_op_array *op_array,
zend_op *opline,
uint32_t var,
zval *val TSRMLS_DC)
int zend_optimizer_replace_var_by_const(zend_op_array *op_array,
zend_op *opline,
uint32_t var,
zval *val TSRMLS_DC)
{
zend_op *end = op_array->opcodes + op_array->last;
@ -321,7 +295,7 @@ static int replace_var_by_const(zend_op_array *op_array,
default:
break;
}
update_op1_const(op_array, opline, val TSRMLS_CC);
zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC);
break;
}
@ -333,7 +307,7 @@ static int replace_var_by_const(zend_op_array *op_array,
default:
break;
}
update_op2_const(op_array, opline, val TSRMLS_CC);
zend_optimizer_update_op2_const(op_array, opline, val TSRMLS_CC);
break;
}
opline++;
@ -342,11 +316,11 @@ static int replace_var_by_const(zend_op_array *op_array,
return 1;
}
static void replace_tmp_by_const(zend_op_array *op_array,
zend_op *opline,
uint32_t var,
zval *val
TSRMLS_DC)
void zend_optimizer_replace_tmp_by_const(zend_op_array *op_array,
zend_op *opline,
uint32_t var,
zval *val
TSRMLS_DC)
{
zend_op *end = op_array->opcodes + op_array->last;
@ -364,13 +338,13 @@ static void replace_tmp_by_const(zend_op_array *op_array,
zval old_val;
ZVAL_COPY_VALUE(&old_val, val);
zval_copy_ctor(val);
update_op1_const(op_array, opline, val TSRMLS_CC);
zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC);
ZVAL_COPY_VALUE(val, &old_val);
} else if (opline->opcode == ZEND_FREE) {
MAKE_NOP(opline);
break;
} else {
update_op1_const(op_array, opline, val TSRMLS_CC);
zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC);
val = NULL;
break;
}
@ -379,7 +353,7 @@ static void replace_tmp_by_const(zend_op_array *op_array,
if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
ZEND_OP2(opline).var == var) {
update_op2_const(op_array, opline, val TSRMLS_CC);
zend_optimizer_update_op2_const(op_array, opline, val TSRMLS_CC);
/* TMP_VAR may be used only once */
val = NULL;
break;
@ -391,12 +365,6 @@ static void replace_tmp_by_const(zend_op_array *op_array,
}
}
#include "Optimizer/nop_removal.c"
#include "Optimizer/block_pass.c"
#include "Optimizer/optimize_temp_vars_5.c"
#include "Optimizer/compact_literals.c"
#include "Optimizer/optimize_func_calls.c"
static void zend_optimize(zend_op_array *op_array,
zend_optimizer_ctx *ctx TSRMLS_DC)
{
@ -410,7 +378,9 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize series of ADD_STRING and/or ADD_CHAR
* - convert CAST(IS_BOOL,x) into BOOL(x)
*/
#include "Optimizer/pass1_5.c"
if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
zend_optimizer_pass1(op_array, ctx TSRMLS_CC);
}
/* pass 2:
* - convert non-numeric constants to numeric constants in numeric operators
@ -418,14 +388,18 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize static BRKs and CONTs
* - pre-evaluate constant function calls
*/
#include "Optimizer/pass2.c"
if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
zend_optimizer_pass2(op_array TSRMLS_CC);
}
/* pass 3:
* - optimize $i = $i+expr to $i+=expr
* - optimize series of JMPs
* - change $i++ to ++$i where possible
*/
#include "Optimizer/pass3.c"
if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
zend_optimizer_pass3(op_array TSRMLS_CC);
}
/* pass 4:
* - INIT_FCALL_BY_NAME -> DO_FCALL
@ -437,23 +411,29 @@ static void zend_optimize(zend_op_array *op_array,
/* pass 5:
* - CFG optimization
*/
#include "Optimizer/pass5.c"
if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
optimize_cfg(op_array, ctx TSRMLS_CC);
}
/* pass 9:
* - Optimize temp variables usage
*/
#include "Optimizer/pass9.c"
if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
optimize_temporary_variables(op_array, ctx);
}
/* pass 10:
* - remove NOPs
*/
#include "Optimizer/pass10.c"
if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
zend_optimizer_nop_removal(op_array);
}
/* pass 11:
* - Compact literals table
*/
if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
optimizer_compact_literals(op_array, ctx TSRMLS_CC);
zend_optimizer_compact_literals(op_array, ctx TSRMLS_CC);
}
}

54
ext/opcache/Optimizer/zend_optimizer_internal.h

@ -76,4 +76,58 @@ struct _zend_block_source {
zend_block_source *next;
};
#define OPTIMIZATION_LEVEL \
ZCG(accel_directives).optimization_level
#define LITERAL_LONG(op, val) do { \
zval _c; \
ZVAL_LONG(&_c, val); \
op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
} while (0)
#define LITERAL_BOOL(op, val) do { \
zval _c; \
ZVAL_BOOL(&_c, val); \
op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
} while (0)
#define literal_dtor(zv) do { \
zval_dtor(zv); \
ZVAL_NULL(zv); \
} while (0)
#define COPY_NODE(target, src) do { \
target ## _type = src ## _type; \
target = src; \
} while (0)
int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy TSRMLS_DC);
void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value);
int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value);
int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name);
void zend_optimizer_update_op1_const(zend_op_array *op_array,
zend_op *opline,
zval *val TSRMLS_DC);
void zend_optimizer_update_op2_const(zend_op_array *op_array,
zend_op *opline,
zval *val TSRMLS_DC);
int zend_optimizer_replace_var_by_const(zend_op_array *op_array,
zend_op *opline,
uint32_t var,
zval *val TSRMLS_DC);
void zend_optimizer_replace_tmp_by_const(zend_op_array *op_array,
zend_op *opline,
uint32_t var,
zval *val TSRMLS_DC);
void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC);
void zend_optimizer_pass2(zend_op_array *op_array TSRMLS_DC);
void zend_optimizer_pass3(zend_op_array *op_array TSRMLS_DC);
void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC);
void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC);
void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx);
void zend_optimizer_nop_removal(zend_op_array *op_array);
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC);
#endif

10
ext/opcache/config.m4

@ -376,7 +376,15 @@ fi
shared_alloc_shm.c \
shared_alloc_mmap.c \
shared_alloc_posix.c \
Optimizer/zend_optimizer.c,
Optimizer/zend_optimizer.c \
Optimizer/pass1_5.c \
Optimizer/pass2.c \
Optimizer/pass3.c \
Optimizer/optimize_func_calls.c \
Optimizer/block_pass.c \
Optimizer/optimize_temp_vars_5.c \
Optimizer/nop_removal.c \
Optimizer/compact_literals.c,
shared,,,,yes)
PHP_ADD_BUILD_DIR([$ext_builddir/Optimizer], 1)

2
ext/opcache/config.w32

@ -16,7 +16,7 @@ if (PHP_OPCACHE != "no") {
zend_shared_alloc.c \
shared_alloc_win32.c", true);
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c", "opcache", "OptimizerObj");
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", "opcache", "OptimizerObj");
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);

Loading…
Cancel
Save