Skip to content

Commit 57c3724

Browse files
committed
Zend: store user exception handler as a FCC
1 parent 63047b1 commit 57c3724

7 files changed

Lines changed: 50 additions & 49 deletions

File tree

Zend/zend.c

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,39 +1928,38 @@ ZEND_API ZEND_COLD void zend_output_debug_string(bool trigger_break, const char
19281928

19291929
ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
19301930
{
1931-
zval orig_user_exception_handler;
1932-
zval params[1], retval2;
1933-
zend_object *old_exception;
1934-
19351931
if (zend_is_unwind_exit(EG(exception))) {
19361932
return;
19371933
}
19381934

1939-
old_exception = EG(exception);
1935+
zend_object *old_exception = EG(exception);
19401936
EG(exception) = NULL;
1937+
1938+
zval params[1];
19411939
ZVAL_OBJ(&params[0], old_exception);
19421940

1943-
ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
1944-
zend_stack_push(&EG(user_exception_handlers), &orig_user_exception_handler);
1945-
ZVAL_UNDEF(&EG(user_exception_handler));
1941+
zend_fcall_info_cache fcc = EG(user_exception_handler);
1942+
/* Push the current handler on the stack and set the current one to the default handler to prevent recursion */
1943+
zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
19461944

1947-
if (call_user_function(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params) == SUCCESS) {
1948-
zval_ptr_dtor(&retval2);
1949-
if (EG(exception)) {
1950-
OBJ_RELEASE(EG(exception));
1951-
EG(exception) = NULL;
1952-
}
1953-
OBJ_RELEASE(old_exception);
1954-
} else {
1955-
EG(exception) = old_exception;
1945+
int current_stack_position = zend_stack_count(&EG(user_exception_handlers));
1946+
1947+
EG(user_exception_handler) = empty_fcall_info_cache;
1948+
1949+
zend_call_known_fcc(&fcc, NULL, 1, params, NULL);
1950+
if (EG(exception)) {
1951+
OBJ_RELEASE(EG(exception));
1952+
EG(exception) = NULL;
19561953
}
1954+
OBJ_RELEASE(old_exception);
19571955

1958-
if (Z_TYPE(EG(user_exception_handler)) == IS_UNDEF) {
1959-
zval *tmp = zend_stack_top(&EG(user_exception_handlers));
1960-
if (tmp) {
1961-
ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
1962-
zend_stack_del_top(&EG(user_exception_handlers));
1963-
}
1956+
if (
1957+
current_stack_position == zend_stack_count(&EG(user_exception_handlers))
1958+
&& !ZEND_FCC_INITIALIZED(EG(user_exception_handler))
1959+
) {
1960+
const zend_fcall_info_cache *tmp = zend_stack_top(&EG(user_exception_handlers));
1961+
EG(user_exception_handler) = *tmp;
1962+
zend_stack_del_top(&EG(user_exception_handlers));
19641963
}
19651964
} /* }}} */
19661965

@@ -1975,7 +1974,7 @@ ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handl
19751974
if (op_array) {
19761975
zend_execute(op_array, retval);
19771976
if (UNEXPECTED(EG(exception))) {
1978-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1977+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) {
19791978
zend_user_exception_handler();
19801979
}
19811980
if (EG(exception)) {

Zend/zend_builtin_functions.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,18 +1349,21 @@ ZEND_FUNCTION(set_exception_handler)
13491349
Z_PARAM_FUNC_OR_NULL(fci, fcc)
13501350
ZEND_PARSE_PARAMETERS_END();
13511351

1352-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1353-
ZVAL_COPY(return_value, &EG(user_exception_handler));
1352+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) {
1353+
zend_get_callable_zval_from_fcc(&EG(user_exception_handler), return_value);
13541354
}
13551355

1356+
/* Push current error handler onto the stack, so that it can be restored later */
13561357
zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
13571358

1358-
if (!ZEND_FCI_INITIALIZED(fci)) { /* unset user-defined handler */
1359-
ZVAL_UNDEF(&EG(user_exception_handler));
1359+
/* if passed null the user want's to use the default PHP error handler */
1360+
if (!ZEND_FCC_INITIALIZED(fcc)) {
1361+
EG(user_exception_handler) = empty_fcall_info_cache;
13601362
return;
13611363
}
13621364

1363-
ZVAL_COPY(&EG(user_exception_handler), &(fci.function_name));
1365+
zend_fcc_dup(&EG(user_exception_handler), &fcc);
1366+
// TODO Need to free trampoline?
13641367
}
13651368
/* }}} */
13661369

@@ -1369,14 +1372,14 @@ ZEND_FUNCTION(restore_exception_handler)
13691372
{
13701373
ZEND_PARSE_PARAMETERS_NONE();
13711374

1372-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1373-
zval_ptr_dtor(&EG(user_exception_handler));
1375+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) {
1376+
zend_fcc_dtor(&EG(user_exception_handler));
1377+
EG(user_exception_handler) = empty_fcall_info_cache;
13741378
}
1375-
if (zend_stack_is_empty(&EG(user_exception_handlers))) {
1376-
ZVAL_UNDEF(&EG(user_exception_handler));
1377-
} else {
1378-
zval *tmp = zend_stack_top(&EG(user_exception_handlers));
1379-
ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
1379+
1380+
if (!zend_stack_is_empty(&EG(user_exception_handlers))) {
1381+
const zend_fcall_info_cache *tmp = zend_stack_top(&EG(user_exception_handlers));
1382+
EG(user_exception_handler) = *tmp;
13801383
zend_stack_del_top(&EG(user_exception_handlers));
13811384
}
13821385

@@ -1389,8 +1392,8 @@ ZEND_FUNCTION(get_exception_handler)
13891392
{
13901393
ZEND_PARSE_PARAMETERS_NONE();
13911394

1392-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1393-
RETURN_COPY(&EG(user_exception_handler));
1395+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) {
1396+
zend_get_callable_zval_from_fcc(&EG(user_exception_handler), return_value);
13941397
}
13951398
}
13961399

Zend/zend_compile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void);
978978

979979
#define zend_try_exception_handler() do { \
980980
if (UNEXPECTED(EG(exception))) { \
981-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) { \
981+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) { \
982982
zend_user_exception_handler(); \
983983
} \
984984
} \

Zend/zend_exceptions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /*
183183
return;
184184
}
185185
if (EG(exception)) {
186-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF
186+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))
187187
&& !zend_is_unwind_exit(EG(exception))
188188
&& !zend_is_graceful_exit(EG(exception))) {
189189
zend_user_exception_handler();

Zend/zend_execute_API.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,13 @@ void init_executor(void) /* {{{ */
161161

162162
EG(current_executed_error_handler_stack_position) = -1;
163163
EG(user_error_handler) = empty_fcall_info_cache;
164-
ZVAL_UNDEF(&EG(user_exception_handler));
164+
EG(user_exception_handler) = empty_fcall_info_cache;
165165

166166
EG(current_execute_data) = NULL;
167167

168168
zend_stack_init(&EG(user_error_handlers_error_reporting), sizeof(int));
169169
zend_stack_init(&EG(user_error_handlers), sizeof(zend_fcall_info_cache));
170-
zend_stack_init(&EG(user_exception_handlers), sizeof(zval));
170+
zend_stack_init(&EG(user_exception_handlers), sizeof(zend_fcall_info_cache));
171171

172172
zend_objects_store_init(&EG(objects_store), 1024);
173173
zend_lazy_objects_init(&EG(lazy_objects_store));
@@ -416,15 +416,14 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
416416
zend_fcc_dtor(&EG(user_error_handler));
417417
EG(user_error_handler) = empty_fcall_info_cache;
418418
}
419-
420-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
421-
zval_ptr_dtor(&EG(user_exception_handler));
422-
ZVAL_UNDEF(&EG(user_exception_handler));
419+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) {
420+
zend_fcc_dtor(&EG(user_exception_handler));
421+
EG(user_exception_handler) = empty_fcall_info_cache;
423422
}
424423

425424
zend_stack_clean(&EG(user_error_handlers_error_reporting), NULL, 1);
426425
zend_stack_clean(&EG(user_error_handlers), (void (*)(void *))zend_fcc_dtor_if_set, true);
427-
zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))ZVAL_PTR_DTOR, 1);
426+
zend_stack_clean(&EG(user_exception_handlers), (void (*)(void *))zend_fcc_dtor_if_set, true);
428427

429428
zend_hash_clean(&EG(callable_convert_cache));
430429
zend_hash_clean(&EG(partial_function_application_cache));

Zend/zend_globals.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ struct _zend_executor_globals {
244244
bool exception_ignore_args;
245245
int current_executed_error_handler_stack_position;
246246
zend_fcall_info_cache user_error_handler;
247-
zval user_exception_handler;
247+
zend_fcall_info_cache user_exception_handler;
248248
zend_stack user_error_handlers_error_reporting;
249249
zend_stack user_error_handlers;
250250
zend_stack user_exception_handlers;

ext/opcache/ZendAccelerator.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4857,7 +4857,7 @@ static zend_result accel_preload(const char *config, bool in_child)
48574857
if (op_array) {
48584858
zend_execute(op_array, NULL);
48594859
if (UNEXPECTED(EG(exception))) {
4860-
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
4860+
if (ZEND_FCC_INITIALIZED(EG(user_exception_handler))) {
48614861
zend_user_exception_handler();
48624862
}
48634863
if (EG(exception)) {

0 commit comments

Comments
 (0)