Skip to content

Commit de4cfff

Browse files
committedNov 2, 2022
Add various APIs to handle FCC structures
1 parent 7c45b95 commit de4cfff

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed
 

‎Zend/zend_API.c

+18
Original file line numberDiff line numberDiff line change
@@ -4145,6 +4145,24 @@ ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_
41454145
}
41464146
/* }}} */
41474147

4148+
ZEND_API void zend_get_callable_zval_from_fcc(const zend_fcall_info_cache *fcc, zval *callable)
4149+
{
4150+
if (fcc->closure) {
4151+
ZVAL_OBJ_COPY(callable, fcc->closure);
4152+
} else if (fcc->function_handler->common.scope) {
4153+
array_init(callable);
4154+
if (fcc->object) {
4155+
GC_ADDREF(fcc->object);
4156+
add_next_index_object(callable, fcc->object);
4157+
} else {
4158+
add_next_index_str(callable, zend_string_copy(fcc->calling_scope->name));
4159+
}
4160+
add_next_index_str(callable, zend_string_copy(fcc->function_handler->common.function_name));
4161+
} else {
4162+
ZVAL_STR_COPY(callable, fcc->function_handler->common.function_name);
4163+
}
4164+
}
4165+
41484166
ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
41494167
{
41504168
zend_string *lname;

‎Zend/zend_API.h

+58
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ typedef struct _zend_fcall_info_cache {
328328
zend_class_backed_enum_table(ce)
329329

330330
#define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)
331+
#define ZEND_FCC_INITIALIZED(fcc) ((fcc).function_handler != NULL)
331332

332333
ZEND_API int zend_next_free_module(void);
333334

@@ -729,6 +730,57 @@ ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...);
729730
*/
730731
ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval, zval *args);
731732

733+
/* Zend FCC API to store and handle PHP userland functions */
734+
static zend_always_inline bool zend_fcc_equals(const zend_fcall_info_cache* a, const zend_fcall_info_cache* b)
735+
{
736+
return a->function_handler == b->function_handler
737+
&& a->object == b->object
738+
&& a->calling_scope == b->calling_scope
739+
&& a->closure == b->closure
740+
;
741+
}
742+
743+
static zend_always_inline void zend_fcc_addref(zend_fcall_info_cache *fcc)
744+
{
745+
if (fcc->object) {
746+
GC_ADDREF(fcc->object);
747+
}
748+
if (fcc->closure) {
749+
GC_ADDREF(fcc->closure);
750+
}
751+
}
752+
753+
static zend_always_inline void zend_fcc_dup(/* restrict */ zend_fcall_info_cache *dest, const zend_fcall_info_cache *src)
754+
{
755+
memcpy(dest, src, sizeof(zend_fcall_info_cache));
756+
zend_fcc_addref(dest);
757+
}
758+
759+
static zend_always_inline void zend_fcc_dtor(zend_fcall_info_cache *fcc)
760+
{
761+
if (fcc->object) {
762+
OBJ_RELEASE(fcc->object);
763+
}
764+
if (fcc->closure) {
765+
OBJ_RELEASE(fcc->closure);
766+
}
767+
memcpy(fcc, &empty_fcall_info_cache, sizeof(zend_fcall_info_cache));
768+
}
769+
770+
ZEND_API void zend_get_callable_zval_from_fcc(const zend_fcall_info_cache *fcc, zval *callable);
771+
772+
/* Moved out of zend_gc.h because zend_fcall_info_cache is an unknown type in that header */
773+
static zend_always_inline void zend_get_gc_buffer_add_fcc(zend_get_gc_buffer *gc_buffer, zend_fcall_info_cache *fcc)
774+
{
775+
ZEND_ASSERT(ZEND_FCC_INITIALIZED(*fcc));
776+
if (fcc->object) {
777+
zend_get_gc_buffer_add_obj(gc_buffer, fcc->object);
778+
}
779+
if (fcc->closure) {
780+
zend_get_gc_buffer_add_obj(gc_buffer, fcc->closure);
781+
}
782+
}
783+
732784
/* Can only return FAILURE if EG(active) is false during late engine shutdown.
733785
* If the call or call setup throws, EG(exception) will be set and the retval
734786
* will be UNDEF. Otherwise, the retval will be a non-UNDEF value. */
@@ -751,6 +803,12 @@ ZEND_API void zend_call_known_function(
751803
zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr,
752804
uint32_t param_count, zval *params, HashTable *named_params);
753805

806+
static zend_always_inline void zend_call_known_fcc(
807+
zend_fcall_info_cache *fcc, zval *retval_ptr, uint32_t param_count, zval *params, HashTable *named_params)
808+
{
809+
zend_call_known_function(fcc->function_handler, fcc->object, fcc->called_scope, retval_ptr, param_count, params, named_params);
810+
}
811+
754812
/* Call the provided zend_function instance method on an object. */
755813
static zend_always_inline void zend_call_known_instance_method(
756814
zend_function *fn, zend_object *object, zval *retval_ptr,

0 commit comments

Comments
 (0)