SEND_VAR_NO_REF optimization

This commit is contained in:
Dmitry Stogov 2014-11-18 14:37:36 +03:00
parent d86b5e2b08
commit e20a727430
5 changed files with 35 additions and 39 deletions

View file

@ -2478,7 +2478,12 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc TSRMLS_DC) /* {{{ *
if (fbc) {
flags |= ZEND_ARG_COMPILE_TIME_BOUND;
}
opline->extended_value = flags;
if ((flags & ZEND_ARG_COMPILE_TIME_BOUND) && !(flags & ZEND_ARG_SEND_BY_REF)) {
opline->opcode = ZEND_SEND_VAR;
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
} else {
opline->extended_value = flags;
}
} else if (fbc) {
opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
}

View file

@ -3062,11 +3062,8 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
zval *varptr, *arg;
SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_VAR);
}
} else {
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_VAR);
}
@ -3081,20 +3078,18 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
if (OP1_TYPE == IS_CV) {
Z_ADDREF_P(varptr);
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY(arg, varptr);
FREE_OP1_IF_VAR();
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY_VALUE(arg, varptr);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}

View file

@ -16482,11 +16482,8 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
zval *varptr, *arg;
SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
return ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
} else {
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
return ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@ -16501,20 +16498,18 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
if (IS_VAR == IS_CV) {
Z_ADDREF_P(varptr);
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY(arg, varptr);
zval_ptr_dtor_nogc(free_op1);
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY_VALUE(arg, varptr);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@ -34276,11 +34271,8 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
zval *varptr, *arg;
SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
return ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
} else {
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
return ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
@ -34295,20 +34287,18 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
if (IS_CV == IS_CV) {
Z_ADDREF_P(varptr);
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY(arg, varptr);
}
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
EX(call)->num_args = opline->op2.num;
ZVAL_COPY_VALUE(arg, varptr);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}

View file

@ -143,8 +143,6 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND | ZEND_ARG_SEND_BY_REF;
} else if (opline->extended_value) {
opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND;
} else {
opline->opcode = ZEND_SEND_VAR;
opline->extended_value = 0;

View file

@ -283,6 +283,14 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
case ZEND_ASSIGN_DIM:
case ZEND_SEPARATE:
return 0;
case ZEND_SEND_VAR:
opline->extended_value = 0;
opline->opcode = ZEND_SEND_VAL;
break;
case ZEND_SEND_VAR_EX:
opline->extended_value = 0;
opline->opcode = ZEND_SEND_VAL_EX;
break;
case ZEND_SEND_VAR_NO_REF:
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {