summaryrefslogtreecommitdiff
path: root/ext/opcache/Optimizer/zend_optimizer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache/Optimizer/zend_optimizer.c')
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c121
1 files changed, 118 insertions, 3 deletions
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index 89f5de800d..afd1c15597 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -53,6 +53,25 @@ void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval*
zend_hash_add(ctx->constants, Z_STR_P(name), &val);
}
+zend_uchar zend_compound_assign_to_binary_op(zend_uchar opcode)
+{
+ switch (opcode) {
+ case ZEND_ASSIGN_ADD: return ZEND_ADD;
+ case ZEND_ASSIGN_SUB: return ZEND_SUB;
+ case ZEND_ASSIGN_MUL: return ZEND_MUL;
+ case ZEND_ASSIGN_DIV: return ZEND_DIV;
+ case ZEND_ASSIGN_MOD: return ZEND_MOD;
+ case ZEND_ASSIGN_SL: return ZEND_SL;
+ case ZEND_ASSIGN_SR: return ZEND_SR;
+ case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT;
+ case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR;
+ case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND;
+ case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR;
+ case ZEND_ASSIGN_POW: return ZEND_POW;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+
int zend_optimizer_eval_binary_op(zval *result, zend_uchar opcode, zval *op1, zval *op2) /* {{{ */
{
binary_op_type binary_op = get_binary_op(opcode);
@@ -237,11 +256,53 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
zend_op *opline,
zval *val)
{
+ zend_op *target_opline;
+
switch (opline->opcode) {
+ case ZEND_JMPZ:
+ if (zend_is_true(val)) {
+ MAKE_NOP(opline);
+ } else {
+ opline->opcode = ZEND_JMP;
+ COPY_NODE(opline->op1, opline->op2);
+ opline->op2_type = IS_UNUSED;
+ }
+ zval_ptr_dtor_nogc(val);
+ return 1;
+ case ZEND_JMPNZ:
+ if (zend_is_true(val)) {
+ opline->opcode = ZEND_JMP;
+ COPY_NODE(opline->op1, opline->op2);
+ opline->op2_type = IS_UNUSED;
+ } else {
+ MAKE_NOP(opline);
+ }
+ zval_ptr_dtor_nogc(val);
+ return 1;
+ case ZEND_JMPZNZ:
+ if (zend_is_true(val)) {
+ target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
+ } else {
+ target_opline = ZEND_OP2_JMP_ADDR(opline);
+ }
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
+ opline->op1_type = IS_UNUSED;
+ opline->extended_value = 0;
+ opline->opcode = ZEND_JMP;
+ zval_ptr_dtor_nogc(val);
+ return 1;
case ZEND_FREE:
MAKE_NOP(opline);
zval_ptr_dtor_nogc(val);
return 1;
+ case ZEND_SEND_VAR_EX:
+ case ZEND_FETCH_DIM_W:
+ case ZEND_FETCH_DIM_RW:
+ case ZEND_FETCH_DIM_FUNC_ARG:
+ case ZEND_FETCH_DIM_UNSET:
+ case ZEND_ASSIGN_DIM:
+ case ZEND_RETURN_BY_REF:
+ return 0;
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_CATCH:
case ZEND_FETCH_CONSTANT:
@@ -305,6 +366,8 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
zend_op *opline,
zval *val)
{
+ zval tmp;
+
switch (opline->opcode) {
case ZEND_ASSIGN_REF:
case ZEND_FAST_CALL:
@@ -331,7 +394,13 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
break;
case ZEND_INIT_FCALL:
REQUIRES_STRING(val);
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ if (Z_REFCOUNT_P(val) == 1) {
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ } else {
+ ZVAL_STR(&tmp, zend_string_tolower(Z_STR_P(val)));
+ zval_ptr_dtor_nogc(val);
+ val = &tmp;
+ }
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
alloc_cache_slots_op2(op_array, opline, 1);
break;
@@ -482,6 +551,23 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var)
}
}
+void zend_optimizer_remove_live_range_ex(zend_op_array *op_array, uint32_t var, uint32_t start)
+{
+ uint32_t i = 0;
+
+ while (i < op_array->last_live_range) {
+ if (op_array->live_range[i].var == var
+ && op_array->live_range[i].start == start) {
+ op_array->last_live_range--;
+ if (i < op_array->last_live_range) {
+ memmove(&op_array->live_range[i], &op_array->live_range[i+1], (op_array->last_live_range - i) * sizeof(zend_live_range));
+ }
+ break;
+ }
+ i++;
+ }
+}
+
int zend_optimizer_replace_by_const(zend_op_array *op_array,
zend_op *opline,
zend_uchar type,
@@ -973,13 +1059,24 @@ static void zend_optimize(zend_op_array *op_array,
/* pass 11:
* - Compact literals table
*/
- if (ZEND_OPTIMIZER_PASS_11 & ctx->optimization_level) {
+ if ((ZEND_OPTIMIZER_PASS_11 & ctx->optimization_level) &&
+ (!(ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) ||
+ !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level))) {
zend_optimizer_compact_literals(op_array, ctx);
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_11) {
zend_dump_op_array(op_array, 0, "after pass 11", NULL);
}
}
+ if ((ZEND_OPTIMIZER_PASS_13 & ctx->optimization_level) &&
+ (!(ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) ||
+ !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level))) {
+ zend_optimizer_compact_vars(op_array);
+ if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_13) {
+ zend_dump_op_array(op_array, 0, "after pass 13", NULL);
+ }
+ }
+
if (ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level) {
return;
}
@@ -1176,7 +1273,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
for (i = 0; i < call_graph.op_arrays_count; i++) {
func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
if (func_info) {
- zend_dfa_optimize_op_array(call_graph.op_arrays[i], &ctx, &func_info->ssa);
+ zend_dfa_optimize_op_array(call_graph.op_arrays[i], &ctx, &func_info->ssa, func_info->call_map);
}
}
@@ -1186,6 +1283,24 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend
}
}
+ if (ZEND_OPTIMIZER_PASS_11 & optimization_level) {
+ for (i = 0; i < call_graph.op_arrays_count; i++) {
+ zend_optimizer_compact_literals(call_graph.op_arrays[i], &ctx);
+ if (debug_level & ZEND_DUMP_AFTER_PASS_11) {
+ zend_dump_op_array(call_graph.op_arrays[i], 0, "after pass 11", NULL);
+ }
+ }
+ }
+
+ if (ZEND_OPTIMIZER_PASS_13 & optimization_level) {
+ for (i = 0; i < call_graph.op_arrays_count; i++) {
+ zend_optimizer_compact_vars(call_graph.op_arrays[i]);
+ if (debug_level & ZEND_DUMP_AFTER_PASS_13) {
+ zend_dump_op_array(call_graph.op_arrays[i], 0, "after pass 13", NULL);
+ }
+ }
+ }
+
if (ZEND_OPTIMIZER_PASS_12 & optimization_level) {
for (i = 0; i < call_graph.op_arrays_count; i++) {
zend_adjust_fcall_stack_size_graph(call_graph.op_arrays[i]);