summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index a0ea594560..f789e3397f 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
+ | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -2549,8 +2549,11 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
}
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
} else {
+ zend_function **function_ptr_ptr;
+ zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
+ if (*function_ptr_ptr) {
opline->opcode = ZEND_DO_FCALL;
SET_NODE(opline->op1, function_name);
SET_UNUSED(opline->op2);
@@ -2562,6 +2565,13 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
opline->op2.num = --CG(context).nested_calls;
+
+ /* This would normally be a ZEND_DO_FCALL, but was forced to use
+ * ZEND_DO_FCALL_BY_NAME due to a ... argument. In this case we need to
+ * free the function_name */
+ if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
+ zval_dtor(&function_name->u.constant);
+ }
}
}
@@ -2582,9 +2592,9 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{{ */
{
zend_op *opline;
- int original_op=op;
+ int original_op = op;
zend_function **function_ptr_ptr, *function_ptr;
- int send_by_reference;
+ int send_by_reference = 0;
int send_function = 0;
zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
@@ -2607,22 +2617,19 @@ 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 (param->op_type & (IS_VAR|IS_CV) && original_op != ZEND_SEND_VAL) {
- send_by_reference = 1;
- if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
+ 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)) {
/* Method call */
op = ZEND_SEND_VAR_NO_REF;
send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
}
} else {
op = ZEND_SEND_VAL;
- send_by_reference = 0;
}
- } else {
- send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
+ } else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+ send_by_reference = ZEND_ARG_SEND_BY_REF;
}
- } else {
- send_by_reference = 0;
}
if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
@@ -2690,6 +2697,39 @@ 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) /* {{{ */
+{
+ zend_op *opline;
+ zend_function **function_ptr_ptr;
+
+ zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
+ if (*function_ptr_ptr) {
+ /* 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
+ * retroactively emit a ZEND_INIT_FCALL_BY_NAME opcode. */
+ zval func_name;
+ ZVAL_STRING(&func_name, (*function_ptr_ptr)->common.function_name, 1);
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_INIT_FCALL_BY_NAME;
+ opline->result.num = CG(context).nested_calls;
+ SET_UNUSED(opline->op1);
+ opline->op2_type = IS_CONST;
+ opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &func_name TSRMLS_CC);
+ GET_CACHE_SLOT(opline->op2.constant);
+
+ ++CG(context).nested_calls;
+ *function_ptr_ptr = NULL;
+ }
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_SEND_UNPACK;
+ SET_NODE(opline->op1, params);
+ SET_UNUSED(opline->op2);
+ opline->op2.num = (zend_uint) offset;
+}
+/* }}} */
+
static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
{
zend_op *opline;