]> granicus.if.org Git - php/commitdiff
Keep extra args in the same VM stack segment (after all CV and TMP vars)
authorDmitry Stogov <dmitry@zend.com>
Fri, 27 Jun 2014 08:25:36 +0000 (12:25 +0400)
committerDmitry Stogov <dmitry@zend.com>
Fri, 27 Jun 2014 08:25:36 +0000 (12:25 +0400)
Zend/zend_builtin_functions.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 15c1d689708d370ae4fba18a0e1542103a1b8443..6b972897158ae468d2be2cfc998a23c881436f80 100644 (file)
@@ -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) {
index 46732f25d0aa87a7a206b31ff67c3f9e3c1d7544..3bdf93d28467ccd1c99ca0fd4b8b11bca4db7fcc 100644 (file)
@@ -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) */
index e6e45674d05834ae99cc5b17169e83322afc0755..41ab9622274618958906cacc76301c31e49a75f3 100644 (file)
@@ -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 {
index 2127e1f2a1c2cea2ebf02909fb1c4311000729b4..095295f6984e624e8dd20d1ae11a1b6d15550fd5 100644 (file)
@@ -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);
index 1efed55eb3e5d1f1d9493995a8a059cadeb67327..92e0ede804c28f9db621be32697a734728063bb8 100644 (file)
@@ -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));
index e8ae1341fd240607e9f38d682302a141b2a7c992..433f8133a617c07915acf6bbc7a88f986afddc84 100644 (file)
@@ -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);
index 0534cfd8b1c65efad064491d72779818e6fdf869..1aa0de2342d8db956709dfd9855cd50d93472470 100644 (file)
@@ -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);