Skip to content

Commit f8b3a0b

Browse files
committed
ext/spl: refactor autoloading to use newer FCC APIs
1 parent 55dea17 commit f8b3a0b

File tree

1 file changed

+43
-131
lines changed

1 file changed

+43
-131
lines changed

ext/spl/php_spl.c

Lines changed: 43 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -340,67 +340,11 @@ PHP_FUNCTION(spl_autoload_extensions)
340340
}
341341
} /* }}} */
342342

343-
typedef struct {
344-
zend_function *func_ptr;
345-
zend_object *obj;
346-
zend_object *closure;
347-
zend_class_entry *ce;
348-
} autoload_func_info;
349-
350-
static void autoload_func_info_destroy(autoload_func_info *alfi) {
351-
if (alfi->obj) {
352-
zend_object_release(alfi->obj);
353-
}
354-
if (alfi->func_ptr &&
355-
UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
356-
zend_string_release_ex(alfi->func_ptr->common.function_name, 0);
357-
zend_free_trampoline(alfi->func_ptr);
358-
}
359-
if (alfi->closure) {
360-
zend_object_release(alfi->closure);
361-
}
362-
efree(alfi);
363-
}
364-
365343
static void autoload_func_info_zval_dtor(zval *element)
366344
{
367-
autoload_func_info_destroy(Z_PTR_P(element));
368-
}
369-
370-
static autoload_func_info *autoload_func_info_from_fci(
371-
zend_fcall_info *fci, zend_fcall_info_cache *fcc) {
372-
autoload_func_info *alfi = emalloc(sizeof(autoload_func_info));
373-
alfi->ce = fcc->calling_scope;
374-
alfi->func_ptr = fcc->function_handler;
375-
alfi->obj = fcc->object;
376-
if (alfi->obj) {
377-
GC_ADDREF(alfi->obj);
378-
}
379-
if (Z_TYPE(fci->function_name) == IS_OBJECT) {
380-
alfi->closure = Z_OBJ(fci->function_name);
381-
GC_ADDREF(alfi->closure);
382-
} else {
383-
alfi->closure = NULL;
384-
}
385-
return alfi;
386-
}
387-
388-
static bool autoload_func_info_equals(
389-
const autoload_func_info *alfi1, const autoload_func_info *alfi2) {
390-
if (UNEXPECTED(
391-
(alfi1->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) &&
392-
(alfi2->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)
393-
)) {
394-
return alfi1->obj == alfi2->obj
395-
&& alfi1->ce == alfi2->ce
396-
&& alfi1->closure == alfi2->closure
397-
&& zend_string_equals(alfi1->func_ptr->common.function_name, alfi2->func_ptr->common.function_name)
398-
;
399-
}
400-
return alfi1->func_ptr == alfi2->func_ptr
401-
&& alfi1->obj == alfi2->obj
402-
&& alfi1->ce == alfi2->ce
403-
&& alfi1->closure == alfi2->closure;
345+
zend_fcall_info_cache *fcc = Z_PTR_P(element);
346+
zend_fcc_dtor(fcc);
347+
efree(fcc);
404348
}
405349

406350
static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_string *lc_name) {
@@ -410,36 +354,29 @@ static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_stri
410354

411355
/* We don't use ZEND_HASH_MAP_FOREACH here,
412356
* because autoloaders may be added/removed during autoloading. */
413-
HashPosition pos;
357+
HashPosition pos = 0;
414358
zend_hash_internal_pointer_reset_ex(spl_autoload_functions, &pos);
415-
while (1) {
416-
autoload_func_info *alfi =
359+
360+
zval zname;
361+
ZVAL_STR(&zname, class_name);
362+
while (true) {
363+
zend_fcall_info_cache *fcc =
417364
zend_hash_get_current_data_ptr_ex(spl_autoload_functions, &pos);
418-
if (!alfi) {
365+
if (!fcc) {
419366
break;
420367
}
421368

422-
zend_function *func = alfi->func_ptr;
423-
if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
424-
func = emalloc(sizeof(zend_op_array));
425-
memcpy(func, alfi->func_ptr, sizeof(zend_op_array));
426-
zend_string_addref(func->op_array.function_name);
427-
}
428-
429-
zval param;
430-
ZVAL_STR(&param, class_name);
431-
zend_call_known_function(func, alfi->obj, alfi->ce, NULL, 1, &param, NULL);
432-
if (EG(exception)) {
433-
break;
369+
zend_call_known_fcc(fcc, NULL ,1, &zname, NULL);
370+
if (UNEXPECTED(EG(exception))) {
371+
return NULL;
434372
}
435373

436-
if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) {
374+
if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) {
437375
return (zend_class_entry*)ZSTR_GET_CE_CACHE(class_name);
438-
} else {
439-
zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name);
440-
if (ce) {
441-
return ce;
442-
}
376+
}
377+
zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name);
378+
if (ce != NULL) {
379+
return ce;
443380
}
444381

445382
zend_hash_move_forward_ex(spl_autoload_functions, &pos);
@@ -471,14 +408,14 @@ PHP_FUNCTION(spl_autoload_call)
471408
zend_hash_rehash(ht); \
472409
} while (0)
473410

474-
static Bucket *spl_find_registered_function(autoload_func_info *find_alfi) {
411+
static Bucket *spl_find_registered_function(const zend_fcall_info_cache *find_fcc) {
475412
if (!spl_autoload_functions) {
476413
return NULL;
477414
}
478415

479-
autoload_func_info *alfi;
480-
ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) {
481-
if (autoload_func_info_equals(alfi, find_alfi)) {
416+
zend_fcall_info_cache *fcc;
417+
ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, fcc) {
418+
if (zend_fcc_equals(fcc, find_fcc)) {
482419
return _p;
483420
}
484421
} ZEND_HASH_FOREACH_END();
@@ -491,8 +428,7 @@ PHP_FUNCTION(spl_autoload_register)
491428
bool do_throw = 1;
492429
bool prepend = 0;
493430
zend_fcall_info fci = {0};
494-
zend_fcall_info_cache fcc;
495-
autoload_func_info *alfi;
431+
zend_fcall_info_cache fcc = {0};
496432

497433
ZEND_PARSE_PARAMETERS_START(0, 3)
498434
Z_PARAM_OPTIONAL
@@ -508,7 +444,7 @@ PHP_FUNCTION(spl_autoload_register)
508444

509445
if (!spl_autoload_functions) {
510446
ALLOC_HASHTABLE(spl_autoload_functions);
511-
zend_hash_init(spl_autoload_functions, 1, NULL, autoload_func_info_zval_dtor, 0);
447+
zend_hash_init(spl_autoload_functions, 1, NULL, autoload_func_info_zval_dtor, false);
512448
/* Initialize as non-packed hash table for prepend functionality. */
513449
zend_hash_real_init_mixed(spl_autoload_functions);
514450
}
@@ -527,30 +463,19 @@ PHP_FUNCTION(spl_autoload_register)
527463
zend_argument_value_error(1, "must not be the spl_autoload_call() function");
528464
RETURN_THROWS();
529465
}
530-
531-
alfi = autoload_func_info_from_fci(&fci, &fcc);
532-
if (UNEXPECTED(alfi->func_ptr == &EG(trampoline))) {
533-
zend_function *copy = emalloc(sizeof(zend_op_array));
534-
535-
memcpy(copy, alfi->func_ptr, sizeof(zend_op_array));
536-
alfi->func_ptr->common.function_name = NULL;
537-
alfi->func_ptr = copy;
538-
}
539466
} else {
540-
alfi = emalloc(sizeof(autoload_func_info));
541-
alfi->func_ptr = zend_hash_str_find_ptr(
542-
CG(function_table), "spl_autoload", sizeof("spl_autoload") - 1);
543-
alfi->obj = NULL;
544-
alfi->ce = NULL;
545-
alfi->closure = NULL;
467+
fcc.function_handler = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("spl_autoload"));
546468
}
547469

548-
if (spl_find_registered_function(alfi)) {
549-
autoload_func_info_destroy(alfi);
470+
if (spl_find_registered_function(&fcc)) {
471+
/* Release call trampoline */
472+
zend_release_fcall_info_cache(&fcc);
550473
RETURN_TRUE;
551474
}
552475

553-
zend_hash_next_index_insert_ptr(spl_autoload_functions, alfi);
476+
zend_fcall_info_cache *entry = emalloc(sizeof(zend_fcall_info_cache));
477+
zend_fcc_dup(entry, &fcc);
478+
zend_hash_next_index_insert_ptr(spl_autoload_functions, entry);
554479
if (prepend && spl_autoload_functions->nNumOfElements > 1) {
555480
/* Move the newly created element to the head of the hashtable */
556481
HT_MOVE_TAIL_TO_HEAD(spl_autoload_functions);
@@ -592,9 +517,9 @@ PHP_FUNCTION(spl_autoload_unregister)
592517
zend_is_callable_ex(&fci.function_name, NULL, 0, NULL, &fcc, NULL);
593518
}
594519

595-
autoload_func_info *alfi = autoload_func_info_from_fci(&fci, &fcc);
596-
Bucket *p = spl_find_registered_function(alfi);
597-
autoload_func_info_destroy(alfi);
520+
Bucket *p = spl_find_registered_function(&fcc);
521+
/* Release trampoline */
522+
zend_release_fcall_info_cache(&fcc);
598523
if (p) {
599524
zend_hash_del_bucket(spl_autoload_functions, p);
600525
RETURN_TRUE;
@@ -606,32 +531,19 @@ PHP_FUNCTION(spl_autoload_unregister)
606531
/* {{{ Return all registered autoloader functions */
607532
PHP_FUNCTION(spl_autoload_functions)
608533
{
609-
autoload_func_info *alfi;
610-
611534
ZEND_PARSE_PARAMETERS_NONE();
612535

613-
array_init(return_value);
614536
if (spl_autoload_functions) {
615-
ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) {
616-
if (alfi->closure) {
617-
GC_ADDREF(alfi->closure);
618-
add_next_index_object(return_value, alfi->closure);
619-
} else if (alfi->func_ptr->common.scope) {
620-
zval tmp;
621-
622-
array_init(&tmp);
623-
if (alfi->obj) {
624-
GC_ADDREF(alfi->obj);
625-
add_next_index_object(&tmp, alfi->obj);
626-
} else {
627-
add_next_index_str(&tmp, zend_string_copy(alfi->ce->name));
628-
}
629-
add_next_index_str(&tmp, zend_string_copy(alfi->func_ptr->common.function_name));
630-
add_next_index_zval(return_value, &tmp);
631-
} else {
632-
add_next_index_str(return_value, zend_string_copy(alfi->func_ptr->common.function_name));
633-
}
537+
zend_fcall_info_cache *fcc;
538+
539+
array_init_size(return_value, zend_hash_num_elements(spl_autoload_functions));
540+
ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, fcc) {
541+
zval tmp;
542+
zend_get_callable_zval_from_fcc(fcc, &tmp);
543+
add_next_index_zval(return_value, &tmp);
634544
} ZEND_HASH_FOREACH_END();
545+
} else {
546+
RETURN_EMPTY_ARRAY();
635547
}
636548
} /* }}} */
637549

0 commit comments

Comments
 (0)