From: Dmitry Stogov Date: Fri, 27 Jun 2014 08:25:36 +0000 (+0400) Subject: Keep extra args in the same VM stack segment (after all CV and TMP vars) X-Git-Tag: POST_PHPNG_MERGE~90^2~19 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=032f33591a643c0cabe615a016b8f79f2fd9b277;p=php Keep extra args in the same VM stack segment (after all CV and TMP vars) --- diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 15c1d68970..6b97289715 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -436,8 +436,8 @@ ZEND_FUNCTION(func_get_arg) RETURN_FALSE; } - if (ex->extra_args && requested_offset >= ex->func->op_array.num_args) { - arg = ex->extra_args + (requested_offset - ex->func->op_array.num_args); + if (requested_offset >= ex->func->op_array.num_args && (ex->num_args > ex->func->op_array.num_args)) { + arg = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - ex->func->op_array.num_args); } else { arg = ZEND_CALL_ARG(ex, requested_offset + 1); } @@ -469,7 +469,7 @@ ZEND_FUNCTION(func_get_args) i = 0; q = Z_ARRVAL_P(return_value)->arData; p = ZEND_CALL_ARG(ex, 1); - if (ex->extra_args) { + if (ex->num_args > ex->func->op_array.num_args) { while (i < ex->func->op_array.num_args) { q->h = i; q->key = NULL; @@ -482,7 +482,7 @@ ZEND_FUNCTION(func_get_args) q++; i++; } - p = ex->extra_args; + p = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T); } while (i < arg_count) { q->h = i; @@ -1985,14 +1985,14 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TS int i = 0; zval *p = ZEND_CALL_ARG(call, 1); - if (call->extra_args) { + if (call->func->type == ZEND_USER_FUNCTION && (call->num_args > call->func->op_array.num_args)) { while (i < call->func->op_array.num_args) { if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p); zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p); p++; i++; } - p = call->extra_args; + p = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T); } while (i < num_args) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 46732f25d0..3bdf93d284 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -372,7 +372,6 @@ struct _zend_execute_data { void **run_time_cache; zend_execute_data *prev_execute_data; zval *return_value; - zval *extra_args; vm_frame_kind frame_kind; zval old_error_reporting; struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index e6e45674d0..41ab962227 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1531,10 +1531,14 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* * +----------------------------------------+ * EX_CV_NUM(0) ---------> | VAR[0] = ARG[1] | * | ... | + * | VAR[op_array->num_args-1] = ARG[N] | + * | ... | * | VAR[op_array->last_var-1] | - * | VAR[op_array->last_var] | + * | VAR[op_array->last_var] = TMP[0] | * | ... | * | VAR[op_array->last_var+op_array->T-1] | + * | ARG[N+1] (extra_args) | + * | ... | * +----------------------------------------+ */ @@ -1561,9 +1565,9 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da } else { if (UNEXPECTED(EX(num_args) > op_array->num_args)) { - /* move extra args into separate array */ - EX(extra_args) = safe_emalloc(EX(num_args) - op_array->num_args, sizeof(zval), 0); - memcpy(EX(extra_args), EX_VAR_NUM(op_array->num_args), sizeof(zval) * (EX(num_args) - op_array->num_args)); + /* move extra args into separate array after all CV and TMP vars */ + zval *extra_args = EX_VAR_NUM(op_array->last_var + op_array->T); + memmove(extra_args, EX_VAR_NUM(op_array->num_args), sizeof(zval) * (EX(num_args) - op_array->num_args)); } do { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 2127e1f2a1..095295f698 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -210,13 +210,11 @@ static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC) static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uint flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC) { - int used_stack = ZEND_CALL_FRAME_SLOT; + int used_stack = ZEND_CALL_FRAME_SLOT + num_args; zend_execute_data *call; - if (func && (func->type == ZEND_USER_FUNCTION || func->type == ZEND_EVAL_CODE)) { - used_stack += MAX(func->op_array.last_var + func->op_array.T, num_args); - } else { - used_stack += num_args; + if (func->type == ZEND_USER_FUNCTION || func->type == ZEND_EVAL_CODE) { + used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args); } ZEND_VM_STACK_GROW_IF_NEEDED(used_stack); call = (zend_execute_data*)EG(argument_stack)->top; @@ -226,21 +224,19 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_ call->called_scope = called_scope; call->object = object; call->prev_nested_call = prev; - call->extra_args = NULL; EG(argument_stack)->top += used_stack; return call; } static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC) { - if (UNEXPECTED(call->extra_args != NULL)) { - zval *p = call->extra_args + (call->num_args - call->func->op_array.num_args); - zval *end = call->extra_args; + if (UNEXPECTED(call->num_args > call->func->op_array.num_args)) { + zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T); + zval *p = end + (call->num_args - call->func->op_array.num_args); do { p--; i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC); } while (p != end); - efree(end); } } @@ -249,22 +245,9 @@ static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call T zend_uint num_args = call->num_args; if (num_args > 0) { - zval *p; - zval *end; - - if (UNEXPECTED(call->extra_args != NULL)) { - p = call->extra_args + (num_args - call->func->op_array.num_args); - end = call->extra_args; - do { - p--; - i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC); - } while (p != end); - efree(end); - num_args = call->func->op_array.num_args; - } - - p = ZEND_CALL_ARG(call, num_args + 1); - end = p - num_args; + zval *p = ZEND_CALL_ARG(call, num_args + 1); + zval *end = p - num_args;; + do { p--; i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 1efed55eb3..92e0ede804 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -911,7 +911,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS ZVAL_UNDEF(fci->retval); } } -//??? zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC); if (Z_OBJ(EG(This))) { zval_ptr_dtor(&EG(This)); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e8ae1341fd..433f8133a6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3358,7 +3358,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) ZVAL_COPY_VALUE(&tmp, params); array_init_size(params, arg_count - arg_num + 1); - param = EX(extra_args); + param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zend_verify_arg_type(EX(func), arg_num, &tmp, opline->extended_value TSRMLS_CC); zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0534cfd8b1..1aa0de2342 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -949,7 +949,7 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_COPY_VALUE(&tmp, params); array_init_size(params, arg_count - arg_num + 1); - param = EX(extra_args); + param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { zend_verify_arg_type(EX(func), arg_num, &tmp, opline->extended_value TSRMLS_CC); zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);