@@ -122,8 +122,9 @@ PHPAPI php_basic_globals basic_globals;
122
122
#endif
123
123
124
124
typedef struct _user_tick_function_entry {
125
- zend_fcall_info fci ;
126
125
zend_fcall_info_cache fci_cache ;
126
+ zval * params ;
127
+ uint32_t param_count ;
127
128
bool calling ;
128
129
} user_tick_function_entry ;
129
130
@@ -1577,51 +1578,34 @@ PHP_FUNCTION(forward_static_call_array)
1577
1578
}
1578
1579
/* }}} */
1579
1580
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
-
1596
1581
void user_shutdown_function_dtor (zval * zv ) /* {{{ */
1597
1582
{
1598
1583
php_shutdown_function_entry * shutdown_function_entry = Z_PTR_P (zv );
1599
1584
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 );
1602
1590
efree (shutdown_function_entry );
1603
1591
}
1604
1592
/* }}} */
1605
1593
1606
1594
void user_tick_function_dtor (user_tick_function_entry * tick_function_entry ) /* {{{ */
1607
1595
{
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 );
1610
1601
}
1611
1602
/* }}} */
1612
1603
1613
1604
static int user_shutdown_function_call (zval * zv ) /* {{{ */
1614
1605
{
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 );
1624
1607
1608
+ zend_call_known_fcc (& entry -> fci_cache , NULL , entry -> param_count , entry -> params , NULL );
1625
1609
return 0 ;
1626
1610
}
1627
1611
/* }}} */
@@ -1630,16 +1614,8 @@ static void user_tick_function_call(user_tick_function_entry *tick_fe) /* {{{ */
1630
1614
{
1631
1615
/* Prevent re-entrant calls to the same user ticks function */
1632
1616
if (!tick_fe -> calling ) {
1633
- zval tmp ;
1634
-
1635
- /* set tmp zval */
1636
- tick_fe -> fci .retval = & tmp ;
1637
-
1638
1617
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 );
1643
1619
tick_fe -> calling = false;
1644
1620
}
1645
1621
}
@@ -1653,25 +1629,13 @@ static void run_user_tick_functions(int tick_count, void *arg) /* {{{ */
1653
1629
1654
1630
static int user_tick_function_compare (user_tick_function_entry * tick_fe1 , user_tick_function_entry * tick_fe2 ) /* {{{ */
1655
1631
{
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 );
1669
1633
1670
- if (ret && tick_fe1 -> calling ) {
1634
+ if (is_equal && tick_fe1 -> calling ) {
1671
1635
zend_throw_error (NULL , "Registered tick function cannot be unregistered while it is being executed" );
1672
- return 0 ;
1636
+ return false ;
1673
1637
}
1674
- return ret ;
1638
+ return is_equal ;
1675
1639
}
1676
1640
/* }}} */
1677
1641
@@ -1703,17 +1667,27 @@ PHPAPI void php_free_shutdown_functions(void) /* {{{ */
1703
1667
/* {{{ Register a user-level function to be called on request termination */
1704
1668
PHP_FUNCTION (register_shutdown_function )
1705
1669
{
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
+ };
1707
1676
zval * params = NULL ;
1708
- uint32_t param_count = 0 ;
1709
1677
bool status ;
1710
1678
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 ) {
1712
1680
RETURN_THROWS ();
1713
1681
}
1714
1682
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
+ }
1717
1691
1718
1692
status = append_user_shutdown_function (& entry );
1719
1693
ZEND_ASSERT (status );
@@ -2283,17 +2257,27 @@ PHP_FUNCTION(getprotobynumber)
2283
2257
/* {{{ Registers a tick callback function */
2284
2258
PHP_FUNCTION (register_tick_function )
2285
2259
{
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 ;
2287
2267
zval * params = NULL ;
2288
- uint32_t param_count = 0 ;
2289
2268
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 ) {
2291
2270
RETURN_THROWS ();
2292
2271
}
2293
2272
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
+ }
2297
2281
2298
2282
if (!BG (user_tick_functions )) {
2299
2283
BG (user_tick_functions ) = (zend_llist * ) emalloc (sizeof (zend_llist ));
@@ -2312,17 +2296,24 @@ PHP_FUNCTION(register_tick_function)
2312
2296
/* {{{ Unregisters a tick callback function */
2313
2297
PHP_FUNCTION (unregister_tick_function )
2314
2298
{
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 ;
2316
2306
2317
2307
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 )
2319
2309
ZEND_PARSE_PARAMETERS_END ();
2320
2310
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 ) ;
2323
2313
}
2324
2314
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 );
2326
2317
}
2327
2318
/* }}} */
2328
2319
0 commit comments