summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-12-12 09:01:42 +0300
committerDmitry Stogov <dmitry@zend.com>2014-12-12 09:01:42 +0300
commit9ea35a37b9425fc0dc392a754dac7e53791f5521 (patch)
tree5b7a2e6b6dc1e49be998d815738dfad6ce36be7c
parent2ea5f7aea4fe0ab7fe7f931040aebb52d3112999 (diff)
downloadphp-git-9ea35a37b9425fc0dc392a754dac7e53791f5521.tar.gz
Make ZEND_INIT_FCALL keep predcalculted size of necessary stack space in opline->op1.num to avoid its recalculation on each execution.
-rw-r--r--Zend/zend_compile.c6
-rw-r--r--Zend/zend_execute.h29
-rw-r--r--Zend/zend_vm_def.h4
-rw-r--r--Zend/zend_vm_execute.h4
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c13
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;