Skip to content

Commit 6ab38b5

Browse files
committed
ext/standard: Refactor tick and shutdown functions
Remove usage of FCI and store the parameters and count of it directly on the relevant structures This reduces the size of the structs by ~50
1 parent 51884ed commit 6ab38b5

File tree

3 files changed

+81
-93
lines changed

3 files changed

+81
-93
lines changed

ext/session/session.c

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,19 +2175,17 @@ PHP_FUNCTION(session_set_save_handler)
21752175

21762176
if (register_shutdown) {
21772177
/* create shutdown function */
2178-
php_shutdown_function_entry shutdown_function_entry;
2179-
zval callable;
2180-
zend_result result;
2181-
2182-
ZVAL_STRING(&callable, "session_register_shutdown");
2183-
result = zend_fcall_info_init(&callable, 0, &shutdown_function_entry.fci,
2184-
&shutdown_function_entry.fci_cache, NULL, NULL);
2185-
2186-
ZEND_ASSERT(result == SUCCESS);
2178+
php_shutdown_function_entry shutdown_function_entry = {
2179+
.fci_cache = empty_fcall_info_cache,
2180+
.params = NULL,
2181+
.param_count = 0,
2182+
};
2183+
zend_function *fn_entry = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("session_register_shutdown"));
2184+
ZEND_ASSERT(fn_entry != NULL);
2185+
shutdown_function_entry.fci_cache.function_handler = fn_entry;
21872186

21882187
/* add shutdown function, removing the old one if it exists */
2189-
if (!register_user_shutdown_function("session_shutdown", strlen("session_shutdown"), &shutdown_function_entry)) {
2190-
zval_ptr_dtor(&callable);
2188+
if (!register_user_shutdown_function(ZEND_STRL("session_shutdown"), &shutdown_function_entry)) {
21912189
php_error_docref(NULL, E_WARNING, "Unable to register session shutdown function");
21922190
RETURN_FALSE;
21932191
}
@@ -2826,9 +2824,11 @@ PHP_FUNCTION(session_status)
28262824
/* {{{ Registers session_write_close() as a shutdown function */
28272825
PHP_FUNCTION(session_register_shutdown)
28282826
{
2829-
php_shutdown_function_entry shutdown_function_entry;
2830-
zval callable;
2831-
zend_result result;
2827+
php_shutdown_function_entry shutdown_function_entry = {
2828+
.fci_cache = empty_fcall_info_cache,
2829+
.params = NULL,
2830+
.param_count = 0,
2831+
};
28322832

28332833
ZEND_PARSE_PARAMETERS_NONE();
28342834

@@ -2838,15 +2838,11 @@ PHP_FUNCTION(session_register_shutdown)
28382838
* function after calling session_set_save_handler(), which expects
28392839
* the session still to be available.
28402840
*/
2841-
ZVAL_STRING(&callable, "session_write_close");
2842-
result = zend_fcall_info_init(&callable, 0, &shutdown_function_entry.fci,
2843-
&shutdown_function_entry.fci_cache, NULL, NULL);
2844-
2845-
ZEND_ASSERT(result == SUCCESS);
2841+
zend_function *fn_entry = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("session_write_close"));
2842+
ZEND_ASSERT(fn_entry != NULL);
2843+
shutdown_function_entry.fci_cache.function_handler = fn_entry;
28462844

28472845
if (!append_user_shutdown_function(&shutdown_function_entry)) {
2848-
zval_ptr_dtor(&callable);
2849-
28502846
/* Unable to register shutdown function, presumably because of lack
28512847
* of memory, so flush the session now. It would be done in rshutdown
28522848
* anyway but the handler will have had it's dtor called by then.

ext/standard/basic_functions.c

Lines changed: 62 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,9 @@ PHPAPI php_basic_globals basic_globals;
122122
#endif
123123

124124
typedef 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-
15961581
void 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

16061594
void 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

16131604
static 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

16541630
static 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 */
17041668
PHP_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 */
22842258
PHP_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 */
23132297
PHP_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

ext/standard/basic_functions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,9 @@ PHPAPI double php_get_nan(void);
123123
PHPAPI double php_get_inf(void);
124124

125125
typedef struct _php_shutdown_function_entry {
126-
zend_fcall_info fci;
127126
zend_fcall_info_cache fci_cache;
127+
zval *params;
128+
uint32_t param_count;
128129
} php_shutdown_function_entry;
129130

130131
PHPAPI extern bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry);

0 commit comments

Comments
 (0)