Skip to content

Commit 82d44e6

Browse files
committed
Add a simple optimization to remove nearly all ZEND_SEND_VAL_SPEC_TMP_TMP_HANDLERs
1 parent 2a230dc commit 82d44e6

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

ext/opcache/Optimizer/optimize_func_calls.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
4545
int call = 0;
4646
void *checkpoint;
4747
optimizer_call_info *call_stack;
48+
zend_bool had_fcall;
4849

4950
if (op_array->last < 2) {
5051
return;
@@ -80,6 +81,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
8081
case ZEND_DO_FCALL_BY_NAME:
8182
case ZEND_DO_UNPACK_FCALL:
8283
call--;
84+
had_fcall = call != 0; /* we must not replace ZEND_SEND_VAL after a DO_FCALL inside nested calls */
8385
if (call_stack[call].func && call_stack[call].opline) {
8486
zend_op *fcall = call_stack[call].opline;
8587

@@ -139,13 +141,32 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
139141
}
140142
break;
141143
case ZEND_SEND_VAL_EX:
142-
if (call_stack[call - 1].func) {
143-
if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
144-
/* We won't convert it into_DO_FCALL to emit error at run-time */
145-
call_stack[call - 1].opline = NULL;
146-
} else {
147-
opline->opcode = ZEND_SEND_VAL;
144+
if (!call_stack[call - 1].func) {
145+
break;
146+
}
147+
if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
148+
/* We won't convert it into_DO_FCALL to emit error at run-time */
149+
call_stack[call - 1].opline = NULL;
150+
break;
151+
}
152+
153+
opline->opcode = ZEND_SEND_VAL;
154+
/* break intentionally missing */
155+
case ZEND_SEND_VAL:
156+
if (!had_fcall && opline->op1_type == IS_TMP_VAR) {
157+
zend_op *orig = opline;
158+
while (--orig >= op_array->opcodes) {
159+
if (orig->op1.var == opline->op1.var && orig->op1_type == IS_TMP_VAR) {
160+
orig->op1.var = opline->result.var;
161+
}
162+
if (orig->op2.var == opline->op2.var && orig->op2_type == IS_TMP_VAR) {
163+
orig->op2.var = opline->result.var;
164+
}
165+
if (orig->result.var == opline->op1.var && orig->result_type == IS_TMP_VAR) {
166+
orig->result.var = opline->result.var;
167+
}
148168
}
169+
opline->opcode = ZEND_NOP;
149170
}
150171
break;
151172
case ZEND_SEND_VAR_EX:

0 commit comments

Comments
 (0)