Skip to content

Commit f4a7ae7

Browse files
Girgiasnielsdos
andcommitted
Zend: Exception::__toString() no need to allocate the method name
We can create the FCI/FCC pair ourself outside of the loop as the method getTraceAsString is final Co-authored-by: Niels Dossche <[email protected]>
1 parent 3f6e664 commit f4a7ae7

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

Zend/zend_exceptions.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -695,32 +695,43 @@ 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+
base_ce = i_get_exception_base(Z_OBJ_P(exception));
706+
707+
/* As getTraceAsString method is final we can grab it once */
708+
zend_function *getTraceAsString = zend_hash_str_find_ptr(&base_ce->function_table, ZEND_STRL("gettraceasstring"));
709+
ZEND_ASSERT(getTraceAsString && "Method getTraceAsString must exist");
710+
711+
712+
zend_fcall_info fci;
713+
fci.size = sizeof(fci);
714+
ZVAL_UNDEF(&fci.function_name);
715+
fci.retval = &trace;
716+
fci.param_count = 0;
717+
fci.params = NULL;
718+
fci.object = NULL;
719+
fci.named_params = NULL;
720+
721+
zend_fcall_info_cache fcc;
722+
fcc.function_handler = getTraceAsString;
723+
fcc.called_scope = base_ce;
724+
fcc.closure = NULL;
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+
fcc.object = Z_OBJ_P(exception);
733+
fcc.calling_scope = Z_OBJCE_P(exception);
734+
zend_call_function(&fci, &fcc);
724735

725736
if (Z_TYPE(trace) != IS_STRING) {
726737
zval_ptr_dtor(&trace);
@@ -765,11 +776,11 @@ ZEND_METHOD(Exception, __toString)
765776
break;
766777
}
767778
}
768-
zend_string_release_ex(fname, 0);
769779

770780
exception = ZEND_THIS;
771781
/* Reset apply counts */
772-
while (Z_TYPE_P(exception) == IS_OBJECT && (base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), base_ce)) {
782+
zend_class_entry *previous_base_ce;
783+
while (Z_TYPE_P(exception) == IS_OBJECT && (previous_base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), previous_base_ce)) {
773784
if (Z_IS_RECURSIVE_P(exception)) {
774785
Z_UNPROTECT_RECURSION_P(exception);
775786
} else {
@@ -779,13 +790,10 @@ ZEND_METHOD(Exception, __toString)
779790
ZVAL_DEREF(exception);
780791
}
781792

782-
exception = ZEND_THIS;
783-
base_ce = i_get_exception_base(Z_OBJ_P(exception));
784-
785793
/* We store the result in the private property string so we can access
786794
* the result in uncaught exception handlers without memleaks. */
787795
ZVAL_STR(&tmp, str);
788-
zend_update_property_ex(base_ce, Z_OBJ_P(exception), ZSTR_KNOWN(ZEND_STR_STRING), &tmp);
796+
zend_update_property_ex(base_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_STRING), &tmp);
789797

790798
RETURN_STR(str);
791799
}

0 commit comments

Comments
 (0)