@@ -758,20 +758,63 @@ ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...);
758758ZEND_API zend_result zend_fcall_info_call (zend_fcall_info * fci , zend_fcall_info_cache * fcc , zval * retval , zval * args );
759759
760760/* Zend FCC API to store and handle PHP userland functions */
761+ extern ZEND_API zend_class_entry * zend_ce_closure ;
762+ ZEND_API const zend_function * zend_get_closure_method_def (zend_object * obj );
763+
764+ static zend_always_inline bool zend_fcc_closure_objects_equals (zend_object * closure1 , zend_object * closure2 )
765+ {
766+ if (closure1 == closure2 ) {
767+ return true;
768+ }
769+ if (!closure1 || !closure2 ) {
770+ return false;
771+ }
772+ if (closure1 -> ce != zend_ce_closure || closure2 -> ce != zend_ce_closure ) {
773+ return false;
774+ }
775+
776+ const zend_function * func1 = zend_get_closure_method_def (closure1 );
777+ const zend_function * func2 = zend_get_closure_method_def (closure2 );
778+
779+ if (!(func1 -> common .fn_flags & ZEND_ACC_FAKE_CLOSURE ) ||
780+ !(func2 -> common .fn_flags & ZEND_ACC_FAKE_CLOSURE )) {
781+ return false;
782+ }
783+ if (func1 == func2 ) {
784+ return true;
785+ }
786+ if (func1 -> type != func2 -> type ||
787+ func1 -> common .scope != func2 -> common .scope ||
788+ !zend_string_equals (func1 -> common .function_name , func2 -> common .function_name )) {
789+ return false;
790+ }
791+
792+ if (func1 -> type == ZEND_USER_FUNCTION ) {
793+ return func1 -> op_array .opcodes == func2 -> op_array .opcodes ;
794+ }
795+
796+ return func1 -> internal_function .handler == func2 -> internal_function .handler ;
797+ }
798+
761799static zend_always_inline bool zend_fcc_equals (const zend_fcall_info_cache * a , const zend_fcall_info_cache * b )
762800{
801+ if (a -> closure || b -> closure ) {
802+ return a -> object == b -> object
803+ && a -> calling_scope == b -> calling_scope
804+ && a -> called_scope == b -> called_scope
805+ && zend_fcc_closure_objects_equals (a -> closure , b -> closure )
806+ ;
807+ }
763808 if (UNEXPECTED ((a -> function_handler -> common .fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE ) &&
764809 (b -> function_handler -> common .fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE ))) {
765810 return a -> object == b -> object
766811 && a -> calling_scope == b -> calling_scope
767- && a -> closure == b -> closure
768812 && zend_string_equals (a -> function_handler -> common .function_name , b -> function_handler -> common .function_name )
769813 ;
770814 }
771815 return a -> function_handler == b -> function_handler
772816 && a -> object == b -> object
773817 && a -> calling_scope == b -> calling_scope
774- && a -> closure == b -> closure
775818 ;
776819}
777820
0 commit comments