summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2014-02-26 00:14:50 +0100
committerNikita Popov <nikic@php.net>2014-02-26 16:40:25 +0100
commit2eae18794945db6c8e2540525b10a59759e0ade9 (patch)
treeb279722e740529682bc1c4bc668bb4351dba4df9
parentcefa7f8d087e707f65f50a046ad2260f3e2b1405 (diff)
downloadphp-git-2eae18794945db6c8e2540525b10a59759e0ade9.tar.gz
Store arg_num in fcall entry
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...)
-rw-r--r--Zend/zend_compile.c38
-rw-r--r--Zend/zend_compile.h9
-rw-r--r--Zend/zend_language_parser.y41
3 files changed, 45 insertions, 43 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 76a38d2818..d53cb96cd0 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -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));
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 0ea3be4f11..270c085d03 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -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);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 5d3f73beaf..d3844540cf 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -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: