diff options
-rw-r--r-- | Zend/zend_compile.c | 6 | ||||
-rw-r--r-- | Zend/zend_execute.h | 29 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 4 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 4 | ||||
-rw-r--r-- | ext/opcache/Optimizer/optimize_func_calls.c | 13 |
5 files changed, 32 insertions, 24 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 086c7d0db1..44ee16a574 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2509,6 +2509,10 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function * opline = &CG(active_op_array)->opcodes[opnum_init]; opline->extended_value = arg_count; + if (opline->opcode == ZEND_INIT_FCALL) { + opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc); + } + call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0); opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC); opline->op1.num = call_flags; @@ -2662,7 +2666,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL TSRMLS_CC); opline->extended_value = num_args; - + opline->op1.num = zend_vm_calc_used_stack(num_args, fbc); opline->op2_type = IS_CONST; LITERAL_STR(opline->op2, lcname); zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index f13624be47..5ab083e9f2 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -143,15 +143,10 @@ static zend_always_inline zval* zend_vm_stack_alloc(size_t size TSRMLS_DC) return (zval*)top; } -static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC) +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t call_info, zend_function *func, uint32_t used_stack, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC) { - uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args; - zend_execute_data *call; - - if (ZEND_USER_CODE(func->type)) { - used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args); - } - call = (zend_execute_data*)zend_vm_stack_alloc(used_stack * sizeof(zval) TSRMLS_CC); + zend_execute_data *call = (zend_execute_data*)zend_vm_stack_alloc(used_stack TSRMLS_CC); + call->func = func; Z_OBJ(call->This) = object; ZEND_SET_CALL_INFO(call, call_info); @@ -161,6 +156,24 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint3 return call; } +static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, zend_function *func) +{ + uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args; + + if (ZEND_USER_CODE(func->type)) { + used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args); + } + return used_stack * sizeof(zval); +} + +static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC) +{ + uint32_t used_stack = zend_vm_calc_used_stack(num_args, func); + + return zend_vm_stack_push_call_frame_ex(call_info, + func, used_stack, called_scope, object, prev TSRMLS_CC); +} + static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC) { uint32_t first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7490e577d7..c40574c902 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2736,8 +2736,8 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST) CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); } - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame_ex(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->op1.num, NULL, NULL, EX(call) TSRMLS_CC); FREE_OP2(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e542fd538d..64d7789185 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1656,8 +1656,8 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc); } - EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, - fbc, opline->extended_value, NULL, NULL, EX(call) TSRMLS_CC); + EX(call) = zend_vm_stack_push_call_frame_ex(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->op1.num, NULL, NULL, EX(call) TSRMLS_CC); ZEND_VM_NEXT_OPCODE(); } diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index 9031a38f56..5c765cef4e 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -80,11 +80,13 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; + fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]); literal_dtor(&ZEND_OP2_LITERAL(fcall)); fcall->op2.constant = fcall->op2.constant + 1; } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; + fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant + 2]); @@ -92,17 +94,6 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS } else { ZEND_ASSERT(0); } - } else if (call_stack[call].opline && - call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME && - call_stack[call].opline->extended_value == 0 && - ZEND_OP2_IS_CONST_STRING(call_stack[call].opline)) { - - zend_op *fcall = call_stack[call].opline; - - fcall->opcode = ZEND_INIT_FCALL; - Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]); - literal_dtor(&ZEND_OP2_LITERAL(fcall)); - fcall->op2.constant = fcall->op2.constant + 1; } call_stack[call].func = NULL; call_stack[call].opline = NULL; |