Skip to content
Draft
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
22 changes: 10 additions & 12 deletions Zend/Optimizer/block_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
if (src < op_array->opcodes + block->start) {
break;
}
src->result_type = IS_UNUSED;
SET_UNUSED(src->result);
VAR_SOURCE(opline->op1) = NULL;
MAKE_NOP(opline);
++(*opt_count);
Expand All @@ -325,7 +325,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
src->opcode != ZEND_FETCH_OBJ_R &&
src->opcode != ZEND_NEW &&
src->opcode != ZEND_FETCH_THIS) {
src->result_type = IS_UNUSED;
SET_UNUSED(src->result);
MAKE_NOP(opline);
++(*opt_count);
if (src->opcode == ZEND_QM_ASSIGN) {
Expand Down Expand Up @@ -413,8 +413,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
literal_dtor(&ZEND_OP1_LITERAL(opline));
literal_dtor(&ZEND_OP2_LITERAL(opline));
opline->opcode = ZEND_JMP;
opline->op1_type = IS_UNUSED;
opline->op2_type = IS_UNUSED;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
block->successors_count = 1;
block->successors[0] = target;
}
Expand Down Expand Up @@ -821,8 +821,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
opline->opcode = ZEND_CAST;
opline->extended_value = IS_STRING;
COPY_NODE(opline->op1, opline->op2);
opline->op2_type = IS_UNUSED;
opline->op2.var = 0;
SET_UNUSED(opline->op2);
++(*opt_count);
} else if (opline->op2_type == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
Expand All @@ -831,8 +830,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
literal_dtor(&ZEND_OP2_LITERAL(opline));
opline->opcode = ZEND_CAST;
opline->extended_value = IS_STRING;
opline->op2_type = IS_UNUSED;
opline->op2.var = 0;
SET_UNUSED(opline->op2);
++(*opt_count);
} else if (opline->opcode == ZEND_CONCAT &&
(opline->op1_type == IS_CONST ||
Expand Down Expand Up @@ -1148,8 +1146,8 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
zend_op *end = opline + len;
while (opline < end) {
if (opline->opcode == ZEND_FAST_RET &&
opline->op2.num != (uint32_t)-1 &&
opline->op2.num < (uint32_t)j) {
opline->op2.num != (uint16_t)-1 &&
opline->op2.num < (uint16_t)j) {
opline->op2.num = map[opline->op2.num];
}
opline++;
Expand Down Expand Up @@ -1606,7 +1604,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
case ZEND_DO_FCALL_BY_NAME:
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
break;
case ZEND_POST_INC:
case ZEND_POST_DEC:
Expand All @@ -1615,7 +1613,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
case ZEND_POST_INC_STATIC_PROP:
case ZEND_POST_DEC_STATIC_PROP:
opline->opcode -= 2;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
break;
case ZEND_QM_ASSIGN:
case ZEND_BOOL:
Expand Down
3 changes: 1 addition & 2 deletions Zend/Optimizer/dce.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,7 @@ static bool try_remove_var_def(context *ctx, int free_var, int use_chain, zend_o
case ZEND_YIELD:
case ZEND_YIELD_FROM:
case ZEND_ASSERT_CHECK:
def_opline->result_type = IS_UNUSED;
def_opline->result.var = 0;
SET_UNUSED(def_opline->result);
def_op->result_def = -1;
var->definition = -1;
return 1;
Expand Down
26 changes: 11 additions & 15 deletions Zend/Optimizer/dfa_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,10 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
&& zend_string_equals_literal_ci(call_info->callee_func->common.function_name, "in_array")) {

bool strict = 0;
bool has_opdata = op->opcode == ZEND_FRAMELESS_ICALL_3;
bool has_opdata = op->opcode == ZEND_FRAMELESS_ICALL_2 || op->opcode == ZEND_FRAMELESS_ICALL_3;
ZEND_ASSERT(!call_info->is_prototype);

if (has_opdata) {
if (has_opdata && (op + 1)->op1_type == IS_CONST) {
if (zend_is_true(CT_CONSTANT_EX(op_array, (op + 1)->op1.constant))) {
strict = 1;
}
Expand Down Expand Up @@ -801,7 +801,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
if (ssa->vars[ssa_op->result_def].use_chain < 0
&& ssa->vars[ssa_op->result_def].phi_use_chain == NULL) {
opline->opcode = ZEND_JMPZ;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
goto optimize_jmpz;
} else if (opline->op1_type == IS_CONST) {
Expand All @@ -815,7 +815,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
if (ssa->vars[ssa_op->result_def].use_chain < 0
&& ssa->vars[ssa_op->result_def].phi_use_chain == NULL) {
opline->opcode = ZEND_JMPNZ;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
goto optimize_jmpnz;
} else if (opline->op1_type == IS_CONST) {
Expand All @@ -829,7 +829,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
if (ssa->vars[ssa_op->result_def].use_chain < 0
&& ssa->vars[ssa_op->result_def].phi_use_chain == NULL) {
opline->opcode = ZEND_JMPNZ;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
goto optimize_jmpnz;
} else if (opline->op1_type == IS_CONST) {
Expand All @@ -855,7 +855,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
goto optimize_nop;
} else {
opline->opcode = ZEND_JMP;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
COPY_NODE(opline->op1, opline->op2);
take_successor_0(ssa, block_num, block);
Expand All @@ -871,7 +871,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
&& var->use_chain < 0 && var->phi_use_chain == NULL) {
if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op1.constant)) == IS_NULL) {
opline->opcode = ZEND_JMP;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
COPY_NODE(opline->op1, opline->op2);
take_successor_0(ssa, block_num, block);
Expand Down Expand Up @@ -1000,8 +1000,7 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss
ssa->vars[result_var].use_chain = -1;
ssa->ops[def].result_def = -1;

op_array->opcodes[def].result_type = IS_UNUSED;
op_array->opcodes[def].result.var = 0;
SET_UNUSED(op_array->opcodes[def].result);

if (ssa->ops[use].op1_use == result_var) {
ssa->ops[use].op1_use = cv_var;
Expand Down Expand Up @@ -1167,8 +1166,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
opline->opcode = ZEND_QM_ASSIGN;
opline->op1_type = opline->op2_type;
opline->op1.var = opline->op2.var;
opline->op2_type = IS_UNUSED;
opline->op2.num = 0;
SET_UNUSED(opline->op2);
ssa->ops[op_1].op1_use = ssa->ops[op_1].op2_use;
ssa->ops[op_1].op1_use_chain = ssa->ops[op_1].op2_use_chain;
ssa->ops[op_1].op2_use = -1;
Expand Down Expand Up @@ -1216,8 +1214,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
// op_1: #v.? = ADD #?.? [double,long], 0 => #v.? = QM_ASSIGN #?.?

opline->opcode = ZEND_QM_ASSIGN;
opline->op2_type = IS_UNUSED;
opline->op2.num = 0;
SET_UNUSED(opline->op2);
}
} else if (opline->opcode == ZEND_MUL
&& (OP1_INFO() & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_LONG|MAY_BE_DOUBLE))) == 0) {
Expand Down Expand Up @@ -1587,8 +1584,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
opline->result.var = opline->op1.var;
opline->op1_type = opline->op2_type;
opline->op1.var = opline->op2.var;
opline->op2_type = IS_UNUSED;
opline->op2.var = 0;
SET_UNUSED(opline->op2);
opline->opcode = ZEND_QM_ASSIGN;
}
}
Expand Down
5 changes: 2 additions & 3 deletions Zend/Optimizer/pass1.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,9 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
opline->opcode = ZEND_DECLARE_CONST;
opline->op1_type = IS_CONST;
opline->op2_type = IS_CONST;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
opline->op1.constant = send1_opline->op1.constant;
opline->op2.constant = send2_opline->op1.constant;
opline->result.num = 0;

literal_dtor(&ZEND_OP2_LITERAL(init_opline));
MAKE_NOP(init_opline);
Expand Down Expand Up @@ -321,7 +320,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
should_jmp = !should_jmp;
}
literal_dtor(&ZEND_OP1_LITERAL(opline));
opline->op1_type = IS_UNUSED;
SET_UNUSED(opline->op1);
if (should_jmp) {
opline->opcode = ZEND_JMP;
COPY_NODE(opline->op1, opline->op2);
Expand Down
19 changes: 10 additions & 9 deletions Zend/Optimizer/sccp.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,14 +804,15 @@ static inline zend_result ct_eval_func_call_ex(

zend_execute_data *prev_execute_data = EG(current_execute_data);
zend_execute_data *execute_data, dummy_frame;
zend_op dummy_opline;
zend_slim_op dummy_opline;

/* Add a dummy frame to get the correct strict_types behavior. */
memset(&dummy_frame, 0, sizeof(zend_execute_data));
memset(&dummy_opline, 0, sizeof(zend_op));
memset(&dummy_opline, 0, sizeof(zend_slim_op));
dummy_frame.func = (zend_function *) op_array;
dummy_frame.opline = &dummy_opline;
dummy_opline.opcode = ZEND_DO_FCALL;
// FIXME: Do we need this?
// dummy_opline.opcode = ZEND_DO_FCALL;

execute_data = safe_emalloc(num_args, sizeof(zval), ZEND_CALL_FRAME_SLOT * sizeof(zval));
memset(execute_data, 0, sizeof(zend_execute_data));
Expand Down Expand Up @@ -2134,7 +2135,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
if (opline->opcode == ZEND_ASSIGN) {
/* We can't drop the ASSIGN, but we can remove the result. */
if (var->use_chain < 0 && var->phi_use_chain == NULL) {
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
}
return 0;
Expand Down Expand Up @@ -2165,7 +2166,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
case ZEND_YIELD:
case ZEND_YIELD_FROM:
case ZEND_ASSERT_CHECK:
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
zend_ssa_remove_result_def(ssa, ssa_op);
break;
default:
Expand Down Expand Up @@ -2205,7 +2206,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
if (opline->opcode == ZEND_DO_ICALL) {
removed_ops = remove_call(ctx, opline, ssa_op) - 1;
} else {
bool has_op_data = opline->opcode == ZEND_FRAMELESS_ICALL_3;
bool has_op_data = opline->opcode == ZEND_FRAMELESS_ICALL_2 || opline->opcode == ZEND_FRAMELESS_ICALL_3;
zend_ssa_remove_instr(ssa, opline, ssa_op);
removed_ops++;
if (has_op_data) {
Expand Down Expand Up @@ -2237,7 +2238,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
* operand, based on type inference information. Make sure the operand is
* freed and leave further cleanup to DCE. */
opline->opcode = ZEND_FREE;
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
removed_ops++;
} else {
return 0;
Expand All @@ -2247,7 +2248,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
if (opline->opcode == ZEND_DO_ICALL) {
removed_ops = remove_call(ctx, opline, ssa_op);
} else {
bool has_op_data = opline->opcode == ZEND_FRAMELESS_ICALL_3;
bool has_op_data = opline->opcode == ZEND_FRAMELESS_ICALL_2 || opline->opcode == ZEND_FRAMELESS_ICALL_3;
zend_ssa_remove_instr(ssa, opline, ssa_op);
removed_ops++;
if (has_op_data) {
Expand Down Expand Up @@ -2305,7 +2306,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
if (ssa->vars[ssa_op->result_def].use_chain < 0
&& ssa->vars[ssa_op->result_def].phi_use_chain == NULL) {
zend_ssa_remove_result_def(ssa, ssa_op);
opline->result_type = IS_UNUSED;
SET_UNUSED(opline->result);
} else if (opline->opcode != ZEND_PRE_INC &&
opline->opcode != ZEND_PRE_DEC) {
/* op1_def and result_def are different */
Expand Down
23 changes: 18 additions & 5 deletions Zend/Optimizer/zend_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@
#include "zend_dump.h"
#include "zend_smart_str.h"

#define SOP_TO_WOP_OFFSET(node) \
(uint16_t)((int16_t)(node) / (uint16_t)sizeof(zend_slim_op) * (uint16_t)sizeof(zend_op))

#define CRT_OP_JMP_ADDR(op_array, opline, op) \
((((op_array)->fn_flags) & ZEND_ACC_DONE_PASS_TWO) \
? ((zend_op*)(((char*)(opline)) + (int16_t)SOP_TO_WOP_OFFSET((op).num))) \
: OP_JMP_ADDR(opline, op))

#define CRT_OFFSET_TO_OPLINE_NUM(op_array, base, offset) \
((((op_array)->fn_flags) & ZEND_ACC_DONE_PASS_TWO) \
? ((zend_op*)(((char*)(base)) + (int16_t)SOP_TO_WOP_OFFSET(offset))) - op_array->opcodes \
: ZEND_OFFSET_TO_OPLINE(base, offset) - op_array->opcodes)

void zend_dump_ht(HashTable *ht)
{
zend_ulong index;
Expand Down Expand Up @@ -133,7 +146,7 @@ static void zend_dump_unused_op(const zend_op *opline, znode_op op, uint32_t fla
if (ZEND_VM_OP_NUM == (flags & ZEND_VM_OP_MASK)) {
fprintf(stderr, " %u", op.num);
} else if (ZEND_VM_OP_TRY_CATCH == (flags & ZEND_VM_OP_MASK)) {
if (op.num != (uint32_t)-1) {
if (op.num != (uint16_t)-1) {
fprintf(stderr, " try-catch(%u)", op.num);
}
} else if (ZEND_VM_OP_THIS == (flags & ZEND_VM_OP_MASK)) {
Expand Down Expand Up @@ -662,7 +675,7 @@ ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block
if (b) {
fprintf(stderr, " BB%d", b->successors[n++]);
} else {
fprintf(stderr, " %04u", (uint32_t)(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes));
fprintf(stderr, " %04u", (uint32_t)(CRT_OP_JMP_ADDR(op_array, opline, opline->op1) - op_array->opcodes));
}
} else {
zend_dump_unused_op(opline, opline->op1, op1_flags);
Expand All @@ -689,7 +702,7 @@ ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block
if (b) {
fprintf(stderr, " BB%d,", b->successors[n++]);
} else {
fprintf(stderr, " %04u,", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)));
fprintf(stderr, " %04u,", (uint32_t)CRT_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)));
}
} ZEND_HASH_FOREACH_END();
fprintf(stderr, " default:");
Expand Down Expand Up @@ -724,7 +737,7 @@ ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block
if (b) {
fprintf(stderr, " BB%d", b->successors[n++]);
} else {
fprintf(stderr, " %04u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes));
fprintf(stderr, " %04u", (uint32_t)(CRT_OP_JMP_ADDR(op_array, opline, opline->op2) - op_array->opcodes));
}
}
} else {
Expand All @@ -736,7 +749,7 @@ ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block
if (b) {
fprintf(stderr, " BB%d", b->successors[n++]);
} else {
fprintf(stderr, " %04u", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
fprintf(stderr, " %04u", (uint32_t)CRT_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
}
}
if (opline->result_type == IS_CONST) {
Expand Down
Loading