summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2014-07-01 10:29:11 +0800
committerXinchen Hui <laruence@php.net>2014-07-01 10:29:11 +0800
commit42bfa2382ce4461c34c1b1c169ae0ac7c68a5170 (patch)
treec4d0c5d809f1df36e77cdc653a192bcd0df018ed
parentd660d7f5997347942452ab639345fee7711254a2 (diff)
parentfd62771fe5f209790c292c8917e8ee0b6053c283 (diff)
downloadphp-git-42bfa2382ce4461c34c1b1c169ae0ac7c68a5170.tar.gz
Merge branch 'phpng' of https://git.php.net/repository/php-src into phpng
-rw-r--r--Zend/tests/67468.phpt11
-rw-r--r--Zend/tests/bug67368.phpt12
-rw-r--r--Zend/zend_API.c58
-rw-r--r--Zend/zend_ast.c14
-rw-r--r--Zend/zend_builtin_functions.c222
-rw-r--r--Zend/zend_closures.c4
-rw-r--r--Zend/zend_compile.c146
-rw-r--r--Zend/zend_compile.h69
-rw-r--r--Zend/zend_execute.c303
-rw-r--r--Zend/zend_execute.h135
-rw-r--r--Zend/zend_execute_API.c166
-rw-r--r--Zend/zend_generators.c84
-rw-r--r--Zend/zend_object_handlers.c4
-rw-r--r--Zend/zend_opcode.c5
-rw-r--r--Zend/zend_vm_def.h1061
-rw-r--r--Zend/zend_vm_execute.h2942
-rw-r--r--Zend/zend_vm_execute.skl15
-rw-r--r--Zend/zend_vm_opcodes.c2
-rw-r--r--Zend/zend_vm_opcodes.h2
-rw-r--r--build/libtool.m48
-rw-r--r--ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp8
-rw-r--r--ext/intl/idn/idn.c30
-rw-r--r--ext/intl/locale/locale_methods.c15
-rw-r--r--ext/intl/msgformat/msgformat_helpers.cpp8
-rw-r--r--ext/intl/tests/bug62082.phpt7
-rw-r--r--ext/intl/tests/bug67397.phpt21
-rw-r--r--ext/intl/tests/locale_parse_locale2.phpt6
-rw-r--r--ext/intl/timezone/timezone_methods.cpp4
-rw-r--r--ext/opcache/Optimizer/block_pass.c1
-rw-r--r--ext/opcache/Optimizer/compact_literals.c4
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c49
-rw-r--r--ext/opcache/Optimizer/pass1_5.c123
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c17
-rw-r--r--ext/opcache/Optimizer/zend_optimizer_internal.h2
-rw-r--r--ext/phar/phar_object.c4
-rw-r--r--ext/spl/php_spl.c4
-rw-r--r--ext/spl/spl_array.c4
-rw-r--r--ext/spl/spl_observer.c4
-rw-r--r--ext/spl/tests/SplObjectStorage_unserialize_bad.phpt5
-rw-r--r--ext/standard/info.c8
-rw-r--r--ext/standard/tests/general_functions/bug67498.phpt15
-rw-r--r--sapi/cli/php_cli.c1
-rw-r--r--sapi/fpm/fpm/fpm_conf.c3
-rw-r--r--sapi/fpm/fpm/fpm_main.c25
-rw-r--r--sapi/fpm/fpm/fpm_php_trace.c3
-rw-r--r--sapi/phpdbg/Makefile.frag3
-rw-r--r--sapi/phpdbg/config.m42
-rw-r--r--sapi/phpdbg/phpdbg.159
-rw-r--r--sapi/phpdbg/phpdbg.h5
-rw-r--r--sapi/phpdbg/phpdbg_cmd.c6
-rw-r--r--sapi/phpdbg/phpdbg_help.c7
-rw-r--r--sapi/phpdbg/phpdbg_lexer.c1005
-rw-r--r--sapi/phpdbg/phpdbg_lexer.l38
-rw-r--r--sapi/phpdbg/phpdbg_list.c23
-rw-r--r--sapi/phpdbg/phpdbg_parser.c80
-rw-r--r--sapi/phpdbg/phpdbg_parser.y12
-rw-r--r--sapi/phpdbg/phpdbg_prompt.c5
-rw-r--r--sapi/phpdbg/phpdbg_utils.c6
-rwxr-xr-xtravis/compile.sh1
59 files changed, 3564 insertions, 3322 deletions
diff --git a/Zend/tests/67468.phpt b/Zend/tests/67468.phpt
new file mode 100644
index 0000000000..767217644a
--- /dev/null
+++ b/Zend/tests/67468.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #67468 (Segfault in highlight_file()/highlight_string())
+--SKIPIF--
+<?php if(!function_exists("leak")) print "skip only for debug builds"; ?>
+--FILE--
+<?php
+highlight_string("<?php __CLASS__;", true);
+echo "done";
+?>
+--EXPECT--
+done
diff --git a/Zend/tests/bug67368.phpt b/Zend/tests/bug67368.phpt
new file mode 100644
index 0000000000..c92e994b94
--- /dev/null
+++ b/Zend/tests/bug67368.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #67368 (Memory leak with immediately dereferenced array in class constant)
+--INI--
+report_memleaks=1
+--FILE--
+<?php
+class FooBar {
+ const bar = ["bar" => 3]["bar"];
+}
+echo "okey";
+--EXPECTF--
+okey
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 1568374f4e..6b469c2b0a 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -44,14 +44,13 @@ static zend_class_entry **class_cleanup_handlers;
/* this function doesn't check for too many parameters */
ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
{
- zval *p;
int arg_count;
va_list ptr;
zval **param, *param_ptr;
TSRMLS_FETCH();
- p = zend_vm_stack_top(TSRMLS_C) - 1;
- arg_count = Z_LVAL_P(p);
+ param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+ arg_count = EG(current_execute_data)->call->num_args;
if (param_count>arg_count) {
return FAILURE;
@@ -61,7 +60,6 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
while (param_count-->0) {
param = va_arg(ptr, zval **);
- param_ptr = (p-arg_count);
if (!Z_ISREF_P(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
zval new_tmp;
@@ -70,7 +68,7 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
ZVAL_COPY_VALUE(param_ptr, &new_tmp);
}
*param = param_ptr;
- arg_count--;
+ param_ptr++;
}
va_end(ptr);
@@ -82,14 +80,13 @@ ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
/* this function doesn't check for too many parameters */
ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
{
- zval *p;
int arg_count;
va_list ptr;
- zval **param;
+ zval **param, *param_ptr;
TSRMLS_FETCH();
- p = zend_vm_stack_top(TSRMLS_C) - 1;
- arg_count = Z_LVAL_P(p);
+ param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+ arg_count = EG(current_execute_data)->call->num_args;
if (param_count>arg_count) {
return FAILURE;
@@ -98,7 +95,8 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
va_start(ptr, param_count);
while (param_count-->0) {
param = va_arg(ptr, zval **);
- *param = p-(arg_count--);
+ *param = param_ptr;
+ param_ptr++;
}
va_end(ptr);
@@ -108,22 +106,20 @@ ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
{
- zval *p;
+ zval *param_ptr;
int arg_count;
- p = zend_vm_stack_top(TSRMLS_C) - 1;
- arg_count = Z_LVAL_P(p);
+ param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+ arg_count = EG(current_execute_data)->call->num_args;
if (param_count>arg_count) {
return FAILURE;
}
while (param_count-->0) {
- zval *value = (p-arg_count);
-
- ZVAL_COPY_VALUE(argument_array, value);
+ ZVAL_COPY_VALUE(argument_array, param_ptr);
argument_array++;
- arg_count--;
+ param_ptr++;
}
return SUCCESS;
@@ -132,22 +128,22 @@ ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array
ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
{
- zval *p;
+ zval *param_ptr;
int arg_count;
- p = zend_vm_stack_top(TSRMLS_C) - 1;
- arg_count = Z_LVAL_P(p);
+ param_ptr = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+ arg_count = EG(current_execute_data)->call->num_args;
if (param_count>arg_count) {
return FAILURE;
}
while (param_count-->0) {
- zval *param = p-(arg_count--);
- if (Z_REFCOUNTED_P(param)) {
- Z_ADDREF_P(param);
+ if (Z_REFCOUNTED_P(param_ptr)) {
+ Z_ADDREF_P(param_ptr);
}
- add_next_index_zval(argument_array, param);
+ zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
+ param_ptr++;
}
return SUCCESS;
@@ -807,7 +803,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
case '+':
if (have_varargs) {
if (!quiet) {
- zend_function *active_function = EG(current_execute_data)->function_state.function;
+ zend_function *active_function = EG(current_execute_data)->call->func;
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
class_name,
@@ -827,7 +823,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
default:
if (!quiet) {
- zend_function *active_function = EG(current_execute_data)->function_state.function;
+ zend_function *active_function = EG(current_execute_data)->call->func;
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
class_name,
@@ -850,7 +846,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
if (!quiet) {
- zend_function *active_function = EG(current_execute_data)->function_state.function;
+ zend_function *active_function = EG(current_execute_data)->call->func;
const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
class_name,
@@ -864,7 +860,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
return FAILURE;
}
- arg_count = Z_LVAL_P(zend_vm_stack_top(TSRMLS_C) - 1);
+ arg_count = EG(current_execute_data)->call->num_args;
if (num_args > arg_count) {
zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
@@ -888,7 +884,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
if (num_varargs > 0) {
*n_varargs = num_varargs;
- *varargs = (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
+ *varargs = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1);
/* adjust how many args we have left and restart loop */
num_args += 1 - num_varargs;
i += num_varargs;
@@ -899,7 +895,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
}
}
- arg = zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i);
+ arg = ZEND_CALL_ARG(EG(current_execute_data)->call, i + 1);
if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
/* clean up varargs array if it was used */
@@ -970,7 +966,7 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr
* Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
* In that case EG(This) would still be the $this from the calling code and we'd take the
* wrong branch here. */
- zend_bool is_method = EG(current_execute_data)->function_state.function->common.scope != NULL;
+ zend_bool is_method = EG(current_execute_data)->call->func->common.scope != NULL;
if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
RETURN_IF_ZERO_ARGS(num_args, p, 0);
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 7a9547b475..e173afd2f9 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -350,6 +350,20 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
}
}
break;
+//???
+#if 0
+ case ZEND_FETCH_DIM_R:
+ zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC);
+ zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC);
+ {
+ zval *tmp;
+ zend_fetch_dimension_by_zval(&tmp, &op1, &op2 TSRMLS_CC);
+ ZVAL_ZVAL(result, tmp, 1, 1);
+ }
+ zval_dtor(&op1);
+ zval_dtor(&op2);
+ break;
+#endif
default:
zend_error(E_ERROR, "Unsupported constant expression");
}
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index cb2205b82c..df81c5d666 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -394,10 +394,10 @@ ZEND_FUNCTION(gc_disable)
Get the number of arguments that were passed to the function */
ZEND_FUNCTION(func_num_args)
{
- zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+ zend_execute_data *ex = EG(current_execute_data);
- if (ex && ex->function_state.arguments) {
- RETURN_LONG(Z_LVAL_P(ex->function_state.arguments));
+ if (ex->frame_kind == VM_FRAME_NESTED_FUNCTION || ex->frame_kind == VM_FRAME_TOP_FUNCTION) {
+ RETURN_LONG(ex->num_args);
} else {
zend_error(E_WARNING, "func_num_args(): Called from the global scope - no function context");
RETURN_LONG(-1);
@@ -409,11 +409,10 @@ ZEND_FUNCTION(func_num_args)
Get the $arg_num'th argument that was passed to the function */
ZEND_FUNCTION(func_get_arg)
{
- zval *p;
- int arg_count;
+ int arg_count, first_extra_arg;
zval *arg;
long requested_offset;
- zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+ zend_execute_data *ex;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &requested_offset) == FAILURE) {
return;
@@ -424,20 +423,28 @@ ZEND_FUNCTION(func_get_arg)
RETURN_FALSE;
}
- if (!ex || !ex->function_state.arguments) {
+ ex = EG(current_execute_data);
+ if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
zend_error(E_WARNING, "func_get_arg(): Called from the global scope - no function context");
RETURN_FALSE;
}
- p = ex->function_state.arguments;
- arg_count = Z_LVAL_P(p); /* this is the amount of arguments passed to func_get_arg(); */
+ arg_count = ex->num_args;
if (requested_offset >= arg_count) {
zend_error(E_WARNING, "func_get_arg(): Argument %ld not passed to function", requested_offset);
RETURN_FALSE;
}
- arg = p-(arg_count-requested_offset);
+ first_extra_arg = ex->func->op_array.num_args;
+ if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+ first_extra_arg--;
+ }
+ if (requested_offset >= first_extra_arg && (ex->num_args > first_extra_arg)) {
+ arg = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
+ } else {
+ arg = ZEND_CALL_ARG(ex, requested_offset + 1);
+ }
RETURN_ZVAL_FAST(arg);
}
/* }}} */
@@ -447,26 +454,45 @@ ZEND_FUNCTION(func_get_arg)
ZEND_FUNCTION(func_get_args)
{
zval *p;
- int arg_count;
+ int arg_count, first_extra_arg;
int i;
- zend_execute_data *ex = EG(current_execute_data)->prev_execute_data;
+ zend_execute_data *ex = EG(current_execute_data);
- if (!ex || !ex->function_state.arguments) {
+ if (ex->frame_kind != VM_FRAME_NESTED_FUNCTION && ex->frame_kind != VM_FRAME_TOP_FUNCTION) {
zend_error(E_WARNING, "func_get_args(): Called from the global scope - no function context");
RETURN_FALSE;
}
- p = ex->function_state.arguments;
- arg_count = Z_LVAL_P(p); /* this is the amount of arguments passed to func_get_args(); */
+ arg_count = ex->num_args;
array_init_size(return_value, arg_count);
if (arg_count) {
Bucket *q;
- p -= arg_count;
+ first_extra_arg = ex->func->op_array.num_args;
+ if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+ first_extra_arg--;
+ }
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
+ i = 0;
q = Z_ARRVAL_P(return_value)->arData;
- for (i=0; i<arg_count; i++) {
+ p = ZEND_CALL_ARG(ex, 1);
+ if (ex->num_args > first_extra_arg) {
+ while (i < first_extra_arg) {
+ q->h = i;
+ q->key = NULL;
+ if (!Z_ISREF_P(p)) {
+ ZVAL_COPY(&q->val, p);
+ } else {
+ ZVAL_DUP(&q->val, Z_REFVAL_P(p));
+ }
+ p++;
+ q++;
+ i++;
+ }
+ p = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T);
+ }
+ while (i < arg_count) {
q->h = i;
q->key = NULL;
if (!Z_ISREF_P(p)) {
@@ -476,6 +502,7 @@ ZEND_FUNCTION(func_get_args)
}
p++;
q++;
+ i++;
}
Z_ARRVAL_P(return_value)->nNumUsed = i;
Z_ARRVAL_P(return_value)->nNumOfElements = i;
@@ -1957,22 +1984,37 @@ ZEND_FUNCTION(get_defined_constants)
/* }}} */
-static void debug_backtrace_get_args(zval *curpos, zval *arg_array TSRMLS_DC)
+static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TSRMLS_DC)
{
- zval *p = curpos;
- zval *arg;
- int arg_count = Z_LVAL_P(p);
+ int num_args = call->num_args;
- array_init_size(arg_array, arg_count);
- p -= arg_count;
+ array_init_size(arg_array, num_args);
+ if (num_args) {
+ int i = 0;
+ zval *p = ZEND_CALL_ARG(call, 1);
- while (--arg_count >= 0) {
- arg = p++;
- if (arg) {
- if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
- add_next_index_zval(arg_array, arg);
- } else {
- add_next_index_null(arg_array);
+ if (call->func->type == ZEND_USER_FUNCTION) {
+ int first_extra_arg = call->func->op_array.num_args;
+
+ if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+ first_extra_arg--;
+ }
+ if (call->num_args > first_extra_arg) {
+ while (i < first_extra_arg) {
+ if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
+ zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
+ p++;
+ i++;
+ }
+ p = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
+ }
+ }
+
+ while (i < 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++;
}
}
}
@@ -1996,6 +2038,7 @@ ZEND_FUNCTION(debug_print_backtrace)
zend_execute_data *ptr, *skip;
zend_object *object;
int lineno, frameno = 0;
+ zend_function *func;
const char *function_name;
const char *filename;
zend_string *class_name = NULL;
@@ -2025,17 +2068,16 @@ ZEND_FUNCTION(debug_print_backtrace)
skip = ptr;
/* skip internal handler */
- if (!skip->op_array &&
+ if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
skip->prev_execute_data &&
skip->prev_execute_data->opline &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
skip = skip->prev_execute_data;
}
- if (skip->op_array) {
- filename = skip->op_array->filename->val;
+ if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
+ filename = skip->func->op_array.filename->val;
lineno = skip->opline->lineno;
} else {
filename = NULL;
@@ -2044,41 +2086,47 @@ ZEND_FUNCTION(debug_print_backtrace)
/* $this may be passed into regular internal functions */
if (object &&
- ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
- !ptr->function_state.function->common.scope) {
+ ptr->call &&
+ ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
+ !ptr->call->func->common.scope) {
object = NULL;
}
- function_name = (ptr->function_state.function->common.scope &&
- ptr->function_state.function->common.scope->trait_aliases) ?
+ if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
+ func = ptr->call->func;
+ function_name = (func->common.scope &&
+ func->common.scope->trait_aliases) ?
zend_resolve_method_name(
- object ?
+ (object ?
zend_get_class_entry(object TSRMLS_CC) :
- ptr->function_state.function->common.scope,
- ptr->function_state.function)->val :
- (ptr->function_state.function->common.function_name ?
- ptr->function_state.function->common.function_name->val :
- NULL);
+ func->common.scope), func)->val :
+ (func->common.function_name ?
+ func->common.function_name->val : NULL);
+ } else {
+ func = ptr->func;
+ function_name = func && func->common.function_name ?
+ func->common.function_name->val : NULL;
+ }
if (function_name) {
if (object) {
- if (ptr->function_state.function->common.scope) {
- class_name = ptr->function_state.function->common.scope->name;
+ if (func->common.scope) {
+ class_name = func->common.scope->name;
} else {
class_name = zend_get_object_classname(object TSRMLS_CC);
}
call_type = "->";
- } else if (ptr->function_state.function->common.scope) {
- class_name = ptr->function_state.function->common.scope->name;
+ } else if (func->common.scope) {
+ class_name = func->common.scope->name;
call_type = "::";
} else {
class_name = NULL;
call_type = NULL;
}
- if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) {
- if (ptr->function_state.arguments && (options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
- debug_backtrace_get_args(ptr->function_state.arguments, &arg_array TSRMLS_CC);
+ if (func->type != ZEND_EVAL_CODE) {
+ if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
+ debug_backtrace_get_args(ptr->call, &arg_array TSRMLS_CC);
}
}
} else {
@@ -2137,13 +2185,14 @@ ZEND_FUNCTION(debug_print_backtrace)
zend_execute_data *prev = skip->prev_execute_data;
while (prev) {
- if (prev->function_state.function &&
- prev->function_state.function->common.type != ZEND_USER_FUNCTION) {
+ if (prev->call &&
+ prev->call->func &&
+ !ZEND_USER_CODE(prev->call->func->common.type)) {
prev = NULL;
break;
}
- if (prev->op_array) {
- zend_printf(") called at [%s:%d]\n", prev->op_array->filename->val, prev->opline->lineno);
+ if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
+ zend_printf(") called at [%s:%d]\n", prev->func->op_array.filename->val, prev->opline->lineno);
break;
}
prev = prev->prev_execute_data;
@@ -2166,6 +2215,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
zend_execute_data *ptr, *skip;
zend_object *object = Z_OBJ(EG(This));
int lineno, frameno = 0;
+ zend_function *func;
const char *function_name;
const char *filename;
zend_string *class_name;
@@ -2194,17 +2244,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
skip = ptr;
/* skip internal handler */
- if (!skip->op_array &&
+ if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
skip->prev_execute_data &&
skip->prev_execute_data->opline &&
skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
- skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
skip = skip->prev_execute_data;
}
- if (skip->op_array) {
- filename = skip->op_array->filename->val;
+ if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
+ filename = skip->func->op_array.filename->val;
lineno = skip->opline->lineno;
add_assoc_string_ex(&stack_frame, "file", sizeof("file")-1, (char*)filename);
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno);
@@ -2216,15 +2265,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
zend_execute_data *prev = skip->prev_execute_data;
while (prev) {
- if (prev->function_state.function &&
- prev->function_state.function->common.type != ZEND_USER_FUNCTION &&
- !(prev->function_state.function->common.type == ZEND_INTERNAL_FUNCTION &&
- (prev->function_state.function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
+ if (prev->call &&
+ prev->call->func &&
+ !ZEND_USER_CODE(prev->call->func->common.type) &&
+ !(prev->call->func->common.type == ZEND_INTERNAL_FUNCTION &&
+ (prev->call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER))) {
break;
}
- if (prev->op_array) {
+ if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
// TODO: we have to duplicate it, becaise it may be stored in opcache SHM ???
- add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_DUP(prev->op_array->filename, 0));
+ add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, STR_DUP(prev->func->op_array.filename, 0));
add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
break;
}
@@ -2235,28 +2285,34 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
/* $this may be passed into regular internal functions */
if (object &&
- ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
- !ptr->function_state.function->common.scope) {
+ ptr->call &&
+ ptr->call->func->type == ZEND_INTERNAL_FUNCTION &&
+ !ptr->call->func->common.scope) {
object = NULL;
}
- function_name = (ptr->function_state.function->common.scope &&
- ptr->function_state.function->common.scope->trait_aliases) ?
+ if (ptr->call && ptr->call->func && (ptr->call->flags & ZEND_CALL_DONE)) {
+ func = ptr->call->func;
+ function_name = (func->common.scope &&
+ func->common.scope->trait_aliases) ?
zend_resolve_method_name(
- object ?
+ (object ?
zend_get_class_entry(object TSRMLS_CC) :
- ptr->function_state.function->common.scope,
- ptr->function_state.function)->val :
- (ptr->function_state.function->common.function_name ?
- ptr->function_state.function->common.function_name->val :
- NULL);
+ func->common.scope), func)->val :
+ (func->common.function_name ?
+ func->common.function_name->val : NULL);
+ } else {
+ func = ptr->func;
+ function_name = func && func->common.function_name ?
+ func->common.function_name->val : NULL;
+ }
if (function_name) {
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
if (object) {
- if (ptr->function_state.function->common.scope) {
- add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
+ if (func->common.scope) {
+ add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
} else {
class_name = zend_get_object_classname(object TSRMLS_CC);
add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
@@ -2270,16 +2326,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
}
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
- } else if (ptr->function_state.function->common.scope) {
- add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
+ } else if (func->common.scope) {
+ add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(func->common.scope->name));
add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "::");
}
if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
- ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL)))) {
- if (ptr->function_state.arguments) {
+ func->type != ZEND_EVAL_CODE) {
+ if (ptr->call) {
zval args;
- debug_backtrace_get_args(ptr->function_state.arguments, &args TSRMLS_CC);
+ debug_backtrace_get_args(ptr->call, &args TSRMLS_CC);
add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
}
}
@@ -2333,7 +2389,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
}
- add_next_index_zval(return_value, &stack_frame);
+ zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
include_filename = filename;
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 3c2921f53c..053a5eb199 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -47,7 +47,7 @@ static zend_object_handlers closure_handlers;
ZEND_METHOD(Closure, __invoke) /* {{{ */
{
- zend_function *func = EG(current_execute_data)->function_state.function;
+ zend_function *func = EG(current_execute_data)->call->func;
zval *arguments;
arguments = emalloc(sizeof(zval) * ZEND_NUM_ARGS());
@@ -213,7 +213,7 @@ static void zend_closure_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
if (closure->func.type == ZEND_USER_FUNCTION) {
zend_execute_data *ex = EG(current_execute_data);
while (ex) {
- if (ex->op_array == &closure->func.op_array) {
+ if (ex->func == &closure->func) {
zend_error(E_ERROR, "Cannot destroy active lambda function");
}
ex = ex->prev_execute_data;
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index c6116693b7..647fab48be 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -97,9 +97,9 @@ ZEND_API zend_compiler_globals compiler_globals;
ZEND_API zend_executor_globals executor_globals;
#endif
-static void zend_push_function_call_entry(zend_function *fbc TSRMLS_DC) /* {{{ */
+static void zend_push_function_call_entry(zend_function *fbc, zend_uint opline_num TSRMLS_DC) /* {{{ */
{
- zend_function_call_entry fcall = { fbc };
+ zend_function_call_entry fcall = { fbc, opline_num };
zend_stack_push(&CG(function_call_stack), &fcall);
}
/* }}} */
@@ -182,8 +182,6 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
CG(context).literals_size = 0;
CG(context).current_brk_cont = -1;
CG(context).backpatch_count = 0;
- CG(context).nested_calls = 0;
- CG(context).used_stack = 0;
CG(context).in_finally = 0;
CG(context).labels = NULL;
}
@@ -1463,6 +1461,11 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
&& opline->result.var == op1->u.op.var) {
if (opline->opcode == ZEND_NEW) {
opline->result_type |= EXT_TYPE_UNUSED;
+ opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
+ while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) {
+ opline--;
+ }
+ opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED;
}
break;
}
@@ -1841,7 +1844,9 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
var.u.op.var = lookup_cv(CG(active_op_array), Z_STR(varname->u.constant) TSRMLS_CC);
Z_STR(varname->u.constant) = CG(active_op_array)->vars[EX_VAR_TO_NUM(var.u.op.var)];
var.EA = 0;
- if (Z_STRHASH(varname->u.constant) == THIS_HASHVAL &&
+ if (EX_VAR_TO_NUM(var.u.op.var) != CG(active_op_array)->num_args) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter %s", Z_STRVAL(varname->u.constant));
+ } else if (Z_STRHASH(varname->u.constant) == THIS_HASHVAL &&
Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
!memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
if (CG(active_op_array)->scope &&
@@ -1949,6 +1954,8 @@ void zend_do_receive_param(zend_uchar op, znode *varname, znode *initialization,
int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
{
+ zend_op *opline;
+ zend_uint op_number;
zend_function *function;
zend_string *lcname;
char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
@@ -1977,10 +1984,14 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace
STR_RELEASE(Z_STR(function_name->u.constant));
Z_STR(function_name->u.constant) = lcname;
- zend_push_function_call_entry(function TSRMLS_CC);
- if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
- CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
- }
+ op_number = get_next_op_number(CG(active_op_array));
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_INIT_FCALL;
+ SET_UNUSED(opline->op1);
+ SET_NODE(opline->op2, function_name);
+ GET_CACHE_SLOT(opline->op2.constant);
+
+ zend_push_function_call_entry(function, op_number TSRMLS_CC);
zend_do_extended_fcall_begin(TSRMLS_C);
return 0;
}
@@ -2017,12 +2028,10 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
}
last_op->opcode = ZEND_INIT_METHOD_CALL;
last_op->result_type = IS_UNUSED;
- last_op->result.num = CG(context).nested_calls;
Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
} else {
zend_op *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);
if (left_bracket->op_type == IS_CONST) {
opline->op2_type = IS_CONST;
@@ -2033,10 +2042,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
}
}
- zend_push_function_call_entry(NULL TSRMLS_CC);
- if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
- CG(active_op_array)->nested_calls = CG(context).nested_calls;
- }
+ zend_push_function_call_entry(NULL, last_op_number TSRMLS_CC);
zend_do_extended_fcall_begin(TSRMLS_C);
}
/* }}} */
@@ -2056,21 +2062,21 @@ void zend_do_clone(znode *result, znode *expr TSRMLS_DC) /* {{{ */
void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
{
+ zend_uint op_number;
zend_op *opline;
+ op_number = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
if (ns_call) {
/* In run-time PHP will check for function with full name and
internal function with short name */
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
- opline->result.num = CG(context).nested_calls;
SET_UNUSED(opline->op1);
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
GET_CACHE_SLOT(opline->op2.constant);
} else {
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
- opline->result.num = CG(context).nested_calls;
SET_UNUSED(opline->op1);
if (function_name->op_type == IS_CONST) {
opline->op2_type = IS_CONST;
@@ -2081,10 +2087,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
}
}
- zend_push_function_call_entry(NULL TSRMLS_CC);
- if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
- CG(active_op_array)->nested_calls = CG(context).nested_calls;
- }
+ zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
zend_do_extended_fcall_begin(TSRMLS_C);
}
/* }}} */
@@ -2481,6 +2484,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c
int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
{
znode class_node;
+ zend_uint op_number;
zend_op *opline;
if (method_name->op_type == IS_CONST) {
@@ -2501,14 +2505,14 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
zend_resolve_class_name(class_name TSRMLS_CC);
class_node = *class_name;
+ op_number = get_next_op_number(CG(active_op_array) TSRMLS_CC);
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
} else {
zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
+ op_number = get_next_op_number(CG(active_op_array) TSRMLS_CC);
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->extended_value = class_node.EA ;
}
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
- opline->result.num = CG(context).nested_calls;
if (class_node.op_type == IS_CONST) {
opline->op1_type = IS_CONST;
opline->op1.constant =
@@ -2529,10 +2533,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
SET_NODE(opline->op2, method_name);
}
- zend_push_function_call_entry(NULL TSRMLS_CC);
- if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
- CG(active_op_array)->nested_calls = CG(context).nested_calls;
- }
+ zend_push_function_call_entry(NULL, op_number TSRMLS_CC);
zend_do_extended_fcall_begin(TSRMLS_C);
return 1; /* Dynamic */
}
@@ -2550,26 +2551,20 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
}
opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
} else {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- if (fcall->fbc) {
- opline->opcode = ZEND_DO_FCALL;
- SET_NODE(opline->op1, function_name);
- SET_UNUSED(opline->op2);
- opline->op2.num = CG(context).nested_calls;
- GET_CACHE_SLOT(opline->op1.constant);
- } else {
- opline->opcode = ZEND_DO_FCALL_BY_NAME;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- opline->op2.num = --CG(context).nested_calls;
+ zend_uint call_flags = 0;
- /* 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);
- }
+ opline = &CG(active_op_array)->opcodes[fcall->op_number];
+ opline->extended_value = fcall->arg_num;
+
+ if (opline->opcode == ZEND_NEW) {
+ call_flags = ZEND_CALL_CTOR;
}
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_DO_FCALL;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);
+ opline->op1.num = call_flags;
}
opline->result.var = get_temporary_variable(CG(active_op_array));
@@ -2577,10 +2572,6 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
GET_NODE(result, opline->result);
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 -= fcall->arg_num;
zend_stack_del_top(&CG(function_call_stack));
}
/* }}} */
@@ -2682,19 +2673,13 @@ void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
}
} else {
if (function_ptr) {
- opline->extended_value = ZEND_DO_FCALL;
- } else {
- opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
}
}
opline->opcode = op;
SET_NODE(opline->op1, param);
opline->op2.opline_num = fcall->arg_num;
SET_UNUSED(opline->op2);
-
- if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
- CG(active_op_array)->used_stack = CG(context).used_stack;
- }
}
/* }}} */
@@ -2705,25 +2690,6 @@ void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
fcall->uses_argument_unpacking = 1;
- 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
- * retroactively emit a ZEND_INIT_FCALL_BY_NAME opcode. */
- zval func_name;
- ZVAL_STR(&func_name, STR_COPY(fcall->fbc->common.function_name));
-
- 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;
- fcall->fbc = NULL;
- }
-
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_SEND_UNPACK;
SET_NODE(opline->op1, params);
@@ -5619,16 +5585,12 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /*
new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_NEW;
- opline->extended_value = CG(context).nested_calls;
opline->result_type = IS_VAR;
opline->result.var = get_temporary_variable(CG(active_op_array));
SET_NODE(opline->op1, class_type);
SET_UNUSED(opline->op2);
- zend_push_function_call_entry(NULL TSRMLS_CC);
- if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
- CG(active_op_array)->nested_calls = CG(context).nested_calls;
- }
+ zend_push_function_call_entry(NULL, new_token->u.op.opline_num TSRMLS_CC);
}
/* }}} */
@@ -5819,6 +5781,14 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_INIT_FCALL;
+ opline->extended_value = 1;
+ SET_UNUSED(opline->op1);
+ opline->op2_type = IS_CONST;
+ LITERAL_STR(opline->op2, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
+ GET_CACHE_SLOT(opline->op2.constant);
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
switch (cmd->op_type) {
case IS_CONST:
case IS_TMP_VAR:
@@ -5830,28 +5800,18 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC) /* {{{ */
}
SET_NODE(opline->op1, cmd);
opline->op2.opline_num = 1;
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
SET_UNUSED(opline->op2);
/* FIXME: exception support not added to this op2 */
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_DO_FCALL;
+ opline->extended_value = 1;
opline->result.var = get_temporary_variable(CG(active_op_array));
opline->result_type = IS_VAR;
- LITERAL_STR(opline->op1, STR_INIT("shell_exec", sizeof("shell_exec")-1, 0));
- opline->op1_type = IS_CONST;
- GET_CACHE_SLOT(opline->op1.constant);
- opline->extended_value = 1;
+ SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
- opline->op2.num = CG(context).nested_calls;
GET_NODE(result, opline->result);
-
- if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
- CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
- }
- if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) {
- CG(active_op_array)->used_stack = CG(context).used_stack + 2;
- }
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 5b5397844f..b053ee9820 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -59,8 +59,6 @@ typedef struct _zend_compiler_context {
int literals_size;
int current_brk_cont;
int backpatch_count;
- int nested_calls;
- int used_stack;
int in_finally;
HashTable *labels;
} zend_compiler_context;
@@ -266,9 +264,6 @@ struct _zend_op_array {
zend_uint T;
- zend_uint nested_calls;
- zend_uint used_stack;
-
zend_brk_cont_element *brk_cont_array;
int last_brk_cont;
@@ -336,14 +331,9 @@ union _zend_function {
zend_internal_function internal_function;
};
-
-typedef struct _zend_function_state {
- zend_function *function;
- zval *arguments;
-} zend_function_state;
-
typedef struct _zend_function_call_entry {
zend_function *fbc;
+ zend_uint op_number;
zend_uint arg_num;
zend_bool uses_argument_unpacking;
} zend_function_call_entry;
@@ -361,15 +351,6 @@ typedef struct _list_llist_element {
znode value;
} list_llist_element;
-typedef struct _call_slot {
- zend_function *fbc;
- zend_class_entry *called_scope;
- zend_object *object;
- zend_uint num_additional_args;
- zend_bool is_ctor_call;
- zend_bool is_ctor_result_used;
-} call_slot;
-
typedef enum _vm_frame_kind {
VM_FRAME_NESTED_FUNCTION, /* stackless VM call to function */
VM_FRAME_NESTED_CODE, /* stackless VM call to include/require/eval */
@@ -379,28 +360,38 @@ typedef enum _vm_frame_kind {
struct _zend_execute_data {
struct _zend_op *opline; /* executed opline */
- zend_op_array *op_array; /* executed op_array */
- zend_function_state function_state; /* called function and arguments */
- zend_object *object; /* current $this */
- zend_class_entry *scope; /* function scope (self) */
- zend_class_entry *called_scope; /* function called scope (static) */
- zend_array *symbol_table;
+ zend_execute_data *call; /* current call */
void **run_time_cache;
+ zend_function *func; /* executed op_array */
+ zend_uint num_args;
+ zend_uchar flags;
+ zend_uchar frame_kind;
+ zend_class_entry *called_scope;
+ zend_object *object;
+ zend_execute_data *prev_nested_call;
zend_execute_data *prev_execute_data;
zval *return_value;
- vm_frame_kind frame_kind;
- // TODO: simplify call sequence and remove call_* ???
- zval old_error_reporting;
- struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
- zend_object *delayed_exception;
- call_slot *call_slots;
- call_slot *call;
+ zend_class_entry *scope; /* function scope (self) */
+ zend_array *symbol_table;
+ struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
+ zend_object *delayed_exception;
+ zval old_error_reporting;
};
+#define ZEND_CALL_CTOR (1 << 0)
+#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1)
+#define ZEND_CALL_DONE (1 << 2)
+
+#define ZEND_CALL_FRAME_SLOT \
+ ((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
+
+#define ZEND_CALL_ARG(call, n) \
+ (((zval*)(call)) + ((n) + (ZEND_CALL_FRAME_SLOT - 1)))
+
#define EX(element) execute_data.element
#define EX_VAR_2(ex, n) ((zval*)(((char*)(ex)) + ((int)(n))))
-#define EX_VAR_NUM_2(ex, n) (((zval*)(((char*)(ex))+ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))))+(n))
+#define EX_VAR_NUM_2(ex, n) (((zval*)(ex)) + (ZEND_CALL_FRAME_SLOT + ((int)(n))))
#define EX_VAR(n) EX_VAR_2(execute_data, n)
#define EX_VAR_NUM(n) EX_VAR_NUM_2(execute_data, n)
@@ -730,8 +721,8 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_FETCH_CLASS_DEFAULT 0
#define ZEND_FETCH_CLASS_SELF 1
#define ZEND_FETCH_CLASS_PARENT 2
-#define ZEND_FETCH_CLASS_MAIN 3 /* unused */
-#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused */
+#define ZEND_FETCH_CLASS_MAIN 3 /* unused ??? */
+#define ZEND_FETCH_CLASS_GLOBAL 4 /* unused ??? */
#define ZEND_FETCH_CLASS_AUTO 5
#define ZEND_FETCH_CLASS_INTERFACE 6
#define ZEND_FETCH_CLASS_STATIC 7
@@ -750,7 +741,6 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_PARSED_NEW (1<<6)
#define ZEND_PARSED_LIST_EXPR (1<<7)
-
/* unset types */
#define ZEND_UNSET_REG 0
@@ -770,6 +760,9 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
#define ZEND_EVAL_CODE 4
#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
+/* A quick check (type == ZEND_USER_FUNCTION || type == ZEND_EVAL_CODE) */
+#define ZEND_USER_CODE(type) ((type & 1) == 0)
+
#define ZEND_INTERNAL_CLASS 1
#define ZEND_USER_CLASS 2
@@ -877,7 +870,7 @@ END_EXTERN_C()
/* call op_array handler of extendions */
#define ZEND_COMPILE_HANDLE_OP_ARRAY (1<<1)
-/* generate ZEND_DO_FCALL_BY_NAME for internal functions instead of ZEND_DO_FCALL */
+/* generate ZEND_INIT_FCALL_BY_NAME for internal functions instead of ZEND_INIT_FCALL */
#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
/* don't perform early binding for classes inherited form internal ones;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index a6f6d65d72..5318bbe2d3 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -525,12 +525,13 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ul
}
}
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
{
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
const char *fname = zf->common.function_name->val;
const char *fsep;
const char *fclass;
+ zval old_arg;
if (zf->common.scope) {
fsep = "::";
@@ -540,11 +541,20 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zen
fclass = "";
}
- if (ptr && ptr->op_array) {
- zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->op_array->filename->val, ptr->opline->lineno);
+ if (arg && zf->common.type == ZEND_USER_FUNCTION) {
+ ZVAL_COPY_VALUE(&old_arg, arg);
+ ZVAL_UNDEF(arg);
+ }
+
+ if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
+ zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno);
} else {
zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
}
+
+ if (arg && zf->common.type == ZEND_USER_FUNCTION) {
+ ZVAL_COPY_VALUE(arg, &old_arg);
+ }
}
static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
@@ -572,21 +582,21 @@ static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg
if (Z_TYPE_P(arg) == IS_OBJECT) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC);
}
} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC);
}
} else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) {
ZVAL_DEREF(arg);
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
}
} else if (cur_arg_info->type_hint == IS_CALLABLE) {
if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
}
#if ZEND_DEBUG
} else {
@@ -618,12 +628,12 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
char *class_name;
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL TSRMLS_CC);
} else if (cur_arg_info->type_hint) {
if (cur_arg_info->type_hint == IS_ARRAY) {
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL TSRMLS_CC);
} else if (cur_arg_info->type_hint == IS_CALLABLE) {
- zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "", NULL TSRMLS_CC);
#if ZEND_DEBUG
} else {
zend_error(E_ERROR, "Unknown typehint");
@@ -635,15 +645,15 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_
static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint arg_num TSRMLS_DC)
{
- if (EXPECTED(!(EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
- zend_verify_missing_arg_type((zend_function *) EX(op_array), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
- const char *class_name = EX(op_array)->scope ? EX(op_array)->scope->name->val : "";
- const char *space = EX(op_array)->scope ? "::" : "";
- const char *func_name = EX(op_array)->function_name ? EX(op_array)->function_name->val : "main";
+ if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
+ zend_verify_missing_arg_type(EX(func), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
+ const char *class_name = EX(func)->common.scope ? EX(func)->common.scope->name->val : "";
+ const char *space = EX(func)->common.scope ? "::" : "";
+ const char *func_name = EX(func)->common.function_name ? EX(func)->common.function_name->val : "main";
zend_execute_data *ptr = EX(prev_execute_data);
- if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ptr->op_array->filename->val, ptr->opline->lineno);
+ if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ptr->func->op_array.filename->val, ptr->opline->lineno);
} else {
zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
}
@@ -1468,13 +1478,13 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci TSRMLS_DC)
{
if (fci != NULL) {
- execute_data_ptr->function_state.function->internal_function.handler(
+ execute_data_ptr->call->func->internal_function.handler(
fci->param_count, fci->retval TSRMLS_CC
);
} else {
zval *return_value = EX_VAR_2(execute_data_ptr, execute_data_ptr->opline->result.var);
- execute_data_ptr->function_state.function->internal_function.handler(
- execute_data_ptr->opline->extended_value + execute_data_ptr->call->num_additional_args, return_value TSRMLS_CC
+ execute_data_ptr->call->func->internal_function.handler(
+ execute_data_ptr->call->num_args, return_value TSRMLS_CC
);
}
}
@@ -1495,9 +1505,9 @@ void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{
static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */
{
- if (EXPECTED(EX(op_array)->last_var > 0)) {
+ if (EXPECTED(EX(func)->op_array.last_var > 0)) {
zval *cv = EX_VAR_NUM(0);
- zval *end = cv + EX(op_array)->last_var;
+ zval *end = cv + EX(func)->op_array.last_var;
do {
zval_ptr_dtor(cv);
cv++;
@@ -1517,132 +1527,65 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
* ==================
*
* +========================================+
- * | zend_execute_data |<---+
- * | EX(function_state).arguments |--+ |
- * | ... | | |
- * | ARGUMENT [1] | | |
- * | ... | | |
- * | ARGUMENT [ARGS_NUMBER] | | |
- * | ARGS_NUMBER |<-+ |
- * +========================================+ |
- * |
- * +========================================+ |
- * EG(current_execute_data) -> | zend_execute_data | |
- * | EX(prev_execute_data) |----+
+ * EG(current_execute_data) -> | zend_execute_data |
* +----------------------------------------+
- * EX_CV_NUM(0) ---------> | VAR[0] |
+ * 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] |
- * +----------------------------------------+
- * EX(call_slots) -> | CALL_SLOT[0] |
+ * | ARG[N+1] (extra_args) |
* | ... |
- * | CALL_SLOT[op_array->nested_calls-1] |
- * +----------------------------------------+
- * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] |
- * | ... |
- * zend_vm_stack_top --------> | ... |
- * | ... |
- * | ARGUMENTS STACK [op_array->used_stack] |
* +----------------------------------------+
*/
-static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
- zend_execute_data *execute_data;
-
- /*
- * When allocating the execute_data, memory for compiled variables and
- * temporary variables is also allocated before and after the actual
- * zend_execute_data struct. In addition we also allocate space to store
- * information about syntactically nested called functions and actual
- * parameters. op_array->last_var specifies the number of compiled
- * variables and op_array->T is the number of temporary variables. If there
- * is no symbol table, then twice as much memory is allocated for compiled
- * variables. In that case the first half contains zval**s and the second
- * half the actual zval*s (which would otherwise be in the symbol table).
- */
- size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data));
- size_t vars_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (op_array->last_var + op_array->T);
- size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls;
- size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * op_array->used_stack;
- size_t total_size = execute_data_size + vars_size + call_slots_size + stack_size;
-
- /*
- * Normally the execute_data is allocated on the VM stack (because it does
- * not actually do any allocation and thus is faster). For generators
- * though this behavior would be suboptimal, because the (rather large)
- * structure would have to be copied back and forth every time execution is
- * suspended or resumed. That's why for generators the execution context
- * is allocated using a separate VM stack, thus allowing to save and
- * restore it simply by replacing a pointer. The same segment also keeps
- * a copy of previous execute_data and passed parameters.
- */
- if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
- /* Prepend the regular stack frame with a copy of prev_execute_data
- * and the passed arguments
- */
- int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data));
- size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval)) * (args_count + 1);
-
- total_size += args_size + execute_data_size;
-
- EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(zval) - 1)) / sizeof(zval));
- EG(argument_stack)->prev = NULL;
- execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size);
-
- /* copy prev_execute_data */
- EX(prev_execute_data) = (zend_execute_data*)ZEND_VM_STACK_ELEMETS(EG(argument_stack));
- memset(EX(prev_execute_data), 0, sizeof(zend_execute_data));
- EX(prev_execute_data)->function_state.function = (zend_function*)op_array;
- EX(prev_execute_data)->function_state.arguments = (zval*)(((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + execute_data_size + args_size - sizeof(zval)));
-
- /* copy arguments */
- ZVAL_LONG(EX(prev_execute_data)->function_state.arguments, args_count);
- if (args_count > 0) {
- zval *arg_src = zend_vm_stack_get_arg_ex(EG(current_execute_data), 1);
- zval *arg_dst = zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1);
- int i;
-
- for (i = 0; i < args_count; i++) {
- ZVAL_COPY(arg_dst + i, arg_src + i);
- }
- }
- } else {
- execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC);
- EX(prev_execute_data) = EG(current_execute_data);
- }
+ ZEND_ASSERT(EX(func) == (zend_function*)op_array);
+ ZEND_ASSERT(EX(object) == Z_OBJ(EG(This)));
+ ZEND_ASSERT(EX(called_scope) == EG(called_scope));
EX(return_value) = return_value;
EX(frame_kind) = frame_kind;
ZVAL_UNDEF(&EX(old_error_reporting));
EX(delayed_exception) = NULL;
- EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + vars_size);
EX(call) = NULL;
EG(opline_ptr) = &EX(opline);
EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
- EX(function_state).function = (zend_function *) op_array;
- EX(function_state).arguments = NULL;
- EX(op_array) = op_array;
- EX(object) = Z_OBJ(EG(This));
EX(scope) = EG(scope);
- EX(called_scope) = EG(called_scope);
EX(symbol_table) = EG(active_symbol_table);
- if (EX(symbol_table)) {
+ if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_attach_symbol_table(execute_data);
} else {
+ zend_uint first_extra_arg = op_array->num_args;
+
+ if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
+ first_extra_arg--;
+ }
+ if (UNEXPECTED(EX(num_args) > first_extra_arg)) {
+ /* 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(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg));
+ }
+
do {
- /* Initialize CV variables */
- zval *var = EX_VAR_NUM(0);
- zval *end = var + op_array->last_var;
+ /* Initialize CV variables (skip arguments) */
+ int num_args = MIN(op_array->num_args, EX(num_args));
- while (var != end) {
- ZVAL_UNDEF(var);
- var++;
+ if (EXPECTED(num_args < op_array->last_var)) {
+ zval *var = EX_VAR_NUM(num_args);
+ zval *end = EX_VAR_NUM(op_array->last_var);
+
+ do {
+ ZVAL_UNDEF(var);
+ var++;
+ } while (var != end);
}
} while (0);
@@ -1661,62 +1604,120 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
}
EX(run_time_cache) = op_array->run_time_cache;
- EG(argument_stack)->top = (zval*)zend_vm_stack_frame_base(execute_data);
EG(current_execute_data) = execute_data;
+}
+/* }}} */
+
+ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op_array, zval *return_value TSRMLS_DC) /* {{{ */
+{
+ /*
+ * Normally the execute_data is allocated on the VM stack (because it does
+ * not actually do any allocation and thus is faster). For generators
+ * though this behavior would be suboptimal, because the (rather large)
+ * structure would have to be copied back and forth every time execution is
+ * suspended or resumed. That's why for generators the execution context
+ * is allocated using a separate VM stack, thus allowing to save and
+ * restore it simply by replacing a pointer.
+ */
+ zend_execute_data *execute_data;
+ zend_uint num_args = EG(current_execute_data)->call->num_args;
+
+ EG(argument_stack) = zend_vm_stack_new_page(
+ MAX(ZEND_VM_STACK_PAGE_SIZE,
+ ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)));
+ EG(argument_stack)->prev = NULL;
+
+ execute_data = zend_vm_stack_push_call_frame(
+ (zend_function*)op_array,
+ num_args,
+ EG(current_execute_data)->call->flags,
+ EG(current_execute_data)->call->called_scope,
+ EG(current_execute_data)->call->object,
+ NULL TSRMLS_CC);
+ execute_data->num_args = num_args;
+
+ /* copy arguments */
+ if (num_args > 0) {
+ zval *arg_src = ZEND_CALL_ARG(EG(current_execute_data)->call, 1);
+ zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
+ int i;
+
+ for (i = 0; i < num_args; i++) {
+ ZVAL_COPY_VALUE(arg_dst + i, arg_src + i);
+ }
+ }
+
+ i_init_execute_data(execute_data, op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
return execute_data;
}
/* }}} */
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
+ZEND_API zend_execute_data *zend_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
{
- return i_create_execute_data_from_op_array(op_array, return_value, frame_kind TSRMLS_CC);
+ zend_execute_data *execute_data;
+
+ execute_data = EG(current_execute_data)->call;
+ EX(prev_execute_data) = EG(current_execute_data);
+ i_init_execute_data(execute_data, op_array, return_value, frame_kind TSRMLS_CC);
+
+ return execute_data;
}
/* }}} */
-static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, call_slot *call TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(zend_op *opline, zend_execute_data *call TSRMLS_DC) /* {{{ */
{
zend_uint arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
- return ARG_SHOULD_BE_SENT_BY_REF(call->fbc, arg_num);
+ return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
}
/* }}} */
-static zval *zend_vm_stack_push_args_with_copy(int count TSRMLS_DC) /* {{{ */
-{
- zend_vm_stack p = EG(argument_stack);
-
- zend_vm_stack_extend(count + 1 TSRMLS_CC);
+static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
+{
+ zend_execute_data *new_call;
+ int used_stack = (EG(argument_stack)->top - (zval*)call) + additional_args;
+
+ /* copy call frame into new stack segment */
+ zend_vm_stack_extend(used_stack TSRMLS_CC);
+ new_call = (zend_execute_data*)EG(argument_stack)->top;
+ EG(argument_stack)->top += used_stack;
+ *new_call = *call;
+ if (passed_args) {
+ zval *src = ZEND_CALL_ARG(call, 1);
+ zval *dst = ZEND_CALL_ARG(new_call, 1);
+ do {
+ ZVAL_COPY_VALUE(dst, src);
+ passed_args--;
+ src++;
+ dst++;
+ } while (passed_args);
+ }
- EG(argument_stack)->top += count;
- ZVAL_LONG(EG(argument_stack)->top, count);
- while (count-- > 0) {
- zval *data = --p->top;
- ZVAL_COPY_VALUE(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count, data);
+ /* delete old call_frame from previous stack segment */
+ EG(argument_stack)->prev->top = (zval*)call;
- if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) {
- zend_vm_stack r = p;
+ /* delete previous stack segment if it becames empty */
+ if (UNEXPECTED(EG(argument_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)->prev))) {
+ zend_vm_stack r = EG(argument_stack)->prev;
- EG(argument_stack)->prev = p->prev;
- p = p->prev;
- efree(r);
- }
+ EG(argument_stack)->prev = r->prev;
+ efree(r);
}
- return EG(argument_stack)->top++;
+
+ return new_call;
}
/* }}} */
-static zend_always_inline zval *zend_vm_stack_push_args(int count TSRMLS_DC) /* {{{ */
+static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, zend_uint passed_args, zend_uint additional_args TSRMLS_DC) /* {{{ */
{
- if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count)
- || UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) {
- return zend_vm_stack_push_args_with_copy(count TSRMLS_CC);
+ if (EXPECTED(EG(argument_stack)->end - EG(argument_stack)->top > additional_args)) {
+ EG(argument_stack)->top += additional_args;
+ } else {
+ *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args TSRMLS_CC);
}
- ZVAL_LONG(EG(argument_stack)->top, count);
- return EG(argument_stack)->top++;
}
/* }}} */
-
#define ZEND_VM_NEXT_OPCODE() \
CHECK_SYMBOL_TABLES() \
ZEND_VM_INC_OPCODE(); \
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index b80d2adff8..40f42ae2dd 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -35,7 +35,8 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt
void init_executor(TSRMLS_D);
void shutdown_executor(TSRMLS_D);
void shutdown_destructors(TSRMLS_D);
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
+ZEND_API zend_execute_data *zend_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
+ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_op_array *op_array, zval *return_value TSRMLS_DC);
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
@@ -48,7 +49,7 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
{
@@ -149,7 +150,7 @@ ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *s
ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope TSRMLS_DC);
/* dedicated Zend executor functions - do not use! */
-#define ZEND_VM_STACK_PAGE_SIZE ((16 * 1024) - 16)
+#define ZEND_VM_STACK_PAGE_SIZE (16 * 1024) /* should be a power of 2 */
struct _zend_vm_stack {
zval *top;
@@ -157,22 +158,26 @@ struct _zend_vm_stack {
zend_vm_stack prev;
};
+#define ZEND_VM_STACK_HEADER_SLOT \
+ ((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
+
#define ZEND_VM_STACK_ELEMETS(stack) \
- ((zval*)(((char*)(stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack))))
-
-#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
- do { \
- if (UNEXPECTED((count) > \
- EG(argument_stack)->end - EG(argument_stack)->top)) { \
- zend_vm_stack_extend((count) TSRMLS_CC); \
- } \
+ (((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOT)
+
+#define ZEND_VM_STACK_GROW_IF_NEEDED(count) \
+ do { \
+ if (UNEXPECTED(((count) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) > \
+ ((char*)EG(argument_stack)->end) - \
+ ((char*)EG(argument_stack)->top))) { \
+ zend_vm_stack_extend((count) TSRMLS_CC); \
+ } \
} while (0)
static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
- zend_vm_stack page = (zend_vm_stack)emalloc(ZEND_MM_ALIGNED_SIZE(sizeof(*page)) + sizeof(zval) * count);
+ zend_vm_stack page = (zend_vm_stack)emalloc(count * ZEND_MM_ALIGNED_SIZE(sizeof(zval)));
page->top = ZEND_VM_STACK_ELEMETS(page);
- page->end = page->top + count;
+ page->end = (zval*)page + count;
page->prev = NULL;
return page;
}
@@ -180,6 +185,7 @@ static zend_always_inline zend_vm_stack zend_vm_stack_new_page(int count) {
static zend_always_inline void zend_vm_stack_init(TSRMLS_D)
{
EG(argument_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE);
+ EG(argument_stack)->top++;
}
static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
@@ -195,95 +201,90 @@ static zend_always_inline void zend_vm_stack_destroy(TSRMLS_D)
static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
{
- zend_vm_stack p = zend_vm_stack_new_page(count >= ZEND_VM_STACK_PAGE_SIZE ? count : ZEND_VM_STACK_PAGE_SIZE);
+ int size = count * ZEND_MM_ALIGNED_SIZE(sizeof(zval));
+ zend_vm_stack p = zend_vm_stack_new_page(
+ (size >= (ZEND_VM_STACK_PAGE_SIZE - ZEND_VM_STACK_HEADER_SLOT) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) ?
+ (size + ((ZEND_VM_STACK_HEADER_SLOT + ZEND_VM_STACK_PAGE_SIZE) * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) &
+ ~((ZEND_VM_STACK_PAGE_SIZE * ZEND_MM_ALIGNED_SIZE(sizeof(zval))) - 1) :
+ ZEND_VM_STACK_PAGE_SIZE);
p->prev = EG(argument_stack);
EG(argument_stack) = p;
}
-static zend_always_inline zval *zend_vm_stack_top(TSRMLS_D)
-{
- return EG(argument_stack)->top;
-}
-
-static zend_always_inline zval *zend_vm_stack_top_inc(TSRMLS_D)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
{
- return EG(argument_stack)->top++;
+ int used_stack = ZEND_CALL_FRAME_SLOT + num_args;
+ zend_execute_data *call;
+
+ if (ZEND_USER_CODE(func->type)) {
+ 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;
+ EG(argument_stack)->top += used_stack;
+ call->func = func;
+ call->num_args = 0;
+ call->flags = flags;
+ call->called_scope = called_scope;
+ call->object = object;
+ call->prev_nested_call = prev;
+ return call;
}
-static zend_always_inline void zend_vm_stack_push(zval *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
{
- ZVAL_COPY_VALUE(EG(argument_stack)->top, ptr);
- EG(argument_stack)->top++;
-}
+ zend_uint first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
-static zend_always_inline zval *zend_vm_stack_pop(TSRMLS_D)
-{
- return --EG(argument_stack)->top;
+ if (UNEXPECTED(call->num_args > first_extra_arg)) {
+ zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
+ zval *p = end + (call->num_args - first_extra_arg);
+ do {
+ p--;
+ i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+ } while (p != end);
+ }
}
-static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call TSRMLS_DC)
{
- zval *ret;
- int count = (size + (sizeof(zval) - 1)) / sizeof(zval);
+ zend_uint num_args = call->num_args;
- ZEND_VM_STACK_GROW_IF_NEEDED(count);
- ret = EG(argument_stack)->top;
- EG(argument_stack)->top += count;
- return ret;
-}
+ if (num_args > 0) {
+ zval *p = ZEND_CALL_ARG(call, num_args + 1);
+ zval *end = p - num_args;;
-static zend_always_inline zval* zend_vm_stack_frame_base(zend_execute_data *ex)
-{
- return (zval*)((char*)ex->call_slots +
- ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls);
+ do {
+ p--;
+ i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
+ } while (p != end);
+ }
}
-static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC)
+static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call TSRMLS_DC)
{
- if (UNEXPECTED((void*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == ptr)) {
+ if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (zval*)call)) {
zend_vm_stack p = EG(argument_stack);
EG(argument_stack) = p->prev;
efree(p);
} else {
- EG(argument_stack)->top = (zval*)ptr;
- }
-}
-
-static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
-{
- zval *p = EG(argument_stack)->top - 1;
-
- if (EXPECTED(Z_LVAL_P(p) > 0)) {
- zval *end = p - Z_LVAL_P(p);
-
- do {
- p--;
- i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
- } while (p != end);
- }
- if (nested) {
- EG(argument_stack)->top = p;
- } else {
- zend_vm_stack_free(p TSRMLS_CC);
+ EG(argument_stack)->top = (zval*)call;
}
}
static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
{
- zval *p = ex->function_state.arguments;
- return Z_LVAL_P(p);
+ return ex->call->num_args;
}
static zend_always_inline zval* zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
{
- zval *p = ex->function_state.arguments;
- int arg_count = Z_LVAL_P(p);
+ int arg_count = ex->call->num_args;
if (UNEXPECTED(requested_arg > arg_count)) {
return NULL;
}
- return p - arg_count + requested_arg - 1;
+ return ZEND_CALL_ARG(ex->call, requested_arg);
}
static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index ebb995a262..2ba582942a 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -156,7 +156,6 @@ void init_executor(TSRMLS_D) /* {{{ */
EG(error_handling) = EH_NORMAL;
zend_vm_stack_init(TSRMLS_C);
- ZVAL_LONG(zend_vm_stack_top_inc(TSRMLS_C), 0);
zend_hash_init(&EG(symbol_table).ht, 64, NULL, ZVAL_PTR_DTOR, 0);
GC_REFCOUNT(&EG(symbol_table)) = 1;
@@ -393,17 +392,25 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
/* return class name and "::" or "". */
ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */
{
+ zend_function *func;
+
if (!zend_is_executing(TSRMLS_C)) {
if (space) {
*space = "";
}
return "";
}
- switch (EG(current_execute_data)->function_state.function->type) {
+
+ if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
+ func = EG(current_execute_data)->call->func;
+ } else {
+ func = EG(current_execute_data)->func;
+ }
+ switch (func->type) {
case ZEND_USER_FUNCTION:
case ZEND_INTERNAL_FUNCTION:
{
- zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
+ zend_class_entry *ce = func->common.scope;
if (space) {
*space = ce ? "::" : "";
@@ -421,12 +428,19 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
{
+ zend_function *func;
+
if (!zend_is_executing(TSRMLS_C)) {
return NULL;
}
- switch (EG(current_execute_data)->function_state.function->type) {
+ if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
+ func = EG(current_execute_data)->call->func;
+ } else {
+ func = EG(current_execute_data)->func;
+ }
+ switch (func->type) {
case ZEND_USER_FUNCTION: {
- zend_string *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
+ zend_string *function_name = func->common.function_name;
if (function_name) {
return function_name->val;
@@ -436,7 +450,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
}
break;
case ZEND_INTERNAL_FUNCTION:
- return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name->val;
+ return func->common.function_name->val;
break;
default:
return NULL;
@@ -655,6 +669,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_class_entry *called_scope = NULL;
zend_execute_data execute_data;
zend_fcall_info_cache fci_cache_local;
+ zend_function *func;
zval tmp;
ZVAL_UNDEF(fci->retval);
@@ -681,7 +696,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EX(object) = Z_OBJ(EG(This));
EX(scope) = EG(scope);
EX(called_scope) = EG(called_scope);
- EX(op_array) = NULL;
+ EX(func) = NULL;
EX(opline) = NULL;
} else {
/* This only happens when we're called outside any execute()'s
@@ -719,7 +734,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
STR_RELEASE(callable_name);
}
- EX(function_state).function = fci_cache->function_handler;
+ func = fci_cache->function_handler;
+ EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
calling_scope = fci_cache->calling_scope;
called_scope = fci_cache->called_scope;
fci->object = fci_cache->object;
@@ -729,24 +745,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
return FAILURE;
}
- if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name->val, EX(function_state).function->common.function_name->val);
+ if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
+ if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", func->common.scope->name->val, func->common.function_name->val);
}
- if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
+ if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
- EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
- EX(function_state).function->common.scope ? "::" : "",
- EX(function_state).function->common.function_name->val);
+ func->common.scope ? func->common.scope->name->val : "",
+ func->common.scope ? "::" : "",
+ func->common.function_name->val);
}
}
- ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
-
for (i=0; i<fci->param_count; i++) {
zval *param;
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
// TODO: Scalar values don't have reference counters anymore.
// They are assumed to be 1, and they may be easily passed by
// reference now. However, previously scalars with refcount==1
@@ -766,19 +780,19 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
(!Z_ISREF(fci->params[i]) && Z_REFCOUNT(fci->params[i]) > 1)) {
if (fci->no_separation &&
- !ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
- if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
+ !ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
+ if (i) {
/* hack to clean up the stack */
- ZVAL_LONG(&tmp, i);
- zend_vm_stack_push(&tmp TSRMLS_CC);
- zend_vm_stack_clear_multiple(0 TSRMLS_CC);
+ EX(call)->num_args = i;
+ zend_vm_stack_free_args(EX(call) TSRMLS_CC);
}
+ zend_vm_stack_free_call_frame(EX(call) TSRMLS_CC);
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
i+1,
- EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
- EX(function_state).function->common.scope ? "::" : "",
- EX(function_state).function->common.function_name->val);
+ func->common.scope ? func->common.scope->name->val : "",
+ func->common.scope ? "::" : "",
+ func->common.function_name->val);
return FAILURE;
}
@@ -794,27 +808,26 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
} else if (Z_REFCOUNTED(fci->params[i])) {
Z_ADDREF(fci->params[i]);
}
- param = &fci->params[i];
+ param = ZEND_CALL_ARG(EX(call), i+1);
+ ZVAL_COPY_VALUE(param, &fci->params[i]);
} else if (Z_ISREF(fci->params[i]) &&
/* don't separate references for __call */
- (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
+ (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
param = &tmp;
+ param = ZEND_CALL_ARG(EX(call), i+1);
ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
} else {
- param = &tmp;
+ param = ZEND_CALL_ARG(EX(call), i+1);
ZVAL_COPY(param, &fci->params[i]);
}
- zend_vm_stack_push(param TSRMLS_CC);
}
-
- EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_LONG(EX(function_state).arguments, fci->param_count);
+ EX(call)->num_args = fci->param_count;
EG(scope) = calling_scope;
EG(called_scope) = called_scope;
if (!fci->object ||
- (EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
- Z_OBJ(EG(This)) = NULL;
+ (func->common.fn_flags & ZEND_ACC_STATIC)) {
+ Z_OBJ(EG(This)) = EX(call)->object = NULL;
} else {
Z_OBJ(EG(This)) = fci->object;
Z_ADDREF(EG(This));
@@ -823,9 +836,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EX(prev_execute_data) = EG(current_execute_data);
EG(current_execute_data) = &execute_data;
- if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
+ if (func->type == ZEND_USER_FUNCTION) {
calling_symbol_table = EG(active_symbol_table);
- EG(scope) = EX(function_state).function->common.scope;
+ EG(scope) = func->common.scope;
if (fci->symbol_table) {
EG(active_symbol_table) = fci->symbol_table;
} else {
@@ -833,7 +846,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}
original_op_array = EG(active_op_array);
- EG(active_op_array) = (zend_op_array *) EX(function_state).function;
+ EG(active_op_array) = (zend_op_array *) func;
original_opline_ptr = EG(opline_ptr);
if (EXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) == 0)) {
@@ -848,18 +861,21 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
}
EG(active_symbol_table) = calling_symbol_table;
- } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
- int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+ } else if (func->type == ZEND_INTERNAL_FUNCTION) {
+ int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
ZVAL_NULL(fci->retval);
- if (EX(function_state).function->common.scope) {
- EG(scope) = EX(function_state).function->common.scope;
+ if (func->common.scope) {
+ EG(scope) = func->common.scope;
}
if (EXPECTED(zend_execute_internal == NULL)) {
/* saves one function call if zend_execute_internal is not used */
- EX(function_state).function->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
+ func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
} else {
zend_execute_internal(&execute_data, fci TSRMLS_CC);
}
+ zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+ zend_vm_stack_free_call_frame(EX(call) TSRMLS_CC);
+
/* We shouldn't fix bad extensions here,
because it can break proper ones (Bug #34045)
if (!EX(function_state).function->common.return_reference)
@@ -880,22 +896,21 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
/* Not sure what should be done here if it's a static method */
if (fci->object) {
- fci->object->handlers->call_method(EX(function_state).function->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
+ fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
- if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- STR_RELEASE(EX(function_state).function->common.function_name);
+ if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+ STR_RELEASE(func->common.function_name);
}
- efree(EX(function_state).function);
+ efree(func);
if (EG(exception)) {
zval_ptr_dtor(fci->retval);
ZVAL_UNDEF(fci->retval);
}
}
- zend_vm_stack_clear_multiple(0 TSRMLS_CC);
if (Z_OBJ(EG(This))) {
zval_ptr_dtor(&EG(This));
@@ -1080,6 +1095,10 @@ ZEND_API int zend_eval_stringl(char *str, int str_len, zval *retval_ptr, char *s
zend_try {
ZVAL_UNDEF(&local_retval);
+ if (EG(current_execute_data)) {
+ EG(current_execute_data)->call = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC);
+ }
zend_execute(new_op_array, &local_retval TSRMLS_CC);
} zend_catch {
destroy_op_array(new_op_array TSRMLS_CC);
@@ -1583,33 +1602,34 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
/* Search for last called user function */
ex = EG(current_execute_data);
- while (ex && !ex->op_array) {
+ while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->common.type))) {
ex = ex->prev_execute_data;
}
- if (ex && ex->symbol_table) {
+ if (!ex) {
+ return;
+ }
+ if (ex->symbol_table) {
EG(active_symbol_table) = ex->symbol_table;
return;
}
- if (ex && ex->op_array) {
- if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
- /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
- EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
- } else {
- EG(active_symbol_table) = emalloc(sizeof(zend_array));
- GC_REFCOUNT(EG(active_symbol_table)) = 0;
- GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY;
- zend_hash_init(&EG(active_symbol_table)->ht, ex->op_array->last_var, NULL, ZVAL_PTR_DTOR, 0);
- /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
- }
- ex->symbol_table = EG(active_symbol_table);
- for (i = 0; i < ex->op_array->last_var; i++) {
- zval zv;
-
- ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
- zend_hash_add_new(&EG(active_symbol_table)->ht,
- ex->op_array->vars[i], &zv);
- }
+ if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
+ /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
+ EG(active_symbol_table) = *(EG(symtable_cache_ptr)--);
+ } else {
+ EG(active_symbol_table) = emalloc(sizeof(zend_array));
+ GC_REFCOUNT(EG(active_symbol_table)) = 0;
+ GC_TYPE_INFO(EG(active_symbol_table)) = IS_ARRAY;
+ zend_hash_init(&EG(active_symbol_table)->ht, ex->func->op_array.last_var, NULL, ZVAL_PTR_DTOR, 0);
+ /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/
+ }
+ ex->symbol_table = EG(active_symbol_table);
+ for (i = 0; i < ex->func->op_array.last_var; i++) {
+ zval zv;
+
+ ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
+ zend_hash_add_new(&EG(active_symbol_table)->ht,
+ ex->func->op_array.vars[i], &zv);
}
}
}
@@ -1618,7 +1638,7 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
{
int i;
- zend_op_array *op_array = execute_data->op_array;
+ zend_op_array *op_array = &execute_data->func->op_array;
HashTable *ht = &execute_data->symbol_table->ht;
/* copy real values from symbol table into CV slots and create
@@ -1649,7 +1669,7 @@ ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ *
ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
{
int i;
- zend_op_array *op_array = execute_data->op_array;
+ zend_op_array *op_array = &execute_data->func->op_array;
HashTable *ht = &execute_data->symbol_table->ht;
/* copy real values from CV slots into symbol table */
@@ -1669,7 +1689,7 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS
if (!EG(active_symbol_table)) {
int i;
zend_execute_data *execute_data = EG(current_execute_data);
- zend_op_array *op_array = execute_data->op_array;
+ zend_op_array *op_array = &execute_data->func->op_array;
zend_ulong h = STR_HASH_VAL(name);
if (op_array) {
@@ -1702,7 +1722,7 @@ ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int
if (!EG(active_symbol_table)) {
int i;
zend_execute_data *execute_data = EG(current_execute_data);
- zend_op_array *op_array = execute_data->op_array;
+ zend_op_array *op_array = &execute_data->func->op_array;
zend_ulong h = zend_hash_func(name, len);
if (op_array) {
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index c80e909565..f4847b0839 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -32,7 +32,7 @@ static zend_object *zend_generator_create(zend_class_entry *class_type TSRMLS_DC
static void zend_generator_cleanup_unfinished_execution(zend_generator *generator TSRMLS_DC) /* {{{ */
{
zend_execute_data *execute_data = generator->execute_data;
- zend_op_array *op_array = execute_data->op_array;
+ zend_op_array *op_array = &execute_data->func->op_array;
if (generator->send_target) {
if (Z_REFCOUNTED_P(generator->send_target)) Z_DELREF_P(generator->send_target);
@@ -75,23 +75,13 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
}
}
- /* Clear any backed up stack arguments */
- {
- zval *ptr = generator->stack->top - 1;
- zval *end = zend_vm_stack_frame_base(execute_data);
-
- for (; ptr >= end; --ptr) {
- zval_ptr_dtor((zval*) ptr);
- }
- }
-
/* If yield was used as a function argument there may be active
* method calls those objects need to be freed */
- while (execute_data->call >= execute_data->call_slots) {
+ while (execute_data->call) {
if (execute_data->call->object) {
OBJ_RELEASE(execute_data->call->object);
}
- execute_data->call--;
+ execute_data->call = execute_data->call->prev_nested_call;
}
}
/* }}} */
@@ -110,7 +100,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
if (generator->execute_data) {
zend_execute_data *execute_data = generator->execute_data;
- zend_op_array *op_array = execute_data->op_array;
+ zend_op_array *op_array = &execute_data->func->op_array;
if (!execute_data->symbol_table) {
zend_free_compiled_variables(execute_data TSRMLS_CC);
@@ -128,23 +118,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
return;
}
- /* We have added an additional stack frame in prev_execute_data, so we
- * have to free it. It also contains the arguments passed to the
- * generator (for func_get_args) so those have to be freed too. */
- {
- zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
- zval *arguments = prev_execute_data->function_state.arguments;
-
- if (arguments) {
- int arguments_count = Z_LVAL_P(arguments);
- zval *arguments_start = arguments - arguments_count;
- int i;
-
- for (i = 0; i < arguments_count; ++i) {
- zval_ptr_dtor(arguments_start + i);
- }
- }
- }
+ zend_vm_stack_free_extra_args(generator->execute_data TSRMLS_CC);
/* Some cleanups are only necessary if the generator was closued
* before it could finish execution (reach a return statement). */
@@ -158,6 +132,10 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
efree(op_array);
}
+ if (generator->execute_data->prev_execute_data) {
+ generator->execute_data->prev_execute_data->call = generator->execute_data->prev_nested_call;
+ }
+
efree(generator->stack);
generator->execute_data = NULL;
}
@@ -171,18 +149,18 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
zend_uint op_num, finally_op_num;
int i;
- if (!ex || !ex->op_array->has_finally_block) {
+ if (!ex || !ex->func->op_array.has_finally_block) {
return;
}
/* -1 required because we want the last run opcode, not the
* next to-be-run one. */
- op_num = ex->opline - ex->op_array->opcodes - 1;
+ op_num = ex->opline - ex->func->op_array.opcodes - 1;
/* Find next finally block */
finally_op_num = 0;
- for (i = 0; i < ex->op_array->last_try_catch; i++) {
- zend_try_catch_element *try_catch = &ex->op_array->try_catch_array[i];
+ for (i = 0; i < ex->func->op_array.last_try_catch; i++) {
+ zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i];
if (op_num < try_catch->try_op) {
break;
@@ -196,7 +174,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
/* If a finally block was found we jump directly to it and
* resume the generator. */
if (finally_op_num) {
- ex->opline = &ex->op_array->opcodes[finally_op_num];
+ ex->opline = &ex->func->op_array.opcodes[finally_op_num];
ex->fast_ret = NULL;
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
zend_generator_resume(generator TSRMLS_CC);
@@ -288,7 +266,7 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
opline_ptr = EG(opline_ptr);
current_symbol_table = EG(active_symbol_table);
EG(active_symbol_table) = NULL;
- execute_data = zend_create_execute_data_from_op_array(op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+ execute_data = zend_create_generator_execute_data(op_array, return_value TSRMLS_CC);
EG(active_symbol_table) = current_symbol_table;
EG(current_execute_data) = current_execute_data;
EG(opline_ptr) = opline_ptr;
@@ -300,8 +278,8 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
}
/* Save execution context in generator object. */
- execute_data->prev_execute_data->object = Z_OBJ_P(return_value);
generator = (zend_generator *) Z_OBJ_P(return_value);
+ execute_data->prev_execute_data = NULL;
generator->execute_data = execute_data;
generator->stack = EG(argument_stack);
EG(argument_stack) = current_stack;
@@ -343,13 +321,14 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
zend_class_entry *original_scope = EG(scope);
zend_class_entry *original_called_scope = EG(called_scope);
zend_vm_stack original_stack = EG(argument_stack);
+ zend_execute_data *prev_execute_data;
original_This = Z_OBJ(EG(This));
/* Set executor globals */
EG(current_execute_data) = generator->execute_data;
EG(opline_ptr) = &generator->execute_data->opline;
- EG(active_op_array) = generator->execute_data->op_array;
+ EG(active_op_array) = &generator->execute_data->func->op_array;
EG(active_symbol_table) = generator->execute_data->symbol_table;
Z_OBJ(EG(This)) = generator->execute_data->object;
EG(scope) = generator->execute_data->scope;
@@ -358,17 +337,32 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
/* We want the backtrace to look as if the generator function was
* called from whatever method we are current running (e.g. next()).
- * The first prev_execute_data contains an additional stack frame,
- * which makes the generator function show up in the backtrace and
- * makes the arguments available to func_get_args(). So we have to
- * set the prev_execute_data of that prev_execute_data :) */
- generator->execute_data->prev_execute_data->prev_execute_data = original_execute_data;
+ * So we have to link generator call frame with caller call frames */
+
+ prev_execute_data = original_execute_data;
+ if (prev_execute_data &&
+ prev_execute_data->call &&
+ (prev_execute_data->call->flags & ZEND_CALL_DONE)) {
+ prev_execute_data->call->prev_execute_data = prev_execute_data;
+ prev_execute_data = prev_execute_data->call;
+ }
+ generator->execute_data->prev_execute_data = prev_execute_data;
+ if (prev_execute_data) {
+ generator->execute_data->prev_nested_call = prev_execute_data->call;
+ prev_execute_data->call = generator->execute_data;
+ }
/* Resume execution */
generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING;
zend_execute_ex(generator->execute_data TSRMLS_CC);
generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING;
+ /* Unlink generator call_frame from the caller */
+ if (generator->execute_data && generator->execute_data->prev_execute_data) {
+ generator->execute_data->prev_execute_data->call = generator->execute_data->prev_nested_call;
+ generator->execute_data->prev_execute_data = NULL;
+ }
+
/* Restore executor globals */
EG(current_execute_data) = original_execute_data;
EG(opline_ptr) = original_opline_ptr;
@@ -670,7 +664,7 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob
return NULL;
}
- if (by_ref && !(generator->execute_data->op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
+ if (by_ref && !(generator->execute_data->func->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
zend_throw_exception(NULL, "You can only iterate a generator by-reference if it declared that it yields by-reference", 0 TSRMLS_CC);
return NULL;
}
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index ac4599282e..e38fbfc640 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -905,7 +905,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{
ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
- zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
+ zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func;
zval method_name, method_args;
zval method_result;
zend_class_entry *ce = Z_OBJCE_P(getThis());
@@ -1123,7 +1123,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str
ZEND_API void zend_std_callstatic_user_call(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
- zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->function_state.function;
+ zend_internal_function *func = (zend_internal_function *)EG(current_execute_data)->call->func;
zval method_name, method_args;
zval method_result;
zend_class_entry *ce = EG(scope);
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 7ecccdaf32..cad1dd2e9c 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -70,9 +70,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->T = 0;
- op_array->nested_calls = 0;
- op_array->used_stack = 0;
-
op_array->function_name = NULL;
op_array->filename = zend_get_compiled_filename(TSRMLS_C);
op_array->doc_comment = NULL;
@@ -631,7 +628,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
{
zend_op *opline, *end;
- if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) {
+ if (!ZEND_USER_CODE(op_array->type)) {
return 0;
}
if (op_array->has_finally_block) {
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 38377d3cce..f0da4eeded 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1772,6 +1772,7 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
{
vm_frame_kind frame_kind = EX(frame_kind);
+ zend_execute_data *prev_nested_call;
EG(current_execute_data) = EX(prev_execute_data);
@@ -1780,22 +1781,22 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
}
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
- zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
+ zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
}
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
execute_data = EG(current_execute_data);
+ EX(call) = prev_nested_call;
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
EG(active_symbol_table) = EX(symbol_table);
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
-
if (Z_OBJ(EG(This))) {
- if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
- if (EX(call)->is_ctor_result_used) {
+ if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
+ if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
@@ -1812,10 +1813,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
- EX(call)--;
-
- zend_vm_stack_clear_multiple(1 TSRMLS_CC);
-
if (UNEXPECTED(EG(exception) != NULL)) {
zend_op *opline = EX(opline);
zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -1830,16 +1827,16 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
ZEND_VM_LEAVE();
} else if (frame_kind == VM_FRAME_NESTED_CODE) {
zend_detach_symbol_table(execute_data);
- destroy_op_array(EX(op_array) TSRMLS_CC);
- efree(EX(op_array));
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+ destroy_op_array(&EX(func)->op_array TSRMLS_CC);
+ efree(EX(func));
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
execute_data = EG(current_execute_data);
+ EX(call) = prev_nested_call;
zend_attach_symbol_table(execute_data);
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION_LEAVE();
@@ -1851,6 +1848,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
} else {
if (frame_kind == VM_FRAME_TOP_FUNCTION) {
i_free_compiled_variables(execute_data TSRMLS_CC);
+ zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
} else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
zend_array *symbol_table = EX(symbol_table);
zend_execute_data *old_execute_data;
@@ -1858,7 +1856,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
zend_detach_symbol_table(execute_data);
old_execute_data = EX(prev_execute_data);
while (old_execute_data) {
- if (old_execute_data->op_array) {
+ if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) {
if (old_execute_data->symbol_table == symbol_table) {
zend_attach_symbol_table(old_execute_data);
}
@@ -1867,224 +1865,20 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
old_execute_data = old_execute_data->prev_execute_data;
}
}
- if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
- zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
+ zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
+ }
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
+
+ if (EG(current_execute_data)) {
+ EG(current_execute_data)->call = prev_nested_call;
}
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
EG(opline_ptr) = NULL;
ZEND_VM_RETURN();
}
}
-ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
-{
- USE_OPLINE
- zend_function *fbc = EX(function_state).function;
- zend_object *object;
- zend_uint num_args;
-
- SAVE_OPLINE();
- object = EX(call)->object;
- if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
- if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
- }
- if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
- zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
- fbc->common.scope ? fbc->common.scope->name->val : "",
- fbc->common.scope ? "::" : "",
- fbc->common.function_name->val);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- }
- if (fbc->common.scope &&
- !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
- !object) {
-
- if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- /* FIXME: output identifiers properly */
- zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- } else {
- /* FIXME: output identifiers properly */
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
- }
- }
-
- if (EXPECTED(EX(call)->num_additional_args == 0)) {
- num_args = opline->extended_value;
- EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_LONG(EX(function_state).arguments, num_args);
- } else {
- num_args = opline->extended_value + EX(call)->num_additional_args;
- EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
- }
- LOAD_OPLINE();
-
- if (fbc->type == ZEND_INTERNAL_FUNCTION) {
- int should_change_scope = 0;
- zval *ret;
-
- if (fbc->common.scope) {
- should_change_scope = 1;
- Z_OBJ(EG(This)) = object;
- /* TODO: we don't set scope if we call an object method ??? */
- /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
-#if 1
- EG(scope) = (object) ? NULL : fbc->common.scope;
-#else
- EG(scope) = fbc->common.scope;
-#endif
- EG(called_scope) = EX(call)->called_scope;
- }
-
- if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
- zend_uint i;
- zval *p = EX(function_state).arguments - num_args;
-
- for (i = 0; i < num_args; ++i, ++p) {
- zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
- }
- if (UNEXPECTED(EG(exception) != NULL)) {
- if (RETURN_VALUE_USED(opline)) {
- ZVAL_UNDEF(EX_VAR(opline->result.var));
- }
- if (UNEXPECTED(should_change_scope)) {
- ZEND_VM_C_GOTO(fcall_end_change_scope);
- } else {
- ZEND_VM_C_GOTO(fcall_end);
- }
- }
- }
-
- ret = EX_VAR(opline->result.var);
- ZVAL_NULL(ret);
- Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
-
- if (!zend_execute_internal) {
- /* saves one function call if zend_execute_internal is not used */
- fbc->internal_function.handler(num_args, ret TSRMLS_CC);
- } else {
- zend_execute_internal(execute_data, NULL TSRMLS_CC);
- }
-
- if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(ret);
- }
-
- if (UNEXPECTED(should_change_scope)) {
- ZEND_VM_C_GOTO(fcall_end_change_scope);
- } else {
- ZEND_VM_C_GOTO(fcall_end);
- }
- } else if (fbc->type == ZEND_USER_FUNCTION) {
- zval *return_value = NULL;
-
- Z_OBJ(EG(This)) = object;
- EG(scope) = fbc->common.scope;
- EG(called_scope) = EX(call)->called_scope;
- EG(active_symbol_table) = NULL;
- EG(active_op_array) = &fbc->op_array;
- if (RETURN_VALUE_USED(opline)) {
- return_value = EX_VAR(opline->result.var);
-
- ZVAL_NULL(return_value);
- Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
- }
-
- if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
- if (RETURN_VALUE_USED(opline)) {
- zend_generator_create_zval(EG(active_op_array), EX_VAR(opline->result.var) TSRMLS_CC);
- }
- } else if (EXPECTED(zend_execute_ex == execute_ex)) {
- if (EXPECTED(EG(exception) == NULL)) {
- i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
- ZEND_VM_ENTER();
- }
- } else {
- zend_execute(EG(active_op_array), return_value TSRMLS_CC);
- }
-
- EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
- if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
- zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
- }
- EG(active_symbol_table) = EX(symbol_table);
- } else { /* ZEND_OVERLOADED_FUNCTION */
- Z_OBJ(EG(This)) = object;
-//??? EG(scope) = NULL;
- EG(scope) = fbc->common.scope;
- EG(called_scope) = EX(call)->called_scope;
-
- ZVAL_NULL(EX_VAR(opline->result.var));
-
- /* Not sure what should be done here if it's a static method */
- if (EXPECTED(object != NULL)) {
- object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
- } else {
- zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
- }
-
- if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
- STR_RELEASE(fbc->common.function_name);
- }
- efree(fbc);
-
- if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(EX_VAR(opline->result.var));
- } else {
-//??? Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
-//??? Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
- Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0;
- }
- }
-
-ZEND_VM_C_LABEL(fcall_end_change_scope):
- if (Z_OBJ(EG(This))) {
- if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
- if (EX(call)->is_ctor_result_used) {
- Z_DELREF(EG(This));
- }
- if (Z_REFCOUNT(EG(This)) == 1) {
- zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
- }
- }
- if (!Z_DELREF(EG(This))) {
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
- _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
- } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
- gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
- }
- }
- Z_OBJ(EG(This)) = EX(object);
- EG(scope) = EX(scope);
- EG(called_scope) = EX(called_scope);
-
-ZEND_VM_C_LABEL(fcall_end):
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
- EX(call)--;
-
- zend_vm_stack_clear_multiple(1 TSRMLS_CC);
-
- if (UNEXPECTED(EG(exception) != NULL)) {
- zend_throw_exception_internal(NULL TSRMLS_CC);
- if (RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(EX_VAR(opline->result.var));
- }
- HANDLE_EXCEPTION();
- }
-
- ZEND_VM_NEXT_OPCODE();
-}
-
ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
{
USE_OPLINE
@@ -2407,8 +2201,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
USE_OPLINE
zval *function_name;
zend_free_op free_op1, free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -2423,32 +2219,8 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
}
object = GET_OP1_OBJ_ZVAL_PTR_DEREF(BP_VAR_R);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (OP2_TYPE != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
-
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (OP2_TYPE == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
FREE_OP2();
HANDLE_EXCEPTION();
@@ -2456,15 +2228,38 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (OP2_TYPE != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (OP2_TYPE == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
FREE_OP2();
FREE_OP1_IF_VAR();
@@ -2478,7 +2273,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -2487,7 +2283,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2496,24 +2292,17 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (OP1_TYPE == IS_CONST &&
OP2_TYPE == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (OP1_TYPE != IS_CONST &&
OP2_TYPE == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (OP2_TYPE != IS_UNUSED) {
zend_free_op free_op2;
@@ -2529,20 +2318,20 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (OP2_TYPE == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (OP1_TYPE == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (OP2_TYPE != IS_CONST) {
@@ -2555,33 +2344,37 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (OP1_TYPE != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -2590,32 +2383,32 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
{
USE_OPLINE
- zval *function_name_ptr, *function_name, *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
+ zval *function_name, *func;
if (OP2_TYPE == IS_CONST) {
- function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+ function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
} else {
zend_string *lcname;
zend_free_op free_op2;
+ zend_class_entry *called_scope;
+ zend_object *object;
+ zval *function_name_ptr;
SAVE_OPLINE();
function_name_ptr = function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -2634,37 +2427,23 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
}
STR_FREE(lcname);
FREE_OP2();
-
- call->fbc = Z_FUNC_P(func);
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
+ fbc = Z_FUNC_P(func);
+ called_scope = NULL;
+ object = NULL;
} else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
- Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+ if (object) {
+ GC_REFCOUNT(object)++;
}
if (OP2_TYPE == IS_VAR && OP2_FREE && Z_REFCOUNT_P(function_name) == 1 &&
- call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+ fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- call->fbc->common.prototype = (zend_function*)function_name_ptr;
+ fbc->common.prototype = (zend_function*)function_name_ptr;
} else {
FREE_OP2();
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else if (OP2_TYPE != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -2687,51 +2466,49 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
}
if (Z_TYPE_P(obj) == IS_STRING) {
- call->object = NULL;
- call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
- if (UNEXPECTED(call->called_scope == NULL)) {
+ object = NULL;
+ called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (call->called_scope->get_static_method) {
- call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+ if (called_scope->get_static_method) {
+ fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+ fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
} else {
- call->called_scope = Z_OBJCE_P(obj);
- call->object = Z_OBJ_P(obj);
+ called_scope = Z_OBJCE_P(obj);
+ object = Z_OBJ_P(obj);
- call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+ fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ object = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(object)++; /* For $this pointer */
}
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
FREE_OP2();
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ ZEND_VM_CONTINUE(); /* Never reached */
}
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
}
@@ -2741,68 +2518,263 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
USE_OPLINE
zval *func_name;
zval *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
func_name = opline->op2.zv + 1;
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
func_name++;
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(61, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
-{
- EX(function_state).function = EX(call)->fbc;
- ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper);
-}
-
-ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
+ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
{
USE_OPLINE
- zend_free_op free_op1;
- zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zend_free_op free_op2;
+ zval *fname = GET_OP2_ZVAL_PTR(BP_VAR_R);
zval *func;
- call_slot *call = EX(call_slots) + opline->op2.num;
+ zend_function *fbc;
if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
- EX(function_state).function = CACHED_PTR(Z_CACHE_SLOT_P(fname));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
} else {
- EX(function_state).function = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(fname), EX(function_state).function);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
}
- call->fbc = EX(function_state).function;
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
- FREE_OP1();
+ FREE_OP2();
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
+{
+ USE_OPLINE
+ zend_execute_data *call = EX(call);
+ zend_function *fbc = call->func;
+
+ SAVE_OPLINE();
+ call->flags = ZEND_CALL_DONE;
+ if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+ zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
+ fbc->common.scope ? fbc->common.scope->name->val : "",
+ fbc->common.scope ? "::" : "",
+ fbc->common.function_name->val);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ }
+ if (fbc->common.scope &&
+ !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
+ !call->object) {
+
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ /* FIXME: output identifiers properly */
+ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ /* FIXME: output identifiers properly */
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
+ }
+
+ LOAD_OPLINE();
+
+ if (UNEXPECTED(fbc->type == ZEND_INTERNAL_FUNCTION)) {
+ int should_change_scope = 0;
+ zval *ret;
+
+ if (fbc->common.scope) {
+ should_change_scope = 1;
+ Z_OBJ(EG(This)) = call->object;
+ /* TODO: we don't set scope if we call an object method ??? */
+ /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
+#if 1
+ EG(scope) = (call->object) ? NULL : fbc->common.scope;
+#else
+ EG(scope) = fbc->common.scope;
+#endif
+ EG(called_scope) = call->called_scope;
+ }
+
+ if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ zend_uint i;
+ zval *p = ZEND_CALL_ARG(call, 1);
+
+ for (i = 0; i < call->num_args; ++i) {
+ zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
+ p++;
+ }
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ if (RETURN_VALUE_USED(opline)) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
+ }
+ if (UNEXPECTED(should_change_scope)) {
+ ZEND_VM_C_GOTO(fcall_end_change_scope);
+ } else {
+ ZEND_VM_C_GOTO(fcall_end);
+ }
+ }
+ }
+
+ ret = EX_VAR(opline->result.var);
+ ZVAL_NULL(ret);
+ Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+
+ if (!zend_execute_internal) {
+ /* saves one function call if zend_execute_internal is not used */
+ fbc->internal_function.handler(call->num_args, ret TSRMLS_CC);
+ } else {
+ zend_execute_internal(execute_data, NULL TSRMLS_CC);
+ }
+
+ zend_vm_stack_free_args(call TSRMLS_CC);
+
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
+ if (!RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(ret);
+ }
- ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper);
+ if (UNEXPECTED(should_change_scope)) {
+ ZEND_VM_C_GOTO(fcall_end_change_scope);
+ } else {
+ ZEND_VM_C_GOTO(fcall_end);
+ }
+ } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
+ zval *return_value = NULL;
+
+ Z_OBJ(EG(This)) = call->object;
+ EG(scope) = fbc->common.scope;
+ EG(called_scope) = call->called_scope;
+ EG(active_symbol_table) = NULL;
+ EG(active_op_array) = &fbc->op_array;
+ if (RETURN_VALUE_USED(opline)) {
+ return_value = EX_VAR(opline->result.var);
+
+ ZVAL_NULL(return_value);
+ Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+ }
+
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ if (RETURN_VALUE_USED(opline)) {
+ zend_generator_create_zval(&fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC);
+ }
+
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+ } else {
+ call->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
+
+ if (EXPECTED(zend_execute_ex == execute_ex)) {
+ ZEND_VM_ENTER();
+ } else {
+ execute_ex(call TSRMLS_CC);
+ }
+ }
+
+ EG(opline_ptr) = &EX(opline);
+ EG(active_op_array) = &EX(func)->op_array;
+ if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
+ zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
+ }
+ EG(active_symbol_table) = EX(symbol_table);
+ } else { /* ZEND_OVERLOADED_FUNCTION */
+ Z_OBJ(EG(This)) = call->object;
+//??? EG(scope) = NULL;
+ EG(scope) = fbc->common.scope;
+ EG(called_scope) = call->called_scope;
+
+ ZVAL_NULL(EX_VAR(opline->result.var));
+
+ /* Not sure what should be done here if it's a static method */
+ if (EXPECTED(call->object != NULL)) {
+ call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC);
+ } else {
+ zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
+ }
+
+ zend_vm_stack_free_args(call TSRMLS_CC);
+
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
+ if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
+ STR_RELEASE(fbc->common.function_name);
+ }
+ efree(fbc);
+
+ if (!RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(EX_VAR(opline->result.var));
+ } else {
+//??? Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
+//??? Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
+ Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0;
+ }
+ }
+
+ZEND_VM_C_LABEL(fcall_end_change_scope):
+ if (Z_OBJ(EG(This))) {
+ if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
+ if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
+ Z_DELREF(EG(This));
+ }
+ if (Z_REFCOUNT(EG(This)) == 1) {
+ zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
+ }
+ }
+ if (!Z_DELREF(EG(This))) {
+ _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
+ } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
+ gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
+ }
+ }
+ Z_OBJ(EG(This)) = EX(object);
+ EG(scope) = EX(scope);
+ EG(called_scope) = EX(called_scope);
+
+ZEND_VM_C_LABEL(fcall_end):
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zend_throw_exception_internal(NULL TSRMLS_CC);
+ if (RETURN_VALUE_USED(opline)) {
+ zval_ptr_dtor(EX_VAR(opline->result.var));
+ }
+ HANDLE_EXCEPTION();
+ }
+
+ ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
@@ -2945,7 +2917,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
/* Check whether an exception has been thrown, if not, jump over code */
zend_exception_restore(TSRMLS_C);
if (EG(exception) == NULL) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
@@ -2969,7 +2941,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
}
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
@@ -2991,22 +2963,23 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
{
USE_OPLINE
- zval *value, *top;
+ zval *value, *arg;
zend_free_op free_op1;
SAVE_OPLINE();
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
- if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
}
}
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
- top = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_COPY_VALUE(top, value);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, value);
if (OP1_TYPE == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
- zval_copy_ctor_func(top);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
+ zval_copy_ctor_func(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -3015,18 +2988,19 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
zend_free_op free_op1;
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY(top, Z_REFVAL_P(varptr));
+ ZVAL_COPY(arg, Z_REFVAL_P(varptr));
FREE_OP1();
} else {
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
if (OP1_TYPE == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+ if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -3036,7 +3010,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
@@ -3044,7 +3018,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
} else {
- if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
}
@@ -3061,15 +3035,18 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
if (OP1_TYPE == IS_CV) {
Z_ADDREF_P(varptr);
}
- zend_vm_stack_push(varptr TSRMLS_CC);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
- !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_COPY(top, varptr);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY(arg, varptr);
FREE_OP1_IF_VAR();
}
CHECK_EXCEPTION();
@@ -3080,7 +3057,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
@@ -3089,23 +3066,24 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
- ZVAL_NEW_REF(top, &EG(uninitialized_zval));
+ ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
ZEND_VM_NEXT_OPCODE();
}
if (Z_ISREF_P(varptr)) {
Z_ADDREF_P(varptr);
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
} else if (OP1_TYPE == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
- ZVAL_COPY_VALUE(top, varptr);
- ZVAL_MAKE_REF(top);
+ ZVAL_COPY_VALUE(arg, varptr);
+ ZVAL_MAKE_REF(arg);
} else {
ZVAL_MAKE_REF(varptr);
Z_ADDREF_P(varptr);
- ZVAL_REF(top, Z_REF_P(varptr));
+ ZVAL_REF(arg, Z_REF_P(varptr));
}
FREE_OP1_VAR_PTR();
@@ -3115,24 +3093,25 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
zend_free_op free_op1;
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
}
}
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY(top, Z_REFVAL_P(varptr));
+ ZVAL_COPY(arg, Z_REFVAL_P(varptr));
FREE_OP1();
} else {
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
if (OP1_TYPE == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+ if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -3147,7 +3126,7 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
SAVE_OPLINE();
args = GET_OP1_ZVAL_PTR(BP_VAR_R);
- arg_num = opline->op2.num + EX(call)->num_additional_args + 1;
+ arg_num = EX(call)->num_args + 1;
ZEND_VM_C_LABEL(send_again):
switch (Z_TYPE_P(args)) {
@@ -3156,7 +3135,7 @@ ZEND_VM_C_LABEL(send_again):
zval *arg, *top;
zend_string *name;
- ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht));
+ zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht) TSRMLS_DC);
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
int i;
@@ -3164,7 +3143,7 @@ ZEND_VM_C_LABEL(send_again):
/* check if any of arguments are going to be passed by reference */
for (i = 0; i < zend_hash_num_elements(ht); i++) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num + i)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
separate = 1;
break;
}
@@ -3183,8 +3162,8 @@ ZEND_VM_C_LABEL(send_again):
ZEND_VM_NEXT_OPCODE();
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+ top = ZEND_CALL_ARG(EX(call), arg_num);
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (!Z_IMMUTABLE_P(args)) {
ZVAL_MAKE_REF(arg);
Z_ADDREF_P(arg);
@@ -3193,12 +3172,13 @@ ZEND_VM_C_LABEL(send_again):
ZVAL_DUP(top, arg);
}
} else if (Z_ISREF_P(arg)) {
+//TODO: change into ZVAL_COPY()???
ZVAL_DUP(top, Z_REFVAL_P(arg));
} else {
ZVAL_COPY(top, arg);
}
- EX(call)->num_additional_args++;
+ EX(call)->num_args++;
arg_num++;
} ZEND_HASH_FOREACH_END();
@@ -3232,7 +3212,7 @@ ZEND_VM_C_LABEL(send_again):
}
for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
- zval *arg;
+ zval *arg, *top;
if (UNEXPECTED(EG(exception) != NULL)) {
ZEND_VM_C_GOTO(unpack_iter_dtor);
@@ -3260,13 +3240,13 @@ ZEND_VM_C_LABEL(send_again):
zval_dtor(&key);
}
- if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+ if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
zend_error(
E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
" by unpacking a Traversable, passing by-value instead", arg_num,
- EX(call)->fbc->common.scope ? EX(call)->fbc->common.scope->name->val : "",
- EX(call)->fbc->common.scope ? "::" : "",
- EX(call)->fbc->common.function_name->val
+ EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
+ EX(call)->func->common.scope ? "::" : "",
+ EX(call)->func->common.function_name->val
);
}
@@ -3276,9 +3256,10 @@ ZEND_VM_C_LABEL(send_again):
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
- ZEND_VM_STACK_GROW_IF_NEEDED(1);
- zend_vm_stack_push(arg TSRMLS_CC);
- EX(call)->num_additional_args++;
+ zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1 TSRMLS_DC);
+ top = ZEND_CALL_ARG(EX(call), arg_num);
+ ZVAL_COPY_VALUE(top, arg);
+ EX(call)->num_args++;
iter->funcs->move_forward(iter TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3307,25 +3288,18 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *arguments = EX(prev_execute_data)->function_state.arguments;
- zend_uint arg_count = Z_LVAL_P(arguments);
SAVE_OPLINE();
- if (UNEXPECTED(arg_num > arg_count)) {
+ if (UNEXPECTED(arg_num > EX(num_args))) {
zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
- } else {
- zval *var_ptr;
- zval *param = arguments - arg_count + arg_num - 1;
+ CHECK_EXCEPTION();
+ } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
- }
- var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
- ZVAL_COPY(var_ptr, param);
+ zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
}
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -3333,30 +3307,24 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *arguments = EX(prev_execute_data)->function_state.arguments;
- zend_uint arg_count = Z_LVAL_P(arguments);
- zval *var_ptr;
+ zval *param;
SAVE_OPLINE();
- var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
- if (arg_num > arg_count) {
- ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
- if (Z_OPT_CONSTANT_P(var_ptr)) {
- zval_update_constant(var_ptr, 0 TSRMLS_CC);
+ param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (arg_num > EX(num_args)) {
+ ZVAL_COPY_VALUE(param, opline->op2.zv);
+ if (Z_OPT_CONSTANT_P(param)) {
+ zval_update_constant(param, 0 TSRMLS_CC);
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
- if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
- zval_copy_ctor_func(var_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
+ zval_copy_ctor_func(param);
}
}
- } else {
- zval *param = arguments - arg_count + arg_num - 1;
- ZVAL_COPY(var_ptr, param);
}
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type((zend_function *) EX(op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
}
CHECK_EXCEPTION();
@@ -3367,21 +3335,21 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *arguments = EX(prev_execute_data)->function_state.arguments;
- zend_uint arg_count = Z_LVAL_P(arguments);
+ zend_uint arg_count = EX(num_args);
zval *params;
SAVE_OPLINE();
params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED(Z_REFCOUNTED_P(params))) Z_DELREF_P(params);
if (arg_num <= arg_count) {
- zval *param = arguments - arg_count + arg_num - 1;
+ zval *param;
+
array_init_size(params, arg_count - arg_num + 1);
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- do {
- zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+ 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)) {
+ do {
+ zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
param++;
@@ -3423,8 +3391,8 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
- EX(op_array), execute_data TSRMLS_CC);
- ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
+ &EX(func)->op_array, execute_data TSRMLS_CC);
+ ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
}
ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
@@ -3434,8 +3402,8 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
- EX(op_array), execute_data TSRMLS_CC);
- ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
+ &EX(func)->op_array, execute_data TSRMLS_CC);
+ ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
}
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
@@ -3446,9 +3414,9 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
- EX(op_array), execute_data TSRMLS_CC);
+ &EX(func)->op_array, execute_data TSRMLS_CC);
- brk_opline = EX(op_array)->opcodes + el->brk;
+ brk_opline = EX(func)->op_array.opcodes + el->brk;
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -3515,21 +3483,19 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
}
ZEND_VM_JMP(opline->op2.jmp_addr);
} else {
- call_slot *call = EX(call_slots) + opline->extended_value;
+ /* We are not handling overloaded classes right now */
+ EX(call) = zend_vm_stack_push_call_frame(
+ constructor, opline->extended_value,
+ RETURN_VALUE_USED(opline) ?
+ ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED),
+ Z_CE_P(EX_VAR(opline->op1.var)),
+ Z_OBJ(object_zval),
+ EX(call) TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
}
- /* We are not handling overloaded classes right now */
- call->fbc = constructor;
- call->object = Z_OBJ(object_zval);
- call->called_scope = Z_CE_P(EX_VAR(opline->op1.var));
- call->num_additional_args = 0;
- call->is_ctor_call = 1;
- call->is_ctor_result_used = RETURN_VALUE_USED(opline);
- EX(call) = call;
-
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -4014,23 +3980,23 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
return_value = EX_VAR(opline->result.var);
}
- EX(function_state).function = (zend_function *) new_op_array;
+ EX(call) = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
+ EX(call)->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
- zend_execute(new_op_array, return_value TSRMLS_CC);
+ execute_ex(EG(current_execute_data) TSRMLS_CC);
}
- EX(function_state).function = (zend_function *) EX(op_array);
-
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -4861,7 +4827,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
{
SAVE_OPLINE();
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(op_array)->function_name->val);
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(func)->op_array.function_name->val);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -4987,7 +4953,7 @@ ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
{
SAVE_OPLINE();
if (!EG(no_extensions)) {
- zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC);
+ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(func) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -4997,7 +4963,7 @@ ZEND_VM_HANDLER(102, ZEND_EXT_FCALL_BEGIN, ANY, ANY)
{
SAVE_OPLINE();
if (!EG(no_extensions)) {
- zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC);
+ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(func) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -5007,7 +4973,7 @@ ZEND_VM_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
{
SAVE_OPLINE();
if (!EG(no_extensions)) {
- zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC);
+ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(func) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -5018,7 +4984,7 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY)
USE_OPLINE
SAVE_OPLINE();
- Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(EX(op_array), opline, EG(class_table), 0 TSRMLS_CC);
+ Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0 TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -5028,7 +4994,7 @@ ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY)
USE_OPLINE
SAVE_OPLINE();
- Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+ Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -5042,7 +5008,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
if ((zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op2.zv))) == NULL ||
((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op1.zv))) != NULL &&
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
- do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+ do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -5053,7 +5019,7 @@ ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
USE_OPLINE
SAVE_OPLINE();
- do_bind_function(EX(op_array), opline, EG(function_table), 0);
+ do_bind_function(&EX(func)->op_array, opline, EG(function_table), 0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -5173,45 +5139,37 @@ ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
{
- zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
+ zend_uint op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
int i;
zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
- zval *stack_frame;
-
- /* Figure out where the next stack frame (which maybe contains pushed
- * arguments that have to be dtor'ed) starts */
- stack_frame = zend_vm_stack_frame_base(execute_data);
- /* If the exception was thrown during a function call there might be
- * arguments pushed to the stack that have to be dtor'ed. */
- while (zend_vm_stack_top(TSRMLS_C) != stack_frame) {
- zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
- zval_ptr_dtor(stack_zval_p);
- }
-
- for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
- if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
+ for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
+ if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
/* further blocks will not be relevant... */
break;
}
- if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
- catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
+ if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) {
+ catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op;
}
- if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
- finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
+ if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
+ finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
}
- if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op &&
- op_num < EG(active_op_array)->try_catch_array[i].finally_end) {
- finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end;
+ if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
+ op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
+ finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
}
}
- if (EX(call) >= EX(call_slots)) {
- call_slot *call = EX(call);
+ if (EX(call)) {
+ zend_execute_data *call = EX(call);
do {
+ /* If the exception was thrown during a function call there might be
+ * arguments pushed to the stack that have to be dtor'ed. */
+ zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+
if (call->object) {
- if (call->is_ctor_call) {
- if (call->is_ctor_result_used) {
+ if (call->flags & ZEND_CALL_CTOR) {
+ if (!(call->flags & ZEND_CALL_CTOR_RESULT_UNUSED)) {
GC_REFCOUNT(call->object)--;
}
if (GC_REFCOUNT(call->object) == 1) {
@@ -5220,21 +5178,22 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
OBJ_RELEASE(call->object);
}
- call--;
- } while (call >= EX(call_slots));
- EX(call) = NULL;
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+ call = EX(call);
+ } while (call);
}
- for (i=0; i<EX(op_array)->last_brk_cont; i++) {
- if (EX(op_array)->brk_cont_array[i].start < 0) {
+ for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
+ if (EX(func)->op_array.brk_cont_array[i].start < 0) {
continue;
- } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
+ } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
/* further blocks will not be relevant... */
break;
- } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+ } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
if (!catch_op_num ||
- catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
- zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
+ catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
+ zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -5270,7 +5229,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
EX(delayed_exception) = EG(exception);
EG(exception) = NULL;
EX(fast_ret) = NULL;
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else if (catch_op_num) {
if (finally_op_end && catch_op_num > finally_op_end) {
@@ -5280,14 +5239,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
EX(delayed_exception) = NULL;
}
}
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
if (EX(delayed_exception)) {
zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
EX(delayed_exception) = NULL;
}
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -5318,7 +5277,7 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
case ZEND_USER_OPCODE_CONTINUE:
ZEND_VM_CONTINUE();
case ZEND_USER_OPCODE_RETURN:
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -5382,7 +5341,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
}
closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC;
- closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->function_state.function->common.fn_flags & ZEND_ACC_STATIC;
+ closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->call->func->common.fn_flags & ZEND_ACC_STATIC;
if (closure_is_static || closure_is_being_defined_inside_static_context) {
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(called_scope), NULL TSRMLS_CC);
} else {
@@ -5432,7 +5391,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
if (OP1_TYPE != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
@@ -5560,7 +5519,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
if (opline->extended_value &&
UNEXPECTED(EG(prev_exception) != NULL)) {
/* in case of unhandled exception jump to catch block instead of finally */
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
}
EX(fast_ret) = opline + 1;
@@ -5579,15 +5538,15 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
EG(exception) = EX(delayed_exception);
EX(delayed_exception) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
- } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
@@ -5646,4 +5605,4 @@ ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
+ZEND_VM_EXPORT_HANDLER(zend_do_fcall, ZEND_DO_FCALL)
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index b69dcbf711..3f373a1a98 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -375,15 +375,27 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC)
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC)
{
+ zend_execute_data *execute_data;
+
if (EG(exception) != NULL) {
return;
- }
- zend_execute_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
+ }
+
+ if (EG(current_execute_data) && EG(current_execute_data)->call) {
+ execute_data = EG(current_execute_data)->call;
+ } else {
+ execute_data = zend_vm_stack_push_call_frame(
+ (zend_function*)op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC);
+ }
+ EX(prev_execute_data) = EG(current_execute_data);
+ i_init_execute_data(execute_data, op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+ zend_execute_ex(execute_data TSRMLS_CC);
}
static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
vm_frame_kind frame_kind = EX(frame_kind);
+ zend_execute_data *prev_nested_call;
EG(current_execute_data) = EX(prev_execute_data);
@@ -392,22 +404,22 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
}
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
- zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
+ zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
}
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
execute_data = EG(current_execute_data);
+ EX(call) = prev_nested_call;
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
EG(active_symbol_table) = EX(symbol_table);
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
-
if (Z_OBJ(EG(This))) {
- if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
- if (EX(call)->is_ctor_result_used) {
+ if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
+ if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
@@ -424,10 +436,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EG(scope) = EX(scope);
EG(called_scope) = EX(called_scope);
- EX(call)--;
-
- zend_vm_stack_clear_multiple(1 TSRMLS_CC);
-
if (UNEXPECTED(EG(exception) != NULL)) {
zend_op *opline = EX(opline);
zend_throw_exception_internal(NULL TSRMLS_CC);
@@ -442,16 +450,16 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_LEAVE();
} else if (frame_kind == VM_FRAME_NESTED_CODE) {
zend_detach_symbol_table(execute_data);
- destroy_op_array(EX(op_array) TSRMLS_CC);
- efree(EX(op_array));
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+ destroy_op_array(&EX(func)->op_array TSRMLS_CC);
+ efree(EX(func));
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
execute_data = EG(current_execute_data);
+ EX(call) = prev_nested_call;
zend_attach_symbol_table(execute_data);
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION_LEAVE();
@@ -463,6 +471,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
} else {
if (frame_kind == VM_FRAME_TOP_FUNCTION) {
i_free_compiled_variables(execute_data TSRMLS_CC);
+ zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
} else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
zend_array *symbol_table = EX(symbol_table);
zend_execute_data *old_execute_data;
@@ -470,7 +479,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_detach_symbol_table(execute_data);
old_execute_data = EX(prev_execute_data);
while (old_execute_data) {
- if (old_execute_data->op_array) {
+ if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) {
if (old_execute_data->symbol_table == symbol_table) {
zend_attach_symbol_table(old_execute_data);
}
@@ -479,24 +488,47 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
old_execute_data = old_execute_data->prev_execute_data;
}
}
- if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
- zval_ptr_dtor((zval*)EX(op_array)->prototype);
+ if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
+ zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
+ }
+ prev_nested_call = EX(prev_nested_call);
+ zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
+
+ if (EG(current_execute_data)) {
+ EG(current_execute_data)->call = prev_nested_call;
}
- zend_vm_stack_free((char*)execute_data TSRMLS_CC);
EG(opline_ptr) = NULL;
ZEND_VM_RETURN();
}
}
-static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
+static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zend_function *fbc = EX(function_state).function;
- zend_object *object;
- zend_uint num_args;
+
+ ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
+ ZEND_VM_CONTINUE();
+}
+
+static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *tmp = EX_VAR(opline->result.var);
+
+ SAVE_OPLINE();
+ ZVAL_EMPTY_STRING(tmp);
+ /*CHECK_EXCEPTION();*/
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_execute_data *call = EX(call);
+ zend_function *fbc = call->func;
SAVE_OPLINE();
- object = EX(call)->object;
+ call->flags = ZEND_CALL_DONE;
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@@ -513,7 +545,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
if (fbc->common.scope &&
!(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
- !object) {
+ !call->object) {
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
@@ -528,39 +560,32 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
}
}
- if (EXPECTED(EX(call)->num_additional_args == 0)) {
- num_args = opline->extended_value;
- EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_LONG(EX(function_state).arguments, num_args);
- } else {
- num_args = opline->extended_value + EX(call)->num_additional_args;
- EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
- }
LOAD_OPLINE();
- if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+ if (UNEXPECTED(fbc->type == ZEND_INTERNAL_FUNCTION)) {
int should_change_scope = 0;
zval *ret;
if (fbc->common.scope) {
should_change_scope = 1;
- Z_OBJ(EG(This)) = object;
+ Z_OBJ(EG(This)) = call->object;
/* TODO: we don't set scope if we call an object method ??? */
/* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
#if 1
- EG(scope) = (object) ? NULL : fbc->common.scope;
+ EG(scope) = (call->object) ? NULL : fbc->common.scope;
#else
EG(scope) = fbc->common.scope;
#endif
- EG(called_scope) = EX(call)->called_scope;
+ EG(called_scope) = call->called_scope;
}
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
zend_uint i;
- zval *p = EX(function_state).arguments - num_args;
+ zval *p = ZEND_CALL_ARG(call, 1);
- for (i = 0; i < num_args; ++i, ++p) {
+ for (i = 0; i < call->num_args; ++i) {
zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
+ p++;
}
if (UNEXPECTED(EG(exception) != NULL)) {
if (RETURN_VALUE_USED(opline)) {
@@ -580,11 +605,16 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
- fbc->internal_function.handler(num_args, ret TSRMLS_CC);
+ fbc->internal_function.handler(call->num_args, ret TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL TSRMLS_CC);
}
+ zend_vm_stack_free_args(call TSRMLS_CC);
+
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
if (!RETURN_VALUE_USED(opline)) {
zval_ptr_dtor(ret);
}
@@ -594,12 +624,12 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
} else {
goto fcall_end;
}
- } else if (fbc->type == ZEND_USER_FUNCTION) {
+ } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
zval *return_value = NULL;
- Z_OBJ(EG(This)) = object;
+ Z_OBJ(EG(This)) = call->object;
EG(scope) = fbc->common.scope;
- EG(called_scope) = EX(call)->called_scope;
+ EG(called_scope) = call->called_scope;
EG(active_symbol_table) = NULL;
EG(active_op_array) = &fbc->op_array;
if (RETURN_VALUE_USED(opline)) {
@@ -609,40 +639,50 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
}
- if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
if (RETURN_VALUE_USED(opline)) {
- zend_generator_create_zval(EG(active_op_array), EX_VAR(opline->result.var) TSRMLS_CC);
+ zend_generator_create_zval(&fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC);
}
- } else if (EXPECTED(zend_execute_ex == execute_ex)) {
- if (EXPECTED(EG(exception) == NULL)) {
- i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
+
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+ } else {
+ call->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(call, &fbc->op_array, return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
+
+ if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
+ } else {
+ execute_ex(call TSRMLS_CC);
}
- } else {
- zend_execute(EG(active_op_array), return_value TSRMLS_CC);
}
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
- Z_OBJ(EG(This)) = object;
+ Z_OBJ(EG(This)) = call->object;
//??? EG(scope) = NULL;
EG(scope) = fbc->common.scope;
- EG(called_scope) = EX(call)->called_scope;
+ EG(called_scope) = call->called_scope;
ZVAL_NULL(EX_VAR(opline->result.var));
/* Not sure what should be done here if it's a static method */
- if (EXPECTED(object != NULL)) {
- object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
+ if (EXPECTED(call->object != NULL)) {
+ call->object->handlers->call_method(fbc->common.function_name, call->object, call->num_args, EX_VAR(opline->result.var) TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
+ zend_vm_stack_free_args(call TSRMLS_CC);
+
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
STR_RELEASE(fbc->common.function_name);
}
@@ -659,8 +699,8 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
fcall_end_change_scope:
if (Z_OBJ(EG(This))) {
- if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
- if (EX(call)->is_ctor_result_used) {
+ if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
+ if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
Z_DELREF(EG(This));
}
if (Z_REFCOUNT(EG(This)) == 1) {
@@ -668,8 +708,6 @@ fcall_end_change_scope:
}
}
if (!Z_DELREF(EG(This))) {
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
_zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
} else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
@@ -680,12 +718,6 @@ fcall_end_change_scope:
EG(called_scope) = EX(called_scope);
fcall_end:
- EX(function_state).function = (zend_function *) EX(op_array);
- EX(function_state).arguments = NULL;
- EX(call)--;
-
- zend_vm_stack_clear_multiple(1 TSRMLS_CC);
-
if (UNEXPECTED(EG(exception) != NULL)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
@@ -697,31 +729,6 @@ fcall_end:
ZEND_VM_NEXT_OPCODE();
}
-static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
- ZEND_VM_CONTINUE();
-}
-
-static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zval *tmp = EX_VAR(opline->result.var);
-
- SAVE_OPLINE();
- ZVAL_EMPTY_STRING(tmp);
- /*CHECK_EXCEPTION();*/
- ZEND_VM_NEXT_OPCODE();
-}
-
-static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- EX(function_state).function = EX(call)->fbc;
- return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
/* The generator object is stored in EX(return_value) */
@@ -743,7 +750,7 @@ static int ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
SAVE_OPLINE();
args = get_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R);
- arg_num = opline->op2.num + EX(call)->num_additional_args + 1;
+ arg_num = EX(call)->num_args + 1;
send_again:
switch (Z_TYPE_P(args)) {
@@ -752,7 +759,7 @@ send_again:
zval *arg, *top;
zend_string *name;
- ZEND_VM_STACK_GROW_IF_NEEDED(zend_hash_num_elements(ht));
+ zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht) TSRMLS_DC);
if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
int i;
@@ -760,7 +767,7 @@ send_again:
/* check if any of arguments are going to be passed by reference */
for (i = 0; i < zend_hash_num_elements(ht); i++) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num + i)) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
separate = 1;
break;
}
@@ -779,8 +786,8 @@ send_again:
ZEND_VM_NEXT_OPCODE();
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+ top = ZEND_CALL_ARG(EX(call), arg_num);
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (!Z_IMMUTABLE_P(args)) {
ZVAL_MAKE_REF(arg);
Z_ADDREF_P(arg);
@@ -789,12 +796,13 @@ send_again:
ZVAL_DUP(top, arg);
}
} else if (Z_ISREF_P(arg)) {
+//TODO: change into ZVAL_COPY()???
ZVAL_DUP(top, Z_REFVAL_P(arg));
} else {
ZVAL_COPY(top, arg);
}
- EX(call)->num_additional_args++;
+ EX(call)->num_args++;
arg_num++;
} ZEND_HASH_FOREACH_END();
@@ -828,7 +836,7 @@ send_again:
}
for (; iter->funcs->valid(iter TSRMLS_CC) == SUCCESS; ++arg_num) {
- zval *arg;
+ zval *arg, *top;
if (UNEXPECTED(EG(exception) != NULL)) {
goto unpack_iter_dtor;
@@ -856,13 +864,13 @@ send_again:
zval_dtor(&key);
}
- if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
+ if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
zend_error(
E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
" by unpacking a Traversable, passing by-value instead", arg_num,
- EX(call)->fbc->common.scope ? EX(call)->fbc->common.scope->name->val : "",
- EX(call)->fbc->common.scope ? "::" : "",
- EX(call)->fbc->common.function_name->val
+ EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
+ EX(call)->func->common.scope ? "::" : "",
+ EX(call)->func->common.function_name->val
);
}
@@ -872,9 +880,10 @@ send_again:
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
- ZEND_VM_STACK_GROW_IF_NEEDED(1);
- zend_vm_stack_push(arg TSRMLS_CC);
- EX(call)->num_additional_args++;
+ zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1 TSRMLS_DC);
+ top = ZEND_CALL_ARG(EX(call), arg_num);
+ ZVAL_COPY_VALUE(top, arg);
+ EX(call)->num_args++;
iter->funcs->move_forward(iter TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -903,25 +912,18 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *arguments = EX(prev_execute_data)->function_state.arguments;
- zend_uint arg_count = Z_LVAL_P(arguments);
SAVE_OPLINE();
- if (UNEXPECTED(arg_num > arg_count)) {
+ if (UNEXPECTED(arg_num > EX(num_args))) {
zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
- } else {
- zval *var_ptr;
- zval *param = arguments - arg_count + arg_num - 1;
+ CHECK_EXCEPTION();
+ } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
- }
- var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
- ZVAL_COPY(var_ptr, param);
+ zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
+ CHECK_EXCEPTION();
}
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -929,21 +931,21 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *arguments = EX(prev_execute_data)->function_state.arguments;
- zend_uint arg_count = Z_LVAL_P(arguments);
+ zend_uint arg_count = EX(num_args);
zval *params;
SAVE_OPLINE();
params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED(Z_REFCOUNTED_P(params))) Z_DELREF_P(params);
if (arg_num <= arg_count) {
- zval *param = arguments - arg_count + arg_num - 1;
+ zval *param;
+
array_init_size(params, arg_count - arg_num + 1);
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ 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)) {
do {
- zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+ zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
param++;
@@ -990,21 +992,19 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
ZEND_VM_JMP(opline->op2.jmp_addr);
} else {
- call_slot *call = EX(call_slots) + opline->extended_value;
+ /* We are not handling overloaded classes right now */
+ EX(call) = zend_vm_stack_push_call_frame(
+ constructor, opline->extended_value,
+ RETURN_VALUE_USED(opline) ?
+ ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED),
+ Z_CE_P(EX_VAR(opline->op1.var)),
+ Z_OBJ(object_zval),
+ EX(call) TSRMLS_CC);
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
}
- /* We are not handling overloaded classes right now */
- call->fbc = constructor;
- call->object = Z_OBJ(object_zval);
- call->called_scope = Z_CE_P(EX_VAR(opline->op1.var));
- call->num_additional_args = 0;
- call->is_ctor_call = 1;
- call->is_ctor_result_used = RETURN_VALUE_USED(opline);
- EX(call) = call;
-
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -1056,7 +1056,7 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
static int ZEND_FASTCALL ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
SAVE_OPLINE();
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(op_array)->function_name->val);
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name->val, EX(func)->op_array.function_name->val);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -1064,7 +1064,7 @@ static int ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
SAVE_OPLINE();
if (!EG(no_extensions)) {
- zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(op_array) TSRMLS_CC);
+ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(func) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -1074,7 +1074,7 @@ static int ZEND_FASTCALL ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_
{
SAVE_OPLINE();
if (!EG(no_extensions)) {
- zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(op_array) TSRMLS_CC);
+ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(func) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -1084,7 +1084,7 @@ static int ZEND_FASTCALL ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
{
SAVE_OPLINE();
if (!EG(no_extensions)) {
- zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(op_array) TSRMLS_CC);
+ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(func) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -1095,7 +1095,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
USE_OPLINE
SAVE_OPLINE();
- Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(EX(op_array), opline, EG(class_table), 0 TSRMLS_CC);
+ Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0 TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -1105,7 +1105,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER(ZEND_OPCODE_
USE_OPLINE
SAVE_OPLINE();
- Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+ Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -1119,7 +1119,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER(ZEND
if ((zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op2.zv))) == NULL ||
((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(opline->op1.zv))) != NULL &&
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
- do_bind_inherited_class(EX(op_array), opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
+ do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0 TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -1130,7 +1130,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
USE_OPLINE
SAVE_OPLINE();
- do_bind_function(EX(op_array), opline, EG(function_table), 0);
+ do_bind_function(&EX(func)->op_array, opline, EG(function_table), 0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -1202,45 +1202,37 @@ static int ZEND_FASTCALL ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
+ zend_uint op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
int i;
zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
- zval *stack_frame;
- /* Figure out where the next stack frame (which maybe contains pushed
- * arguments that have to be dtor'ed) starts */
- stack_frame = zend_vm_stack_frame_base(execute_data);
-
- /* If the exception was thrown during a function call there might be
- * arguments pushed to the stack that have to be dtor'ed. */
- while (zend_vm_stack_top(TSRMLS_C) != stack_frame) {
- zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C);
- zval_ptr_dtor(stack_zval_p);
- }
-
- for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
- if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
+ for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
+ if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
/* further blocks will not be relevant... */
break;
}
- if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
- catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
+ if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) {
+ catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op;
}
- if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
- finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
+ if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
+ finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
}
- if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op &&
- op_num < EG(active_op_array)->try_catch_array[i].finally_end) {
- finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end;
+ if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
+ op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
+ finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
}
}
- if (EX(call) >= EX(call_slots)) {
- call_slot *call = EX(call);
+ if (EX(call)) {
+ zend_execute_data *call = EX(call);
do {
+ /* If the exception was thrown during a function call there might be
+ * arguments pushed to the stack that have to be dtor'ed. */
+ zend_vm_stack_free_args(EX(call) TSRMLS_CC);
+
if (call->object) {
- if (call->is_ctor_call) {
- if (call->is_ctor_result_used) {
+ if (call->flags & ZEND_CALL_CTOR) {
+ if (!(call->flags & ZEND_CALL_CTOR_RESULT_UNUSED)) {
GC_REFCOUNT(call->object)--;
}
if (GC_REFCOUNT(call->object) == 1) {
@@ -1249,21 +1241,22 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
}
OBJ_RELEASE(call->object);
}
- call--;
- } while (call >= EX(call_slots));
- EX(call) = NULL;
+ EX(call) = call->prev_nested_call;
+ zend_vm_stack_free_call_frame(call TSRMLS_CC);
+ call = EX(call);
+ } while (call);
}
- for (i=0; i<EX(op_array)->last_brk_cont; i++) {
- if (EX(op_array)->brk_cont_array[i].start < 0) {
+ for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
+ if (EX(func)->op_array.brk_cont_array[i].start < 0) {
continue;
- } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
+ } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
/* further blocks will not be relevant... */
break;
- } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+ } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
if (!catch_op_num ||
- catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
- zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
+ catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
+ zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -1299,7 +1292,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
EX(delayed_exception) = EG(exception);
EG(exception) = NULL;
EX(fast_ret) = NULL;
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else if (catch_op_num) {
if (finally_op_end && catch_op_num > finally_op_end) {
@@ -1309,14 +1302,14 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
EX(delayed_exception) = NULL;
}
}
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
if (EX(delayed_exception)) {
zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
EX(delayed_exception) = NULL;
}
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1347,7 +1340,7 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
case ZEND_USER_OPCODE_CONTINUE:
ZEND_VM_CONTINUE();
case ZEND_USER_OPCODE_RETURN:
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1381,7 +1374,7 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (opline->extended_value &&
UNEXPECTED(EG(prev_exception) != NULL)) {
/* in case of unhandled exception jump to catch block instead of finally */
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
}
EX(fast_ret) = opline + 1;
@@ -1400,15 +1393,15 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
EG(exception) = EX(delayed_exception);
EX(delayed_exception) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
- } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {
+ } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1459,32 +1452,32 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *function_name_ptr, *function_name, *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
+ zval *function_name, *func;
if (IS_CONST == IS_CONST) {
- function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+ function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
} else {
zend_string *lcname;
+ zend_class_entry *called_scope;
+ zend_object *object;
+ zval *function_name_ptr;
SAVE_OPLINE();
function_name_ptr = function_name = opline->op2.zv;
@@ -1503,36 +1496,23 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
}
STR_FREE(lcname);
- call->fbc = Z_FUNC_P(func);
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
+ fbc = Z_FUNC_P(func);
+ called_scope = NULL;
+ object = NULL;
} else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
- Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+ if (object) {
+ GC_REFCOUNT(object)++;
}
if (IS_CONST == IS_VAR && 0 && Z_REFCOUNT_P(function_name) == 1 &&
- call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+ fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- call->fbc->common.prototype = (zend_function*)function_name_ptr;
+ fbc->common.prototype = (zend_function*)function_name_ptr;
} else {
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else if (IS_CONST != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -1555,50 +1535,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
}
if (Z_TYPE_P(obj) == IS_STRING) {
- call->object = NULL;
- call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
- if (UNEXPECTED(call->called_scope == NULL)) {
+ object = NULL;
+ called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (call->called_scope->get_static_method) {
- call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+ if (called_scope->get_static_method) {
+ fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+ fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
} else {
- call->called_scope = Z_OBJCE_P(obj);
- call->object = Z_OBJ_P(obj);
+ called_scope = Z_OBJCE_P(obj);
+ object = Z_OBJ_P(obj);
- call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+ fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ object = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(object)++; /* For $this pointer */
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ ZEND_VM_CONTINUE(); /* Never reached */
}
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
}
@@ -1608,30 +1587,51 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC
USE_OPLINE
zval *func_name;
zval *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
func_name = opline->op2.zv + 1;
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
func_name++;
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *fname = opline->op2.zv;
+ zval *func;
+ zend_function *fbc;
+
+ if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
+ } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
+ SAVE_OPLINE();
+ zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
+ } else {
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
+ }
+
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
}
@@ -1640,30 +1640,24 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *arguments = EX(prev_execute_data)->function_state.arguments;
- zend_uint arg_count = Z_LVAL_P(arguments);
- zval *var_ptr;
+ zval *param;
SAVE_OPLINE();
- var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
- if (arg_num > arg_count) {
- ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
- if (Z_OPT_CONSTANT_P(var_ptr)) {
- zval_update_constant(var_ptr, 0 TSRMLS_CC);
+ param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (arg_num > EX(num_args)) {
+ ZVAL_COPY_VALUE(param, opline->op2.zv);
+ if (Z_OPT_CONSTANT_P(param)) {
+ zval_update_constant(param, 0 TSRMLS_CC);
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
- if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
- zval_copy_ctor_func(var_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
+ zval_copy_ctor_func(param);
}
}
- } else {
- zval *param = arguments - arg_count + arg_num - 1;
- ZVAL_COPY(var_ptr, param);
}
- if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type((zend_function *) EX(op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
}
CHECK_EXCEPTION();
@@ -1677,8 +1671,8 @@ static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
- EX(op_array), execute_data TSRMLS_CC);
- ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
+ &EX(func)->op_array, execute_data TSRMLS_CC);
+ ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
}
static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -1688,8 +1682,8 @@ static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
- EX(op_array), execute_data TSRMLS_CC);
- ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
+ &EX(func)->op_array, execute_data TSRMLS_CC);
+ ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
}
static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -1700,9 +1694,9 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
SAVE_OPLINE();
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value,
- EX(op_array), execute_data TSRMLS_CC);
+ &EX(func)->op_array, execute_data TSRMLS_CC);
- brk_opline = EX(op_array)->opcodes + el->brk;
+ brk_opline = EX(func)->op_array.opcodes + el->brk;
if (brk_opline->opcode == ZEND_SWITCH_FREE) {
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
@@ -1786,32 +1780,32 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *function_name_ptr, *function_name, *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
+ zval *function_name, *func;
if (IS_TMP_VAR == IS_CONST) {
- function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+ function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
} else {
zend_string *lcname;
zend_free_op free_op2;
+ zend_class_entry *called_scope;
+ zend_object *object;
+ zval *function_name_ptr;
SAVE_OPLINE();
function_name_ptr = function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -1830,37 +1824,23 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
}
STR_FREE(lcname);
zval_dtor(free_op2.var);
-
- call->fbc = Z_FUNC_P(func);
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
+ fbc = Z_FUNC_P(func);
+ called_scope = NULL;
+ object = NULL;
} else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
- Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+ if (object) {
+ GC_REFCOUNT(object)++;
}
if (IS_TMP_VAR == IS_VAR && 1 && Z_REFCOUNT_P(function_name) == 1 &&
- call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+ fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- call->fbc->common.prototype = (zend_function*)function_name_ptr;
+ fbc->common.prototype = (zend_function*)function_name_ptr;
} else {
zval_dtor(free_op2.var);
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else if (IS_TMP_VAR != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -1883,51 +1863,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
}
if (Z_TYPE_P(obj) == IS_STRING) {
- call->object = NULL;
- call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
- if (UNEXPECTED(call->called_scope == NULL)) {
+ object = NULL;
+ called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (call->called_scope->get_static_method) {
- call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+ if (called_scope->get_static_method) {
+ fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+ fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
} else {
- call->called_scope = Z_OBJCE_P(obj);
- call->object = Z_OBJ_P(obj);
+ called_scope = Z_OBJCE_P(obj);
+ object = Z_OBJ_P(obj);
- call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+ fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ object = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(object)++; /* For $this pointer */
}
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
zval_dtor(free_op2.var);
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ ZEND_VM_CONTINUE(); /* Never reached */
}
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
}
@@ -1975,32 +1953,32 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *function_name_ptr, *function_name, *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
+ zval *function_name, *func;
if (IS_VAR == IS_CONST) {
- function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+ function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
} else {
zend_string *lcname;
zend_free_op free_op2;
+ zend_class_entry *called_scope;
+ zend_object *object;
+ zval *function_name_ptr;
SAVE_OPLINE();
function_name_ptr = function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
@@ -2019,37 +1997,23 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
}
STR_FREE(lcname);
zval_ptr_dtor_nogc(free_op2.var);
-
- call->fbc = Z_FUNC_P(func);
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
+ fbc = Z_FUNC_P(func);
+ called_scope = NULL;
+ object = NULL;
} else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
- Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+ if (object) {
+ GC_REFCOUNT(object)++;
}
if (IS_VAR == IS_VAR && (free_op2.var != NULL) && Z_REFCOUNT_P(function_name) == 1 &&
- call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+ fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- call->fbc->common.prototype = (zend_function*)function_name_ptr;
+ fbc->common.prototype = (zend_function*)function_name_ptr;
} else {
zval_ptr_dtor_nogc(free_op2.var);
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else if (IS_VAR != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -2072,51 +2036,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
}
if (Z_TYPE_P(obj) == IS_STRING) {
- call->object = NULL;
- call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
- if (UNEXPECTED(call->called_scope == NULL)) {
+ object = NULL;
+ called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (call->called_scope->get_static_method) {
- call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+ if (called_scope->get_static_method) {
+ fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+ fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
} else {
- call->called_scope = Z_OBJCE_P(obj);
- call->object = Z_OBJ_P(obj);
+ called_scope = Z_OBJCE_P(obj);
+ object = Z_OBJ_P(obj);
- call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+ fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ object = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(object)++; /* For $this pointer */
}
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
zval_ptr_dtor_nogc(free_op2.var);
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ ZEND_VM_CONTINUE(); /* Never reached */
}
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
}
@@ -2202,32 +2164,32 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *function_name_ptr, *function_name, *func;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_function *fbc;
+ zval *function_name, *func;
if (IS_CV == IS_CONST) {
- function_name_ptr = function_name = (zval*)(opline->op2.zv+1);
+ function_name = (zval*)(opline->op2.zv+1);
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
SAVE_OPLINE();
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
} else {
- call->fbc = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), call->fbc);
+ fbc = Z_FUNC_P(func);
+ CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), fbc);
}
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, NULL, NULL, EX(call) TSRMLS_CC);
/*CHECK_EXCEPTION();*/
ZEND_VM_NEXT_OPCODE();
} else {
zend_string *lcname;
+ zend_class_entry *called_scope;
+ zend_object *object;
+ zval *function_name_ptr;
SAVE_OPLINE();
function_name_ptr = function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
@@ -2246,36 +2208,23 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
}
STR_FREE(lcname);
- call->fbc = Z_FUNC_P(func);
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
+ fbc = Z_FUNC_P(func);
+ called_scope = NULL;
+ object = NULL;
} else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
Z_OBJ_HANDLER_P(function_name, get_closure) &&
- Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) {
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object TSRMLS_CC) == SUCCESS) {
+ if (object) {
+ GC_REFCOUNT(object)++;
}
if (IS_CV == IS_VAR && 0 && Z_REFCOUNT_P(function_name) == 1 &&
- call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
+ fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
- call->fbc->common.prototype = (zend_function*)function_name_ptr;
+ fbc->common.prototype = (zend_function*)function_name_ptr;
} else {
}
-
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else if (IS_CV != IS_CONST &&
EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
@@ -2298,50 +2247,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
}
if (Z_TYPE_P(obj) == IS_STRING) {
- call->object = NULL;
- call->called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
- if (UNEXPECTED(call->called_scope == NULL)) {
+ object = NULL;
+ called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0 TSRMLS_CC);
+ if (UNEXPECTED(called_scope == NULL)) {
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (call->called_scope->get_static_method) {
- call->fbc = call->called_scope->get_static_method(call->called_scope, Z_STR_P(method) TSRMLS_CC);
+ if (called_scope->get_static_method) {
+ fbc = called_scope->get_static_method(called_scope, Z_STR_P(method) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(call->called_scope, Z_STR_P(method), NULL TSRMLS_CC);
+ fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", call->called_scope->name->val, Z_STRVAL_P(method));
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
}
} else {
- call->called_scope = Z_OBJCE_P(obj);
- call->object = Z_OBJ_P(obj);
+ called_scope = Z_OBJCE_P(obj);
+ object = Z_OBJ_P(obj);
- call->fbc = Z_OBJ_HT_P(obj)->get_method(&call->object, Z_STR_P(method), NULL TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(method));
+ fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(object), Z_STRVAL_P(method));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ object = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(object)++; /* For $this pointer */
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE();
} else {
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
zend_error_noreturn(E_ERROR, "Function name must be a string");
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
+ ZEND_VM_CONTINUE(); /* Never reached */
}
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, object, EX(call) TSRMLS_CC);
+
+ CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
}
@@ -2557,34 +2505,6 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ZEND_VM_JMP(opline);
}
-static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
-
- zval *fname = opline->op1.zv;
- zval *func;
- call_slot *call = EX(call_slots) + opline->op2.num;
-
- if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
- EX(function_state).function = CACHED_PTR(Z_CACHE_SLOT_P(fname));
- } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
- SAVE_OPLINE();
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
- } else {
- EX(function_state).function = Z_FUNC_P(func);
- CACHE_PTR(Z_CACHE_SLOT_P(fname), EX(function_state).function);
- }
-
- call->fbc = EX(function_state).function;
- call->object = NULL;
- call->called_scope = NULL;
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
-
- return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-}
-
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -2705,22 +2625,23 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *value, *top;
+ zval *value, *arg;
SAVE_OPLINE();
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
- if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
}
}
value = opline->op1.zv;
- top = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_COPY_VALUE(top, value);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, value);
if (IS_CONST == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
- zval_copy_ctor_func(top);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
+ zval_copy_ctor_func(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -2999,23 +2920,23 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
return_value = EX_VAR(opline->result.var);
}
- EX(function_state).function = (zend_function *) new_op_array;
+ EX(call) = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
+ EX(call)->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
- zend_execute(new_op_array, return_value TSRMLS_CC);
+ execute_ex(EG(current_execute_data) TSRMLS_CC);
}
- EX(function_state).function = (zend_function *) EX(op_array);
-
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3789,7 +3710,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -3798,7 +3720,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3807,24 +3729,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_CONST == IS_CONST &&
IS_CONST == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_CONST != IS_CONST &&
IS_CONST == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_CONST != IS_UNUSED) {
@@ -3840,20 +3755,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_CONST == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_CONST != IS_CONST) {
@@ -3866,33 +3781,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_CONST != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -4336,7 +4255,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
if (IS_CONST != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -4757,7 +4676,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -4766,7 +4686,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -4775,24 +4695,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_CONST == IS_CONST &&
IS_TMP_VAR == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_CONST != IS_CONST &&
IS_TMP_VAR == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op2;
@@ -4808,20 +4721,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_TMP_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_TMP_VAR != IS_CONST) {
@@ -4834,33 +4747,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_CONST != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -5022,7 +4939,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
if (IS_CONST != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -5593,7 +5510,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -5602,7 +5520,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -5611,24 +5529,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_CONST == IS_CONST &&
IS_VAR == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_CONST != IS_CONST &&
IS_VAR == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_VAR != IS_UNUSED) {
zend_free_op free_op2;
@@ -5644,20 +5555,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_VAR != IS_CONST) {
@@ -5670,33 +5581,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_CONST != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -6009,7 +5924,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
if (IS_CONST != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -6288,7 +6203,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -6297,7 +6213,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -6306,24 +6222,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_CONST == IS_CONST &&
IS_UNUSED == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_CONST != IS_CONST &&
IS_UNUSED == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_UNUSED != IS_UNUSED) {
@@ -6339,20 +6248,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_UNUSED == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_UNUSED != IS_CONST) {
@@ -6365,33 +6274,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_CONST != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -6681,7 +6594,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER
}
closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC;
- closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->function_state.function->common.fn_flags & ZEND_ACC_STATIC;
+ closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->call->func->common.fn_flags & ZEND_ACC_STATIC;
if (closure_is_static || closure_is_being_defined_inside_static_context) {
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(called_scope), NULL TSRMLS_CC);
} else {
@@ -6713,7 +6626,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
if (IS_CONST != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -7119,7 +7032,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -7128,7 +7042,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -7137,24 +7051,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_CONST == IS_CONST &&
IS_CV == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_CONST != IS_CONST &&
IS_CV == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_CV != IS_UNUSED) {
@@ -7170,20 +7077,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_CV == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_CV != IS_CONST) {
@@ -7196,33 +7103,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_CONST != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -7238,7 +7149,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
/* Check whether an exception has been thrown, if not, jump over code */
zend_exception_restore(TSRMLS_C);
if (EG(exception) == NULL) {
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
@@ -7262,7 +7173,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
zend_throw_exception_internal(NULL TSRMLS_CC);
HANDLE_EXCEPTION();
}
- ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
}
@@ -7436,7 +7347,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
if (IS_CONST != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -7906,22 +7817,23 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *value, *top;
+ zval *value, *arg;
zend_free_op free_op1;
SAVE_OPLINE();
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
- if (ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
}
}
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- top = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_COPY_VALUE(top, value);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, value);
if (IS_TMP_VAR == IS_CONST) {
- if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
- zval_copy_ctor_func(top);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
+ zval_copy_ctor_func(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -8202,23 +8114,23 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
return_value = EX_VAR(opline->result.var);
}
- EX(function_state).function = (zend_function *) new_op_array;
+ EX(call) = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
+ EX(call)->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
- zend_execute(new_op_array, return_value TSRMLS_CC);
+ execute_ex(EG(current_execute_data) TSRMLS_CC);
}
- EX(function_state).function = (zend_function *) EX(op_array);
-
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -9079,8 +8991,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
USE_OPLINE
zval *function_name;
zend_free_op free_op1;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -9095,48 +9009,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
}
object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CONST != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CONST == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CONST != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
@@ -9449,7 +9362,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -9914,8 +9827,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
USE_OPLINE
zval *function_name;
zend_free_op free_op1, free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -9930,32 +9845,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
}
object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (IS_TMP_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
-
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_TMP_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_dtor(free_op2.var);
HANDLE_EXCEPTION();
@@ -9963,15 +9854,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_dtor(free_op2.var);
@@ -10135,7 +10049,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -10750,8 +10664,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
USE_OPLINE
zval *function_name;
zend_free_op free_op1, free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -10766,32 +10682,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
}
object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (IS_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
-
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2.var);
HANDLE_EXCEPTION();
@@ -10799,15 +10691,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
@@ -11122,7 +11037,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -11687,7 +11602,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -12136,8 +12051,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
USE_OPLINE
zval *function_name;
zend_free_op free_op1;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -12152,48 +12069,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
}
object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CV == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CV != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
@@ -12355,7 +12271,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -13044,18 +12960,19 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
zend_free_op free_op1;
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY(top, Z_REFVAL_P(varptr));
+ ZVAL_COPY(arg, Z_REFVAL_P(varptr));
zval_ptr_dtor_nogc(free_op1.var);
} else {
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
if (IS_VAR == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+ if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -13065,7 +12982,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
{
USE_OPLINE
zend_free_op free_op1;
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
@@ -13073,7 +12990,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
} else {
- if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
@@ -13090,15 +13007,18 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
if (IS_VAR == IS_CV) {
Z_ADDREF_P(varptr);
}
- zend_vm_stack_push(varptr TSRMLS_CC);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
- !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_COPY(top, varptr);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY(arg, varptr);
zval_ptr_dtor_nogc(free_op1.var);
}
CHECK_EXCEPTION();
@@ -13109,7 +13029,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
{
USE_OPLINE
zend_free_op free_op1;
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
@@ -13118,23 +13038,24 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (IS_VAR == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
- ZVAL_NEW_REF(top, &EG(uninitialized_zval));
+ ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
ZEND_VM_NEXT_OPCODE();
}
if (Z_ISREF_P(varptr)) {
Z_ADDREF_P(varptr);
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
} else if (IS_VAR == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
- ZVAL_COPY_VALUE(top, varptr);
- ZVAL_MAKE_REF(top);
+ ZVAL_COPY_VALUE(arg, varptr);
+ ZVAL_MAKE_REF(arg);
} else {
ZVAL_MAKE_REF(varptr);
Z_ADDREF_P(varptr);
- ZVAL_REF(top, Z_REF_P(varptr));
+ ZVAL_REF(arg, Z_REF_P(varptr));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -13144,24 +13065,25 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
zend_free_op free_op1;
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY(top, Z_REFVAL_P(varptr));
+ ZVAL_COPY(arg, Z_REFVAL_P(varptr));
zval_ptr_dtor_nogc(free_op1.var);
} else {
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
if (IS_VAR == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+ if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -13453,23 +13375,23 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
return_value = EX_VAR(opline->result.var);
}
- EX(function_state).function = (zend_function *) new_op_array;
+ EX(call) = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
+ EX(call)->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
- zend_execute(new_op_array, return_value TSRMLS_CC);
+ execute_ex(EG(current_execute_data) TSRMLS_CC);
}
- EX(function_state).function = (zend_function *) EX(op_array);
-
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -15334,8 +15256,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
USE_OPLINE
zval *function_name;
zend_free_op free_op1;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -15350,48 +15274,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
}
object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CONST != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CONST == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CONST != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_ptr_dtor_nogc(free_op1.var);
@@ -15404,7 +15327,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -15413,7 +15337,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -15422,24 +15346,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_VAR == IS_CONST &&
IS_CONST == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_VAR != IS_CONST &&
IS_CONST == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_CONST != IS_UNUSED) {
@@ -15455,20 +15372,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_CONST == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_CONST != IS_CONST) {
@@ -15481,33 +15398,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_VAR != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -16187,7 +16108,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -17562,8 +17483,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
USE_OPLINE
zval *function_name;
zend_free_op free_op1, free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -17578,32 +17501,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
}
object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
-
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (IS_TMP_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_TMP_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_dtor(free_op2.var);
HANDLE_EXCEPTION();
@@ -17611,15 +17510,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_dtor(free_op2.var);
zval_ptr_dtor_nogc(free_op1.var);
@@ -17633,7 +17555,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -17642,7 +17565,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -17651,24 +17574,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_VAR == IS_CONST &&
IS_TMP_VAR == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_VAR != IS_CONST &&
IS_TMP_VAR == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op2;
@@ -17684,20 +17600,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_TMP_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_TMP_VAR != IS_CONST) {
@@ -17710,33 +17626,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_VAR != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -18169,7 +18089,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -19758,8 +19678,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
USE_OPLINE
zval *function_name;
zend_free_op free_op1, free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -19774,32 +19696,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
}
object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
-
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (IS_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2.var);
HANDLE_EXCEPTION();
@@ -19807,15 +19705,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
zval_ptr_dtor_nogc(free_op1.var);
@@ -19829,7 +19750,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -19838,7 +19760,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -19847,24 +19769,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_VAR == IS_CONST &&
IS_VAR == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_VAR != IS_CONST &&
IS_VAR == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_VAR != IS_UNUSED) {
zend_free_op free_op2;
@@ -19880,20 +19795,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_VAR != IS_CONST) {
@@ -19906,33 +19821,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_VAR != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -20516,7 +20435,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -21295,7 +21214,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -21304,7 +21224,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -21313,24 +21233,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_VAR == IS_CONST &&
IS_UNUSED == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_VAR != IS_CONST &&
IS_UNUSED == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_UNUSED != IS_UNUSED) {
@@ -21346,20 +21259,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_UNUSED == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_UNUSED != IS_CONST) {
@@ -21372,33 +21285,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_VAR != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -21713,7 +21630,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -23129,8 +23046,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
USE_OPLINE
zval *function_name;
zend_free_op free_op1;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -23145,48 +23064,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
}
object = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CV == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CV != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_ptr_dtor_nogc(free_op1.var);
@@ -23199,7 +23117,8 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- call_slot *call = EX(call_slots) + opline->result.num;
+ zend_object *object;
+ zend_function *fbc;
SAVE_OPLINE();
@@ -23208,7 +23127,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {
ce = CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv));
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, opline->extended_value TSRMLS_CC);
+ ce = zend_fetch_class_by_name(Z_STR_P(opline->op1.zv), opline->op1.zv + 1, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -23217,24 +23136,17 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
}
CACHE_PTR(Z_CACHE_SLOT_P(opline->op1.zv), ce);
}
- call->called_scope = ce;
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
- call->called_scope = EG(called_scope);
- } else {
- call->called_scope = ce;
- }
}
if (IS_VAR == IS_CONST &&
IS_CV == IS_CONST &&
CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) {
- call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
+ fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv));
} else if (IS_VAR != IS_CONST &&
IS_CV == IS_CONST &&
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce))) {
/* do nothing */
} else if (IS_CV != IS_UNUSED) {
@@ -23250,20 +23162,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
}
if (ce->get_static_method) {
- call->fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name) TSRMLS_CC);
} else {
- call->fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
}
- if (UNEXPECTED(call->fbc == NULL)) {
+ if (UNEXPECTED(fbc == NULL)) {
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
}
if (IS_CV == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
if (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(function_name), call->fbc);
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, call->fbc);
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
}
}
if (IS_CV != IS_CONST) {
@@ -23276,33 +23188,37 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
if (Z_OBJ(EG(This)) && Z_OBJCE(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
}
- call->fbc = ce->constructor;
+ fbc = ce->constructor;
}
- if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) {
- call->object = NULL;
- } else {
- if (Z_OBJ(EG(This)) &&
- Z_OBJ_HT(EG(This))->get_class_entry &&
- !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
- /* We are calling method of the other (incompatible) class,
- but passing $this. This is done for compatibility with php-4. */
- if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
- } else {
- /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
- zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name->val, call->fbc->common.function_name->val);
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EG(This))) {
+ if (Z_OBJ_HT(EG(This))->get_class_entry &&
+ !instanceof_function(Z_OBJCE(EG(This)), ce TSRMLS_CC)) {
+ /* We are calling method of the other (incompatible) class,
+ but passing $this. This is done for compatibility with php-4. */
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ } else {
+ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
+ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", fbc->common.scope->name->val, fbc->common.function_name->val);
+ }
}
+ object = Z_OBJ(EG(This));
+ GC_REFCOUNT(object)++;
}
- call->object = Z_OBJ(EG(This));
- if (call->object) {
- GC_REFCOUNT(call->object)++;
+ }
+
+ if (IS_VAR != IS_CONST) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
+ ce = EG(called_scope);
}
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -23732,7 +23648,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -24706,8 +24622,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
USE_OPLINE
zval *function_name;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -24722,48 +24640,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
}
object = _get_obj_zval_ptr_unused(TSRMLS_C);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (IS_CONST != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ if (IS_CONST != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CONST == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
@@ -25190,7 +25107,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
if (IS_UNUSED != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -26079,8 +25996,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
USE_OPLINE
zval *function_name;
zend_free_op free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -26095,32 +26014,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
}
object = _get_obj_zval_ptr_unused(TSRMLS_C);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
-
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
- if (IS_TMP_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
-
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_TMP_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_dtor(free_op2.var);
HANDLE_EXCEPTION();
@@ -26128,15 +26023,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_dtor(free_op2.var);
@@ -26467,7 +26385,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
if (IS_UNUSED != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -27356,8 +27274,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
USE_OPLINE
zval *function_name;
zend_free_op free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -27372,32 +27292,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
}
object = _get_obj_zval_ptr_unused(TSRMLS_C);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
-
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
- if (IS_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
-
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2.var);
HANDLE_EXCEPTION();
@@ -27405,15 +27301,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
@@ -27744,7 +27663,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
if (IS_UNUSED != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -28260,7 +28179,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
if (IS_UNUSED != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -29143,8 +29062,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
USE_OPLINE
zval *function_name;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -29159,48 +29080,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
}
object = _get_obj_zval_ptr_unused(TSRMLS_C);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CV == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CV != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
@@ -29528,7 +29448,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
if (IS_UNUSED != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -30187,18 +30107,19 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY(top, Z_REFVAL_P(varptr));
+ ZVAL_COPY(arg, Z_REFVAL_P(varptr));
} else {
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
if (IS_CV == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+ if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -30208,7 +30129,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
@@ -30216,7 +30137,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
} else {
- if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
@@ -30233,15 +30154,18 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
if (IS_CV == IS_CV) {
Z_ADDREF_P(varptr);
}
- zend_vm_stack_push(varptr TSRMLS_CC);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
- !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
- ZVAL_COPY(top, varptr);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY(arg, varptr);
}
CHECK_EXCEPTION();
@@ -30252,7 +30176,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
SAVE_OPLINE();
varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
@@ -30261,23 +30185,24 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
}
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (IS_CV == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
- ZVAL_NEW_REF(top, &EG(uninitialized_zval));
+ ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
ZEND_VM_NEXT_OPCODE();
}
if (Z_ISREF_P(varptr)) {
Z_ADDREF_P(varptr);
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
} else if (IS_CV == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
- ZVAL_COPY_VALUE(top, varptr);
- ZVAL_MAKE_REF(top);
+ ZVAL_COPY_VALUE(arg, varptr);
+ ZVAL_MAKE_REF(arg);
} else {
ZVAL_MAKE_REF(varptr);
Z_ADDREF_P(varptr);
- ZVAL_REF(top, Z_REF_P(varptr));
+ ZVAL_REF(arg, Z_REF_P(varptr));
}
ZEND_VM_NEXT_OPCODE();
@@ -30286,24 +30211,25 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *varptr, *top;
+ zval *varptr, *arg;
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.num)) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- top = zend_vm_stack_top_inc(TSRMLS_C);
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY(top, Z_REFVAL_P(varptr));
+ ZVAL_COPY(arg, Z_REFVAL_P(varptr));
} else {
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_COPY_VALUE(arg, varptr);
if (IS_CV == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(varptr)) Z_ADDREF_P(varptr);
+ if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
}
}
ZEND_VM_NEXT_OPCODE();
@@ -30582,23 +30508,23 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
return_value = EX_VAR(opline->result.var);
}
- EX(function_state).function = (zend_function *) new_op_array;
+ EX(call) = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EX(call) TSRMLS_CC);
if (!EG(active_symbol_table)) {
zend_rebuild_symbol_table(TSRMLS_C);
}
+ EX(call)->prev_execute_data = EG(current_execute_data);
+ i_init_execute_data(EX(call), new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
ZEND_VM_ENTER();
} else {
- zend_execute(new_op_array, return_value TSRMLS_CC);
+ execute_ex(EG(current_execute_data) TSRMLS_CC);
}
- EX(function_state).function = (zend_function *) EX(op_array);
-
EG(opline_ptr) = &EX(opline);
- EG(active_op_array) = EX(op_array);
+ EG(active_op_array) = &EX(func)->op_array;
destroy_op_array(new_op_array TSRMLS_CC);
efree(new_op_array);
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -32312,8 +32238,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
USE_OPLINE
zval *function_name;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -32328,48 +32256,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
}
object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CONST != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CONST == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CONST != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
@@ -32951,7 +32878,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
if (IS_CV != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -34354,8 +34281,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
USE_OPLINE
zval *function_name;
zend_free_op free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -34370,32 +34299,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
}
object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (IS_TMP_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
-
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_TMP_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_dtor(free_op2.var);
HANDLE_EXCEPTION();
@@ -34403,15 +34308,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_TMP_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_TMP_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_TMP_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_dtor(free_op2.var);
@@ -34846,7 +34774,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (IS_CV != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -36432,8 +36360,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
USE_OPLINE
zval *function_name;
zend_free_op free_op2;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -36448,32 +36378,8 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
}
object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
-
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
-
- if (IS_VAR != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
-
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_VAR == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
- }
- } else {
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2.var);
HANDLE_EXCEPTION();
@@ -36481,15 +36387,38 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
+
+ if (IS_VAR != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_VAR == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_VAR == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
+ }
+ }
+
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
zval_ptr_dtor_nogc(free_op2.var);
@@ -37075,7 +37004,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (IS_CV != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -38138,7 +38067,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
if (IS_CV != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -39551,8 +39480,10 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
USE_OPLINE
zval *function_name;
- call_slot *call = EX(call_slots) + opline->result.num;
zval *object;
+ zend_function *fbc;
+ zend_class_entry *called_scope;
+ zend_object *obj;
SAVE_OPLINE();
@@ -39567,48 +39498,47 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
}
object = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- call->object = Z_TYPE_P(object) == IS_OBJECT ? Z_OBJ_P(object) : NULL;
- if (EXPECTED(call->object != NULL)) {
- call->called_scope = zend_get_class_entry(call->object TSRMLS_CC);
+ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
- if (IS_CV != IS_CONST ||
- (call->fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope)) == NULL) {
- zend_object *object = call->object;
+ HANDLE_EXCEPTION();
+ }
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
+ }
- if (UNEXPECTED(object->handlers->get_method == NULL)) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
- }
+ obj = Z_OBJ_P(object);
+ called_scope = zend_get_class_entry(obj TSRMLS_CC);
- /* First, locate the function. */
- call->fbc = object->handlers->get_method(&call->object, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
- if (UNEXPECTED(call->fbc == NULL)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_P(function_name));
- }
- if (IS_CV == IS_CONST &&
- EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) &&
- EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
- EXPECTED(call->object == object)) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), call->called_scope, call->fbc);
- }
+ if (IS_CV != IS_CONST ||
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL) {
+ zend_object *orig_obj = obj;
+
+ if (UNEXPECTED(obj->handlers->get_method == NULL)) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
}
- } else {
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ /* First, locate the function. */
+ fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (opline->op2.zv + 1) : NULL) TSRMLS_CC);
+ if (UNEXPECTED(fbc == NULL)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(obj), Z_STRVAL_P(function_name));
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
+ EXPECTED(obj == orig_obj)) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
}
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
}
- if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
- call->object = NULL;
+ if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
+ obj = NULL;
} else {
- GC_REFCOUNT(call->object)++; /* For $this pointer */
+ GC_REFCOUNT(obj)++; /* For $this pointer */
}
- call->num_additional_args = 0;
- call->is_ctor_call = 0;
- EX(call) = call;
+ EX(call) = zend_vm_stack_push_call_frame(
+ fbc, opline->extended_value, 0, called_scope, obj, EX(call) TSRMLS_CC);
CHECK_EXCEPTION();
@@ -40039,7 +39969,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (IS_CV != IS_UNUSED) {
- if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -41678,56 +41608,56 @@ void zend_init_opcodes_handlers(void)
ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
- ZEND_DO_FCALL_SPEC_CONST_HANDLER,
- ZEND_DO_FCALL_SPEC_CONST_HANDLER,
- ZEND_DO_FCALL_SPEC_CONST_HANDLER,
- ZEND_DO_FCALL_SPEC_CONST_HANDLER,
- ZEND_DO_FCALL_SPEC_CONST_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_DO_FCALL_SPEC_HANDLER,
+ ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
- ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER,
ZEND_RETURN_SPEC_CONST_HANDLER,
ZEND_RETURN_SPEC_CONST_HANDLER,
ZEND_RETURN_SPEC_CONST_HANDLER,
@@ -44438,6 +44368,6 @@ ZEND_API void zend_vm_set_opcode_handler(zend_op* op)
ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl
index fa976cb678..41a834de95 100644
--- a/Zend/zend_vm_execute.skl
+++ b/Zend/zend_vm_execute.skl
@@ -33,10 +33,21 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC)
ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value TSRMLS_DC)
{
+ zend_execute_data *execute_data;
+
if (EG(exception) != NULL) {
return;
- }
- zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
+ }
+
+ if (EG(current_execute_data) && EG(current_execute_data)->call) {
+ execute_data = EG(current_execute_data)->call;
+ } else {
+ execute_data = zend_vm_stack_push_call_frame(
+ (zend_function*)op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), NULL TSRMLS_CC);
+ }
+ EX(prev_execute_data) = EG(current_execute_data);
+ i_init_execute_data(execute_data, op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC);
+ zend_{%EXECUTOR_NAME%}_ex(execute_data TSRMLS_CC);
}
{%EXTERNAL_EXECUTOR%}
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index df127039c6..8859228aad 100644
--- a/Zend/zend_vm_opcodes.c
+++ b/Zend/zend_vm_opcodes.c
@@ -83,7 +83,7 @@ const char *zend_vm_opcodes_map[169] = {
"ZEND_END_SILENCE",
"ZEND_INIT_FCALL_BY_NAME",
"ZEND_DO_FCALL",
- "ZEND_DO_FCALL_BY_NAME",
+ "ZEND_INIT_FCALL",
"ZEND_RETURN",
"ZEND_RECV",
"ZEND_RECV_INIT",
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index df499f946b..7d74a807b5 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -84,7 +84,7 @@ ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
#define ZEND_END_SILENCE 58
#define ZEND_INIT_FCALL_BY_NAME 59
#define ZEND_DO_FCALL 60
-#define ZEND_DO_FCALL_BY_NAME 61
+#define ZEND_INIT_FCALL 61
#define ZEND_RETURN 62
#define ZEND_RECV 63
#define ZEND_RECV_INIT 64
diff --git a/build/libtool.m4 b/build/libtool.m4
index 56658ccbb4..4d948b9078 100644
--- a/build/libtool.m4
+++ b/build/libtool.m4
@@ -1532,10 +1532,6 @@ dgux*)
shlibpath_var=LD_LIBRARY_PATH
;;
-freebsd1*)
- dynamic_linker=no
- ;;
-
freebsd* | dragonfly*)
# DragonFly does not have aout. When/if they implement a new
# versioning mechanism, adjust this.
@@ -5843,10 +5839,6 @@ _LT_EOF
_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
;;
- freebsd1*)
- _LT_AC_TAGVAR(ld_shlibs, $1)=no
- ;;
-
# FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
# support. Future versions do this automatically, but an explicit c++rt0.o
# does not break anything, and helps significantly (at the cost of a little
diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
index 36a3a8d20d..c13a432605 100644
--- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
+++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
@@ -217,10 +217,10 @@ U_CFUNC PHP_FUNCTION(rbbi_get_binary_rules)
RETURN_FALSE;
}
- char *ret_rules = static_cast<char*>(emalloc(rules_len + 1));
- memcpy(ret_rules, rules, rules_len);
- ret_rules[rules_len] = '\0';
+ zend_string *ret_rules = STR_ALLOC(rules_len, 0);
+ memcpy(ret_rules->val, rules, rules_len);
+ ret_rules->val[rules_len] = '\0';
- RETURN_STRINGL(ret_rules, rules_len, 0);
+ RETURN_STR(ret_rules);
}
#endif
diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.c
index f59fea494b..5b463ea58a 100644
--- a/ext/intl/idn/idn.c
+++ b/ext/intl/idn/idn.c
@@ -140,38 +140,39 @@ static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS,
UIDNA *uts46;
int32_t len;
int32_t buffer_capac = 255; /* no domain name may exceed this */
- char *buffer = emalloc(buffer_capac);
+ zend_string *buffer = STR_ALLOC(buffer_capac, 0);
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
int buffer_used = 0;
uts46 = uidna_openUTS46(option, &status);
if (php_intl_idn_check_status(status, "failed to open UIDNA instance",
mode TSRMLS_CC) == FAILURE) {
- efree(buffer);
+ STR_FREE(buffer);
RETURN_FALSE;
}
if (mode == INTL_IDN_TO_ASCII) {
len = uidna_nameToASCII_UTF8(uts46, domain, (int32_t)domain_len,
- buffer, buffer_capac, &info, &status);
+ buffer->val, buffer_capac, &info, &status);
} else {
len = uidna_nameToUnicodeUTF8(uts46, domain, (int32_t)domain_len,
- buffer, buffer_capac, &info, &status);
+ buffer->val, buffer_capac, &info, &status);
}
if (php_intl_idn_check_status(status, "failed to convert name",
mode TSRMLS_CC) == FAILURE) {
uidna_close(uts46);
- efree(buffer);
+ STR_FREE(buffer);
RETURN_FALSE;
}
if (len >= 255) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "ICU returned an unexpected length");
}
- buffer[len] = '\0';
+ buffer->val[len] = '\0';
+ buffer->len = len;
if (info.errors == 0) {
- RETVAL_STRINGL(buffer, len, 0);
+ RETVAL_STR(buffer);
buffer_used = 1;
} else {
RETVAL_FALSE;
@@ -180,21 +181,20 @@ static void php_intl_idn_to_46(INTERNAL_FUNCTION_PARAMETERS,
if (idna_info) {
if (buffer_used) { /* used in return_value then */
zval_addref_p(return_value);
- add_assoc_zval_ex(idna_info, "result", sizeof("result"), return_value);
+ add_assoc_zval_ex(idna_info, "result", sizeof("result")-1, return_value);
} else {
- zval *zv;
- ALLOC_INIT_ZVAL(zv);
- ZVAL_STRINGL(zv, buffer, len, 0);
+ zval zv;
+ ZVAL_STR(&zv, buffer);
buffer_used = 1;
- add_assoc_zval_ex(idna_info, "result", sizeof("result"), zv);
+ add_assoc_zval_ex(idna_info, "result", sizeof("result")-1, &zv);
}
add_assoc_bool_ex(idna_info, "isTransitionalDifferent",
- sizeof("isTransitionalDifferent"), info.isTransitionalDifferent);
- add_assoc_long_ex(idna_info, "errors", sizeof("errors"), (long)info.errors);
+ sizeof("isTransitionalDifferent")-1, info.isTransitionalDifferent);
+ add_assoc_long_ex(idna_info, "errors", sizeof("errors")-1, (long)info.errors);
}
if (!buffer_used) {
- efree(buffer);
+ STR_FREE(buffer);
}
uidna_close(uts46);
diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c
index f58f24a36e..01cbddd062 100644
--- a/ext/intl/locale/locale_methods.c
+++ b/ext/intl/locale/locale_methods.c
@@ -272,8 +272,7 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int*
grOffset = findOffset( LOC_GRANDFATHERED , loc_name );
if( grOffset >= 0 ){
if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
- tag_value = estrdup(loc_name);
- return tag_value;
+ return estrdup(loc_name);
} else {
/* Since Grandfathered , no value , do nothing , retutn NULL */
return NULL;
@@ -283,8 +282,8 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int*
if( fromParseLocale==1 ){
/* Handle singletons */
if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
- if( strlen(loc_name)>1 && (isIDPrefix(loc_name) ==1 ) ){
- return (char *)loc_name;
+ if( strlen(loc_name)>1 && (isIDPrefix(loc_name) == 1) ){
+ return estrdup(loc_name);
}
}
@@ -504,6 +503,14 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME
RETURN_FALSE;
}
+ if(loc_name_len > ULOC_FULLNAME_CAPACITY) {
+ /* See bug 67397: overlong locale names cause trouble in uloc_getDisplayName */
+ spprintf(&msg , 0, "locale_get_display_%s : name too long", tag_name );
+ intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, msg , 1 TSRMLS_CC );
+ efree(msg);
+ RETURN_FALSE;
+ }
+
if(loc_name_len == 0) {
loc_name = intl_locale_get_default(TSRMLS_C);
}
diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp
index fc7315aefc..1c18c6c969 100644
--- a/ext/intl/msgformat/msgformat_helpers.cpp
+++ b/ext/intl/msgformat/msgformat_helpers.cpp
@@ -183,10 +183,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo,
if (name_part.getType() == UMSGPAT_PART_TYPE_ARG_NAME) {
UnicodeString argName = mp.getSubstring(name_part);
- if ((storedType = zend_hash_str_find_ptr(ret, (char*)argName.getBuffer(), argName.length())) == NULL) {
+ if ((storedType = (Formattable::Type*)zend_hash_str_find_ptr(ret, (char*)argName.getBuffer(), argName.length())) == NULL) {
/* not found already; create new entry in HT */
Formattable::Type bogusType = Formattable::kObject;
- if ((storedType = zend_hash_str_update_mem(ret, (char*)argName.getBuffer(), argName.length(),
+ if ((storedType = (Formattable::Type*)zend_hash_str_update_mem(ret, (char*)argName.getBuffer(), argName.length(),
(void*)&bogusType, sizeof(bogusType))) == NULL) {
intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR,
"Write to argument types hash table failed", 0 TSRMLS_CC);
@@ -200,10 +200,10 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo,
"Found part with negative number", 0 TSRMLS_CC);
continue;
}
- if ((storedType = zend_hash_index_find_ptr(ret, (ulong)argNumber)) == NULL) {
+ if ((storedType = (Formattable::Type*)zend_hash_index_find_ptr(ret, (ulong)argNumber)) == NULL) {
/* not found already; create new entry in HT */
Formattable::Type bogusType = Formattable::kObject;
- if ((storedType = zend_hash_index_update_mem(ret, (ulong)argNumber, (void*)&bogusType, sizeof(bogusType))) == NULL) {
+ if ((storedType = (Formattable::Type*)zend_hash_index_update_mem(ret, (ulong)argNumber, (void*)&bogusType, sizeof(bogusType))) == NULL) {
intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR,
"Write to argument types hash table failed", 0 TSRMLS_CC);
continue;
diff --git a/ext/intl/tests/bug62082.phpt b/ext/intl/tests/bug62082.phpt
index e6ca73e300..dab1252afd 100644
--- a/ext/intl/tests/bug62082.phpt
+++ b/ext/intl/tests/bug62082.phpt
@@ -10,6 +10,7 @@ var_dump(locale_get_display_name(str_repeat("a", 300), null));
var_dump(locale_get_display_name(str_repeat("a", 512), null));
var_dump(locale_get_display_name(str_repeat("a", 600), null));
--EXPECT--
-string(300) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-string(512) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-string(600) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+bool(false)
+bool(false)
+bool(false)
+
diff --git a/ext/intl/tests/bug67397.phpt b/ext/intl/tests/bug67397.phpt
new file mode 100644
index 0000000000..b2b2911f8a
--- /dev/null
+++ b/ext/intl/tests/bug67397.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #67397 (Buffer overflow in locale_get_display_name->uloc_getDisplayName (libicu 4.8.1))
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+--FILE--
+<?php
+
+function ut_main()
+{
+ $ret = var_export(ut_loc_get_display_name(str_repeat('*', 256), 'en_us'), true);
+ $ret .= "\n";
+ $ret .= var_export(intl_get_error_message(), true);
+ return $ret;
+}
+
+include_once( 'ut_common.inc' );
+ut_run();
+?>
+--EXPECTF--
+false
+'locale_get_display_name : name too long: U_ILLEGAL_ARGUMENT_ERROR'
diff --git a/ext/intl/tests/locale_parse_locale2.phpt b/ext/intl/tests/locale_parse_locale2.phpt
index 6012862a48..30cc8cc0ae 100644
--- a/ext/intl/tests/locale_parse_locale2.phpt
+++ b/ext/intl/tests/locale_parse_locale2.phpt
@@ -63,7 +63,8 @@ function ut_main()
//Some Invalid Tags:
'de-419-DE',
'a-DE',
- 'ar-a-aaa-b-bbb-a-ccc'
+ 'ar-a-aaa-b-bbb-a-ccc',
+ 'x-AAAAAA',
);
@@ -201,3 +202,6 @@ No values found from Locale parsing.
---------------------
ar-a-aaa-b-bbb-a-ccc:
language : 'ar' ,
+---------------------
+x-AAAAAA:
+private0 : 'AAAAAA' ,
diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp
index cde090c243..2b1bcfab92 100644
--- a/ext/intl/timezone/timezone_methods.cpp
+++ b/ext/intl/timezone/timezone_methods.cpp
@@ -245,9 +245,9 @@ U_CFUNC PHP_FUNCTION(intltz_create_time_zone_id_enumeration)
/* must come before zpp because zpp would convert the arg in the stack to 0 */
if (ZEND_NUM_ARGS() == 3) {
- zval **dummy, **zvoffset;
+ zval *dummy, *zvoffset;
arg3isnull = zend_get_parameters_ex(3, &dummy, &dummy, &zvoffset)
- != FAILURE && Z_TYPE_PP(zvoffset) == IS_NULL;
+ != FAILURE && Z_TYPE_P(zvoffset) == IS_NULL;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s!l",
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 7baebd36d8..a3b6d08578 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -1958,7 +1958,6 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
case ZEND_ASSIGN:
case ZEND_ASSIGN_REF:
case ZEND_DO_FCALL:
- case ZEND_DO_FCALL_BY_NAME:
if (ZEND_RESULT_TYPE(opline) == IS_VAR) {
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED;
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index 26af07a189..480e4f92fe 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -108,8 +108,8 @@ static void optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_c
end = opline + op_array->last;
while (opline < end) {
switch (opline->opcode) {
- case ZEND_DO_FCALL:
- LITERAL_INFO(opline->op1.constant, LITERAL_FUNC, 1, 1, 1);
+ case ZEND_INIT_FCALL:
+ LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1);
break;
case ZEND_INIT_FCALL_BY_NAME:
if (ZEND_OP2_TYPE(opline) == IS_CONST) {
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c
index cd27704de5..3f755bed18 100644
--- a/ext/opcache/Optimizer/optimize_func_calls.c
+++ b/ext/opcache/Optimizer/optimize_func_calls.c
@@ -12,9 +12,15 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
int call = 0;
- void *checkpoint = zend_arena_checkpoint(ctx->arena);
- optimizer_call_info *call_stack = zend_arena_calloc(&ctx->arena, op_array->nested_calls + 1, sizeof(optimizer_call_info));
+ void *checkpoint;
+ optimizer_call_info *call_stack;
+ if (op_array->last < 2) {
+ return;
+ }
+
+ checkpoint = zend_arena_checkpoint(ctx->arena);
+ call_stack = zend_arena_calloc(&ctx->arena, op_array->last / 2, sizeof(optimizer_call_info));
while (opline < end) {
switch (opline->opcode) {
case ZEND_INIT_FCALL_BY_NAME:
@@ -31,23 +37,27 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
case ZEND_NEW:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_INIT_FCALL:
call_stack[call].opline = opline;
call++;
break;
- case ZEND_DO_FCALL_BY_NAME:
+ case ZEND_DO_FCALL:
call--;
if (call_stack[call].func && call_stack[call].opline) {
zend_op *fcall = call_stack[call].opline;
- opline->opcode = ZEND_DO_FCALL;
- ZEND_OP1_TYPE(opline) = IS_CONST;
- opline->op1.constant = fcall->op2.constant + 1;
- Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
- literal_dtor(&ZEND_OP2_LITERAL(fcall));
- if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
+ if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) {
+ fcall->opcode = ZEND_INIT_FCALL;
+ literal_dtor(&ZEND_OP2_LITERAL(fcall));
+ fcall->op2.constant = fcall->op2.constant + 1;
+ } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
+ fcall->opcode = ZEND_INIT_FCALL;
+ literal_dtor(&op_array->literals[fcall->op2.constant]);
literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
+ fcall->op2.constant = fcall->op2.constant + 1;
+ } else {
+ ZEND_ASSERT(0);
}
- MAKE_NOP(fcall);
} else if (opline->extended_value == 0 &&
call_stack[call].opline &&
call_stack[call].opline->opcode == ZEND_INIT_FCALL_BY_NAME &&
@@ -55,12 +65,9 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
zend_op *fcall = call_stack[call].opline;
- opline->opcode = ZEND_DO_FCALL;
- ZEND_OP1_TYPE(opline) = IS_CONST;
- opline->op1.constant = fcall->op2.constant + 1;
- Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]);
+ fcall->opcode = ZEND_INIT_FCALL;
literal_dtor(&ZEND_OP2_LITERAL(fcall));
- MAKE_NOP(fcall);
+ fcall->op2.constant = fcall->op2.constant + 1;
}
call_stack[call].func = NULL;
call_stack[call].opline = NULL;
@@ -79,21 +86,21 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
}
break;
case ZEND_SEND_VAL:
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+ if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
/* We won't convert it into_DO_FCALL to emit error at run-time */
call_stack[call - 1].opline = NULL;
} else {
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
}
}
break;
case ZEND_SEND_VAR:
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+ if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) && call_stack[call - 1].func) {
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) {
opline->opcode = ZEND_SEND_REF;
}
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
}
break;
case ZEND_SEND_VAR_NO_REF:
@@ -104,12 +111,12 @@ static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx
opline->extended_value |= ZEND_ARG_COMPILE_TIME_BOUND;
} else {
opline->opcode = ZEND_SEND_VAR;
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
}
}
break;
case ZEND_SEND_REF:
- if (opline->extended_value == ZEND_DO_FCALL_BY_NAME && call_stack[call - 1].func) {
+ if (opline->extended_value != ZEND_ARG_COMPILE_TIME_BOUND && call_stack[call - 1].func) {
/* We won't handle run-time pass by reference */
call_stack[call - 1].opline = NULL;
}
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index 73fa0d02f9..de97f64db8 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -320,22 +320,25 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
#endif
break;
- case ZEND_DO_FCALL:
+ case ZEND_INIT_FCALL:
/* define("name", scalar); */
if (collect_constants &&
- opline->extended_value == 2 &&
- ZEND_OP1_TYPE(opline) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
- Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("define")-1 &&
- zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 &&
- (opline-1)->opcode == ZEND_SEND_VAL &&
- ZEND_OP1_TYPE(opline-1) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_STRING &&
- (opline-2)->opcode == ZEND_SEND_VAL &&
- ZEND_OP1_TYPE(opline-2) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
- zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
- break;
+ ZEND_OP2_TYPE(opline) == IS_CONST &&
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
+ Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("define")-1 &&
+ zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), "define", sizeof("define")-1) == 0) {
+
+ if ((opline+1)->opcode == ZEND_SEND_VAL &&
+ ZEND_OP1_TYPE(opline+1) == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline+1)) == IS_STRING &&
+ (opline+2)->opcode == ZEND_SEND_VAL &&
+ ZEND_OP1_TYPE(opline+2) == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline+2)) <= IS_STRING &&
+ (opline+3)->opcode == ZEND_DO_FCALL) {
+
+ zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline+1), &ZEND_OP1_LITERAL(opline+2));
+ break;
+ }
} else {
/* don't colllect constants after any other function call */
collect_constants = 0;
@@ -348,40 +351,42 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
is_callable(x)
extension_loaded(x)
*/
- if (opline->extended_value == 1 && (opline - 1)->opcode == ZEND_SEND_VAL &&
- ZEND_OP1_TYPE(opline - 1) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline - 1)) == IS_STRING &&
- ZEND_OP1_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
- if ((Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("function_exists")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ if ((opline + 1)->opcode == ZEND_SEND_VAL &&
+ (opline + 2)->opcode == ZEND_DO_FCALL &&
+ ZEND_OP1_TYPE(opline + 1) == IS_CONST && Z_TYPE(ZEND_OP1_LITERAL(opline + 1)) == IS_STRING &&
+ ZEND_OP2_TYPE(opline) == IS_CONST && Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
+ if ((Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("function_exists")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
"function_exists", sizeof("function_exists")-1)) ||
- (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("is_callable")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
"is_callable", sizeof("is_callable")))) {
zend_internal_function *func;
char *lc_name = zend_str_tolower_dup(
- Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
+ Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
- if ((func = zend_hash_str_find_ptr(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)))) != NULL &&
+ if ((func = zend_hash_str_find_ptr(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)))) != NULL &&
func->type == ZEND_INTERNAL_FUNCTION &&
func->module->type == MODULE_PERSISTENT) {
zval t;
ZVAL_BOOL(&t, 1);
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
+ literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+ MAKE_NOP(opline + 1);
+ MAKE_NOP(opline + 2);
}
}
efree(lc_name);
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
"extension_loaded", sizeof("extension_loaded")-1)) {
zval t;
char *lc_name = zend_str_tolower_dup(
- Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
+ Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
zend_module_entry *m = zend_hash_str_find_ptr(&module_registry,
- lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
+ lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
efree(lc_name);
if (!m) {
@@ -398,51 +403,55 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
}
}
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
+ literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+ MAKE_NOP(opline + 1);
+ MAKE_NOP(opline + 2);
}
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("defined")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("defined")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
"defined", sizeof("defined")-1)) {
zval t;
- if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) {
+ if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 0 TSRMLS_CC)) {
ZVAL_BOOL(&t, 1);
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
+ literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+ MAKE_NOP(opline + 1);
+ MAKE_NOP(opline + 2);
}
}
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("constant")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("constant")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
"constant", sizeof("constant")-1)) {
zval t;
- if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline - 1)), &t, 1 TSRMLS_CC)) {
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ if (zend_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline + 1)), &t, 1 TSRMLS_CC)) {
+ if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
+ literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+ MAKE_NOP(opline + 1);
+ MAKE_NOP(opline + 2);
}
}
- } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("strlen")-1 &&
- !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ } else if (Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("strlen")-1 &&
+ !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
"strlen", sizeof("strlen")-1)) {
zval t;
- ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
- if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
- literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
- MAKE_NOP((opline - 1));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
+ ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
+ if (replace_var_by_const(op_array, opline + 3, ZEND_RESULT(opline + 2).var, &t TSRMLS_CC)) {
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
+ literal_dtor(&ZEND_OP1_LITERAL(opline + 1));
+ MAKE_NOP(opline + 1);
+ MAKE_NOP(opline + 2);
}
}
}
@@ -485,7 +494,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
case ZEND_FE_RESET:
case ZEND_FE_FETCH:
case ZEND_NEW:
- case ZEND_DO_FCALL_BY_NAME:
+ case ZEND_DO_FCALL:
#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
case ZEND_JMP_SET:
#endif
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index 2ea6544e23..681a54a74e 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -178,12 +178,6 @@ static void update_op1_const(zend_op_array *op_array,
zend_optimizer_add_literal(op_array, val TSRMLS_CC);
STR_HASH_VAL(Z_STR(op_array->literals[opline->op1.constant+1]));
break;
- case ZEND_DO_FCALL:
- zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
- opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
- STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline)));
- Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
- break;
default:
opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
STR_HASH_VAL(Z_STR(ZEND_OP1_LITERAL(opline)));
@@ -204,6 +198,13 @@ static void update_op2_const(zend_op_array *op_array,
{
ZEND_OP2_TYPE(opline) = IS_CONST;
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ if (opline->opcode == ZEND_INIT_FCALL) {
+ zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
+ opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
+ STR_HASH_VAL(Z_STR(ZEND_OP2_LITERAL(opline)));
+ Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
+ return;
+ }
opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
if (Z_TYPE_P(val) == IS_STRING) {
STR_HASH_VAL(Z_STR(ZEND_OP2_LITERAL(opline)));
@@ -340,9 +341,9 @@ static int replace_var_by_const(zend_op_array *op_array,
if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
return 0;
}
- opline->extended_value = ZEND_DO_FCALL;
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
} else {
- opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+ opline->extended_value = 0;
}
opline->opcode = ZEND_SEND_VAL;
break;
diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h
index 0ae3feb2ee..361d1207f8 100644
--- a/ext/opcache/Optimizer/zend_optimizer_internal.h
+++ b/ext/opcache/Optimizer/zend_optimizer_internal.h
@@ -44,7 +44,7 @@
#define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX)
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
-# define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED; opline->handler = zend_opcode_handlers[ZEND_NOP]; }
+# define MAKE_NOP(opline) { (opline)->opcode = ZEND_NOP; memset(&(opline)->result, 0, sizeof((opline)->result)); memset(&(opline)->op1, 0, sizeof((opline)->op1)); memset(&(opline)->op2, 0, sizeof((opline)->op2));(opline)->result_type=(opline)->op1_type=(opline)->op2_type=IS_UNUSED; (opline)->handler = zend_opcode_handlers[ZEND_NOP]; }
# define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR)
# define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0)
# define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var)
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index b5f2c95efe..048362d3ec 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -286,6 +286,10 @@ static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char
EG(active_op_array) = new_op_array;
zend_try {
+ if (EG(current_execute_data)) {
+ EG(current_execute_data)->call = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC);
+ }
zend_execute(new_op_array, &result TSRMLS_CC);
if (PHAR_G(cwd)) {
efree(PHAR_G(cwd));
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 22e2a0c671..5ec20cd563 100644
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -292,6 +292,10 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha
}
ZVAL_UNDEF(&result);
+ if (EG(current_execute_data)) {
+ EG(current_execute_data)->call = zend_vm_stack_push_call_frame(
+ (zend_function*)new_op_array, 0, 0, EG(called_scope), Z_OBJ(EG(This)), EG(current_execute_data)->call TSRMLS_CC);
+ }
zend_execute(new_op_array, &result TSRMLS_CC);
destroy_op_array(new_op_array TSRMLS_CC);
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 3e688aaf88..24556b532c 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -1831,7 +1831,9 @@ SPL_METHOD(Array, unserialize)
}
++p;
- if (!php_var_unserialize(&members, &p, s + buf_len, &var_hash TSRMLS_CC)) {
+ ZVAL_UNDEF(&members);
+ if (!php_var_unserialize(&members, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE(members) != IS_ARRAY) {
+ zval_ptr_dtor(&members);
goto outexcept;
}
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
index a13a7db155..bdfff35506 100644
--- a/ext/spl/spl_observer.c
+++ b/ext/spl/spl_observer.c
@@ -891,7 +891,9 @@ SPL_METHOD(SplObjectStorage, unserialize)
}
++p;
- if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) {
+ ZVAL_UNDEF(&pmembers);
+ if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE(pmembers) != IS_ARRAY) {
+ zval_ptr_dtor(&pmembers);
goto outexcept;
}
diff --git a/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt b/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
index a525317093..8f0676de3b 100644
--- a/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
+++ b/ext/spl/tests/SplObjectStorage_unserialize_bad.phpt
@@ -7,6 +7,7 @@ $badblobs = array(
'x:i:2;i:0;,i:1;;i:0;,i:2;;m:a:0:{}',
'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};R:2;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
'x:i:3;O:8:"stdClass":0:{},O:8:"stdClass":0:{};r:2;,i:1;;O:8:"stdClass":0:{},r:2;;m:a:0:{}',
+'x:i:1;O:8:"stdClass":0:{},N;;m:s:40:"1234567890123456789012345678901234567890"',
);
foreach($badblobs as $blob) {
try {
@@ -17,6 +18,7 @@ try {
echo $e->getMessage()."\n";
}
}
+echo "DONE\n";
--EXPECTF--
Error at offset 6 of 34 bytes
Error at offset 46 of 89 bytes
@@ -42,4 +44,5 @@ object(SplObjectStorage)#2 (1) {
}
}
}
-
+Error at offset 79 of 78 bytes
+DONE
diff --git a/ext/standard/info.c b/ext/standard/info.c
index 19f8ebff44..ef397473c2 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -861,16 +861,16 @@ PHPAPI void php_print_info(int flag TSRMLS_DC)
php_info_print_table_start();
php_info_print_table_header(2, "Variable", "Value");
- if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_SELF", sizeof("PHP_SELF")-1)) != NULL) {
+ if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_SELF", sizeof("PHP_SELF")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
php_info_print_table_row(2, "PHP_SELF", Z_STRVAL_P(data));
}
- if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_AUTH_TYPE", sizeof("PHP_AUTH_TYPE")-1)) != NULL) {
+ if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_AUTH_TYPE", sizeof("PHP_AUTH_TYPE")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
php_info_print_table_row(2, "PHP_AUTH_TYPE", Z_STRVAL_P(data));
}
- if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_AUTH_USER", sizeof("PHP_AUTH_USER")-1)) != NULL) {
+ if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_AUTH_USER", sizeof("PHP_AUTH_USER")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
php_info_print_table_row(2, "PHP_AUTH_USER", Z_STRVAL_P(data));
}
- if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_AUTH_PW", sizeof("PHP_AUTH_PW")-1)) != NULL) {
+ if ((data = zend_hash_str_find(&EG(symbol_table).ht, "PHP_AUTH_PW", sizeof("PHP_AUTH_PW")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
php_info_print_table_row(2, "PHP_AUTH_PW", Z_STRVAL_P(data));
}
php_print_gpcse_array(ZEND_STRL("_REQUEST") TSRMLS_CC);
diff --git a/ext/standard/tests/general_functions/bug67498.phpt b/ext/standard/tests/general_functions/bug67498.phpt
new file mode 100644
index 0000000000..5b5951b0f8
--- /dev/null
+++ b/ext/standard/tests/general_functions/bug67498.phpt
@@ -0,0 +1,15 @@
+--TEST--
+phpinfo() Type Confusion Information Leak Vulnerability
+--FILE--
+<?php
+$PHP_SELF = 1;
+phpinfo(INFO_VARIABLES);
+
+?>
+==DONE==
+--EXPECTF--
+phpinfo()
+
+PHP Variables
+%A
+==DONE==
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index d353b00a06..ec76f37715 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -1102,7 +1102,6 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */
memset(&execute_data, 0, sizeof(zend_execute_data));
EG(current_execute_data) = &execute_data;
- EX(function_state).function = pce->constructor;
zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, &arg);
if (EG(exception)) {
diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
index ae7908642c..34e0480101 100644
--- a/sapi/fpm/fpm/fpm_conf.c
+++ b/sapi/fpm/fpm/fpm_conf.c
@@ -1075,6 +1075,9 @@ static int fpm_conf_process_all_pools() /* {{{ */
}
}
for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
+ if (!strcasecmp(kv->key, "error_log") && !strcasecmp(kv->value, "syslog")) {
+ continue;
+ }
for (p = options; *p; p++) {
if (!strcasecmp(kv->key, *p)) {
fpm_evaluate_full_path(&kv->value, wp, NULL, 0);
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index 78566be956..60f8e465eb 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -1137,19 +1137,6 @@ static void init_request_info(TSRMLS_D)
TRANSLATE_SLASHES(env_document_root);
}
- if (env_path_translated != NULL && env_redirect_url != NULL &&
- env_path_translated != script_path_translated &&
- strcmp(env_path_translated, script_path_translated) != 0) {
- /*
- * pretty much apache specific. If we have a redirect_url
- * then our script_filename and script_name point to the
- * php executable
- */
- script_path_translated = env_path_translated;
- /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */
- env_script_name = env_redirect_url;
- }
-
#ifdef __riscos__
/* Convert path to unix format*/
__riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR;
@@ -1318,7 +1305,7 @@ static void init_request_info(TSRMLS_D)
efree(pt);
}
} else {
- /* make sure path_info/translated are empty */
+ /* make sure original values are remembered in ORIG_ copies if we've changed them */
if (!orig_script_filename ||
(script_path_translated != orig_script_filename &&
strcmp(script_path_translated, orig_script_filename) != 0)) {
@@ -1327,16 +1314,6 @@ static void init_request_info(TSRMLS_D)
}
script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC);
}
- if (env_redirect_url) {
- if (orig_path_info) {
- _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC);
- _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC);
- }
- if (orig_path_translated) {
- _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC);
- _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC);
- }
- }
if (env_script_name != orig_script_name) {
if (orig_script_name) {
_sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC);
diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c
index 925f2de64e..d5b4242fc3 100644
--- a/sapi/fpm/fpm/fpm_php_trace.c
+++ b/sapi/fpm/fpm/fpm_php_trace.c
@@ -42,6 +42,8 @@
static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) /* {{{ */
{
+// TODO: fpm_php_trace_dump() has to be reimplemented ???
+#if 0
int callers_limit = 20;
pid_t pid = child->pid;
struct timeval tv;
@@ -131,6 +133,7 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC
break;
}
}
+#endif
return 0;
}
/* }}} */
diff --git a/sapi/phpdbg/Makefile.frag b/sapi/phpdbg/Makefile.frag
index d787b0fb18..b276aaaa53 100644
--- a/sapi/phpdbg/Makefile.frag
+++ b/sapi/phpdbg/Makefile.frag
@@ -26,6 +26,9 @@ install-phpdbg: $(BUILD_BINARY)
@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/log
@$(mkinstalldirs) $(INSTALL_ROOT)$(localstatedir)/run
@$(INSTALL) -m 0755 $(BUILD_BINARY) $(INSTALL_ROOT)$(bindir)/$(program_prefix)phpdbg$(program_suffix)$(EXEEXT)
+ @echo "Installing phpdbg man page: $(INSTALL_ROOT)$(mandir)/man1/"
+ @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
+ @$(INSTALL_DATA) sapi/phpdbg/phpdbg.1 $(INSTALL_ROOT)$(mandir)/man1/$(program_prefix)phpdbg$(program_suffix).1
clean-phpdbg:
@echo "Cleaning phpdbg object files ..."
diff --git a/sapi/phpdbg/config.m4 b/sapi/phpdbg/config.m4
index 1a6640eaca..d78a439af0 100644
--- a/sapi/phpdbg/config.m4
+++ b/sapi/phpdbg/config.m4
@@ -21,7 +21,7 @@ if test "$PHP_PHPDBG" != "no"; then
PHP_PHPDBG_CFLAGS="-D_GNU_SOURCE"
PHP_PHPDBG_FILES="phpdbg.c phpdbg_parser.c phpdbg_lexer.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c phpdbg_set.c phpdbg_frame.c phpdbg_watch.c phpdbg_btree.c"
- if test "$PHP_READLINE" != "no"; then
+ if test "$PHP_READLINE" != "no" -o "$PHP_LIBEDIT" != "no"; then
PHPDBG_EXTRA_LIBS="$PHP_READLINE_LIBS"
fi
diff --git a/sapi/phpdbg/phpdbg.1 b/sapi/phpdbg/phpdbg.1
new file mode 100644
index 0000000000..5e4d144c83
--- /dev/null
+++ b/sapi/phpdbg/phpdbg.1
@@ -0,0 +1,59 @@
+.TH PHPDBG 1
+.SH NAME
+phpdbg \- The interactive PHP debugger
+.SH SYNOPSIS
+.B phpdbg
+[OPTION]
+[\fB\-e\fIFILE\fR]
+.SH DESCRIPTION
+.B phpdbg
+a lightweight, powerful, easy to use debugging platform for PHP5.
+.SH OPTIONS
+The following switches are implemented (just like cli SAPI):
+.TP
+.BR \-n
+No \fBphp.ini\fR file will be used
+.TP
+.BR \-c \fIpath\fB|\fIfile\fR
+Look for \fBphp.ini\fR file in the directory \fIpath\fR or use the specified \fIfile\fR
+.TP
+.BR \-z \fIfile\fR
+Load Zend extension \fIfile\fR
+.TP
+.BR \-d \fIfoo\fB[=\fIbar\fB]\fR
+Define INI entry \fIfoo\fR with value \fIbar\fR
+.PP The following switches change the default behaviour of phpdbg:
+.TP
+.BR \-v
+Disables quietness
+.TP
+.BR \-s
+Enabled stepping
+.TP
+.BR -e \fIfile\fR
+Sets execution context
+.TP
+.BR \-b
+Disables use of colour on the console
+.TP
+.BR \-I
+Ignore .phpdbginit (default init file)
+.TP
+.BR \-i \fIpath\fB|\ffile\fR
+Override .phpgdbinit location (implies -I)
+.TP
+.BR \-O \fIfile\fR
+Set oplog output to \fIfile\fR
+.TP
+.BR \-q
+Do not print banner on startup
+.TP
+.BR \-r
+Jump straight to run
+.TP
+.BR \-E
+Enable step through eval()
+.SH NOTES
+Passing -rr will cause phpdbg to quit after execution, rather than returning to the console
+.SH AUTHOR
+Written by Felipe Pena, Joe Watkins and Bob Weinand, formatted by Ondřej Surý for Debian project.
diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h
index 12350d5425..eb4faf1f94 100644
--- a/sapi/phpdbg/phpdbg.h
+++ b/sapi/phpdbg/phpdbg.h
@@ -64,10 +64,13 @@
# include "TSRM.h"
#endif
-#ifdef HAVE_LIBREADLINE
+#ifdef LIBREADLINE
# include <readline/readline.h>
# include <readline/history.h>
#endif
+#ifdef HAVE_LIBEDIT
+# include <editline/readline.h>
+#endif
#include "phpdbg_lexer.h"
#include "phpdbg_cmd.h"
diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c
index d4ce8ebc55..a45513bee6 100644
--- a/sapi/phpdbg/phpdbg_cmd.c
+++ b/sapi/phpdbg/phpdbg_cmd.c
@@ -792,7 +792,7 @@ PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why TSRMLS_DC)
PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */
{
char *cmd = NULL;
-#ifndef HAVE_LIBREADLINE
+#if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT)
char buf[PHPDBG_MAX_CMD];
#endif
char *buffer = NULL;
@@ -811,7 +811,7 @@ disconnect:
return NULL;
}
-#ifndef HAVE_LIBREADLINE
+#if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT)
if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
if (!phpdbg_write("%s", phpdbg_get_prompt(TSRMLS_C))) {
goto disconnect;
@@ -850,7 +850,7 @@ readline:
buffer = estrdup(cmd);
-#ifdef HAVE_LIBREADLINE
+#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)
if (!buffered && cmd &&
!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) {
free(cmd);
diff --git a/sapi/phpdbg/phpdbg_help.c b/sapi/phpdbg/phpdbg_help.c
index f2d074ded6..1e58dc69ca 100644
--- a/sapi/phpdbg/phpdbg_help.c
+++ b/sapi/phpdbg/phpdbg_help.c
@@ -318,8 +318,9 @@ phpdbg_help_text_t phpdbg_help_text[] = {
"**Information**" CR
" **list** list PHP source" CR
" **info** displays information on the debug session" CR
-" **print** show opcodes " CR
+" **print** show opcodes" CR
" **frame** select a stack frame and print a stack frame summary" CR
+" **back** shows the current backtrace" CR
" **help** provide help on a topic" CR CR
"**Starting and Stopping Execution**" CR
@@ -613,7 +614,7 @@ phpdbg_help_text_t phpdbg_help_text[] = {
{"finish",
"The **finish** command causes control to be passed back to the vm, continuing execution. Any "
"breakpoints that are encountered within the current stack frame will be skipped. Execution "
-"will then continue until the next breakpoint after leaving the stack frame or unitil "
+"will then continue until the next breakpoint after leaving the stack frame or until "
"completion of the script" CR CR
"Note when **step**ping is enabled, any opcode steps within the current stack frame are also "
@@ -629,7 +630,7 @@ phpdbg_help_text_t phpdbg_help_text[] = {
"**Examples**" CR CR
" $P frame 2" CR
-" $P E $count" CR
+" $P ev $count" CR
" Go to frame 2 and print out variable **$count** in that frame" CR CR
"Note that this frame scope is discarded when execution continues, with the execution frame "
diff --git a/sapi/phpdbg/phpdbg_lexer.c b/sapi/phpdbg/phpdbg_lexer.c
index 420dcac042..3092dc396d 100644
--- a/sapi/phpdbg/phpdbg_lexer.c
+++ b/sapi/phpdbg/phpdbg_lexer.c
@@ -96,33 +96,49 @@ yyc_INITIAL:
};
YYDEBUG(0, *YYCURSOR);
- YYFILL(3);
+ YYFILL(4);
yych = *YYCURSOR;
- if (yych <= 0x1F) {
- if (yych <= '\t') {
+ if (yych <= 'D') {
+ if (yych <= '\n') {
if (yych <= 0x00) goto yy6;
if (yych <= 0x08) goto yy11;
+ if (yych >= '\n') goto yy4;
} else {
- if (yych <= '\n') goto yy4;
- if (yych != '\r') goto yy11;
+ if (yych <= '\r') {
+ if (yych <= '\f') goto yy11;
+ } else {
+ if (yych != ' ') goto yy11;
+ }
}
} else {
- if (yych <= 'e') {
- if (yych <= ' ') goto yy2;
- if (yych <= 'd') goto yy11;
- goto yy7;
+ if (yych <= 'd') {
+ if (yych <= 'Q') {
+ if (yych <= 'E') goto yy7;
+ goto yy11;
+ } else {
+ if (yych <= 'R') goto yy10;
+ if (yych <= 'S') goto yy8;
+ goto yy11;
+ }
} else {
- if (yych <= 'q') goto yy11;
- if (yych <= 'r') goto yy9;
- if (yych <= 's') goto yy8;
- goto yy11;
+ if (yych <= 'q') {
+ if (yych <= 'e') goto yy7;
+ goto yy11;
+ } else {
+ if (yych <= 'r') goto yy9;
+ if (yych <= 's') goto yy8;
+ goto yy11;
+ }
}
}
-yy2:
YYDEBUG(2, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 128) {
- goto yy19;
+ if ((yych = *YYCURSOR) <= '\f') {
+ if (yych <= 0x08) goto yy3;
+ if (yych <= '\n') goto yy26;
+ } else {
+ if (yych <= '\r') goto yy26;
+ if (yych == ' ') goto yy26;
}
yy3:
YYDEBUG(3, *YYCURSOR);
@@ -134,49 +150,60 @@ yy3:
YYCURSOR = LEX(text);
goto restart;
}
-#line 138 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+#line 154 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
yy4:
YYDEBUG(4, *YYCURSOR);
++YYCURSOR;
- if (yybm[0+(yych = *YYCURSOR)] & 128) {
- goto yy19;
+ if ((yych = *YYCURSOR) <= '\f') {
+ if (yych <= 0x08) goto yy5;
+ if (yych <= '\n') goto yy26;
+ } else {
+ if (yych <= '\r') goto yy26;
+ if (yych == ' ') goto yy26;
}
+yy5:
YYDEBUG(5, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 68 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
return 0;
}
-#line 151 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+#line 172 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
yy6:
YYDEBUG(6, *YYCURSOR);
yych = *++YYCURSOR;
goto yy3;
yy7:
YYDEBUG(7, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'v') goto yy17;
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == 'V') goto yy22;
+ if (yych == 'v') goto yy22;
goto yy3;
yy8:
YYDEBUG(8, *YYCURSOR);
- yych = *++YYCURSOR;
- if (yych == 'h') goto yy15;
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == 'H') goto yy18;
+ if (yych == 'h') goto yy18;
goto yy3;
yy9:
YYDEBUG(9, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
+ if (yybm[0+yych] & 128) {
+ goto yy15;
+ }
+ if (yych == 'U') goto yy12;
if (yych == 'u') goto yy12;
+ goto yy3;
yy10:
YYDEBUG(10, *YYCURSOR);
- yyleng = (size_t) YYCURSOR - (size_t) yytext;
-#line 155 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
- {
- YYSETCONDITION(RAW);
- phpdbg_init_param(yylval, EMPTY_PARAM);
- return T_RUN;
-}
-#line 180 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == 'U') goto yy12;
+ if (yych == 'u') goto yy12;
+ goto yy3;
yy11:
YYDEBUG(11, *YYCURSOR);
yych = *++YYCURSOR;
@@ -184,18 +211,62 @@ yy11:
yy12:
YYDEBUG(12, *YYCURSOR);
yych = *++YYCURSOR;
+ if (yych == 'N') goto yy14;
if (yych == 'n') goto yy14;
+yy13:
YYDEBUG(13, *YYCURSOR);
YYCURSOR = YYMARKER;
- goto yy10;
+ goto yy3;
yy14:
YYDEBUG(14, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy10;
+ if (yybm[0+yych] & 128) {
+ goto yy15;
+ }
+ goto yy13;
yy15:
YYDEBUG(15, *YYCURSOR);
++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
YYDEBUG(16, *YYCURSOR);
+ if (yybm[0+yych] & 128) {
+ goto yy15;
+ }
+ YYDEBUG(17, *YYCURSOR);
+ yyleng = (size_t) YYCURSOR - (size_t) yytext;
+#line 155 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
+ {
+ YYSETCONDITION(RAW);
+ phpdbg_init_param(yylval, EMPTY_PARAM);
+ return T_RUN;
+}
+#line 245 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy18:
+ YYDEBUG(18, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy13;
+ if (yych >= '\v') goto yy13;
+ } else {
+ if (yych <= '\r') goto yy19;
+ if (yych != ' ') goto yy13;
+ }
+yy19:
+ YYDEBUG(19, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(20, *YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy21;
+ if (yych <= '\n') goto yy19;
+ } else {
+ if (yych <= '\r') goto yy19;
+ if (yych == ' ') goto yy19;
+ }
+yy21:
+ YYDEBUG(21, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 150 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -203,11 +274,32 @@ yy15:
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_SHELL;
}
-#line 207 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy17:
- YYDEBUG(17, *YYCURSOR);
+#line 278 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy22:
+ YYDEBUG(22, *YYCURSOR);
+ yych = *++YYCURSOR;
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy13;
+ if (yych >= '\v') goto yy13;
+ } else {
+ if (yych <= '\r') goto yy23;
+ if (yych != ' ') goto yy13;
+ }
+yy23:
+ YYDEBUG(23, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(18, *YYCURSOR);
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(24, *YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy25;
+ if (yych <= '\n') goto yy23;
+ } else {
+ if (yych <= '\r') goto yy23;
+ if (yych == ' ') goto yy23;
+ }
+yy25:
+ YYDEBUG(25, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 145 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -215,17 +307,22 @@ yy17:
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_EVAL;
}
-#line 219 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy19:
- YYDEBUG(19, *YYCURSOR);
+#line 311 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy26:
+ YYDEBUG(26, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(20, *YYCURSOR);
- if (yybm[0+yych] & 128) {
- goto yy19;
+ YYDEBUG(27, *YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy28;
+ if (yych <= '\n') goto yy26;
+ } else {
+ if (yych <= '\r') goto yy26;
+ if (yych == ' ') goto yy26;
}
- YYDEBUG(21, *YYCURSOR);
+yy28:
+ YYDEBUG(28, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -233,7 +330,7 @@ yy19:
goto restart;
}
-#line 237 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+#line 334 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
}
/* *********************************** */
yyc_NORMAL:
@@ -272,71 +369,60 @@ yyc_NORMAL:
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16,
};
- YYDEBUG(22, *YYCURSOR);
+ YYDEBUG(29, *YYCURSOR);
YYFILL(11);
yych = *YYCURSOR;
- if (yych <= ':') {
- if (yych <= ' ') {
- if (yych <= '\n') {
- if (yych <= 0x00) goto yy29;
- if (yych <= 0x08) goto yy32;
- if (yych >= '\n') goto yy27;
- } else {
- if (yych == '\r') goto yy24;
- if (yych <= 0x1F) goto yy32;
- }
- } else {
- if (yych <= '.') {
- if (yych == '#') goto yy47;
- if (yych <= '-') goto yy32;
- goto yy34;
- } else {
- if (yych <= '/') goto yy32;
- if (yych <= '0') goto yy37;
- if (yych <= '9') goto yy34;
- goto yy49;
- }
- }
- } else {
- if (yych <= 'i') {
- if (yych <= 'd') {
- if (yych == 'Z') goto yy38;
- if (yych <= 'c') goto yy32;
- goto yy39;
- } else {
- if (yych <= 'e') goto yy40;
- if (yych <= 'f') goto yy41;
- if (yych <= 'h') goto yy32;
- goto yy30;
- }
- } else {
- if (yych <= 's') {
- if (yych <= 'm') goto yy32;
- if (yych <= 'n') goto yy42;
- if (yych <= 'o') goto yy43;
- goto yy32;
- } else {
- if (yych <= 'x') {
- if (yych <= 't') goto yy44;
- goto yy32;
- } else {
- if (yych <= 'y') goto yy45;
- if (yych <= 'z') goto yy46;
- goto yy32;
- }
- }
- }
+ YYDEBUG(-1, yych);
+ switch (yych) {
+ case 0x00: goto yy36;
+ case '\t':
+ case '\r':
+ case ' ': goto yy31;
+ case '\n': goto yy34;
+ case '#': goto yy55;
+ case '-': goto yy41;
+ case '.':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': goto yy42;
+ case '0': goto yy45;
+ case ':': goto yy57;
+ case 'D':
+ case 'd': goto yy46;
+ case 'E':
+ case 'e': goto yy47;
+ case 'F':
+ case 'f': goto yy48;
+ case 'I':
+ case 'i': goto yy37;
+ case 'N':
+ case 'n': goto yy49;
+ case 'O':
+ case 'o': goto yy50;
+ case 'T':
+ case 't': goto yy51;
+ case 'Y':
+ case 'y': goto yy52;
+ case 'Z': goto yy53;
+ case 'z': goto yy54;
+ default: goto yy39;
}
-yy24:
- YYDEBUG(24, *YYCURSOR);
+yy31:
+ YYDEBUG(31, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(25, *YYCURSOR);
+ YYDEBUG(32, *YYCURSOR);
if (yybm[0+yych] & 8) {
- goto yy24;
+ goto yy31;
}
- YYDEBUG(26, *YYCURSOR);
+ YYDEBUG(33, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -344,33 +430,34 @@ yy24:
goto restart;
}
-#line 348 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy27:
- YYDEBUG(27, *YYCURSOR);
+#line 434 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy34:
+ YYDEBUG(34, *YYCURSOR);
++YYCURSOR;
if (yybm[0+(yych = *YYCURSOR)] & 8) {
- goto yy24;
+ goto yy31;
}
-yy28:
- YYDEBUG(28, *YYCURSOR);
+yy35:
+ YYDEBUG(35, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 68 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
return 0;
}
-#line 362 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy29:
- YYDEBUG(29, *YYCURSOR);
+#line 448 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy36:
+ YYDEBUG(36, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy28;
-yy30:
- YYDEBUG(30, *YYCURSOR);
+ goto yy35;
+yy37:
+ YYDEBUG(37, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'f') goto yy94;
- goto yy33;
-yy31:
- YYDEBUG(31, *YYCURSOR);
+ if (yych == 'F') goto yy106;
+ if (yych == 'f') goto yy106;
+ goto yy40;
+yy38:
+ YYDEBUG(38, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 125 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -379,48 +466,56 @@ yy31:
yylval->len = yyleng;
return T_ID;
}
-#line 383 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy32:
- YYDEBUG(32, *YYCURSOR);
+#line 470 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy39:
+ YYDEBUG(39, *YYCURSOR);
yyaccept = 0;
YYMARKER = ++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
-yy33:
- YYDEBUG(33, *YYCURSOR);
+yy40:
+ YYDEBUG(40, *YYCURSOR);
if (yybm[0+yych] & 16) {
- goto yy32;
+ goto yy39;
}
- if (yych <= '9') goto yy31;
- goto yy54;
-yy34:
- YYDEBUG(34, *YYCURSOR);
+ if (yych <= '9') goto yy38;
+ goto yy62;
+yy41:
+ YYDEBUG(41, *YYCURSOR);
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yybm[0+yych] & 32) {
+ goto yy42;
+ }
+ goto yy40;
+yy42:
+ YYDEBUG(42, *YYCURSOR);
yyaccept = 1;
YYMARKER = ++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
- YYDEBUG(35, *YYCURSOR);
+ YYDEBUG(43, *YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy34;
+ goto yy42;
}
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy36;
- if (yych <= 0x08) goto yy32;
+ if (yych <= 0x00) goto yy44;
+ if (yych <= 0x08) goto yy39;
} else {
- if (yych != '\r') goto yy32;
+ if (yych != '\r') goto yy39;
}
} else {
if (yych <= '#') {
- if (yych <= ' ') goto yy36;
- if (yych <= '"') goto yy32;
+ if (yych <= ' ') goto yy44;
+ if (yych <= '"') goto yy39;
} else {
- if (yych == ':') goto yy54;
- goto yy32;
+ if (yych == ':') goto yy62;
+ goto yy39;
}
}
-yy36:
- YYDEBUG(36, *YYCURSOR);
+yy44:
+ YYDEBUG(44, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 106 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -428,164 +523,168 @@ yy36:
yylval->num = atoi(yytext);
return T_DIGITS;
}
-#line 432 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy37:
- YYDEBUG(37, *YYCURSOR);
+#line 527 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy45:
+ YYDEBUG(45, *YYCURSOR);
yyaccept = 1;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy34;
+ goto yy42;
}
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy36;
- if (yych <= 0x08) goto yy33;
- goto yy36;
+ if (yych <= 0x00) goto yy44;
+ if (yych <= 0x08) goto yy40;
+ goto yy44;
} else {
- if (yych == '\r') goto yy36;
- goto yy33;
+ if (yych == '\r') goto yy44;
+ goto yy40;
}
} else {
if (yych <= '#') {
- if (yych <= ' ') goto yy36;
- if (yych <= '"') goto yy33;
- goto yy36;
+ if (yych <= ' ') goto yy44;
+ if (yych <= '"') goto yy40;
+ goto yy44;
} else {
- if (yych == 'x') goto yy90;
- goto yy33;
+ if (yych == 'x') goto yy102;
+ goto yy40;
}
}
-yy38:
- YYDEBUG(38, *YYCURSOR);
+yy46:
+ YYDEBUG(46, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'E') goto yy87;
- goto yy33;
-yy39:
- YYDEBUG(39, *YYCURSOR);
+ if (yych == 'I') goto yy96;
+ if (yych == 'i') goto yy96;
+ goto yy40;
+yy47:
+ YYDEBUG(47, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'i') goto yy81;
- goto yy33;
-yy40:
- YYDEBUG(40, *YYCURSOR);
+ if (yych == 'N') goto yy91;
+ if (yych == 'n') goto yy91;
+ goto yy40;
+yy48:
+ YYDEBUG(48, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'n') goto yy76;
- goto yy33;
-yy41:
- YYDEBUG(41, *YYCURSOR);
+ if (yych == 'A') goto yy88;
+ if (yych == 'a') goto yy88;
+ goto yy40;
+yy49:
+ YYDEBUG(49, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'a') goto yy73;
- goto yy33;
-yy42:
- YYDEBUG(42, *YYCURSOR);
+ if (yych == 'O') goto yy84;
+ if (yych == 'o') goto yy84;
+ goto yy40;
+yy50:
+ YYDEBUG(50, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'o') goto yy71;
- goto yy33;
-yy43:
- YYDEBUG(43, *YYCURSOR);
+ if (yych <= 'N') {
+ if (yych == 'F') goto yy83;
+ if (yych <= 'M') goto yy40;
+ goto yy77;
+ } else {
+ if (yych <= 'f') {
+ if (yych <= 'e') goto yy40;
+ goto yy83;
+ } else {
+ if (yych == 'n') goto yy77;
+ goto yy40;
+ }
+ }
+yy51:
+ YYDEBUG(51, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'f') goto yy70;
- if (yych == 'n') goto yy66;
- goto yy33;
-yy44:
- YYDEBUG(44, *YYCURSOR);
+ if (yych == 'R') goto yy81;
+ if (yych == 'r') goto yy81;
+ goto yy40;
+yy52:
+ YYDEBUG(52, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'r') goto yy68;
- goto yy33;
-yy45:
- YYDEBUG(45, *YYCURSOR);
+ if (yych == 'E') goto yy76;
+ if (yych == 'e') goto yy76;
+ goto yy40;
+yy53:
+ YYDEBUG(53, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'e') goto yy65;
- goto yy33;
-yy46:
- YYDEBUG(46, *YYCURSOR);
+ if (yych == 'E') goto yy73;
+ goto yy40;
+yy54:
+ YYDEBUG(54, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'e') goto yy53;
- goto yy33;
-yy47:
- YYDEBUG(47, *YYCURSOR);
+ if (yych == 'e') goto yy61;
+ goto yy40;
+yy55:
+ YYDEBUG(55, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(48, *YYCURSOR);
+ YYDEBUG(56, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 84 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
return T_POUND;
}
-#line 523 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy49:
- YYDEBUG(49, *YYCURSOR);
+#line 634 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy57:
+ YYDEBUG(57, *YYCURSOR);
++YYCURSOR;
- if ((yych = *YYCURSOR) == ':') goto yy51;
- YYDEBUG(50, *YYCURSOR);
+ if ((yych = *YYCURSOR) == ':') goto yy59;
+ YYDEBUG(58, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 90 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
return T_COLON;
}
-#line 534 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy51:
- YYDEBUG(51, *YYCURSOR);
+#line 645 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy59:
+ YYDEBUG(59, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(52, *YYCURSOR);
+ YYDEBUG(60, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 87 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
return T_DCOLON;
}
-#line 544 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy53:
- YYDEBUG(53, *YYCURSOR);
+#line 655 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy61:
+ YYDEBUG(61, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'n') goto yy59;
- goto yy33;
-yy54:
- YYDEBUG(54, *YYCURSOR);
+ if (yych == 'n') goto yy67;
+ goto yy40;
+yy62:
+ YYDEBUG(62, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych == '/') goto yy56;
-yy55:
- YYDEBUG(55, *YYCURSOR);
+ if (yych == '/') goto yy64;
+yy63:
+ YYDEBUG(63, *YYCURSOR);
YYCURSOR = YYMARKER;
- if (yyaccept <= 3) {
- if (yyaccept <= 1) {
- if (yyaccept <= 0) {
- goto yy31;
- } else {
- goto yy36;
- }
+ if (yyaccept <= 1) {
+ if (yyaccept <= 0) {
+ goto yy38;
} else {
- if (yyaccept <= 2) {
- goto yy64;
- } else {
- goto yy67;
- }
+ goto yy44;
}
} else {
- if (yyaccept <= 5) {
- if (yyaccept <= 4) {
- goto yy72;
- } else {
- goto yy93;
- }
+ if (yyaccept <= 2) {
+ goto yy72;
} else {
- goto yy95;
+ goto yy105;
}
}
-yy56:
- YYDEBUG(56, *YYCURSOR);
+yy64:
+ YYDEBUG(64, *YYCURSOR);
yych = *++YYCURSOR;
- if (yych != '/') goto yy55;
- YYDEBUG(57, *YYCURSOR);
+ if (yych != '/') goto yy63;
+ YYDEBUG(65, *YYCURSOR);
++YYCURSOR;
- YYDEBUG(58, *YYCURSOR);
+ YYDEBUG(66, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 78 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -594,52 +693,52 @@ yy56:
yylval->len = yyleng;
return T_PROTO;
}
-#line 598 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy59:
- YYDEBUG(59, *YYCURSOR);
+#line 697 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy67:
+ YYDEBUG(67, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'd') goto yy33;
- YYDEBUG(60, *YYCURSOR);
+ if (yych != 'd') goto yy40;
+ YYDEBUG(68, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != '_') goto yy33;
-yy61:
- YYDEBUG(61, *YYCURSOR);
+ if (yych != '_') goto yy40;
+yy69:
+ YYDEBUG(69, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy62;
+ goto yy70;
}
- goto yy33;
-yy62:
- YYDEBUG(62, *YYCURSOR);
+ goto yy40;
+yy70:
+ YYDEBUG(70, *YYCURSOR);
yyaccept = 2;
YYMARKER = ++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
- YYDEBUG(63, *YYCURSOR);
+ YYDEBUG(71, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy62;
+ goto yy70;
}
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy64;
- if (yych <= 0x08) goto yy32;
+ if (yych <= 0x00) goto yy72;
+ if (yych <= 0x08) goto yy39;
} else {
- if (yych != '\r') goto yy32;
+ if (yych != '\r') goto yy39;
}
} else {
if (yych <= '#') {
- if (yych <= ' ') goto yy64;
- if (yych <= '"') goto yy32;
+ if (yych <= ' ') goto yy72;
+ if (yych <= '"') goto yy39;
} else {
- if (yych == ':') goto yy54;
- goto yy32;
+ if (yych == ':') goto yy62;
+ goto yy39;
}
}
-yy64:
- YYDEBUG(64, *YYCURSOR);
+yy72:
+ YYDEBUG(72, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 118 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -648,32 +747,53 @@ yy64:
yylval->len = yyleng;
return T_OPCODE;
}
-#line 652 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy65:
- YYDEBUG(65, *YYCURSOR);
+#line 751 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy73:
+ YYDEBUG(73, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 's') goto yy33;
-yy66:
- YYDEBUG(66, *YYCURSOR);
- yyaccept = 3;
+ if (yych != 'N') goto yy40;
+ YYDEBUG(74, *YYCURSOR);
+ yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '\r') {
- if (yych <= 0x08) {
- if (yych >= 0x01) goto yy33;
- } else {
- if (yych <= '\n') goto yy67;
- if (yych <= '\f') goto yy33;
- }
+ if (yych != 'D') goto yy40;
+ YYDEBUG(75, *YYCURSOR);
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == '_') goto yy69;
+ goto yy40;
+yy76:
+ YYDEBUG(76, *YYCURSOR);
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych == 'S') goto yy77;
+ if (yych != 's') goto yy40;
+yy77:
+ YYDEBUG(77, *YYCURSOR);
+ yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy40;
+ if (yych >= '\v') goto yy40;
} else {
- if (yych <= ' ') {
- if (yych <= 0x1F) goto yy33;
- } else {
- if (yych != '#') goto yy33;
- }
+ if (yych <= '\r') goto yy78;
+ if (yych != ' ') goto yy40;
}
-yy67:
- YYDEBUG(67, *YYCURSOR);
+yy78:
+ YYDEBUG(78, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(79, *YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy80;
+ if (yych <= '\n') goto yy78;
+ } else {
+ if (yych <= '\r') goto yy78;
+ if (yych == ' ') goto yy78;
+ }
+yy80:
+ YYDEBUG(80, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 94 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -681,42 +801,52 @@ yy67:
yylval->num = 1;
return T_TRUTHY;
}
-#line 685 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy68:
- YYDEBUG(68, *YYCURSOR);
+#line 805 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy81:
+ YYDEBUG(81, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'u') goto yy33;
- YYDEBUG(69, *YYCURSOR);
+ if (yych == 'U') goto yy82;
+ if (yych != 'u') goto yy40;
+yy82:
+ YYDEBUG(82, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'e') goto yy66;
- goto yy33;
-yy70:
- YYDEBUG(70, *YYCURSOR);
+ if (yych == 'E') goto yy77;
+ if (yych == 'e') goto yy77;
+ goto yy40;
+yy83:
+ YYDEBUG(83, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'f') goto yy33;
-yy71:
- YYDEBUG(71, *YYCURSOR);
- yyaccept = 4;
+ if (yych == 'F') goto yy84;
+ if (yych != 'f') goto yy40;
+yy84:
+ YYDEBUG(84, *YYCURSOR);
+ yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '\r') {
- if (yych <= 0x08) {
- if (yych >= 0x01) goto yy33;
- } else {
- if (yych <= '\n') goto yy72;
- if (yych <= '\f') goto yy33;
- }
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy40;
+ if (yych >= '\v') goto yy40;
} else {
- if (yych <= ' ') {
- if (yych <= 0x1F) goto yy33;
- } else {
- if (yych != '#') goto yy33;
- }
+ if (yych <= '\r') goto yy85;
+ if (yych != ' ') goto yy40;
}
-yy72:
- YYDEBUG(72, *YYCURSOR);
+yy85:
+ YYDEBUG(85, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(86, *YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy87;
+ if (yych <= '\n') goto yy85;
+ } else {
+ if (yych <= '\r') goto yy85;
+ if (yych == ' ') goto yy85;
+ }
+yy87:
+ YYDEBUG(87, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 100 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -724,119 +854,130 @@ yy72:
yylval->num = 0;
return T_FALSY;
}
-#line 728 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy73:
- YYDEBUG(73, *YYCURSOR);
- yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'l') goto yy33;
- YYDEBUG(74, *YYCURSOR);
- yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 's') goto yy33;
- YYDEBUG(75, *YYCURSOR);
- yyaccept = 0;
- yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'e') goto yy71;
- goto yy33;
-yy76:
- YYDEBUG(76, *YYCURSOR);
+#line 858 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy88:
+ YYDEBUG(88, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'a') goto yy33;
- YYDEBUG(77, *YYCURSOR);
+ if (yych == 'L') goto yy89;
+ if (yych != 'l') goto yy40;
+yy89:
+ YYDEBUG(89, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'b') goto yy33;
- YYDEBUG(78, *YYCURSOR);
+ if (yych == 'S') goto yy90;
+ if (yych != 's') goto yy40;
+yy90:
+ YYDEBUG(90, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'l') goto yy33;
- YYDEBUG(79, *YYCURSOR);
+ if (yych == 'E') goto yy84;
+ if (yych == 'e') goto yy84;
+ goto yy40;
+yy91:
+ YYDEBUG(91, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'e') goto yy33;
- YYDEBUG(80, *YYCURSOR);
+ if (yych == 'A') goto yy92;
+ if (yych != 'a') goto yy40;
+yy92:
+ YYDEBUG(92, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'd') goto yy66;
- goto yy33;
-yy81:
- YYDEBUG(81, *YYCURSOR);
+ if (yych == 'B') goto yy93;
+ if (yych != 'b') goto yy40;
+yy93:
+ YYDEBUG(93, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 's') goto yy33;
- YYDEBUG(82, *YYCURSOR);
+ if (yych == 'L') goto yy94;
+ if (yych != 'l') goto yy40;
+yy94:
+ YYDEBUG(94, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'a') goto yy33;
- YYDEBUG(83, *YYCURSOR);
+ if (yych == 'E') goto yy95;
+ if (yych != 'e') goto yy40;
+yy95:
+ YYDEBUG(95, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'b') goto yy33;
- YYDEBUG(84, *YYCURSOR);
+ if (yych == 'D') goto yy77;
+ if (yych == 'd') goto yy77;
+ goto yy40;
+yy96:
+ YYDEBUG(96, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'l') goto yy33;
- YYDEBUG(85, *YYCURSOR);
+ if (yych == 'S') goto yy97;
+ if (yych != 's') goto yy40;
+yy97:
+ YYDEBUG(97, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'e') goto yy33;
- YYDEBUG(86, *YYCURSOR);
+ if (yych == 'A') goto yy98;
+ if (yych != 'a') goto yy40;
+yy98:
+ YYDEBUG(98, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == 'd') goto yy71;
- goto yy33;
-yy87:
- YYDEBUG(87, *YYCURSOR);
+ if (yych == 'B') goto yy99;
+ if (yych != 'b') goto yy40;
+yy99:
+ YYDEBUG(99, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'N') goto yy33;
- YYDEBUG(88, *YYCURSOR);
+ if (yych == 'L') goto yy100;
+ if (yych != 'l') goto yy40;
+yy100:
+ YYDEBUG(100, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych != 'D') goto yy33;
- YYDEBUG(89, *YYCURSOR);
+ if (yych == 'E') goto yy101;
+ if (yych != 'e') goto yy40;
+yy101:
+ YYDEBUG(101, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych == '_') goto yy61;
- goto yy33;
-yy90:
- YYDEBUG(90, *YYCURSOR);
+ if (yych == 'D') goto yy84;
+ if (yych == 'd') goto yy84;
+ goto yy40;
+yy102:
+ YYDEBUG(102, *YYCURSOR);
yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy91;
+ goto yy103;
}
- goto yy33;
-yy91:
- YYDEBUG(91, *YYCURSOR);
- yyaccept = 5;
+ goto yy40;
+yy103:
+ YYDEBUG(103, *YYCURSOR);
+ yyaccept = 3;
YYMARKER = ++YYCURSOR;
YYFILL(3);
yych = *YYCURSOR;
- YYDEBUG(92, *YYCURSOR);
+ YYDEBUG(104, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy91;
+ goto yy103;
}
if (yych <= 0x1F) {
if (yych <= '\n') {
- if (yych <= 0x00) goto yy93;
- if (yych <= 0x08) goto yy32;
+ if (yych <= 0x00) goto yy105;
+ if (yych <= 0x08) goto yy39;
} else {
- if (yych != '\r') goto yy32;
+ if (yych != '\r') goto yy39;
}
} else {
if (yych <= '#') {
- if (yych <= ' ') goto yy93;
- if (yych <= '"') goto yy32;
+ if (yych <= ' ') goto yy105;
+ if (yych <= '"') goto yy39;
} else {
- if (yych == ':') goto yy54;
- goto yy32;
+ if (yych == ':') goto yy62;
+ goto yy39;
}
}
-yy93:
- YYDEBUG(93, *YYCURSOR);
+yy105:
+ YYDEBUG(105, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 112 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -844,27 +985,33 @@ yy93:
yylval->addr = strtoul(yytext, 0, 16);
return T_ADDR;
}
-#line 848 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy94:
- YYDEBUG(94, *YYCURSOR);
- yyaccept = 6;
+#line 989 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy106:
+ YYDEBUG(106, *YYCURSOR);
+ yyaccept = 0;
yych = *(YYMARKER = ++YYCURSOR);
- if (yych <= '\r') {
- if (yych <= 0x08) {
- if (yych >= 0x01) goto yy33;
- } else {
- if (yych <= '\n') goto yy95;
- if (yych <= '\f') goto yy33;
- }
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy40;
+ if (yych >= '\v') goto yy40;
} else {
- if (yych <= ' ') {
- if (yych <= 0x1F) goto yy33;
- } else {
- if (yych != '#') goto yy33;
- }
+ if (yych <= '\r') goto yy107;
+ if (yych != ' ') goto yy40;
}
-yy95:
- YYDEBUG(95, *YYCURSOR);
+yy107:
+ YYDEBUG(107, *YYCURSOR);
+ ++YYCURSOR;
+ YYFILL(1);
+ yych = *YYCURSOR;
+ YYDEBUG(108, *YYCURSOR);
+ if (yych <= '\f') {
+ if (yych <= 0x08) goto yy109;
+ if (yych <= '\n') goto yy107;
+ } else {
+ if (yych <= '\r') goto yy107;
+ if (yych == ' ') goto yy107;
+ }
+yy109:
+ YYDEBUG(109, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 72 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -872,7 +1019,7 @@ yy95:
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_IF;
}
-#line 876 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+#line 1023 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
}
/* *********************************** */
yyc_RAW:
@@ -911,29 +1058,29 @@ yyc_RAW:
64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64,
};
- YYDEBUG(96, *YYCURSOR);
+ YYDEBUG(110, *YYCURSOR);
YYFILL(2);
yych = *YYCURSOR;
if (yybm[0+yych] & 32) {
- goto yy98;
+ goto yy112;
}
- if (yych <= 0x00) goto yy103;
- if (yych == '\n') goto yy101;
- goto yy104;
-yy98:
- YYDEBUG(98, *YYCURSOR);
+ if (yych <= 0x00) goto yy117;
+ if (yych == '\n') goto yy115;
+ goto yy118;
+yy112:
+ YYDEBUG(112, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(99, *YYCURSOR);
+ YYDEBUG(113, *YYCURSOR);
if (yybm[0+yych] & 32) {
- goto yy98;
+ goto yy112;
}
- if (yych <= 0x00) goto yy100;
- if (yych == '\n') goto yy106;
- goto yy104;
-yy100:
- YYDEBUG(100, *YYCURSOR);
+ if (yych <= 0x00) goto yy114;
+ if (yych == '\n') goto yy120;
+ goto yy118;
+yy114:
+ YYDEBUG(114, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 132 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -942,45 +1089,45 @@ yy100:
yylval->len = yyleng;
return T_INPUT;
}
-#line 946 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy101:
- YYDEBUG(101, *YYCURSOR);
+#line 1093 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy115:
+ YYDEBUG(115, *YYCURSOR);
++YYCURSOR;
if (yybm[0+(yych = *YYCURSOR)] & 128) {
- goto yy106;
+ goto yy120;
}
-yy102:
- YYDEBUG(102, *YYCURSOR);
+yy116:
+ YYDEBUG(116, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 68 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
return 0;
}
-#line 960 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
-yy103:
- YYDEBUG(103, *YYCURSOR);
+#line 1107 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+yy117:
+ YYDEBUG(117, *YYCURSOR);
yych = *++YYCURSOR;
- goto yy102;
-yy104:
- YYDEBUG(104, *YYCURSOR);
+ goto yy116;
+yy118:
+ YYDEBUG(118, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(105, *YYCURSOR);
+ YYDEBUG(119, *YYCURSOR);
if (yybm[0+yych] & 64) {
- goto yy104;
+ goto yy118;
}
- goto yy100;
-yy106:
- YYDEBUG(106, *YYCURSOR);
+ goto yy114;
+yy120:
+ YYDEBUG(120, *YYCURSOR);
++YYCURSOR;
YYFILL(1);
yych = *YYCURSOR;
- YYDEBUG(107, *YYCURSOR);
+ YYDEBUG(121, *YYCURSOR);
if (yybm[0+yych] & 128) {
- goto yy106;
+ goto yy120;
}
- YYDEBUG(108, *YYCURSOR);
+ YYDEBUG(122, *YYCURSOR);
yyleng = (size_t) YYCURSOR - (size_t) yytext;
#line 139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
{
@@ -988,7 +1135,7 @@ yy106:
goto restart;
}
-#line 992 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
+#line 1139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c"
}
}
#line 168 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l"
diff --git a/sapi/phpdbg/phpdbg_lexer.l b/sapi/phpdbg/phpdbg_lexer.l
index 4d9c837f1e..7b3ce38c47 100644
--- a/sapi/phpdbg/phpdbg_lexer.l
+++ b/sapi/phpdbg/phpdbg_lexer.l
@@ -43,21 +43,21 @@ restart:
/*!re2c
re2c:yyfill:check = 0;
-T_TRUE "true"
-T_YES "yes"
-T_ON "on"
-T_ENABLED "enabled"
-T_FALSE "false"
-T_NO "no"
-T_OFF "off"
-T_DISABLED "disabled"
-T_EVAL "ev"
-T_SHELL "sh"
-T_IF "if"
-T_RUN "run"
+T_TRUE 'true'
+T_YES 'yes'
+T_ON 'on'
+T_ENABLED 'enabled'
+T_FALSE 'false'
+T_NO 'no'
+T_OFF 'off'
+T_DISABLED 'disabled'
+T_EVAL 'ev'
+T_SHELL 'sh'
+T_IF 'if'
+T_RUN 'run'
T_RUN_SHORT "r"
WS [ \r\n\t]+
-DIGITS [0-9\.]+
+DIGITS [-]?[0-9\.]+
ID [^ \r\n\t:#\000]+
ADDR [0][x][a-fA-F0-9]+
OPCODE (ZEND_|zend_)([A-Za-z])+
@@ -69,7 +69,7 @@ INPUT [^\n\000]+
return 0;
}
-<NORMAL>{T_IF} {
+<NORMAL>{T_IF}{WS} {
YYSETCONDITION(RAW);
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_IF;
@@ -91,13 +91,13 @@ INPUT [^\n\000]+
return T_COLON;
}
-<NORMAL>{T_YES}|{T_ON}|{T_ENABLED}|{T_TRUE} {
+<NORMAL>({T_YES}|{T_ON}|{T_ENABLED}|{T_TRUE}){WS} {
phpdbg_init_param(yylval, NUMERIC_PARAM);
yylval->num = 1;
return T_TRUTHY;
}
-<NORMAL>{T_NO}|{T_OFF}|{T_DISABLED}|{T_FALSE} {
+<NORMAL>({T_NO}|{T_OFF}|{T_DISABLED}|{T_FALSE}){WS} {
phpdbg_init_param(yylval, NUMERIC_PARAM);
yylval->num = 0;
return T_FALSY;
@@ -142,17 +142,17 @@ INPUT [^\n\000]+
goto restart;
}
-<INITIAL>{T_EVAL} {
+<INITIAL>{T_EVAL}{WS} {
YYSETCONDITION(RAW);
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_EVAL;
}
-<INITIAL>{T_SHELL} {
+<INITIAL>{T_SHELL}{WS} {
YYSETCONDITION(RAW);
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_SHELL;
}
-<INITIAL>{T_RUN}|{T_RUN_SHORT} {
+<INITIAL>({T_RUN}|{T_RUN_SHORT}){WS} {
YYSETCONDITION(RAW);
phpdbg_init_param(yylval, EMPTY_PARAM);
return T_RUN;
diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c
index 037c6c38b2..e8db4e605c 100644
--- a/sapi/phpdbg/phpdbg_list.c
+++ b/sapi/phpdbg/phpdbg_list.c
@@ -130,14 +130,14 @@ void phpdbg_list_file(const char *filename, long count, long offset, int highlig
char *opened = NULL;
char buffer[8096] = {0,};
long line = 0;
-
+
php_stream *stream = NULL;
if (VCWD_STAT(filename, &st) == FAILURE) {
phpdbg_error("Failed to stat file %s", filename);
return;
}
-
+
stream = php_stream_open_wrapper(filename, "rb", USE_PATH, &opened);
if (!stream) {
@@ -145,11 +145,17 @@ void phpdbg_list_file(const char *filename, long count, long offset, int highlig
return;
}
+ if (offset < 0) {
+ count += offset;
+ offset = 0;
+ }
+
while (php_stream_gets(stream, buffer, sizeof(buffer)) != NULL) {
+ long linelen = strlen(buffer);
+
++line;
- if (!offset || offset <= line) {
- /* Without offset, or offset reached */
+ if (offset <= line) {
if (!highlight) {
phpdbg_write("%05ld: %s", line, buffer);
} else {
@@ -159,10 +165,15 @@ void phpdbg_list_file(const char *filename, long count, long offset, int highlig
phpdbg_write(">%05ld: %s", line, buffer);
}
}
+
+ if (buffer[linelen - 1] != '\n') {
+ phpdbg_write("\n");
+ }
}
-
- if ((count + (offset-1)) == line)
+
+ if (count > 0 && count + offset - 1 < line) {
break;
+ }
}
php_stream_close(stream);
diff --git a/sapi/phpdbg/phpdbg_parser.c b/sapi/phpdbg/phpdbg_parser.c
index f9a3e4d299..e34c2f48ff 100644
--- a/sapi/phpdbg/phpdbg_parser.c
+++ b/sapi/phpdbg/phpdbg_parser.c
@@ -436,7 +436,7 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 25
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 41
+#define YYLAST 42
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 21
@@ -493,8 +493,8 @@ static const yytype_uint8 yytranslate[] =
static const yytype_uint8 yyprhs[] =
{
0, 0, 3, 5, 7, 8, 10, 13, 17, 22,
- 27, 33, 37, 43, 47, 49, 51, 53, 55, 57,
- 59, 61, 64, 67, 70, 72
+ 27, 33, 37, 43, 47, 50, 52, 54, 56, 58,
+ 60, 62, 64, 67, 70, 72
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
@@ -504,9 +504,9 @@ static const yytype_int8 yyrhs[] =
23, 24, -1, 18, 10, 14, -1, 18, 10, 12,
14, -1, 13, 18, 10, 14, -1, 13, 18, 10,
12, 14, -1, 18, 11, 18, -1, 18, 11, 18,
- 12, 14, -1, 18, 12, 14, -1, 17, -1, 16,
- -1, 15, -1, 7, -1, 8, -1, 14, -1, 18,
- -1, 6, 19, -1, 3, 19, -1, 5, 19, -1,
+ 12, 14, -1, 18, 12, 14, -1, 6, 19, -1,
+ 17, -1, 16, -1, 15, -1, 7, -1, 8, -1,
+ 14, -1, 18, -1, 3, 19, -1, 5, 19, -1,
4, -1, 4, 19, -1
};
@@ -514,8 +514,8 @@ static const yytype_int8 yyrhs[] =
static const yytype_uint8 yyrline[] =
{
0, 66, 66, 67, 68, 72, 73, 77, 82, 87,
- 97, 107, 112, 118, 124, 125, 126, 127, 128, 129,
- 130, 134, 139, 144, 149, 153
+ 97, 107, 112, 118, 124, 129, 130, 131, 132, 133,
+ 134, 135, 139, 144, 149, 153
};
#endif
@@ -552,15 +552,15 @@ static const yytype_uint8 yyr1[] =
{
0, 21, 22, 22, 22, 23, 23, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 25, 25, 25, 25, 25
+ 24, 24, 25, 25, 25, 25
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 1, 1, 0, 1, 2, 3, 4, 4,
- 5, 3, 5, 3, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 1, 2
+ 5, 3, 5, 3, 2, 1, 1, 1, 1, 1,
+ 1, 1, 2, 2, 1, 2
};
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -568,9 +568,9 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 4, 0, 24, 0, 0, 17, 18, 0, 19, 16,
- 15, 14, 20, 0, 2, 5, 3, 22, 25, 23,
- 21, 0, 0, 0, 0, 1, 6, 0, 0, 7,
+ 4, 0, 24, 0, 0, 18, 19, 0, 20, 17,
+ 16, 15, 21, 0, 2, 5, 3, 22, 25, 23,
+ 14, 0, 0, 0, 0, 1, 6, 0, 0, 7,
11, 13, 0, 9, 8, 0, 10, 12
};
@@ -585,16 +585,16 @@ static const yytype_int8 yydefgoto[] =
#define YYPACT_NINF -11
static const yytype_int8 yypact[] =
{
- -3, -10, 10, 11, 12, -11, -11, 14, -11, -11,
- -11, -11, -4, 28, 9, -11, -11, -11, -11, -11,
- -11, 23, 6, 16, 21, -11, -11, 7, 22, -11,
- 25, -11, 24, -11, -11, 26, -11, -11
+ -3, -10, 11, 12, 13, -11, -11, 15, -11, -11,
+ -11, -11, -4, 29, 10, -11, -11, -11, -11, -11,
+ -11, 24, 7, 17, 22, -11, -11, 8, 23, -11,
+ 26, -11, 25, -11, -11, 27, -11, -11
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -11, -11, -11, 27, -11
+ -11, -11, -11, 28, -11
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -604,10 +604,10 @@ static const yytype_int8 yypgoto[] =
static const yytype_uint8 yytable[] =
{
1, 2, 3, 4, 5, 6, 22, 23, 24, 17,
- 7, 8, 9, 10, 11, 12, 5, 6, 28, 32,
- 29, 33, 7, 8, 9, 10, 11, 12, 25, 18,
- 19, 20, 21, 27, 30, 31, 34, 35, 36, 0,
- 37, 26
+ 7, 8, 9, 10, 11, 12, 4, 5, 6, 28,
+ 32, 29, 33, 7, 8, 9, 10, 11, 12, 25,
+ 18, 19, 20, 21, 27, 30, 31, 34, 35, 36,
+ 0, 37, 26
};
#define yypact_value_is_default(yystate) \
@@ -619,10 +619,10 @@ static const yytype_uint8 yytable[] =
static const yytype_int8 yycheck[] =
{
3, 4, 5, 6, 7, 8, 10, 11, 12, 19,
- 13, 14, 15, 16, 17, 18, 7, 8, 12, 12,
- 14, 14, 13, 14, 15, 16, 17, 18, 0, 19,
- 19, 19, 18, 10, 18, 14, 14, 12, 14, -1,
- 14, 14
+ 13, 14, 15, 16, 17, 18, 6, 7, 8, 12,
+ 12, 14, 14, 13, 14, 15, 16, 17, 18, 0,
+ 19, 19, 19, 18, 10, 18, 14, 14, 12, 14,
+ -1, 14, 14
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -1563,53 +1563,53 @@ yyreduce:
case 14:
/* Line 1802 of yacc.c */
#line 124 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
- { (yyval) = (yyvsp[(1) - (1)]); }
+ {
+ (yyval).type = COND_PARAM;
+ (yyval).str = (yyvsp[(2) - (2)]).str;
+ (yyval).len = (yyvsp[(2) - (2)]).len;
+ }
break;
case 15:
/* Line 1802 of yacc.c */
-#line 125 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+#line 129 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 16:
/* Line 1802 of yacc.c */
-#line 126 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+#line 130 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 17:
/* Line 1802 of yacc.c */
-#line 127 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+#line 131 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 18:
/* Line 1802 of yacc.c */
-#line 128 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+#line 132 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 19:
/* Line 1802 of yacc.c */
-#line 129 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+#line 133 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 20:
/* Line 1802 of yacc.c */
-#line 130 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+#line 134 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
{ (yyval) = (yyvsp[(1) - (1)]); }
break;
case 21:
/* Line 1802 of yacc.c */
-#line 134 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
- {
- (yyval).type = COND_PARAM;
- (yyval).str = (yyvsp[(2) - (2)]).str;
- (yyval).len = (yyvsp[(2) - (2)]).len;
- }
+#line 135 "/var/root/php-src/sapi/phpdbg/phpdbg_parser.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 22:
diff --git a/sapi/phpdbg/phpdbg_parser.y b/sapi/phpdbg/phpdbg_parser.y
index fd81edfc29..702bf78455 100644
--- a/sapi/phpdbg/phpdbg_parser.y
+++ b/sapi/phpdbg/phpdbg_parser.y
@@ -121,6 +121,11 @@ parameter
$$.len = $1.len;
$$.num = $3.num;
}
+ | T_IF T_INPUT {
+ $$.type = COND_PARAM;
+ $$.str = $2.str;
+ $$.len = $2.len;
+ }
| T_OPCODE { $$ = $1; }
| T_ADDR { $$ = $1; }
| T_LITERAL { $$ = $1; }
@@ -131,12 +136,7 @@ parameter
;
full_expression
- : T_IF T_INPUT {
- $$.type = COND_PARAM;
- $$.str = $2.str;
- $$.len = $2.len;
- }
- | T_EVAL T_INPUT {
+ : T_EVAL T_INPUT {
$$.type = EVAL_PARAM;
$$.str = $2.str;
$$.len = $2.len;
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index 5379e77586..d91ef3f3f5 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -732,6 +732,11 @@ PHPDBG_COMMAND(print) /* {{{ */
#else
phpdbg_writeln("Readline\tno");
#endif
+#ifdef HAVE_LIBEDIT
+ phpdbg_writeln("Libedit\t\tyes");
+#else
+ phpdbg_writeln("Libedit\t\tno");
+#endif
phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none");
phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no");
diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c
index 98748b202a..3ce2fade17 100644
--- a/sapi/phpdbg/phpdbg_utils.c
+++ b/sapi/phpdbg/phpdbg_utils.c
@@ -400,12 +400,16 @@ PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */
}
/* create cached prompt */
+#ifndef HAVE_LIBEDIT
+ /* TODO: libedit doesn't seems to support coloured prompt */
if ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED)) {
asprintf(
&PHPDBG_G(prompt)[1], "\033[%sm%s\033[0m ",
PHPDBG_G(colors)[PHPDBG_COLOR_PROMPT]->code,
PHPDBG_G(prompt)[0]);
- } else {
+ } else
+#endif
+ {
asprintf(
&PHPDBG_G(prompt)[1], "%s ",
PHPDBG_G(prompt)[0]);
diff --git a/travis/compile.sh b/travis/compile.sh
index 6ad3bfc396..babb945a04 100755
--- a/travis/compile.sh
+++ b/travis/compile.sh
@@ -13,6 +13,7 @@ fi
./configure --quiet \
$DEBUG \
$TS \
+--enable-fpm \
--with-pdo-mysql=mysqlnd \
--with-mysql=mysqlnd \
--with-mysqli=mysqlnd \