@@ -122,8 +122,9 @@ PHPAPI php_basic_globals basic_globals;
122122#endif
123123
124124typedef struct _user_tick_function_entry {
125- zend_fcall_info fci ;
126125 zend_fcall_info_cache fci_cache ;
126+ zval * params ;
127+ uint32_t param_count ;
127128 bool calling ;
128129} user_tick_function_entry ;
129130
@@ -1577,51 +1578,34 @@ PHP_FUNCTION(forward_static_call_array)
15771578}
15781579/* }}} */
15791580
1580- static void fci_addref (zend_fcall_info * fci , zend_fcall_info_cache * fci_cache )
1581- {
1582- Z_TRY_ADDREF (fci -> function_name );
1583- if (fci_cache -> object ) {
1584- GC_ADDREF (fci_cache -> object );
1585- }
1586- }
1587-
1588- static void fci_release (zend_fcall_info * fci , zend_fcall_info_cache * fci_cache )
1589- {
1590- zval_ptr_dtor (& fci -> function_name );
1591- if (fci_cache -> object ) {
1592- zend_object_release (fci_cache -> object );
1593- }
1594- }
1595-
15961581void user_shutdown_function_dtor (zval * zv ) /* {{{ */
15971582{
15981583 php_shutdown_function_entry * shutdown_function_entry = Z_PTR_P (zv );
15991584
1600- zend_fcall_info_args_clear (& shutdown_function_entry -> fci , true);
1601- fci_release (& shutdown_function_entry -> fci , & shutdown_function_entry -> fci_cache );
1585+ for (uint32_t i = 0 ; i < shutdown_function_entry -> param_count ; i ++ ) {
1586+ zval_ptr_dtor (& shutdown_function_entry -> params [i ]);
1587+ }
1588+ efree (shutdown_function_entry -> params );
1589+ zend_fcc_dtor (& shutdown_function_entry -> fci_cache );
16021590 efree (shutdown_function_entry );
16031591}
16041592/* }}} */
16051593
16061594void user_tick_function_dtor (user_tick_function_entry * tick_function_entry ) /* {{{ */
16071595{
1608- zend_fcall_info_args_clear (& tick_function_entry -> fci , true);
1609- fci_release (& tick_function_entry -> fci , & tick_function_entry -> fci_cache );
1596+ for (uint32_t i = 0 ; i < tick_function_entry -> param_count ; i ++ ) {
1597+ zval_ptr_dtor (& tick_function_entry -> params [i ]);
1598+ }
1599+ efree (tick_function_entry -> params );
1600+ zend_fcc_dtor (& tick_function_entry -> fci_cache );
16101601}
16111602/* }}} */
16121603
16131604static int user_shutdown_function_call (zval * zv ) /* {{{ */
16141605{
1615- php_shutdown_function_entry * shutdown_function_entry = Z_PTR_P (zv );
1616- zval retval ;
1617- zend_result call_status ;
1618-
1619- /* set retval zval for FCI struct */
1620- shutdown_function_entry -> fci .retval = & retval ;
1621- call_status = zend_call_function (& shutdown_function_entry -> fci , & shutdown_function_entry -> fci_cache );
1622- ZEND_ASSERT (call_status == SUCCESS );
1623- zval_ptr_dtor (& retval );
1606+ php_shutdown_function_entry * entry = Z_PTR_P (zv );
16241607
1608+ zend_call_known_fcc (& entry -> fci_cache , NULL , entry -> param_count , entry -> params , NULL );
16251609 return 0 ;
16261610}
16271611/* }}} */
@@ -1630,16 +1614,8 @@ static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
16301614{
16311615 /* Prevent re-entrant calls to the same user ticks function */
16321616 if (!tick_fe -> calling ) {
1633- zval tmp ;
1634-
1635- /* set tmp zval */
1636- tick_fe -> fci .retval = & tmp ;
1637-
16381617 tick_fe -> calling = true;
1639- zend_call_function (& tick_fe -> fci , & tick_fe -> fci_cache );
1640-
1641- /* Destroy return value */
1642- zval_ptr_dtor (& tmp );
1618+ zend_call_known_fcc (& tick_fe -> fci_cache , NULL , tick_fe -> param_count , tick_fe -> params , NULL );
16431619 tick_fe -> calling = false;
16441620 }
16451621}
@@ -1653,25 +1629,13 @@ static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
16531629
16541630static int user_tick_function_compare (user_tick_function_entry * tick_fe1 , user_tick_function_entry * tick_fe2 ) /* {{{ */
16551631{
1656- zval * func1 = & tick_fe1 -> fci .function_name ;
1657- zval * func2 = & tick_fe2 -> fci .function_name ;
1658- int ret ;
1659-
1660- if (Z_TYPE_P (func1 ) == IS_STRING && Z_TYPE_P (func2 ) == IS_STRING ) {
1661- ret = zend_binary_zval_strcmp (func1 , func2 ) == 0 ;
1662- } else if (Z_TYPE_P (func1 ) == IS_ARRAY && Z_TYPE_P (func2 ) == IS_ARRAY ) {
1663- ret = zend_compare_arrays (func1 , func2 ) == 0 ;
1664- } else if (Z_TYPE_P (func1 ) == IS_OBJECT && Z_TYPE_P (func2 ) == IS_OBJECT ) {
1665- ret = zend_compare_objects (func1 , func2 ) == 0 ;
1666- } else {
1667- ret = 0 ;
1668- }
1632+ bool is_equal = zend_fcc_equals (& tick_fe1 -> fci_cache , & tick_fe2 -> fci_cache );
16691633
1670- if (ret && tick_fe1 -> calling ) {
1634+ if (is_equal && tick_fe1 -> calling ) {
16711635 zend_throw_error (NULL , "Registered tick function cannot be unregistered while it is being executed" );
1672- return 0 ;
1636+ return false ;
16731637 }
1674- return ret ;
1638+ return is_equal ;
16751639}
16761640/* }}} */
16771641
@@ -1703,17 +1667,27 @@ PHPAPI void php_free_shutdown_functions(void) /* {{{ */
17031667/* {{{ Register a user-level function to be called on request termination */
17041668PHP_FUNCTION (register_shutdown_function )
17051669{
1706- php_shutdown_function_entry entry ;
1670+ zend_fcall_info fci ;
1671+ php_shutdown_function_entry entry = {
1672+ .fci_cache = empty_fcall_info_cache ,
1673+ .params = NULL ,
1674+ .param_count = 0 ,
1675+ };
17071676 zval * params = NULL ;
1708- uint32_t param_count = 0 ;
17091677 bool status ;
17101678
1711- if (zend_parse_parameters (ZEND_NUM_ARGS (), "f *" , & entry . fci , & entry .fci_cache , & params , & param_count ) == FAILURE ) {
1679+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "F *" , & fci , & entry .fci_cache , & params , & entry . param_count ) == FAILURE ) {
17121680 RETURN_THROWS ();
17131681 }
17141682
1715- fci_addref (& entry .fci , & entry .fci_cache );
1716- zend_fcall_info_argp (& entry .fci , param_count , params );
1683+ zend_fcc_addref (& entry .fci_cache );
1684+ if (entry .param_count ) {
1685+ ZEND_ASSERT (params != NULL );
1686+ entry .params = (zval * ) safe_emalloc (entry .param_count , sizeof (zval ), 0 );
1687+ for (uint32_t i = 0 ; i < entry .param_count ; i ++ ) {
1688+ ZVAL_COPY (& entry .params [i ], & params [i ]);
1689+ }
1690+ }
17171691
17181692 status = append_user_shutdown_function (& entry );
17191693 ZEND_ASSERT (status );
@@ -2283,17 +2257,27 @@ PHP_FUNCTION(getprotobynumber)
22832257/* {{{ Registers a tick callback function */
22842258PHP_FUNCTION (register_tick_function )
22852259{
2286- user_tick_function_entry tick_fe ;
2260+ user_tick_function_entry tick_fe = {
2261+ .fci_cache = empty_fcall_info_cache ,
2262+ .params = NULL ,
2263+ .param_count = 0 ,
2264+ .calling = false,
2265+ };
2266+ zend_fcall_info fci ;
22872267 zval * params = NULL ;
2288- uint32_t param_count = 0 ;
22892268
2290- if (zend_parse_parameters (ZEND_NUM_ARGS (), "f *" , & tick_fe . fci , & tick_fe .fci_cache , & params , & param_count ) == FAILURE ) {
2269+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "F *" , & fci , & tick_fe .fci_cache , & params , & tick_fe . param_count ) == FAILURE ) {
22912270 RETURN_THROWS ();
22922271 }
22932272
2294- tick_fe .calling = false;
2295- fci_addref (& tick_fe .fci , & tick_fe .fci_cache );
2296- zend_fcall_info_argp (& tick_fe .fci , param_count , params );
2273+ zend_fcc_addref (& tick_fe .fci_cache );
2274+ if (tick_fe .param_count ) {
2275+ ZEND_ASSERT (params != NULL );
2276+ tick_fe .params = (zval * ) safe_emalloc (tick_fe .param_count , sizeof (zval ), 0 );
2277+ for (uint32_t i = 0 ; i < tick_fe .param_count ; i ++ ) {
2278+ ZVAL_COPY (& tick_fe .params [i ], & params [i ]);
2279+ }
2280+ }
22972281
22982282 if (!BG (user_tick_functions )) {
22992283 BG (user_tick_functions ) = (zend_llist * ) emalloc (sizeof (zend_llist ));
@@ -2312,17 +2296,24 @@ PHP_FUNCTION(register_tick_function)
23122296/* {{{ Unregisters a tick callback function */
23132297PHP_FUNCTION (unregister_tick_function )
23142298{
2315- user_tick_function_entry tick_fe ;
2299+ user_tick_function_entry tick_fe = {
2300+ .fci_cache = empty_fcall_info_cache ,
2301+ .params = NULL ,
2302+ .param_count = 0 ,
2303+ .calling = false,
2304+ };
2305+ zend_fcall_info fci ;
23162306
23172307 ZEND_PARSE_PARAMETERS_START (1 , 1 )
2318- Z_PARAM_FUNC ( tick_fe . fci , tick_fe .fci_cache )
2308+ Z_PARAM_FUNC_NO_TRAMPOLINE_FREE ( fci , tick_fe .fci_cache )
23192309 ZEND_PARSE_PARAMETERS_END ();
23202310
2321- if (! BG (user_tick_functions )) {
2322- return ;
2311+ if (BG (user_tick_functions )) {
2312+ zend_llist_del_element ( BG ( user_tick_functions ), & tick_fe , ( int ( * )( void * , void * )) user_tick_function_compare ) ;
23232313 }
23242314
2325- zend_llist_del_element (BG (user_tick_functions ), & tick_fe , (int (* )(void * , void * )) user_tick_function_compare );
2315+ /* Free potential trampoline */
2316+ zend_release_fcall_info_cache (& tick_fe .fci_cache );
23262317}
23272318/* }}} */
23282319
0 commit comments