From 6317b8dee4e7bc34a4b874f8ec7e90b43261ce84 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 20 Jan 2026 14:55:23 +0100 Subject: [PATCH 1/2] Simplify access to names --- Zend/zend_partial.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/Zend/zend_partial.c b/Zend/zend_partial.c index 60ae63b46bfc7..32a3f19271567 100644 --- a/Zend/zend_partial.c +++ b/Zend/zend_partial.c @@ -135,23 +135,28 @@ static zend_string *zp_get_param_name(zend_function *function, uint32_t arg_offs return zend_string_copy(function->common.arg_info[arg_offset].name); } +#define ZP_PARAM_NAME(names, offset) (names)[(offset)] +#define ZP_VARIADIC_PARAM_NAME(names) (names)[argc] +#define ZP_EXTRA_NAMED_PARAMS_LEXICAL_NAME(names) (names)[argc + uses_variadic_placeholder] +#define ZP_FN_LEXICAL_NAME(names) (names)[argc + uses_variadic_placeholder + (extra_named_params != NULL)] + /* Assign a name for every variable that will be used in the generated closure, * including params and used vars. */ static void zp_assign_names(zend_string **names, uint32_t num_names, uint32_t argc, zval *argv, - zend_function *function, bool variadic_partial, + zend_function *function, bool uses_variadic_placeholder, zend_array *extra_named_params) { /* Assign names for params. We never rename those. */ for (uint32_t offset = 0; offset < MIN(argc, function->common.num_args); offset++) { if (Z_IS_PLACEHOLDER_P(&argv[offset])) { - names[offset] = zp_get_param_name(function, offset); + ZP_PARAM_NAME(names, offset) = zp_get_param_name(function, offset); } } /* Assign name for the variadic param. Never renamed. */ - if (variadic_partial && (function->common.fn_flags & ZEND_ACC_VARIADIC)) { - names[argc] = zp_get_param_name(function, function->common.num_args); + if (uses_variadic_placeholder && (function->common.fn_flags & ZEND_ACC_VARIADIC)) { + ZP_VARIADIC_PARAM_NAME(names) = zp_get_param_name(function, function->common.num_args); } /* Assign names for placeholders that bind to the variadic param: @@ -176,7 +181,7 @@ static void zp_assign_names(zend_string **names, uint32_t num_names, } zend_string_release(new_name); } - names[offset] = new_name; + ZP_PARAM_NAME(names, offset) = new_name; zend_string_release(orig_name); } @@ -194,7 +199,7 @@ static void zp_assign_names(zend_string **names, uint32_t num_names, new_name = zend_strpprintf_unchecked(0, "%S%" PRIu32, orig_name, n); n++; } - names[offset] = new_name; + ZP_PARAM_NAME(names, offset) = new_name; zend_string_release(orig_name); } @@ -207,7 +212,7 @@ static void zp_assign_names(zend_string **names, uint32_t num_names, n++; new_name = zend_strpprintf(0, "%s%" PRIu32, "extra_named_params", n); } - names[argc + variadic_partial] = new_name; + ZP_EXTRA_NAMED_PARAMS_LEXICAL_NAME(names) = new_name; } /* Assign name for $fn */ @@ -219,7 +224,7 @@ static void zp_assign_names(zend_string **names, uint32_t num_names, n++; new_name = zend_strpprintf(0, "%s%" PRIu32, "fn", n); } - names[argc + variadic_partial + (extra_named_params != NULL)] = new_name; + ZP_FN_LEXICAL_NAME(names) = new_name; } } @@ -497,7 +502,7 @@ static zend_string *zp_pfa_name(const zend_op_array *declaring_op_array, static zend_ast *zp_compile_forwarding_call( zval *this_ptr, zend_function *function, uint32_t argc, zval *argv, zend_array *extra_named_params, - zend_string **param_names, bool variadic_partial, uint32_t num_args, + zend_string **param_names, bool uses_variadic_placeholder, uint32_t num_args, zend_class_entry *called_scope, zend_type return_type, bool forward_superfluous_args, zend_ast *stmts_ast) @@ -542,19 +547,19 @@ static zend_ast *zp_compile_forwarding_call( args_ast = zend_ast_list_add(args_ast, default_value_ast); } else { args_ast = zend_ast_list_add(args_ast, zend_ast_create(ZEND_AST_VAR, - zend_ast_create_zval_from_str(zend_string_copy(param_names[offset])))); + zend_ast_create_zval_from_str(zend_string_copy(ZP_PARAM_NAME(param_names, offset))))); } } if (extra_named_params) { args_ast = zend_ast_list_add(args_ast, zend_ast_create(ZEND_AST_UNPACK, zend_ast_create(ZEND_AST_VAR, - zend_ast_create_zval_from_str(zend_string_copy(param_names[argc + variadic_partial]))))); + zend_ast_create_zval_from_str(zend_string_copy(ZP_EXTRA_NAMED_PARAMS_LEXICAL_NAME(param_names)))))); } - if (variadic_partial) { + if (uses_variadic_placeholder) { if (function->common.fn_flags & ZEND_ACC_VARIADIC) { args_ast = zend_ast_list_add(args_ast, zend_ast_create(ZEND_AST_UNPACK, zend_ast_create(ZEND_AST_VAR, - zend_ast_create_zval_from_str(zend_string_copy(param_names[argc]))))); + zend_ast_create_zval_from_str(zend_string_copy(ZP_VARIADIC_PARAM_NAME(param_names)))))); } else if (forward_superfluous_args) { /* When a '...' placeholder is used, and the underlying function is * not variadic, superfluous arguments are forwarded. @@ -587,7 +592,7 @@ static zend_ast *zp_compile_forwarding_call( call_ast = zend_ast_create(ZEND_AST_CALL, func_name_ast, args_ast); } else if (function->common.fn_flags & ZEND_ACC_CLOSURE) { zend_ast *fn_ast = zend_ast_create(ZEND_AST_VAR, - zend_ast_create_zval_from_str(zend_string_copy(param_names[argc + variadic_partial + (extra_named_params != NULL)]))); + zend_ast_create_zval_from_str(zend_string_copy(ZP_FN_LEXICAL_NAME(param_names)))); call_ast = zend_ast_create(ZEND_AST_CALL, fn_ast, args_ast); } else if (Z_TYPE_P(this_ptr) == IS_OBJECT) { zend_ast *this_ast = zend_ast_create(ZEND_AST_VAR, @@ -795,7 +800,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, * do_closure_bind(). */ if (function->common.fn_flags & ZEND_ACC_CLOSURE) { zend_ast *lexical_var_ast = zend_ast_create_zval_from_str( - zend_string_copy(param_names[argc + uses_variadic_placeholder + (extra_named_params != NULL)])); + zend_string_copy(ZP_FN_LEXICAL_NAME(param_names))); lexical_vars_ast = zend_ast_list_add(lexical_vars_ast, lexical_var_ast); } @@ -829,14 +834,14 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, params[param_offset] = zend_ast_create_ex(ZEND_AST_PARAM, param_flags, param_type_ast, zend_ast_create_zval_from_str( - zend_string_copy(param_names[offset])), + zend_string_copy(ZP_PARAM_NAME(param_names, offset))), default_value_ast, attributes_ast, NULL, NULL); } else if (!Z_ISUNDEF(argv[offset])) { // TODO: If the pre-bound parameter is a literal, it can be a // literal in the function body instead of a lexical var. zend_ast *lexical_var_ast = zend_ast_create_zval_from_str( - zend_string_copy(param_names[offset])); + zend_string_copy(ZP_PARAM_NAME(param_names, offset))); if (zp_arg_must_be_sent_by_ref(function, offset+1)) { lexical_var_ast->attr = ZEND_BIND_REF; } @@ -852,7 +857,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, if (extra_named_params) { zend_ast *lexical_var_ast = zend_ast_create_zval_from_str( - zend_string_copy(param_names[argc + uses_variadic_placeholder])); + zend_string_copy(ZP_EXTRA_NAMED_PARAMS_LEXICAL_NAME(param_names))); lexical_vars_ast = zend_ast_list_add(lexical_vars_ast, lexical_var_ast); } @@ -870,7 +875,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, params_ast = zend_ast_list_add(params_ast, zend_ast_create_ex(ZEND_AST_PARAM, param_flags, param_type_ast, zend_ast_create_zval_from_str( - zend_string_copy(param_names[argc])), + zend_string_copy(ZP_VARIADIC_PARAM_NAME(param_names))), NULL, attributes_ast, NULL, NULL)); } From 0300706ef2e8a8db08a90f4e6fdd1124498f9870 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 20 Jan 2026 12:22:29 +0100 Subject: [PATCH 2/2] $this placeholder --- Zend/Optimizer/compact_literals.c | 8 +- .../partial_application/rfc_examples.inc | 4 + .../partial_application/this_placeholder.phpt | 107 +++++ .../this_placeholder_abstract.phpt | 40 ++ .../this_placeholder_custom_get_method.phpt | 21 + ...lder_error_duplicate_this_placeholder.phpt | 15 + .../this_placeholder_error_function.phpt | 10 + .../this_placeholder_error_instance.phpt | 10 + ...s_placeholder_error_t_var_placeholder.phpt | 15 + ...laceholder_error_this_non_placeholder.phpt | 15 + .../this_placeholder_error_this_variadic.phpt | 15 + ...laceholder_error_variadic_before_this.phpt | 15 + .../this_placeholder_interface.phpt | 40 ++ .../this_placeholder_magic_call.phpt | 50 ++ .../this_placeholder_name_conflict.phpt | 28 ++ .../this_placeholder_pipe.phpt | 11 + .../this_placeholder_rfc_example.phpt | 16 + ...his_placeholder_rfc_example_interface.phpt | 66 +++ .../this_placeholder_scope.phpt | 31 ++ .../this_placeholder_static_method.phpt | 28 ++ .../this_placeholder_subclass.phpt | 34 ++ ...s_placeholder_subclass_renamed_params.phpt | 34 ++ Zend/zend_compile.c | 73 ++- Zend/zend_compile.h | 3 + Zend/zend_execute.c | 11 +- Zend/zend_execute.h | 1 + Zend/zend_language_parser.y | 2 + Zend/zend_object_handlers.c | 13 +- Zend/zend_partial.c | 80 +++- Zend/zend_partial.h | 2 +- Zend/zend_vm_def.h | 22 +- Zend/zend_vm_execute.h | 448 ++++++++++-------- 32 files changed, 1020 insertions(+), 248 deletions(-) create mode 100644 Zend/tests/partial_application/this_placeholder.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_abstract.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_custom_get_method.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_duplicate_this_placeholder.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_function.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_instance.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_t_var_placeholder.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_this_non_placeholder.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_this_variadic.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_error_variadic_before_this.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_interface.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_magic_call.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_name_conflict.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_pipe.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_rfc_example.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_rfc_example_interface.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_scope.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_static_method.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_subclass.phpt create mode 100644 Zend/tests/partial_application/this_placeholder_subclass_renamed_params.phpt diff --git a/Zend/Optimizer/compact_literals.c b/Zend/Optimizer/compact_literals.c index c534a5ecd8a45..8f1c902ac5ba7 100644 --- a/Zend/Optimizer/compact_literals.c +++ b/Zend/Optimizer/compact_literals.c @@ -577,17 +577,17 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx opline->op1.constant, opline->op2.constant, LITERAL_STATIC_METHOD, - &cache_size); + &cache_size) | (opline->result.num & ZEND_INIT_CALLABLE_THIS); } else { - opline->result.num = cache_size; + opline->result.num = cache_size | (opline->result.num & ZEND_INIT_CALLABLE_THIS); cache_size += 2 * sizeof(void *); } } else if (opline->op1_type == IS_CONST) { // op1 class if (class_slot[opline->op1.constant] >= 0) { - opline->result.num = class_slot[opline->op1.constant]; + opline->result.num = class_slot[opline->op1.constant] | (opline->result.num & ZEND_INIT_CALLABLE_THIS); } else { - opline->result.num = cache_size; + opline->result.num = cache_size | (opline->result.num & ZEND_INIT_CALLABLE_THIS); cache_size += sizeof(void *); class_slot[opline->op1.constant] = opline->result.num; } diff --git a/Zend/tests/partial_application/rfc_examples.inc b/Zend/tests/partial_application/rfc_examples.inc index 53babc07888b6..518c3a6ebf6a3 100644 --- a/Zend/tests/partial_application/rfc_examples.inc +++ b/Zend/tests/partial_application/rfc_examples.inc @@ -53,6 +53,10 @@ function check_equivalence($tests) 'string' => (string) (100 + $i), 'Point' => new Point, 'mixed' => "mixed($i)", + 'MyInterface' => new ParentClass, + 'ParentClass' => new ParentClass, + 'ChildClass' => new ChildClass, + 'array|string' => (string) (100 + $i), '' => "mixed($i)", }; } diff --git a/Zend/tests/partial_application/this_placeholder.phpt b/Zend/tests/partial_application/this_placeholder.phpt new file mode 100644 index 0000000000000..77b0a4ea4f30a --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder.phpt @@ -0,0 +1,107 @@ +--TEST-- +PFA with $this placeholder basics +--FILE-- + +--EXPECTF-- +# Basics +Closure [ static public method {closure:pfa:%s:11} ] { + @@ %s 11 - 11 + + - Parameters [3] { + Parameter #0 [ C $__this ] + Parameter #1 [ $a = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +C::f(a, b) + +# $this: can be used anywhere, and makes anything before it required +Closure [ static public method {closure:pfa:%s:17} ] { + @@ %s 17 - 17 + + - Parameters [3] { + Parameter #0 [ $a ] + Parameter #1 [ C $__this ] + Parameter #2 [ $b = NULL ] + } +} + +C::f(a, b) + +# $this: can be used anywhere, and makes anything before it required (2) +Closure [ static public method {closure:pfa:%s:23} ] { + @@ %s 23 - 23 + + - Parameters [3] { + Parameter #0 [ $a ] + Parameter #1 [ $b ] + Parameter #2 [ C $__this ] + } +} + +C::f(a, b) + +# $this: can be used anywhere (variadic placeholder) +Closure [ static public method {closure:pfa:%s:29} ] { + @@ %s 29 - 29 + + - Parameters [3] { + Parameter #0 [ C $__this ] + Parameter #1 [ $a = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +C::f(a, b) + +# $this: can be used anywhere (names params) +Closure [ static public method {closure:pfa:%s:35} ] { + @@ %s 35 - 35 + + - Parameters [3] { + Parameter #0 [ $b ] + Parameter #1 [ C $__this ] + Parameter #2 [ $a = NULL ] + } +} + +C::f(a, b) diff --git a/Zend/tests/partial_application/this_placeholder_abstract.phpt b/Zend/tests/partial_application/this_placeholder_abstract.phpt new file mode 100644 index 0000000000000..bbc9e54cecea2 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_abstract.phpt @@ -0,0 +1,40 @@ +--TEST-- +PFA with $this placeholder - abstract +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:19} ] { + @@ %s 19 - 19 + + - Parameters [2] { + Parameter #0 [ BaseClass $__this ] + Parameter #1 [ string $foo ] + } + - Return [ string|int|bool ] +} + +string(22) "ParentClass::method(a)" +string(21) "ChildClass::method(a)" diff --git a/Zend/tests/partial_application/this_placeholder_custom_get_method.phpt b/Zend/tests/partial_application/this_placeholder_custom_get_method.phpt new file mode 100644 index 0000000000000..49b9572ae126c --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_custom_get_method.phpt @@ -0,0 +1,21 @@ +--TEST-- +PFA with $this placeholder - custom get_method() +--FILE-- +handlers->get_method() + $f = Closure::__invoke($this: ?); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} + +// SplFileObject implements a custom get_method() handler, but methods can be +// resolved by zend_std_get_static_method() +$f = SplFileObject::ftell($this: ?); +var_dump($f(new SplFileObject(__FILE__))); + +?> +--EXPECT-- +Error: Method Closure::__invoke() does not exist or does not support partial application +int(0) diff --git a/Zend/tests/partial_application/this_placeholder_error_duplicate_this_placeholder.phpt b/Zend/tests/partial_application/this_placeholder_error_duplicate_this_placeholder.phpt new file mode 100644 index 0000000000000..a612154a92b51 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_duplicate_this_placeholder.phpt @@ -0,0 +1,15 @@ +--TEST-- +PFA with $this placeholder: $this placeholder may only appear once +--FILE-- + +--EXPECTF-- +Fatal error: $this placeholder may only appear once in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_error_function.phpt b/Zend/tests/partial_application/this_placeholder_error_function.phpt new file mode 100644 index 0000000000000..88d30fe364409 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_function.phpt @@ -0,0 +1,10 @@ +--TEST-- +PFA with $this placeholder: $this placeholder on free-standing function +--FILE-- + +--EXPECTF-- +Fatal error: Invalid use of $this placeholder in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_error_instance.phpt b/Zend/tests/partial_application/this_placeholder_error_instance.phpt new file mode 100644 index 0000000000000..190634df88f2c --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_instance.phpt @@ -0,0 +1,10 @@ +--TEST-- +PFA with $this placeholder: $this placeholder on instance method +--FILE-- +bar($this: ?); + +?> +--EXPECTF-- +Fatal error: Invalid use of $this placeholder in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_error_t_var_placeholder.phpt b/Zend/tests/partial_application/this_placeholder_error_t_var_placeholder.phpt new file mode 100644 index 0000000000000..410f80d76c412 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_t_var_placeholder.phpt @@ -0,0 +1,15 @@ +--TEST-- +PFA with $this placeholder: T_VARIABLE placeholder can only be $this +--FILE-- + +--EXPECTF-- +Fatal error: Invalid parameter name: $test in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_error_this_non_placeholder.phpt b/Zend/tests/partial_application/this_placeholder_error_this_non_placeholder.phpt new file mode 100644 index 0000000000000..bcd4644db892e --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_this_non_placeholder.phpt @@ -0,0 +1,15 @@ +--TEST-- +PFA with $this placeholder: $this name allowed only for placeholders +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected integer "1", expecting "?" in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_error_this_variadic.phpt b/Zend/tests/partial_application/this_placeholder_error_this_variadic.phpt new file mode 100644 index 0000000000000..7bdb602db339d --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_this_variadic.phpt @@ -0,0 +1,15 @@ +--TEST-- +PFA with $this placeholder: $this placeholder can not be variadic +--FILE-- + +--EXPECTF-- +Parse error: syntax error, unexpected token "...", expecting "?" in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_error_variadic_before_this.phpt b/Zend/tests/partial_application/this_placeholder_error_variadic_before_this.phpt new file mode 100644 index 0000000000000..4c257cfa4928a --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_error_variadic_before_this.phpt @@ -0,0 +1,15 @@ +--TEST-- +PFA with $this placeholder: $this placeholder not allowed after variadic placeholder +--FILE-- + +--EXPECTF-- +Fatal error: Variadic placeholder must be last in %s on line %d diff --git a/Zend/tests/partial_application/this_placeholder_interface.phpt b/Zend/tests/partial_application/this_placeholder_interface.phpt new file mode 100644 index 0000000000000..f72b4c6ff9e00 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_interface.phpt @@ -0,0 +1,40 @@ +--TEST-- +PFA with $this placeholder - interface +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:19} ] { + @@ %s 19 - 19 + + - Parameters [2] { + Parameter #0 [ MyInterface $__this ] + Parameter #1 [ string $foo ] + } + - Return [ string|int|bool ] +} + +string(22) "ParentClass::method(a)" +string(21) "ChildClass::method(a)" diff --git a/Zend/tests/partial_application/this_placeholder_magic_call.phpt b/Zend/tests/partial_application/this_placeholder_magic_call.phpt new file mode 100644 index 0000000000000..e87f9eddc2c7f --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_magic_call.phpt @@ -0,0 +1,50 @@ +--TEST-- +PFA with $this placeholder - __call() +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:18} ] { + @@ %s 18 - 18 + + - Parameters [2] { + Parameter #0 [ C $__this ] + Parameter #1 [ mixed ...$arguments ] + } +} + +C::__call(f, a) +Closure [ static public method {closure:pfa:%s:22} ] { + @@ %s 22 - 22 + + - Parameters [2] { + Parameter #0 [ D $__this ] + Parameter #1 [ mixed ...$arguments ] + } +} + +D::__call(f, a) diff --git a/Zend/tests/partial_application/this_placeholder_name_conflict.phpt b/Zend/tests/partial_application/this_placeholder_name_conflict.phpt new file mode 100644 index 0000000000000..10edf0181d773 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_name_conflict.phpt @@ -0,0 +1,28 @@ +--TEST-- +PFA with $this placeholder - name conflict +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:9} ] { + @@ %s 9 - 9 + + - Parameters [3] { + Parameter #0 [ C $__this2 ] + Parameter #1 [ $__this = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +C::f(a, b) diff --git a/Zend/tests/partial_application/this_placeholder_pipe.phpt b/Zend/tests/partial_application/this_placeholder_pipe.phpt new file mode 100644 index 0000000000000..8f694f099700d --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_pipe.phpt @@ -0,0 +1,11 @@ +--TEST-- +PFA with $this placeholder: pipe +--FILE-- + DateTimeImmutable::format($this: ?, "c"); + +?> +--EXPECT-- +2026-01-19T19:44:42+00:00 diff --git a/Zend/tests/partial_application/this_placeholder_rfc_example.phpt b/Zend/tests/partial_application/this_placeholder_rfc_example.phpt new file mode 100644 index 0000000000000..284c48611c574 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_rfc_example.phpt @@ -0,0 +1,16 @@ +--TEST-- +PFA with $this placeholder: RFC example +--FILE-- + +--EXPECT-- +2026-01-19T19:44:42+00:00 diff --git a/Zend/tests/partial_application/this_placeholder_rfc_example_interface.phpt b/Zend/tests/partial_application/this_placeholder_rfc_example_interface.phpt new file mode 100644 index 0000000000000..66d1fd39578e4 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_rfc_example_interface.phpt @@ -0,0 +1,66 @@ +--TEST-- +PFA with $this placeholder: RFC example: interface +--FILE-- + [ + $i = MyInterface::method($this: ?, ...), + static fn (MyInterface $__this, string $foo): int|string|bool + => $__this->method($foo), + ], + 'ParentClass' => [ + $p = ParentClass::method($this: ?, ...), + static fn (ParentClass $__this, string|array $foo): string + => $__this->method($foo), + ], + 'ChildClass' => [ + $c = ChildClass::method($this: ?, ...), + static fn (ChildClass $__this, string|array $bar): string + => $__this->method($bar), + ], +]; + +check_equivalence($tests); + +try { + // Throws TypeError, since an array is not a valid parameter on the interface, + // despite being valid on ChildClass::method(). + $i(new ChildClass(), []); +} catch (TypeError $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} + +try { + // Throws an Error about an unknown parameter 'bar', because the parameter + // is called 'foo' on the ParentClass::method(). + $p(new ChildClass(), bar: []); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} + +?> +--EXPECTF-- +# MyInterface: Ok +# ParentClass: Ok +# ChildClass: Ok +TypeError: MyInterface::{closure:pfa:%s:23}(): Argument #2 ($foo) must be of type string, array given, called in %s on line %d +Error: Unknown named parameter $bar diff --git a/Zend/tests/partial_application/this_placeholder_scope.phpt b/Zend/tests/partial_application/this_placeholder_scope.phpt new file mode 100644 index 0000000000000..40cd7f9496732 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_scope.phpt @@ -0,0 +1,31 @@ +--TEST-- +PFA with $this placeholder - scope +--FILE-- +get_f(); +echo new ReflectionFunction($f), "\n"; +$f(new C(), 'a', 'b'); + +?> +--EXPECTF-- +Closure [ static public method {closure:pfa:C::get_f():5} ] { + @@ %s 5 - 5 + + - Parameters [3] { + Parameter #0 [ C $__this ] + Parameter #1 [ $a = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +C::f(a, b) diff --git a/Zend/tests/partial_application/this_placeholder_static_method.phpt b/Zend/tests/partial_application/this_placeholder_static_method.phpt new file mode 100644 index 0000000000000..fb4a91f67d576 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_static_method.phpt @@ -0,0 +1,28 @@ +--TEST-- +PFA with $this placeholder - static method +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:9} ] { + @@ %s 9 - 9 + + - Parameters [3] { + Parameter #0 [ C $__this ] + Parameter #1 [ $a = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +C::f(a, b) diff --git a/Zend/tests/partial_application/this_placeholder_subclass.phpt b/Zend/tests/partial_application/this_placeholder_subclass.phpt new file mode 100644 index 0000000000000..f7172271c4313 --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_subclass.phpt @@ -0,0 +1,34 @@ +--TEST-- +PFA with $this placeholder - sub class +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:15} ] { + @@ %s 15 - 15 + + - Parameters [3] { + Parameter #0 [ C $__this ] + Parameter #1 [ $a = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +SubC(SubC)::f(a, b) diff --git a/Zend/tests/partial_application/this_placeholder_subclass_renamed_params.phpt b/Zend/tests/partial_application/this_placeholder_subclass_renamed_params.phpt new file mode 100644 index 0000000000000..ae2b9fc0ce92e --- /dev/null +++ b/Zend/tests/partial_application/this_placeholder_subclass_renamed_params.phpt @@ -0,0 +1,34 @@ +--TEST-- +PFA with $this placeholder - sub class with renamed params +--FILE-- + +--EXPECTF-- +Closure [ static public method {closure:pfa:%s:15} ] { + @@ %s 15 - 15 + + - Parameters [3] { + Parameter #0 [ C $__this ] + Parameter #1 [ $a = NULL ] + Parameter #2 [ $b = NULL ] + } +} + +SubC(SubC)::f(a, b) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index dd3ba8bbeaba1..695f76a0ec253 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3705,12 +3705,13 @@ static uint32_t zend_compile_args_ex( zend_ast *ast, const zend_function *fbc, bool *may_have_extra_named_args, bool is_call_partial, bool *uses_variadic_placeholder_p, - zval *named_positions) /* {{{ */ + bool *uses_this_placeholder_p, zval *named_positions) /* {{{ */ { const zend_ast_list *args = zend_ast_get_list(ast); uint32_t i; bool uses_arg_unpack = false; bool uses_variadic_placeholder = false; + bool uses_this_placeholder = false; uint32_t arg_count = 0; /* number of arguments not including unpacks */ /* Whether named arguments are used syntactically, to enforce language level limitations. @@ -3724,7 +3725,8 @@ static uint32_t zend_compile_args_ex( for (i = 0; i < args->children; ++i) { zend_ast *arg = args->child[i]; zend_string *arg_name = NULL; - uint32_t arg_num = i + 1; + uint32_t arg_num = i + 1 - uses_this_placeholder; + bool is_this = false; znode arg_node; zend_op *opline; @@ -3759,11 +3761,24 @@ static uint32_t zend_compile_args_ex( } if (arg->kind == ZEND_AST_NAMED_ARG) { - uses_named_args = true; - arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0])); + if (arg->child[0]->kind == ZEND_AST_VAR) { + zval *name = zend_ast_get_zval(arg->child[0]->child[0]); + is_this = zend_string_equals_literal(Z_STR_P(name), "this"); + if (!is_this) { + zend_error_noreturn(E_COMPILE_ERROR, + "Invalid parameter name: $%s", Z_STRVAL_P(name)); + } + arg_name = zend_new_interned_string(ZSTR_INIT_LITERAL("$this", false)); + } else { + arg_name = zval_make_interned_string(zend_ast_get_zval(arg->child[0])); + uses_named_args = true; + } + arg = arg->child[1]; - if (fbc && !uses_arg_unpack) { + if (is_this) { + arg_num = (uint32_t) -1; + } else if (fbc && !uses_arg_unpack) { arg_num = zend_get_arg_num(fbc, arg_name); if (arg_num == arg_count + 1 && !may_have_undef) { /* Using named arguments, but passing in order. */ @@ -3815,6 +3830,24 @@ static uint32_t zend_compile_args_ex( } } + if (is_this) { + if (uses_this_placeholder) { + zend_error_noreturn(E_COMPILE_ERROR, + "$this placeholder may only appear once"); + } + uses_this_placeholder = true; + if (Z_ISUNDEF_P(named_positions)) { + array_init(named_positions); + } + zval tmp; + ZVAL_LONG(&tmp, i); + zend_hash_add(Z_ARRVAL_P(named_positions), arg_name, &tmp); + zend_string_release(arg_name); + /* Do not emit a ZEND_SEND_* op: We represent the this placeholder + * with a flag on the ZEND_CONVERT_CALLABLE_PARTIAL op instead. */ + continue; + } + if (arg->kind == ZEND_AST_PLACEHOLDER_ARG) { if (uses_arg_unpack) { zend_error_noreturn(E_COMPILE_ERROR, @@ -3834,7 +3867,7 @@ static uint32_t zend_compile_args_ex( array_init(named_positions); } zval tmp; - ZVAL_LONG(&tmp, zend_hash_num_elements(Z_ARRVAL_P(named_positions))); + ZVAL_LONG(&tmp, zend_hash_num_elements(Z_ARRVAL_P(named_positions)) - uses_this_placeholder); zend_hash_add(Z_ARRVAL_P(named_positions), arg_name, &tmp); } @@ -3968,6 +4001,7 @@ static uint32_t zend_compile_args_ex( } } else { *uses_variadic_placeholder_p = uses_variadic_placeholder; + *uses_this_placeholder_p = uses_this_placeholder; } return arg_count; @@ -3977,7 +4011,8 @@ static uint32_t zend_compile_args_ex( static uint32_t zend_compile_args(zend_ast *ast, const zend_function *fbc, bool *may_have_extra_named_args) /* {{{ */ { - return zend_compile_args_ex(ast, fbc, may_have_extra_named_args, false, NULL, NULL); + return zend_compile_args_ex(ast, fbc, may_have_extra_named_args, false, + NULL, NULL, NULL); } ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *fbc, bool result_used) /* {{{ */ @@ -4015,7 +4050,8 @@ ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *f static void zend_compile_call_partial(znode *result, uint32_t arg_count, bool may_have_extra_named_args, bool uses_variadic_placeholder, - zval *named_positions, uint32_t opnum_init, const zend_function *fbc) { + bool uses_this_placeholder, zval *named_positions, uint32_t opnum_init, + const zend_function *fbc) { zend_op *init_opline = &CG(active_op_array)->opcodes[opnum_init]; @@ -4027,6 +4063,14 @@ static void zend_compile_call_partial(znode *result, uint32_t arg_count, init_opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc); } + if (uses_this_placeholder) { + if (init_opline->opcode != ZEND_INIT_STATIC_METHOD_CALL) { + zend_error_noreturn(E_COMPILE_ERROR, + "Invalid use of $this placeholder"); + } + init_opline->result.num |= ZEND_INIT_CALLABLE_THIS; + } + zend_op *opline = zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT_PARTIAL, NULL, NULL); @@ -4038,6 +4082,9 @@ static void zend_compile_call_partial(znode *result, uint32_t arg_count, if (uses_variadic_placeholder) { opline->extended_value |= ZEND_FCALL_USES_VARIADIC_PLACEHOLDER; } + if (uses_this_placeholder) { + opline->extended_value |= ZEND_FCALL_USES_THIS_PLACEHOLDER; + } if (!Z_ISUNDEF_P(named_positions)) { opline->op2.constant = zend_add_literal(named_positions); @@ -4085,17 +4132,18 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const ze bool may_have_extra_named_args; bool uses_variadic_placeholder; + bool uses_this_placeholder; zval named_positions; ZVAL_UNDEF(&named_positions); uint32_t arg_count = zend_compile_args_ex(args_ast, fbc, &may_have_extra_named_args, true, &uses_variadic_placeholder, - &named_positions); + &uses_this_placeholder, &named_positions); zend_compile_call_partial(result, arg_count, may_have_extra_named_args, uses_variadic_placeholder, - &named_positions, opnum_init, fbc); + uses_this_placeholder, &named_positions, opnum_init, fbc); return true; } @@ -5640,6 +5688,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type opline = get_next_op(); opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; + opline->result.num = 0; zend_set_class_name_op1(opline, &class_node); @@ -6816,6 +6865,10 @@ static zend_ast *zend_partial_apply(zend_ast *callable_ast, zend_ast *pipe_arg) for (uint32_t i = 0; i < arg_list->children; i++) { zend_ast *arg = arg_list->child[i]; if (arg->kind == ZEND_AST_NAMED_ARG) { + if (arg->child[0]->kind == ZEND_AST_VAR) { + /* $this placeholder */ + return NULL; + } uses_named_args = true; arg = arg->child[1]; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index b95cdf3eab6fa..e6f7abd3d4b71 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1120,6 +1120,8 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); #define ZEND_FREE_SWITCH (1<<1) #define ZEND_FREE_VOID_CAST (1<<2) +#define ZEND_INIT_CALLABLE_THIS (1<<0) + #define ZEND_SEND_BY_VAL 0u #define ZEND_SEND_BY_REF 1u #define ZEND_SEND_PREFER_REF 2u @@ -1128,6 +1130,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); #define ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS (1<<0) #define ZEND_FCALL_USES_VARIADIC_PLACEHOLDER (1<<1) +#define ZEND_FCALL_USES_THIS_PLACEHOLDER (1<<2) /* The send mode, the is_variadic, the is_promoted, and the is_tentative flags are stored as part of zend_type */ #define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 765095fca36f5..283953314ee96 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2556,9 +2556,18 @@ ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, return retval; } +ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method_ex(const zend_class_entry *ce, const zend_string *method, bool callable_this) +{ + if (callable_this) { + zend_throw_error(NULL, "Method %s::%s() does not exist or does not support partial application", ZSTR_VAL(ce->name), ZSTR_VAL(method)); + } else { + zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(method)); + } +} + ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method) { - zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(method)); + zend_undefined_method_ex(ce, method, false); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_method_call(zval *object, zval *function_name) diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 104b9c49abe20..2711d2e95ffc0 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -514,6 +514,7 @@ ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable *zend_unfinished_execution_gc(zend_ ZEND_API HashTable *zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield); ZEND_API zval* ZEND_FASTCALL zend_fetch_static_property(zend_execute_data *ex, int fetch_type); ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method); +ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method_ex(const zend_class_entry *ce, const zend_string *method, bool callable_this); ZEND_API void ZEND_FASTCALL zend_non_static_method_call(const zend_function *fbc); ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index e2686c7e1c5a8..10689ba0956d2 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -945,6 +945,8 @@ argument_no_expr: { $$ = zend_ast_create(ZEND_AST_PLACEHOLDER_ARG); } | identifier ':' '?' { $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, zend_ast_create(ZEND_AST_PLACEHOLDER_ARG)); } + | T_VARIABLE ':' '?' + { $$ = zend_ast_create(ZEND_AST_NAMED_ARG, zend_ast_create(ZEND_AST_VAR, $1), zend_ast_create(ZEND_AST_PLACEHOLDER_ARG)); } | T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } ; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 07ff4de9244a4..f5aefa1a88145 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1929,6 +1929,11 @@ static zend_always_inline zend_function *get_static_method_fallback( ZEND_ASSERT(object->ce->__call); return zend_get_call_trampoline_func(object->ce->__call, function_name); + } else if (ce->__call + /* TODO: figure a better way to achieve this */ + && (EG(current_execute_data)->opline->opcode == ZEND_INIT_STATIC_METHOD_CALL + && EG(current_execute_data)->opline->result.num & ZEND_INIT_CALLABLE_THIS)) { + return zend_get_call_trampoline_func(ce->__call, function_name); } else if (ce->__callstatic) { return zend_get_call_trampoline_func(ce->__callstatic, function_name); } else { @@ -1970,8 +1975,12 @@ ZEND_API zend_function *zend_std_get_static_method(const zend_class_entry *ce, z if (EXPECTED(fbc)) { if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { - zend_abstract_method_call(fbc); - goto fail; + /* TODO: figure a better way to achieve this */ + if (EG(current_execute_data)->opline->opcode != ZEND_INIT_STATIC_METHOD_CALL + || !(EG(current_execute_data)->opline->result.num & ZEND_INIT_CALLABLE_THIS)) { + zend_abstract_method_call(fbc); + goto fail; + } } else if (UNEXPECTED(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT)) { zend_error(E_DEPRECATED, "Calling static trait method %s::%s is deprecated, " diff --git a/Zend/zend_partial.c b/Zend/zend_partial.c index 32a3f19271567..9542bf17d95d8 100644 --- a/Zend/zend_partial.c +++ b/Zend/zend_partial.c @@ -138,14 +138,15 @@ static zend_string *zp_get_param_name(zend_function *function, uint32_t arg_offs #define ZP_PARAM_NAME(names, offset) (names)[(offset)] #define ZP_VARIADIC_PARAM_NAME(names) (names)[argc] #define ZP_EXTRA_NAMED_PARAMS_LEXICAL_NAME(names) (names)[argc + uses_variadic_placeholder] -#define ZP_FN_LEXICAL_NAME(names) (names)[argc + uses_variadic_placeholder + (extra_named_params != NULL)] +#define ZP_THIS_PARAM_NAME(names) (names)[argc + uses_variadic_placeholder + (extra_named_params != NULL)] +#define ZP_FN_LEXICAL_NAME(names) (names)[argc + uses_variadic_placeholder + (extra_named_params != NULL) + uses_this_placeholder] /* Assign a name for every variable that will be used in the generated closure, * including params and used vars. */ static void zp_assign_names(zend_string **names, uint32_t num_names, uint32_t argc, zval *argv, - zend_function *function, bool uses_variadic_placeholder, - zend_array *extra_named_params) + zend_function *function, bool uses_this_placeholder, + bool uses_variadic_placeholder, zend_array *extra_named_params) { /* Assign names for params. We never rename those. */ for (uint32_t offset = 0; offset < MIN(argc, function->common.num_args); offset++) { @@ -185,6 +186,18 @@ static void zp_assign_names(zend_string **names, uint32_t num_names, zend_string_release(orig_name); } + /* Assign name for the $this placeholder. */ + if (uses_this_placeholder) { + uint32_t n = 1; + zend_string *new_name = ZSTR_INIT_LITERAL("__this", false); + while (zp_name_exists(names, num_names, new_name)) { + zend_string_release(new_name); + n++; + new_name = zend_strpprintf_unchecked(0, "__this%" PRIu32, n); + } + ZP_THIS_PARAM_NAME(names) = new_name; + } + /* Assign names for pre-bound params (lexical vars). * There may be clashes, we ensure to generate unique names. */ for (uint32_t offset = 0; offset < argc; offset++) { @@ -502,7 +515,8 @@ static zend_string *zp_pfa_name(const zend_op_array *declaring_op_array, static zend_ast *zp_compile_forwarding_call( zval *this_ptr, zend_function *function, uint32_t argc, zval *argv, zend_array *extra_named_params, - zend_string **param_names, bool uses_variadic_placeholder, uint32_t num_args, + zend_string **param_names, bool uses_this_placeholder, + bool uses_variadic_placeholder, uint32_t num_args, zend_class_entry *called_scope, zend_type return_type, bool forward_superfluous_args, zend_ast *stmts_ast) @@ -594,9 +608,12 @@ static zend_ast *zp_compile_forwarding_call( zend_ast *fn_ast = zend_ast_create(ZEND_AST_VAR, zend_ast_create_zval_from_str(zend_string_copy(ZP_FN_LEXICAL_NAME(param_names)))); call_ast = zend_ast_create(ZEND_AST_CALL, fn_ast, args_ast); - } else if (Z_TYPE_P(this_ptr) == IS_OBJECT) { + } else if (Z_TYPE_P(this_ptr) == IS_OBJECT || uses_this_placeholder) { + zend_string *this_name = uses_this_placeholder + ? ZP_THIS_PARAM_NAME(param_names) + : ZSTR_KNOWN(ZEND_STR_THIS); zend_ast *this_ast = zend_ast_create(ZEND_AST_VAR, - zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_THIS))); + zend_ast_create_zval_from_str(zend_string_copy(this_name))); zend_ast *method_name_ast = zend_ast_create_zval_from_str( zend_string_copy(function->common.function_name)); call_ast = zend_ast_create(ZEND_AST_METHOD_CALL, this_ast, @@ -674,9 +691,11 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, const zend_array *named_positions, const zend_op_array *declaring_op_array, const zend_op *declaring_opline, void **cache_slot, - bool uses_variadic_placeholder) { + uint32_t fcall_flags) { zend_op_array *op_array = NULL; + bool uses_variadic_placeholder = fcall_flags & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER; + bool uses_this_placeholder = fcall_flags & ZEND_FCALL_USES_THIS_PLACEHOLDER; if (UNEXPECTED(zp_is_non_dynamic_call_func(function))) { zend_throw_error(NULL, "Cannot call %.*s() dynamically", @@ -713,6 +732,10 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, memcpy(tmp, argv, argc * sizeof(zval)); argv = tmp; + uint32_t this_pos = uses_this_placeholder + ? Z_LVAL_P(zend_hash_str_find(named_positions, "$this", strlen("$this"))) + : UINT32_MAX; + /* Compute param positions and number of required args, add implicit * placeholders. * @@ -722,7 +745,7 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, * - Then implicit placeholders added by '...' */ uint32_t num_params = 0; - uint32_t num_required = 0; + uint32_t num_required = this_pos == UINT32_MAX ? 0 : this_pos + 1; uint32_t *arg_to_param_offset_map = zend_arena_alloc(&CG(ast_arena), sizeof(uint32_t*) * new_argc); { uint32_t num_positional = 0; @@ -746,6 +769,9 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, /* Placeholder is sent as positional */ param_offset = num_positional++; } + if (param_offset >= this_pos) { + param_offset++; + } arg_to_param_offset_map[arg_offset] = param_offset; @@ -753,6 +779,10 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, arg_offset, param_offset, num_required); } + if (uses_this_placeholder) { + num_params++; + } + /* Handle implicit placeholders added by '...' */ if (uses_variadic_placeholder) { for (uint32_t arg_offset = 0; arg_offset < new_argc; arg_offset++) { @@ -779,12 +809,13 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, /* Assign variable names */ - uint32_t num_names = argc + uses_variadic_placeholder + (extra_named_params != NULL) + uint32_t num_names = argc + uses_this_placeholder + uses_variadic_placeholder + (extra_named_params != NULL) + ((function->common.fn_flags & ZEND_ACC_CLOSURE) != 0); zend_string **param_names = zend_arena_calloc(&CG(ast_arena), num_names, sizeof(zend_string*)); zp_assign_names(param_names, num_names, argc, argv, function, - uses_variadic_placeholder, extra_named_params); + uses_this_placeholder, uses_variadic_placeholder, + extra_named_params); /* Generate AST */ @@ -850,6 +881,14 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, } } + if (uses_this_placeholder) { + params[this_pos] = zend_ast_create_ex(ZEND_AST_PARAM, 0, + zp_type_name_to_ast(zend_string_copy(called_scope->name)), + zend_ast_create_zval_from_str( + zend_string_copy(ZP_THIS_PARAM_NAME(param_names))), + NULL, NULL, NULL, NULL); + } + for (uint32_t i = 0; i < num_params; i++) { params_ast = zend_ast_list_add(params_ast, params[i]); } @@ -906,8 +945,9 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, no_forwarding_ast = zp_compile_forwarding_call(this_ptr, function, argc, argv, extra_named_params, - param_names, uses_variadic_placeholder, num_params, - called_scope, return_type, false, no_forwarding_ast); + param_names, uses_this_placeholder, uses_variadic_placeholder, + num_params, called_scope, return_type, false, + no_forwarding_ast); if (!no_forwarding_ast) { ZEND_ASSERT(EG(exception)); @@ -916,8 +956,8 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, forwarding_ast = zp_compile_forwarding_call(this_ptr, function, argc, argv, extra_named_params, - param_names, uses_variadic_placeholder, num_params, - called_scope, return_type, true, forwarding_ast); + param_names, uses_this_placeholder, uses_variadic_placeholder, + num_params, called_scope, return_type, true, forwarding_ast); if (!forwarding_ast) { ZEND_ASSERT(EG(exception)); @@ -943,8 +983,8 @@ static zend_op_array *zp_compile(zval *this_ptr, zend_function *function, } else { stmts_ast = zp_compile_forwarding_call(this_ptr, function, argc, argv, extra_named_params, - param_names, uses_variadic_placeholder, num_params, - called_scope, return_type, false, stmts_ast); + param_names, uses_this_placeholder, uses_variadic_placeholder, + num_params, called_scope, return_type, false, stmts_ast); if (!stmts_ast) { ZEND_ASSERT(EG(exception)); @@ -1019,7 +1059,7 @@ static const zend_op_array *zp_get_op_array(zval *this_ptr, zend_function *funct const zend_array *named_positions, const zend_op_array *declaring_op_array, const zend_op *declaring_opline, void **cache_slot, - bool uses_variadic_placeholder) { + uint32_t fcall_flags) { if (EXPECTED(function->type == ZEND_INTERNAL_FUNCTION ? cache_slot[0] == function @@ -1033,7 +1073,7 @@ static const zend_op_array *zp_get_op_array(zval *this_ptr, zend_function *funct if (UNEXPECTED(!op_array)) { op_array = zp_compile(this_ptr, function, argc, argv, extra_named_params, named_positions, declaring_op_array, declaring_opline, - cache_slot, uses_variadic_placeholder); + cache_slot, fcall_flags); } if (EXPECTED(op_array) && !(function->common.fn_flags & ZEND_ACC_NEVER_CACHE)) { @@ -1099,12 +1139,12 @@ void zend_partial_create(zval *result, zval *this_ptr, zend_function *function, const zend_array *named_positions, const zend_op_array *declaring_op_array, const zend_op *declaring_opline, void **cache_slot, - bool uses_variadic_placeholder) { + uint32_t fcall_flags) { const zend_op_array *op_array = zp_get_op_array(this_ptr, function, argc, argv, extra_named_params, named_positions, declaring_op_array, declaring_opline, - cache_slot, uses_variadic_placeholder); + cache_slot, fcall_flags); if (UNEXPECTED(!op_array)) { ZEND_ASSERT(EG(exception)); diff --git a/Zend/zend_partial.h b/Zend/zend_partial.h index 7999dc99019c1..a605ca8df5061 100644 --- a/Zend/zend_partial.h +++ b/Zend/zend_partial.h @@ -25,7 +25,7 @@ void zend_partial_create(zval *result, zval *this_ptr, zend_function *function, const zend_array *named_positions, const zend_op_array *declaring_op_array, const zend_op *declaring_opline, void **cache_slot, - bool uses_variadic_placeholder); + uint32_t fcall_flags); void zend_partial_op_array_dtor(zval *pDest); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d23645c819346..4ef28b0dad5a1 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3746,7 +3746,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, if (OP1_TYPE == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -3754,7 +3754,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, HANDLE_EXCEPTION(); } if (OP2_TYPE != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (OP1_TYPE == IS_UNUSED) { @@ -3769,12 +3769,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (OP1_TYPE != IS_CONST && OP2_TYPE == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (OP2_TYPE != IS_UNUSED) { function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE != IS_CONST) { @@ -3805,7 +3805,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } FREE_OP2(); HANDLE_EXCEPTION(); @@ -3813,7 +3813,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, if (OP2_TYPE == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -3837,7 +3837,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -9032,7 +9034,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) execute_data = EG(current_execute_data) = EX(prev_execute_data); call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; - ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_top)) - (char*)call)); ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -9823,7 +9825,7 @@ ZEND_VM_HANDLER(212, ZEND_CALLABLE_CONVERT_PARTIAL, CACHE_SLOT, CONST|UNUSED, NU call->extra_named_params : NULL, OP2_TYPE == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL, &EX(func)->op_array, opline, cache_slot, - opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER); + opline->extended_value); if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { zend_array_release(call->extra_named_params); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 64e8a807e61c8..29d78d4f43a81 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3590,7 +3590,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALL_TRAMPOLI execute_data = EG(current_execute_data) = EX(prev_execute_data); call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; - ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_top)) - (char*)call)); ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -3738,7 +3738,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALL_TRAMPOLI execute_data = EG(current_execute_data) = EX(prev_execute_data); call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; - ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_top)) - (char*)call)); ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -4263,7 +4263,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONV call->extra_named_params : NULL, IS_CONST == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL, &EX(func)->op_array, opline, cache_slot, - opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER); + opline->extended_value); if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { zend_array_release(call->extra_named_params); @@ -4446,7 +4446,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONV call->extra_named_params : NULL, IS_UNUSED == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL, &EX(func)->op_array, opline, cache_slot, - opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER); + opline->extended_value); if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { zend_array_release(call->extra_named_params); @@ -7572,7 +7572,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -7581,7 +7581,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -7597,12 +7597,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && IS_CONST == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { @@ -7634,7 +7634,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -7643,7 +7643,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -7668,7 +7668,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -10282,7 +10284,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -10290,7 +10292,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -10305,12 +10307,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -10341,7 +10343,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); @@ -10349,7 +10351,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -10373,7 +10375,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -11063,7 +11067,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -11072,7 +11076,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -11088,12 +11092,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { function_name = NULL; if (IS_UNUSED != IS_CONST) { @@ -11125,7 +11129,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -11134,7 +11138,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -11159,7 +11163,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -12859,7 +12865,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -12868,7 +12874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -12884,12 +12890,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && IS_CV == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { @@ -12921,7 +12927,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -12930,7 +12936,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -12955,7 +12961,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -26120,7 +26128,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -26129,7 +26137,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -26145,12 +26153,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST && IS_CONST == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { @@ -26182,7 +26190,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -26191,7 +26199,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -26216,7 +26224,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -29127,7 +29137,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -29135,7 +29145,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -29150,12 +29160,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -29186,7 +29196,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); @@ -29194,7 +29204,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -29218,7 +29228,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -30679,7 +30691,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -30688,7 +30700,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -30704,12 +30716,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { function_name = NULL; if (IS_UNUSED != IS_CONST) { @@ -30741,7 +30753,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -30750,7 +30762,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -30775,7 +30787,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -33678,7 +33692,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -33687,7 +33701,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -33703,12 +33717,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_VAR == IS_CONST && IS_CV == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { @@ -33740,7 +33754,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -33749,7 +33763,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -33774,7 +33788,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -36032,7 +36048,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -36041,7 +36057,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -36057,12 +36073,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && IS_CONST == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { @@ -36094,7 +36110,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -36103,7 +36119,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CONST == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -36128,7 +36144,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -38284,7 +38302,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -38292,7 +38310,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -38307,12 +38325,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -38343,7 +38361,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); @@ -38351,7 +38369,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -38375,7 +38393,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -38701,7 +38721,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -38710,7 +38730,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -38726,12 +38746,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { function_name = NULL; if (IS_UNUSED != IS_CONST) { @@ -38763,7 +38783,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -38772,7 +38792,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -38797,7 +38817,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -41030,7 +41052,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -41039,7 +41061,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -41055,12 +41077,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_UNUSED == IS_CONST && IS_CV == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { @@ -41092,7 +41114,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -41101,7 +41123,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -41126,7 +41148,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_M } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -59401,7 +59425,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALL_TRAMPOLINE_SP execute_data = EG(current_execute_data) = EX(prev_execute_data); call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; - ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_top)) - (char*)call)); ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -59549,7 +59573,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALL_TRAMPOLINE_SP execute_data = EG(current_execute_data) = EX(prev_execute_data); call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; - ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_top)) - (char*)call)); ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); @@ -60074,7 +60098,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_P call->extra_named_params : NULL, IS_CONST == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL, &EX(func)->op_array, opline, cache_slot, - opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER); + opline->extended_value); if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { zend_array_release(call->extra_named_params); @@ -60257,7 +60281,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_P call->extra_named_params : NULL, IS_UNUSED == IS_CONST ? Z_ARRVAL_P(named_positions) : NULL, &EX(func)->op_array, opline, cache_slot, - opline->extended_value & ZEND_FCALL_USES_VARIADIC_PLACEHOLDER); + opline->extended_value); if (ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { zend_array_release(call->extra_named_params); @@ -63383,7 +63407,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -63392,7 +63416,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -63408,12 +63432,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && IS_CONST == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { @@ -63445,7 +63469,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -63454,7 +63478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -63479,7 +63503,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -66093,7 +66119,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -66101,7 +66127,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -66116,12 +66142,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -66152,7 +66178,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); @@ -66160,7 +66186,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -66184,7 +66210,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -66772,7 +66800,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -66781,7 +66809,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -66797,12 +66825,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { function_name = NULL; if (IS_UNUSED != IS_CONST) { @@ -66834,7 +66862,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -66843,7 +66871,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -66868,7 +66896,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -68568,7 +68598,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -68577,7 +68607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_CONST == IS_UNUSED) { @@ -68593,12 +68623,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && IS_CV == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_CONST != IS_CONST && IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { @@ -68630,7 +68660,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -68639,7 +68669,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -68664,7 +68694,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -81729,7 +81761,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -81738,7 +81770,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -81754,12 +81786,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST && IS_CONST == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { @@ -81791,7 +81823,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -81800,7 +81832,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -81825,7 +81857,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -84736,7 +84770,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -84744,7 +84778,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -84759,12 +84793,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -84795,7 +84829,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); @@ -84803,7 +84837,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -84827,7 +84861,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -86288,7 +86324,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -86297,7 +86333,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -86313,12 +86349,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { function_name = NULL; if (IS_UNUSED != IS_CONST) { @@ -86350,7 +86386,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -86359,7 +86395,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -86384,7 +86420,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -89287,7 +89325,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -89296,7 +89334,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_VAR == IS_UNUSED) { @@ -89312,12 +89350,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_VAR == IS_CONST && IS_CV == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_VAR != IS_CONST && IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { @@ -89349,7 +89387,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -89358,7 +89396,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -89383,7 +89421,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -91641,7 +91681,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -91650,7 +91690,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -91666,12 +91706,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && IS_CONST == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && IS_CONST == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CONST != IS_UNUSED) { function_name = RT_CONSTANT(opline, opline->op2); if (IS_CONST != IS_CONST) { @@ -91703,7 +91743,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -91712,7 +91752,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CONST == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -91737,7 +91777,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -93893,7 +93935,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -93901,7 +93943,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -93916,12 +93958,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { @@ -93952,7 +93994,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); HANDLE_EXCEPTION(); @@ -93960,7 +94002,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -93984,7 +94026,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -94310,7 +94354,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -94319,7 +94363,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -94335,12 +94379,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && IS_UNUSED == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_UNUSED != IS_UNUSED) { function_name = NULL; if (IS_UNUSED != IS_CONST) { @@ -94372,7 +94416,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -94381,7 +94425,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -94406,7 +94450,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else { @@ -96639,7 +96685,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST) { /* no function found. try a static method in class */ - ce = CACHED_PTR(opline->result.num); + ce = CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS); if (UNEXPECTED(ce == NULL)) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { @@ -96648,7 +96694,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { - CACHE_PTR(opline->result.num, ce); + CACHE_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce); } } } else if (IS_UNUSED == IS_UNUSED) { @@ -96664,12 +96710,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_UNUSED == IS_CONST && IS_CV == IS_CONST && - EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + EXPECTED((fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*))) != NULL)) { /* nothing to do */ } else if (IS_UNUSED != IS_CONST && IS_CV == IS_CONST && - EXPECTED(CACHED_PTR(opline->result.num) == ce)) { - fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + EXPECTED(CACHED_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS) == ce)) { + fbc = CACHED_PTR((opline->result.num & ~ZEND_INIT_CALLABLE_THIS) + sizeof(void*)); } else if (IS_CV != IS_UNUSED) { function_name = EX_VAR(opline->op2.var); if (IS_CV != IS_CONST) { @@ -96701,7 +96747,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { - zend_undefined_method(ce, Z_STR_P(function_name)); + zend_undefined_method_ex(ce, Z_STR_P(function_name), opline->result.num & ZEND_INIT_CALLABLE_THIS); } @@ -96710,7 +96756,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD if (IS_CV == IS_CONST && EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { - CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + CACHE_POLYMORPHIC_PTR(opline->result.num & ~ZEND_INIT_CALLABLE_THIS, ce, fbc); } if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { init_func_run_time_cache(&fbc->op_array); @@ -96735,7 +96781,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD } if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { - if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + if (opline->result.num & ZEND_INIT_CALLABLE_THIS) { + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { ce = (zend_class_entry*)Z_OBJ(EX(This)); call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; } else {