]> granicus.if.org Git - php/commitdiff
Store arg_num in fcall entry
authorNikita Popov <nikic@php.net>
Tue, 25 Feb 2014 23:14:50 +0000 (00:14 +0100)
committerNikita Popov <nikic@php.net>
Wed, 26 Feb 2014 15:40:25 +0000 (16:40 +0100)
Instead of storing the argument number in the znode of the parameter
list, store it in fcall->arg_num. This mainly cleans up the parameter
parsing code, which previously had to duplicate all rules (this
becomes more excessive as more features are added, e.g. named params
would already require a minimum of 14 rules...)

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y

index 76a38d2818cb664bf0ea298b12857630d9f30728..d53cb96cd00b9c86d39f8389f0821d6c0dee996c 100644 (file)
@@ -2552,20 +2552,19 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
 }
 /* }}} */
 
-void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
+void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
 {
        zend_op *opline;
+       zend_function_call_entry *fcall;
+       zend_stack_top(&CG(function_call_stack), (void **) &fcall);
 
        if (is_method && function_name && function_name->op_type == IS_UNUSED) {
                /* clone */
-               if (Z_LVAL(argument_list->u.constant) != 0) {
+               if (fcall->arg_num != 0) {
                        zend_error(E_WARNING, "Clone method does not require arguments");
                }
                opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
        } else {
-               zend_function_call_entry *fcall;
-               zend_stack_top(&CG(function_call_stack), (void **) &fcall);
-
                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                if (fcall->fbc) {
                        opline->opcode = ZEND_DO_FCALL;
@@ -2592,18 +2591,17 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
        opline->result.var = get_temporary_variable(CG(active_op_array));
        opline->result_type = IS_VAR;
        GET_NODE(result, opline->result);
-
-       zend_stack_del_top(&CG(function_call_stack));
-       opline->extended_value = Z_LVAL(argument_list->u.constant);
+       opline->extended_value = fcall->arg_num;
 
        if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
                CG(active_op_array)->used_stack = CG(context).used_stack + 1;
        }
-       CG(context).used_stack -= Z_LVAL(argument_list->u.constant);
+       CG(context).used_stack -= fcall->arg_num;
+       zend_stack_del_top(&CG(function_call_stack));
 }
 /* }}} */
 
-void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{{ */
+void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
 {
        zend_op *opline;
        int original_op = op;
@@ -2614,12 +2612,13 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
 
        zend_stack_top(&CG(function_call_stack), (void **) &fcall);
        function_ptr = fcall->fbc;
+       fcall->arg_num++;
 
        if (original_op == ZEND_SEND_REF) {
                if (function_ptr &&
                    function_ptr->common.function_name &&
                    function_ptr->common.type == ZEND_USER_FUNCTION &&
-                   !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+                   !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
                        zend_error_noreturn(E_COMPILE_ERROR,
                                                "Call-time pass-by-reference has been removed; "
                                                "If you would like to pass argument by reference, modify the declaration of %s().",
@@ -2631,7 +2630,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
        }
 
        if (function_ptr) {
-               if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+               if (ARG_MAY_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
                        if (op == ZEND_SEND_VAR && param->op_type & (IS_VAR|IS_CV)) {
                                send_by_reference = ZEND_ARG_SEND_BY_REF;
                                if (zend_is_function_or_method_call(param)) {
@@ -2642,7 +2641,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
                        } else {
                                op = ZEND_SEND_VAL;
                        }
-               } else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+               } else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
                        send_by_reference = ZEND_ARG_SEND_BY_REF;
                }
        }
@@ -2677,7 +2676,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
                                if (function_ptr) {
                                        zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
                                } else {
-                                       zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
+                                       zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, fcall->arg_num TSRMLS_CC);
                                }
                                break;
                        case ZEND_SEND_REF:
@@ -2703,7 +2702,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
        }
        opline->opcode = op;
        SET_NODE(opline->op1, param);
-       opline->op2.opline_num = offset;
+       opline->op2.opline_num = fcall->arg_num;
        SET_UNUSED(opline->op2);
 
        if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
@@ -2712,12 +2711,13 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
 }
 /* }}} */
 
-void zend_do_unpack_params(znode *params, int offset TSRMLS_DC) /* {{{ */
+void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
 {
        zend_op *opline;
        zend_function_call_entry *fcall;
 
        zend_stack_top(&CG(function_call_stack), (void **) &fcall);
+
        if (fcall->fbc) {
                /* If argument unpacking is used argument numbers and sending modes can no longer be
                 * computed at compile time, thus we need access to EX(call). In order to have it we
@@ -2741,7 +2741,7 @@ void zend_do_unpack_params(znode *params, int offset TSRMLS_DC) /* {{{ */
        opline->opcode = ZEND_SEND_UNPACK;
        SET_NODE(opline->op1, params);
        SET_UNUSED(opline->op2);
-       opline->op2.num = (zend_uint) offset;
+       opline->op2.num = fcall->arg_num;
 }
 /* }}} */
 
@@ -5599,11 +5599,11 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
 }
 /* }}} */
 
-void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC) /* {{{ */
+void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC) /* {{{ */
 {
        znode ctor_result;
 
-       zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
+       zend_do_end_function_call(NULL, &ctor_result, 1, 0 TSRMLS_CC);
        zend_do_free(&ctor_result TSRMLS_CC);
 
        CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
index 0ea3be4f113f3d4b8f4d0773035549e7012ce36f..270c085d0378d36bf2255b9b254a760f0c874c1d 100644 (file)
@@ -365,6 +365,7 @@ typedef struct _zend_function_state {
 
 typedef struct _zend_function_call_entry {
        zend_function *fbc;
+       zend_uint arg_num;
 } zend_function_call_entry;
 
 typedef struct _zend_switch_entry {
@@ -521,7 +522,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int prefix_len TS
 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC);
 void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC);
 int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC);
-void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC);
+void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC);
 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
 void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC);
 void zend_do_handle_exception(TSRMLS_D);
@@ -557,8 +558,8 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
 void zend_do_early_binding(TSRMLS_D);
 ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC);
 
-void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC);
-void zend_do_unpack_params(znode *params, int offset TSRMLS_DC);
+void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC);
+void zend_do_unpack_params(znode *params TSRMLS_DC);
 
 
 void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC);
@@ -588,7 +589,7 @@ void zend_do_pop_object(znode *object TSRMLS_DC);
 
 
 void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC);
-void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC);
+void zend_do_end_new_object(znode *result, const znode *new_token TSRMLS_DC);
 
 void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC);
 
index 5d3f73beafca42e30cc8cfecf29b78fcf25e0186..d3844540cf597a86802e19966bb579ae15c26e53 100644 (file)
@@ -580,19 +580,20 @@ optional_class_type:
 function_call_parameter_list:
                '(' ')' { Z_LVAL($$.u.constant) = 0; }
        |       '(' non_empty_function_call_parameter_list ')'  { $$ = $2; }
-       |       '(' yield_expr ')'      { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$2, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
+       |       '(' yield_expr ')'      { zend_do_pass_param(&$2, ZEND_SEND_VAL TSRMLS_CC); }
 ;
 
 
 non_empty_function_call_parameter_list:
-               expr_without_variable   { Z_LVAL($$.u.constant) = 1;  zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       variable                                { Z_LVAL($$.u.constant) = 1;  zend_do_pass_param(&$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       '&' w_variable                          { Z_LVAL($$.u.constant) = 1;  zend_do_pass_param(&$2, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       T_ELLIPSIS expr                 { Z_LVAL($$.u.constant) = 0;  zend_do_unpack_params(&$2, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       non_empty_function_call_parameter_list ',' expr_without_variable        { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1;  zend_do_pass_param(&$3, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       non_empty_function_call_parameter_list ',' variable                                     { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1;  zend_do_pass_param(&$3, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       non_empty_function_call_parameter_list ',' '&' w_variable                       { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1;  zend_do_pass_param(&$4, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
-       |       non_empty_function_call_parameter_list ',' T_ELLIPSIS expr                      { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant);  zend_do_unpack_params(&$4, Z_LVAL($$.u.constant) TSRMLS_CC); }
+               function_call_parameter
+       |       non_empty_function_call_parameter_list ',' function_call_parameter
+;
+
+function_call_parameter:
+               expr_without_variable   { zend_do_pass_param(&$1, ZEND_SEND_VAL TSRMLS_CC); }
+       |       variable                                { zend_do_pass_param(&$1, ZEND_SEND_VAR TSRMLS_CC); }
+       |       '&' w_variable                  { zend_do_pass_param(&$2, ZEND_SEND_REF TSRMLS_CC); }
+       |       T_ELLIPSIS expr                 { zend_do_unpack_params(&$2 TSRMLS_CC); }
 ;
 
 global_var_list:
@@ -769,14 +770,14 @@ instance_call:
 ;
 
 new_expr:
-               T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+               T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 ;
 
 expr_without_variable:
                T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
        |       variable '=' expr               { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
        |       variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
-       |       variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");  zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
+       |       variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated");  zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
        |       T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
        |       variable T_PLUS_EQUAL expr      { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
        |       variable T_MINUS_EQUAL expr     { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
@@ -890,21 +891,21 @@ lexical_var_list:
 
 function_call:
                namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$3, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
        |       T_NAMESPACE T_NS_SEPARATOR namespace_name { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant);  zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $$.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$5, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
        |       T_NS_SEPARATOR namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(&$2, &$$, &$4, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+               function_call_parameter_list { zend_do_end_function_call(&$2, &$$, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
        |       class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, &$5, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+               function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+               function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+               function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+               function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$3, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
 ;
 
 class_name:
@@ -1117,7 +1118,7 @@ array_method_dereference:
 
 method:
                { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_begin_method_call(&$$ TSRMLS_CC); }
-               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$2, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+               function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
 ;
 
 method_or_not: