Skip to content

Commit 9516807

Browse files
authored
zend_object_handlers: Replace function-like macros by (inline) functions (#22297)
`zend_free_trampoline()` requires access to the globals and thus cannot easily be made an inline function without moving it to a different (less-appropriate) header. Since trampolines should be comparatively rare, having an extra function call here should be okay.
1 parent 51c22d3 commit 9516807

3 files changed

Lines changed: 42 additions & 31 deletions

File tree

Zend/zend_object_handlers.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,18 @@ ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func(
18251825
}
18261826
/* }}} */
18271827

1828+
ZEND_API void zend_free_trampoline(zend_function *func)
1829+
{
1830+
ZEND_ASSERT(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE);
1831+
1832+
if (func == &EG(trampoline)) {
1833+
EG(trampoline).common.attributes = NULL;
1834+
EG(trampoline).common.function_name = NULL;
1835+
} else {
1836+
efree(func);
1837+
}
1838+
}
1839+
18281840
static ZEND_FUNCTION(zend_parent_hook_get_trampoline)
18291841
{
18301842
zend_object *obj = Z_PTR_P(ZEND_THIS);

Zend/zend_object_handlers.h

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,10 @@ struct _zend_object_handlers {
236236
BEGIN_EXTERN_C()
237237
extern const ZEND_API zend_object_handlers std_object_handlers;
238238

239-
#define zend_get_std_object_handlers() \
240-
(&std_object_handlers)
241-
242-
#define zend_get_function_root_class(fbc) \
243-
((fbc)->common.prototype ? (fbc)->common.prototype->common.scope : (fbc)->common.scope)
239+
static zend_always_inline const zend_object_handlers *zend_get_std_object_handlers(void)
240+
{
241+
return &std_object_handlers;
242+
}
244243

245244
#define ZEND_PROPERTY_ISSET 0x0 /* Property exists and is not NULL */
246245
#define ZEND_PROPERTY_NOT_EMPTY ZEND_ISEMPTY /* Property is not empty */
@@ -290,18 +289,20 @@ static zend_always_inline HashTable *zend_std_get_properties_ex(zend_object *obj
290289
/* Implements the fast path for array cast */
291290
ZEND_API HashTable *zend_std_build_object_properties_array(zend_object *zobj);
292291

293-
#define ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(object) ( \
294-
/* We can use zend_std_build_object_properties_array() for objects \
295-
* without properties ht and with standard handlers */ \
296-
Z_OBJ_P(object)->properties == NULL \
297-
&& Z_OBJ_HT_P(object)->get_properties_for == NULL \
298-
&& Z_OBJ_HT_P(object)->get_properties == zend_std_get_properties \
299-
/* For initialized proxies we need to forward to the real instance */ \
300-
&& ( \
301-
!zend_object_is_lazy_proxy(Z_OBJ_P(object)) \
302-
|| !zend_lazy_object_initialized(Z_OBJ_P(object)) \
303-
) \
304-
)
292+
static zend_always_inline bool ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(const zval *zv) {
293+
/* We can use zend_std_build_object_properties_array() for objects
294+
* without properties ht and with standard handlers */
295+
const zend_object *obj = Z_OBJ_P(zv);
296+
297+
return obj->properties == NULL
298+
&& obj->handlers->get_properties_for == NULL
299+
&& obj->handlers->get_properties == zend_std_get_properties
300+
/* For initialized proxies we need to forward to the real instance */
301+
&& (
302+
!zend_object_is_lazy_proxy(obj)
303+
|| !zend_lazy_object_initialized(obj)
304+
);
305+
}
305306

306307
/* Handler for objects that cannot be meaningfully compared.
307308
* Only objects with the same identity will be considered equal. */
@@ -312,6 +313,7 @@ ZEND_API bool zend_check_protected(const zend_class_entry *ce, const zend_class_
312313
ZEND_API zend_result zend_check_property_access(const zend_object *zobj, zend_string *prop_info_name, bool is_dynamic);
313314

314315
ZEND_API ZEND_ATTRIBUTE_NONNULL zend_function *zend_get_call_trampoline_func(const zend_function *fbc, zend_string *method_name);
316+
ZEND_API void zend_free_trampoline(zend_function *func);
315317

316318
ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *member);
317319

@@ -335,20 +337,12 @@ ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_p
335337

336338
void zend_object_handlers_startup(void);
337339

338-
#define zend_release_properties(ht) do { \
339-
if (ht) { \
340-
zend_array_release(ht); \
341-
} \
342-
} while (0)
343-
344-
#define zend_free_trampoline(func) do { \
345-
if ((func) == &EG(trampoline)) { \
346-
EG(trampoline).common.attributes = NULL; \
347-
EG(trampoline).common.function_name = NULL; \
348-
} else { \
349-
efree(func); \
350-
} \
351-
} while (0)
340+
static zend_always_inline void zend_release_properties(HashTable *ht)
341+
{
342+
if (ht) {
343+
zend_array_release(ht);
344+
}
345+
}
352346

353347
/* Fallback to default comparison implementation if the arguments aren't both objects
354348
* and have the same compare() handler. You'll likely want to use this unless you

Zend/zend_objects_API.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ static inline zend_property_info *zend_get_typed_property_info_for_slot(zend_obj
136136
return NULL;
137137
}
138138

139+
static zend_always_inline zend_class_entry *zend_get_function_root_class(const zend_function *fbc)
140+
{
141+
return fbc->common.prototype ? fbc->common.prototype->common.scope : fbc->common.scope;
142+
}
143+
139144
static zend_always_inline bool zend_check_method_accessible(const zend_function *fn, const zend_class_entry *scope)
140145
{
141146
if (!(fn->common.fn_flags & ZEND_ACC_PUBLIC)

0 commit comments

Comments
 (0)