@@ -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-
365343static 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
406350static 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 */
607532PHP_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