Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Zend/Optimizer/dce.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ static inline bool may_have_side_effects(
case ZEND_FUNC_NUM_ARGS:
case ZEND_FUNC_GET_ARGS:
case ZEND_ARRAY_KEY_EXISTS:
case ZEND_COPY_TMP:
/* No side effects */
return 0;
case ZEND_FREE:
Expand Down Expand Up @@ -425,10 +426,12 @@ static bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
return 0;
}

if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !is_var_dead(ctx, ssa_op->op1_use)) {
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
if (may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
&& opline->opcode != ZEND_CASE && opline->opcode != ZEND_CASE_STRICT) {
&& opline->opcode != ZEND_CASE
&& opline->opcode != ZEND_CASE_STRICT
&& opline->opcode != ZEND_COPY_TMP) {
free_var = ssa_op->op1_use;
free_var_type = opline->op1_type;
}
Expand Down
10 changes: 10 additions & 0 deletions Zend/Optimizer/pass1.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
collect_constants = 0;
break;
}
case ZEND_DO_UCALL:
case ZEND_DO_FCALL:
case ZEND_DO_FCALL_BY_NAME:
case ZEND_FRAMELESS_ICALL_0:
case ZEND_FRAMELESS_ICALL_1:
case ZEND_FRAMELESS_ICALL_2:
case ZEND_FRAMELESS_ICALL_3:
/* don't collect constants after any UCALL/FCALL/FRAMELESS ICALL */
collect_constants = 0;
break;
case ZEND_STRLEN:
if (opline->op1_type == IS_CONST &&
zend_optimizer_eval_strlen(&result, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
Expand Down
50 changes: 50 additions & 0 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "zend_API.h"
#include "zend_exceptions.h"
#include "zend_interfaces.h"
#include "zend_types.h"
#include "zend_virtual_cwd.h"
#include "zend_multibyte.h"
#include "zend_language_scanner.h"
Expand Down Expand Up @@ -4954,6 +4955,53 @@ static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args)
return SUCCESS;
}

static zend_result zend_compile_func_printf(znode *result, zend_ast_list *args) /* {{{ */
{
/* Special case: printf with a single constant string argument and no format specifiers.
* In this case, just emit ECHO and return the string length if needed. */
if (args->children == 1) {
zend_eval_const_expr(&args->child[0]);
if (args->child[0]->kind != ZEND_AST_ZVAL) {
return FAILURE;
}
zval *format_string = zend_ast_get_zval(args->child[0]);
if (Z_TYPE_P(format_string) != IS_STRING) {
return FAILURE;
}
/* Check if there are any format specifiers */
if (!memchr(Z_STRVAL_P(format_string), '%', Z_STRLEN_P(format_string))) {
/* No format specifiers - just emit ECHO and return string length */
znode format_node;
zend_compile_expr(&format_node, args->child[0]);
zend_emit_op(NULL, ZEND_ECHO, &format_node, NULL);

/* Return the string length as a constant if the result is used */
result->op_type = IS_CONST;
ZVAL_LONG(&result->u.constant, Z_STRLEN_P(format_string));
return SUCCESS;
}
}

/* Fall back to sprintf optimization for format strings with specifiers */
znode rope_result;
if (zend_compile_func_sprintf(&rope_result, args) != SUCCESS) {
return FAILURE;
}

/* printf() returns the amount of bytes written, so just an ECHO of the
* resulting sprintf() optimisation might not be enough. At this early
* stage we can't detect if the result is actually used, so we just emit
* the opcodes and let them be cleaned up by the dead code elimination
* pass in the Zend Optimizer if the result of the printf() is in fact
* unused */
znode copy;
zend_emit_op_tmp(&copy, ZEND_COPY_TMP, &rope_result, NULL);
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);
zend_emit_op_tmp(result, ZEND_STRLEN, &copy, NULL);

return SUCCESS;
}

static zend_result zend_compile_func_clone(znode *result, zend_ast_list *args)
{
znode arg_node;
Expand Down Expand Up @@ -5036,6 +5084,8 @@ static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *
return zend_compile_func_array_key_exists(result, args);
} else if (zend_string_equals_literal(lcname, "sprintf")) {
return zend_compile_func_sprintf(result, args);
} else if (zend_string_equals_literal(lcname, "printf")) {
return zend_compile_func_printf(result, args);
} else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_CLONE))) {
return zend_compile_func_clone(result, args);
} else {
Expand Down
Loading