summaryrefslogtreecommitdiff
path: root/ext/opcache/Optimizer/pass3.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache/Optimizer/pass3.c')
-rw-r--r--ext/opcache/Optimizer/pass3.c140
1 files changed, 68 insertions, 72 deletions
diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c
index 00217bf295..ce04e4f7cb 100644
--- a/ext/opcache/Optimizer/pass3.c
+++ b/ext/opcache/Optimizer/pass3.c
@@ -39,31 +39,31 @@
/* we use "jmp_hitlist" to avoid infinity loops during jmp optimization */
#define CHECK_JMP(target, label) \
for (i=0; i<jmp_hitlist_count; i++) { \
- if (jmp_hitlist[i] == ZEND_OP1(&op_array->opcodes[target]).opline_num) { \
+ if (jmp_hitlist[i] == ZEND_OP1_JMP_ADDR(target)) { \
goto label; \
} \
} \
- jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1_JMP_ADDR(target);
#define CHECK_JMP2(target, label) \
for (i=0; i<jmp_hitlist_count; i++) { \
- if (jmp_hitlist[i] == ZEND_OP2(&op_array->opcodes[target]).opline_num) { \
+ if (jmp_hitlist[i] == ZEND_OP2_JMP_ADDR(target)) { \
goto label; \
} \
} \
- jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num;
+ jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2_JMP_ADDR(target);
void zend_optimizer_pass3(zend_op_array *op_array)
{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
- uint32_t *jmp_hitlist;
+ zend_op **jmp_hitlist;
int jmp_hitlist_count;
int i;
uint32_t opline_num = 0;
ALLOCA_FLAG(use_heap);
- jmp_hitlist = (uint32_t *)DO_ALLOCA(sizeof(uint32_t)*op_array->last);
+ jmp_hitlist = (zend_op**)do_alloca(sizeof(zend_op*)*op_array->last, use_heap);
opline = op_array->opcodes;
while (opline < end) {
@@ -93,7 +93,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
- if ((ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_CV)
+ if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_CV))
&& ZEND_OP2(opline).var == ZEND_OP1(next_opline).var &&
(opline->opcode == ZEND_ADD ||
opline->opcode == ZEND_MUL ||
@@ -114,7 +114,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
COPY_NODE(opline->op2, tmp);
}
}
- if ((ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_CV)
+ if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_CV))
&& ZEND_OP1(opline).var == ZEND_OP1(next_opline).var
&& ZEND_OP1_TYPE(opline) == ZEND_OP1_TYPE(next_opline)) {
switch (opline->opcode) {
@@ -169,17 +169,17 @@ void zend_optimizer_pass3(zend_op_array *op_array)
}
/* convert L: JMP L+1 to NOP */
- if (ZEND_OP1(opline).opline_num == opline_num + 1) {
+ if (ZEND_OP1_JMP_ADDR(opline) == opline + 1) {
MAKE_NOP(opline);
goto done_jmp_optimization;
}
/* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */
- while (ZEND_OP1(opline).opline_num < op_array->last
- && op_array->opcodes[ZEND_OP1(opline).opline_num].opcode == ZEND_JMP) {
- int target = ZEND_OP1(opline).opline_num;
+ while (ZEND_OP1_JMP_ADDR(opline) < end
+ && ZEND_OP1_JMP_ADDR(opline)->opcode == ZEND_JMP) {
+ zend_op *target = ZEND_OP1_JMP_ADDR(opline);
CHECK_JMP(target, done_jmp_optimization);
- ZEND_OP1(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op1, ZEND_OP1_JMP_ADDR(target));
}
break;
@@ -189,10 +189,10 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
- while (ZEND_OP2(opline).opline_num < op_array->last) {
- int target = ZEND_OP2(opline).opline_num;
- if (op_array->opcodes[target].opcode == ZEND_JMP) {
- ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ while (ZEND_OP2_JMP_ADDR(opline) < end) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
+ if (target->opcode == ZEND_JMP) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
} else {
break;
}
@@ -204,40 +204,41 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
- while (ZEND_OP2(opline).opline_num < op_array->last) {
- int target = ZEND_OP2(opline).opline_num;
+ while (ZEND_OP2_JMP_ADDR(opline) < end) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
- if (op_array->opcodes[target].opcode == ZEND_JMP) {
+ if (target->opcode == ZEND_JMP) {
/* plain JMP */
/* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */
CHECK_JMP(target, done_jmp_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
- } else if (op_array->opcodes[target].opcode == opline->opcode &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
+ } else if (target->opcode == opline->opcode &&
+ SAME_VAR(opline->op1, target->op1)) {
/* same opcode and same var as this opcode */
/* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */
CHECK_JMP2(target, done_jmp_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
- } else if (op_array->opcodes[target].opcode == opline->opcode + 3 &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+ } else if (target->opcode == opline->opcode + 3 &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to
T = JMPZ_EX(X, L2) */
- ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;opline->opcode += 3;
- COPY_NODE(opline->result, op_array->opcodes[target].result);
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+ opline->opcode += 3;
+ COPY_NODE(opline->result, target->result);
break;
- } else if (op_array->opcodes[target].opcode == INV_COND(opline->opcode) &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ } else if (target->opcode == INV_COND(opline->opcode) &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to
JMPZ(X,L1+1) */
- ZEND_OP2(opline).opline_num = target + 1;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
break;
- } else if (op_array->opcodes[target].opcode == INV_COND_EX(opline->opcode) &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ } else if (target->opcode == INV_COND_EX(opline->opcode) &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to
T = JMPZ_EX(X,L1+1) */
- ZEND_OP2(opline).opline_num = target + 1;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
opline->opcode += 3;
- COPY_NODE(opline->result, op_array->opcodes[target].result);
+ COPY_NODE(opline->result, target->result);
break;
} else {
break;
@@ -256,7 +257,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
/* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
/* convert L: T = JMPZ_EX T,L+1 to NOP */
- if (ZEND_OP2(opline).opline_num == opline_num + 1) {
+ if (ZEND_OP2_JMP_ADDR(opline) == opline + 1) {
if (ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
MAKE_NOP(opline);
} else {
@@ -266,36 +267,38 @@ void zend_optimizer_pass3(zend_op_array *op_array)
goto done_jmp_optimization;
}
- while (ZEND_OP2(opline).opline_num < op_array->last) {
- int target = ZEND_OP2(opline).opline_num;
- if (SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) &&
- SAME_VAR(op_array->opcodes[target].op1, T)) {
+ while (ZEND_OP2_JMP_ADDR(opline) < end) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
+
+ if (SAME_OPCODE_EX(opline->opcode, target->opcode) &&
+ SAME_VAR(target->op1, T)) {
/* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */
- if (op_array->opcodes[target].opcode == opline->opcode) {
+ if (target->opcode == opline->opcode) {
/* change T only if we have _EX opcode there */
- COPY_NODE(T, op_array->opcodes[target].result);
+ COPY_NODE(T, target->result);
}
CHECK_JMP2(target, continue_jmp_ex_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
- } else if (op_array->opcodes[target].opcode == ZEND_JMPZNZ &&
- SAME_VAR(op_array->opcodes[target].op1, T)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+ } else if (target->opcode == ZEND_JMPZNZ &&
+ SAME_VAR(target->op1, T)) {
/* Check for JMPZNZ with same cond variable */
- int new_target;
+ zend_op *new_target;
+
CHECK_JMP2(target, continue_jmp_ex_optimization);
if (opline->opcode == ZEND_JMPZ_EX) {
- new_target = ZEND_OP2(&op_array->opcodes[target]).opline_num;
+ new_target = ZEND_OP2_JMP_ADDR(target);
} else {
/* JMPNZ_EX */
- new_target = op_array->opcodes[target].extended_value;
+ new_target = ZEND_OFFSET_TO_OPLINE(target, target->extended_value);
}
- ZEND_OP2(opline).opline_num = new_target;
- } else if ((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) ||
- op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode)) &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_target);
+ } else if ((target->opcode == INV_EX_COND_EX(opline->opcode) ||
+ target->opcode == INV_EX_COND(opline->opcode)) &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to
JMPZ_EX(X,L1+1) */
- ZEND_OP2(opline).opline_num = target + 1;
- break;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
+ break;
} else {
break;
}
@@ -387,19 +390,19 @@ continue_jmp_ex_optimization:
}
/* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
- while (ZEND_OP2(opline).opline_num < op_array->last
- && op_array->opcodes[ZEND_OP2(opline).opline_num].opcode == ZEND_JMP) {
- int target = ZEND_OP2(opline).opline_num;
+ while (ZEND_OP2_JMP_ADDR(opline) < end
+ && ZEND_OP2_JMP_ADDR(opline)->opcode == ZEND_JMP) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
CHECK_JMP(target, continue_jmpznz_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
}
continue_jmpznz_optimization:
/* JMPZNZ(X,L1,L2), L2: JMP(L3) => JMPZNZ(X,L1,L3), L2: JMP(L3) */
- while (opline->extended_value < op_array->last
- && op_array->opcodes[opline->extended_value].opcode == ZEND_JMP) {
- int target = opline->extended_value;
+ while (ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) < end
+ && ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value)->opcode == ZEND_JMP) {
+ zend_op *target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
CHECK_JMP(target, done_jmp_optimization);
- opline->extended_value = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(target));
}
break;
@@ -414,15 +417,8 @@ continue_jmpznz_optimization:
if (next_op->opcode == ZEND_FREE &&
ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) {
MAKE_NOP(next_op);
- switch (opline->opcode) {
- case ZEND_POST_INC:
- opline->opcode = ZEND_PRE_INC;
- break;
- case ZEND_POST_DEC:
- opline->opcode = ZEND_PRE_DEC;
- break;
- }
- ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED;
+ opline->opcode -= 2;
+ ZEND_RESULT_TYPE(opline) = IS_UNUSED;
}
}
break;
@@ -431,5 +427,5 @@ done_jmp_optimization:
opline++;
opline_num++;
}
- FREE_ALLOCA(jmp_hitlist);
+ free_alloca(jmp_hitlist, use_heap);
}