From 006b8417d11d8f5b3ba88c4e9478df2843c5588a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 15 Jun 2016 23:07:46 +0300 Subject: [PATCH] Added specialized handlers for SEND_VAR/SEND_VAR_EX opcodes. --- Zend/zend_vm_def.h | 46 +++++++++++ Zend/zend_vm_execute.h | 181 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 223 insertions(+), 4 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 331ebdb85d..c53c561ebd 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8523,4 +8523,50 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_undef): ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + + varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (OP1_TYPE == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (OP1_TYPE == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +ZEND_VM_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, NUM, SPEC(QUICK_ARG)) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_C_GOTO(send_var_by_ref); + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +ZEND_VM_C_LABEL(send_var_by_ref): + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF); + } + + varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (OP1_TYPE == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (OP1_TYPE == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_DEFINE_OP(137, ZEND_OP_DATA); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ca5b343cf5..64642024f7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -16994,6 +16994,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -37917,6 +37991,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + + varptr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -63737,6 +63885,21 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SIMPLE_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_QUICK_HANDLER, ZEND_NULL_HANDLER }; static const uint32_t specs[] = { @@ -63789,9 +63952,9 @@ void zend_init_opcodes_handlers(void) 1423 | SPEC_RULE_OP1, 1428 | SPEC_RULE_OP1, 1433 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 4481, + 4496, 1458 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG, - 4481, + 4496, 1468 | SPEC_RULE_OP1, 1473 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1498 | SPEC_RULE_OP1 | SPEC_RULE_OP2, @@ -63840,7 +64003,7 @@ void zend_init_opcodes_handlers(void) 2207 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2232 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2257 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 4481, + 4496, 2282, 2283, 2284, @@ -63924,7 +64087,7 @@ void zend_init_opcodes_handlers(void) 3456 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 3481 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 3506 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 4481 + 4496 }; zend_opcode_handlers = labels; zend_handlers_count = sizeof(labels) / sizeof(void*); @@ -64205,11 +64368,21 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint spec = 4441 | SPEC_RULE_OP1; } break; + case ZEND_SEND_VAR_EX: + if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { + spec = 4486 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG; + } + break; case ZEND_FETCH_DIM_R: if ((!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)))) { spec = 4456 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; + case ZEND_SEND_VAR: + if ((op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0) { + spec = 4481 | SPEC_RULE_OP1; + } + break; default: break; } -- 2.50.0