Skip to content

Commit 5d2873a

Browse files
committed
Pass zend_function* directly to zend_get_call_trampoline_func()
Every single callsite already checks if it set to call this function, so no need to duplicate the work
1 parent 525296a commit 5d2873a

File tree

4 files changed

+17
-17
lines changed

4 files changed

+17
-17
lines changed

UPGRADING.INTERNALS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES
3535
. The zval_dtor() alias of zval_ptr_dtor_nogc() has been removed.
3636
Call zval_ptr_dtor_nogc() directly instead.
3737
. The internal zend_copy_parameters_array() function is no longer exposed.
38+
. The zend_get_call_trampoline_func() API now takes the __call or
39+
__callStatic zend_function* instead of a CE.
3840

3941
========================
4042
2. Build system changes

Zend/zend_API.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3951,7 +3951,7 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_
39513951
get_function_via_handler:
39523952
if (fcc->object && fcc->calling_scope == ce_org) {
39533953
if (strict_class && ce_org->__call) {
3954-
fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
3954+
fcc->function_handler = zend_get_call_trampoline_func(ce_org->__call, mname, false);
39553955
call_via_handler = 1;
39563956
retval = true;
39573957
} else {

Zend/zend_object_handlers.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,19 +1674,17 @@ ZEND_API bool zend_check_protected(const zend_class_entry *ce, const zend_class_
16741674
}
16751675
/* }}} */
16761676

1677-
ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce, zend_string *method_name, bool is_static) /* {{{ */
1677+
ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func(
1678+
const zend_function *magic_call, zend_string *method_name, bool is_static) /* {{{ */
16781679
{
16791680
size_t mname_len;
16801681
zend_op_array *func;
1681-
zend_function *fbc = is_static ? ce->__callstatic : ce->__call;
16821682
/* We use non-NULL value to avoid useless run_time_cache allocation.
16831683
* The low bit must be zero, to not be interpreted as a MAP_PTR offset.
16841684
*/
16851685
static const void *dummy = (void*)(intptr_t)2;
16861686
static const zend_arg_info arg_info[1] = {{0}};
16871687

1688-
ZEND_ASSERT(fbc);
1689-
16901688
if (EXPECTED(EG(trampoline).common.function_name == NULL)) {
16911689
func = &EG(trampoline).op_array;
16921690
} else {
@@ -1700,16 +1698,16 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce
17001698
func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE
17011699
| ZEND_ACC_PUBLIC
17021700
| ZEND_ACC_VARIADIC
1703-
| (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD));
1701+
| (magic_call->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_NODISCARD));
17041702
func->fn_flags2 = 0;
17051703
/* Attributes outlive the trampoline because they are created by the compiler. */
1706-
func->attributes = fbc->common.attributes;
1704+
func->attributes = magic_call->common.attributes;
17071705
if (is_static) {
17081706
func->fn_flags |= ZEND_ACC_STATIC;
17091707
}
17101708
func->opcodes = &EG(call_trampoline_op);
17111709
ZEND_MAP_PTR_INIT(func->run_time_cache, (void**)dummy);
1712-
func->scope = fbc->common.scope;
1710+
func->scope = magic_call->common.scope;
17131711
/* reserve space for arguments, local and temporary variables */
17141712
/* EG(trampoline) is reused from other places, like FFI (e.g. zend_ffi_cdata_get_closure()) where
17151713
* it is used as an internal function. It may set fields that don't belong to common, thus
@@ -1718,10 +1716,10 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce
17181716
* frame. This didn't cause any issues until now due to "lucky" structure layout. */
17191717
func->last_var = 0;
17201718
uint32_t min_T = 2 + ZEND_OBSERVER_ENABLED;
1721-
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, min_T) : min_T;
1722-
func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC();
1723-
func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
1724-
func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0;
1719+
func->T = (magic_call->type == ZEND_USER_FUNCTION)? MAX(magic_call->op_array.last_var + magic_call->op_array.T, min_T) : min_T;
1720+
func->filename = (magic_call->type == ZEND_USER_FUNCTION)? magic_call->op_array.filename : ZSTR_EMPTY_ALLOC();
1721+
func->line_start = (magic_call->type == ZEND_USER_FUNCTION)? magic_call->op_array.line_start : 0;
1722+
func->line_end = (magic_call->type == ZEND_USER_FUNCTION)? magic_call->op_array.line_end : 0;
17251723

17261724
//??? keep compatibility for "\0" characters
17271725
//??? see: Zend/tests/bug46238.phpt
@@ -1867,7 +1865,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
18671865
ZSTR_ALLOCA_FREE(lc_method_name, use_heap);
18681866
}
18691867
if (zobj->ce->__call) {
1870-
return zend_get_call_trampoline_func(zobj->ce, method_name, false);
1868+
return zend_get_call_trampoline_func(zobj->ce->__call, method_name, false);
18711869
} else {
18721870
return NULL;
18731871
}
@@ -1893,7 +1891,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
18931891
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
18941892
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
18951893
if (zobj->ce->__call) {
1896-
fbc = zend_get_call_trampoline_func(zobj->ce, method_name, false);
1894+
fbc = zend_get_call_trampoline_func(zobj->ce->__call, method_name, false);
18971895
} else {
18981896
zend_bad_method_call(fbc, method_name, scope);
18991897
fbc = NULL;
@@ -1925,9 +1923,9 @@ static zend_always_inline zend_function *get_static_method_fallback(
19251923
* see: tests/classes/__call_004.phpt */
19261924

19271925
ZEND_ASSERT(object->ce->__call);
1928-
return zend_get_call_trampoline_func(object->ce, function_name, false);
1926+
return zend_get_call_trampoline_func(object->ce->__call, function_name, false);
19291927
} else if (ce->__callstatic) {
1930-
return zend_get_call_trampoline_func(ce, function_name, true);
1928+
return zend_get_call_trampoline_func(ce->__callstatic, function_name, true);
19311929
} else {
19321930
return NULL;
19331931
}

Zend/zend_object_handlers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ ZEND_API bool zend_check_protected(const zend_class_entry *ce, const zend_class_
312312

313313
ZEND_API zend_result zend_check_property_access(const zend_object *zobj, zend_string *prop_info_name, bool is_dynamic);
314314

315-
ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce, zend_string *method_name, bool is_static);
315+
ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func(const zend_function *magic_call, zend_string *method_name, bool is_static);
316316

317317
ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *member);
318318

0 commit comments

Comments
 (0)