@@ -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 ;
1632+ bool is_equal = zend_fcc_equals (& tick_fe1 -> fci_cache , & tick_fe2 -> fci_cache );
16591633
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- }
1669-
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,23 @@ 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{
1670+ zend_fcall_info fci ;
17061671 php_shutdown_function_entry entry ;
17071672 zval * params = NULL ;
1708- uint32_t param_count = 0 ;
17091673 bool status ;
17101674
1711- if (zend_parse_parameters (ZEND_NUM_ARGS (), "f *" , & entry . fci , & entry .fci_cache , & params , & param_count ) == FAILURE ) {
1675+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "F *" , & fci , & entry .fci_cache , & params , & entry . param_count ) == FAILURE ) {
17121676 RETURN_THROWS ();
17131677 }
17141678
1715- fci_addref (& entry .fci , & entry .fci_cache );
1716- zend_fcall_info_argp (& entry .fci , param_count , params );
1679+ zend_fcc_addref (& entry .fci_cache );
1680+ if (entry .param_count ) {
1681+ ZEND_ASSERT (params != NULL );
1682+ entry .params = (zval * ) safe_emalloc (entry .param_count , sizeof (zval ), 0 );
1683+ for (uint32_t i = 0 ; i < entry .param_count ; i ++ ) {
1684+ ZVAL_COPY (& entry .params [i ], & params [i ]);
1685+ }
1686+ }
17171687
17181688 status = append_user_shutdown_function (& entry );
17191689 ZEND_ASSERT (status );
@@ -2286,16 +2256,23 @@ PHP_FUNCTION(getprotobynumber)
22862256PHP_FUNCTION (register_tick_function )
22872257{
22882258 user_tick_function_entry tick_fe ;
2259+ zend_fcall_info fci ;
22892260 zval * params = NULL ;
2290- uint32_t param_count = 0 ;
22912261
2292- if (zend_parse_parameters (ZEND_NUM_ARGS (), "f *" , & tick_fe . fci , & tick_fe .fci_cache , & params , & param_count ) == FAILURE ) {
2262+ if (zend_parse_parameters (ZEND_NUM_ARGS (), "F *" , & fci , & tick_fe .fci_cache , & params , & tick_fe . param_count ) == FAILURE ) {
22932263 RETURN_THROWS ();
22942264 }
22952265
22962266 tick_fe .calling = false;
2297- fci_addref (& tick_fe .fci , & tick_fe .fci_cache );
2298- zend_fcall_info_argp (& tick_fe .fci , param_count , params );
2267+
2268+ zend_fcc_addref (& tick_fe .fci_cache );
2269+ if (tick_fe .param_count ) {
2270+ ZEND_ASSERT (params != NULL );
2271+ tick_fe .params = (zval * ) safe_emalloc (tick_fe .param_count , sizeof (zval ), 0 );
2272+ for (uint32_t i = 0 ; i < tick_fe .param_count ; i ++ ) {
2273+ ZVAL_COPY (& tick_fe .params [i ], & params [i ]);
2274+ }
2275+ }
22992276
23002277 if (!BG (user_tick_functions )) {
23012278 BG (user_tick_functions ) = (zend_llist * ) emalloc (sizeof (zend_llist ));
@@ -2315,16 +2292,19 @@ PHP_FUNCTION(register_tick_function)
23152292PHP_FUNCTION (unregister_tick_function )
23162293{
23172294 user_tick_function_entry tick_fe ;
2295+ zend_fcall_info fci ;
23182296
23192297 ZEND_PARSE_PARAMETERS_START (1 , 1 )
2320- Z_PARAM_FUNC ( tick_fe . fci , tick_fe .fci_cache )
2298+ Z_PARAM_FUNC_NO_TRAMPOLINE_FREE ( fci , tick_fe .fci_cache )
23212299 ZEND_PARSE_PARAMETERS_END ();
23222300
23232301 if (!BG (user_tick_functions )) {
23242302 return ;
23252303 }
23262304
23272305 zend_llist_del_element (BG (user_tick_functions ), & tick_fe , (int (* )(void * , void * )) user_tick_function_compare );
2306+ /* Free potential trampoline */
2307+ zend_release_fcall_info_cache (& tick_fe .fci_cache );
23282308}
23292309/* }}} */
23302310
0 commit comments