Skip to content

Commit 2dee71f

Browse files
committed
readline: store callbacks as FCCs
Rather than a zval that needs to be revalidated at every call.
1 parent e20094b commit 2dee71f

1 file changed

Lines changed: 37 additions & 36 deletions

File tree

‎ext/readline/readline.c‎

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@
3838

3939
#ifdef HAVE_RL_CALLBACK_READ_CHAR
4040

41-
static zval _prepped_callback;
41+
static zend_fcall_info_cache _prepped_callback;
4242

4343
#endif
4444

45-
static zval _readline_completion;
45+
static zend_fcall_info_cache _readline_completion;
4646
static zval _readline_array;
4747

4848
ZEND_TLS char *php_readline_custom_readline_name = NULL;
@@ -81,9 +81,9 @@ PHP_MINIT_FUNCTION(readline)
8181
/* libedit don't need this call which set the tty in cooked mode */
8282
using_history();
8383
#endif
84-
ZVAL_UNDEF(&_readline_completion);
84+
_readline_completion = empty_fcall_info_cache;
8585
#ifdef HAVE_RL_CALLBACK_READ_CHAR
86-
ZVAL_UNDEF(&_prepped_callback);
86+
_prepped_callback = empty_fcall_info_cache;
8787
#endif
8888

8989
register_readline_symbols(module_number);
@@ -98,13 +98,13 @@ PHP_MSHUTDOWN_FUNCTION(readline)
9898

9999
PHP_RSHUTDOWN_FUNCTION(readline)
100100
{
101-
zval_ptr_dtor(&_readline_completion);
102-
ZVAL_UNDEF(&_readline_completion);
101+
if (ZEND_FCC_INITIALIZED(_readline_completion)) {
102+
zend_fcc_dtor(&_readline_completion);
103+
}
103104
#ifdef HAVE_RL_CALLBACK_READ_CHAR
104-
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
105+
if (ZEND_FCC_INITIALIZED(_prepped_callback)) {
105106
rl_callback_handler_remove();
106-
zval_ptr_dtor(&_prepped_callback);
107-
ZVAL_UNDEF(&_prepped_callback);
107+
zend_fcc_dtor(&_prepped_callback);
108108
}
109109
#endif
110110

@@ -449,24 +449,25 @@ char **php_readline_completion_cb(const char *text, int start, int end)
449449
ZVAL_LONG(&params[1], start);
450450
ZVAL_LONG(&params[2], end);
451451

452-
if (call_user_function(NULL, NULL, &_readline_completion, &_readline_array, 3, params) == SUCCESS) {
453-
if (Z_TYPE(_readline_array) == IS_ARRAY) {
454-
SEPARATE_ARRAY(&_readline_array);
455-
if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) {
456-
matches = rl_completion_matches(text,_readline_command_generator);
457-
} else {
458-
/* libedit will read matches[2] */
459-
matches = calloc(3, sizeof(char *));
460-
if (!matches) {
461-
goto out;
462-
}
463-
matches[0] = strdup("");
452+
zend_call_known_fcc(&_readline_completion, &_readline_array, 3, params, NULL);
453+
zval_ptr_dtor(&params[0]);
454+
455+
if (Z_TYPE(_readline_array) == IS_ARRAY) {
456+
SEPARATE_ARRAY(&_readline_array);
457+
if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) {
458+
matches = rl_completion_matches(text,_readline_command_generator);
459+
} else {
460+
/* libedit will read matches[2] */
461+
matches = calloc(3, sizeof(char *));
462+
if (!matches) {
463+
goto out;
464464
}
465+
matches[0] = strdup("");
465466
}
466467
}
468+
// TODO: TypeError if return value is not array?
467469

468470
out:
469-
zval_ptr_dtor(&params[0]);
470471
zval_ptr_dtor(&_readline_array);
471472

472473
return matches;
@@ -477,12 +478,14 @@ PHP_FUNCTION(readline_completion_function)
477478
zend_fcall_info fci;
478479
zend_fcall_info_cache fcc;
479480

480-
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "f", &fci, &fcc)) {
481+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "F", &fci, &fcc)) {
481482
RETURN_THROWS();
482483
}
483484

484-
zval_ptr_dtor(&_readline_completion);
485-
ZVAL_COPY(&_readline_completion, &fci.function_name);
485+
if (ZEND_FCC_INITIALIZED(_readline_completion)) {
486+
zend_fcc_dtor(&_readline_completion);
487+
}
488+
zend_fcc_dup(&_readline_completion, &fcc);
486489

487490
/* NOTE: The rl_attempted_completion_function variable (and others) are part of the readline library, not php */
488491
rl_attempted_completion_function = php_readline_completion_cb;
@@ -497,14 +500,12 @@ PHP_FUNCTION(readline_completion_function)
497500
static void php_rl_callback_handler(char *the_line)
498501
{
499502
zval params[1];
500-
zval dummy;
501503

502504
_readline_string_zval(&params[0], the_line);
503505

504-
call_user_function(NULL, NULL, &_prepped_callback, &dummy, 1, params);
506+
zend_call_known_fcc(&_prepped_callback, NULL, 1, params, NULL);
505507

506508
zval_ptr_dtor(&params[0]);
507-
zval_ptr_dtor(&dummy);
508509
}
509510

510511
/* {{{ Initializes the readline callback interface and terminal, prints the prompt and returns immediately */
@@ -515,16 +516,16 @@ PHP_FUNCTION(readline_callback_handler_install)
515516
zend_fcall_info_cache fcc;
516517
size_t prompt_len;
517518

518-
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sf", &prompt, &prompt_len, &fci, &fcc)) {
519+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "sF", &prompt, &prompt_len, &fci, &fcc)) {
519520
RETURN_THROWS();
520521
}
521522

522-
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
523+
if (ZEND_FCC_INITIALIZED(_prepped_callback)) {
523524
rl_callback_handler_remove();
524-
zval_ptr_dtor(&_prepped_callback);
525+
zend_fcc_dtor(&_prepped_callback);
525526
}
526527

527-
ZVAL_COPY(&_prepped_callback, &fci.function_name);
528+
zend_fcc_dup(&_prepped_callback, &fcc);
528529

529530
rl_callback_handler_install(prompt, php_rl_callback_handler);
530531

@@ -537,7 +538,7 @@ PHP_FUNCTION(readline_callback_read_char)
537538
{
538539
ZEND_PARSE_PARAMETERS_NONE();
539540

540-
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
541+
if (ZEND_FCC_INITIALIZED(_prepped_callback)) {
541542
rl_callback_read_char();
542543
}
543544
}
@@ -548,10 +549,10 @@ PHP_FUNCTION(readline_callback_handler_remove)
548549
{
549550
ZEND_PARSE_PARAMETERS_NONE();
550551

551-
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
552+
if (ZEND_FCC_INITIALIZED(_prepped_callback)) {
552553
rl_callback_handler_remove();
553-
zval_ptr_dtor(&_prepped_callback);
554-
ZVAL_UNDEF(&_prepped_callback);
554+
zend_fcc_dtor(&_prepped_callback);
555+
_prepped_callback = empty_fcall_info_cache;
555556
RETURN_TRUE;
556557
}
557558
RETURN_FALSE;

0 commit comments

Comments
 (0)