@@ -695,32 +695,41 @@ ZEND_METHOD(Exception, __toString)
695695 zval trace , * exception ;
696696 zend_class_entry * base_ce ;
697697 zend_string * str ;
698- zend_fcall_info fci ;
699698 zval rv , tmp ;
700- zend_string * fname ;
701699
702700 ZEND_PARSE_PARAMETERS_NONE ();
703701
704702 str = ZSTR_EMPTY_ALLOC ();
705703
706704 exception = ZEND_THIS ;
707- fname = ZSTR_INIT_LITERAL ("gettraceasstring" , 0 );
705+ /* As getTraceAsString method is final we can grab it once */
706+ zend_function * getTraceAsString = zend_hash_str_find_ptr (& zend_ce_exception -> function_table , ZEND_STRS ("gettraceasstring" ));
707+ ZEND_ASSERT (getTraceAsString && "Method getTraceAsString must exist" );
708+
709+ zend_fcall_info fci = {
710+ .size = sizeof (fci ),
711+ .function_name = {0 },
712+ .retval = & trace ,
713+ .param_count = 0 ,
714+ .params = NULL ,
715+ .object = Z_OBJ_P (exception ),
716+ .named_params = NULL ,
717+ };
718+ zend_fcall_info_cache fcc = {
719+ .function_handler = getTraceAsString ,
720+ .calling_scope = Z_OBJCE_P (exception ),
721+ .called_scope = zend_ce_exception ,
722+ .object = Z_OBJ_P (exception ),
723+ .closure = NULL ,
724+ };
708725
709726 while (exception && Z_TYPE_P (exception ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (exception ), zend_ce_throwable )) {
710727 zend_string * prev_str = str ;
711728 zend_string * message = zval_get_string (GET_PROPERTY (exception , ZEND_STR_MESSAGE ));
712729 zend_string * file = zval_get_string (GET_PROPERTY (exception , ZEND_STR_FILE ));
713730 zend_long line = zval_get_long (GET_PROPERTY (exception , ZEND_STR_LINE ));
714731
715- fci .size = sizeof (fci );
716- ZVAL_STR (& fci .function_name , fname );
717- fci .object = Z_OBJ_P (exception );
718- fci .retval = & trace ;
719- fci .param_count = 0 ;
720- fci .params = NULL ;
721- fci .named_params = NULL ;
722-
723- zend_call_function (& fci , NULL );
732+ zend_call_function (& fci , & fcc );
724733
725734 if (Z_TYPE (trace ) != IS_STRING ) {
726735 zval_ptr_dtor (& trace );
@@ -765,7 +774,6 @@ ZEND_METHOD(Exception, __toString)
765774 break ;
766775 }
767776 }
768- zend_string_release_ex (fname , 0 );
769777
770778 exception = ZEND_THIS ;
771779 /* Reset apply counts */
0 commit comments