diff options
Diffstat (limited to 'ext/opcache/Optimizer/zend_optimizer.c')
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 121 |
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]); |