PATCH: sjlj exceptions
John David Anglin
dave@hiauly1.hia.nrc.ca
Fri Oct 27 13:21:00 GMT 2000
This patch resolves to some extent the problems noted in these two postings:
< http://gcc.gnu.org/ml/gcc-bugs/2000-08/msg00687.html > and
< http://gcc.gnu.org/ml/gcc-bugs/2000-10/msg00083.html >. My investigation
revealed that the problem is only present when sjlj exceptions are used.
The memory expansion occured in the gcse pass and was a result of the
large number of edges present in functions using sjlj exceptions.
There are two separate parts to the fix. The first part is to define
a nonlocal goto label after the setjmp call when a library version of
setjmp. This fixes the basic block reordering problem noted in this post:
< http://gcc.gnu.org/ml/gcc-bugs/2000-10/msg00526.html >.
The second part is to set current_function_calls_setjmp = 1. This causes
the gcse pass to punt, preventing the memory buildup. I think it is also
necessary to ensure that registers are properly saved. It also causes
all the NOTE_INSN_EH_REGION_[BEG,END] notes to be deleted after the first
pass.
The patch has been tested with a complete bootstrap and check.
DONT_USE_BUILTIN_SETJMP was not defined for this test. The tFile.exp
test now completes in a reasonable 196 seconds on a 735. There are no gcc
regressions. Here are the results of the g++ testsuite.
FAIL: g++.eh/crash4.C caused compiler crash
FAIL: g++.ext/attrib5.C (test for excess errors)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 18)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 20)
FAIL: g++.ext/instantiate2.C not instantiated (test for errors, line 16)
FAIL: g++.ext/instantiate3.C not instantiated (test for errors, line 13)
XPASS: g++.mike/eh33.C (test for excess errors)
XPASS: g++.mike/eh33.C Execution test
XPASS: g++.mike/eh50.C (test for excess errors)
XPASS: g++.mike/eh50.C Execution test
FAIL: g++.other/crash18.C (test for excess errors)
XPASS: g++.pt/static3.C (test for excess errors)
XPASS: g++.pt/static3.C Execution test
XPASS: g++.pt/static6.C (test for excess errors)
Thus, all is ok with g++ testsuite.
Issues:
1) The gcse pass no longer runs when sjlj exceptions are used. It
may be possible to run the gcse pass when using sjlj exceptions but
I think make_edges needs improvement first. Given this, should
sjlj still be the default exception mode? On the otherhand, I
doubt -fno-sjlj-exceptions has ever been tested on the pa.
2) The memory used by the gcse pass is very dependent on the number
of edges created by make_edges. I think make_edges has to try
harder to determine the active handler for call insns and aynchronous
exceptions (see code and notes following line 1157 in flow.c).
Currently, calls without a REG_EH_REGION note generate edges to
all nonlocal labels in the function. The function t7 in tFile.cc
has about 60 nonlocal goto labels on the pa and it is not a very
big function. The gcse pass needed about 40MB peak to handle this.
3) There may be an issue regarding inlining. According to
function_cannot_inline_p, functions with current_function_calls_setjmp
!= 0 are not safe to integrate into other functions. Thus, using
sjlj-exceptions may limit inlining. On the otherhand, I don't
think the above restriction is being adhered to.
4) I suspect that expand_calls needs to be modified to add a nonlocal
goto label after "real" setjmp calls to avoid the basic block
reordering problem noted above. This problem may only occur
when the are multiple setjmp calls.
Dave
--
J. David Anglin dave.anglin@nrc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6605)
2000-10-26 J. David Anglin <dave@hiauly1.hia.nrc.ca>
* libgcc2.c: Don't provide an explicit prototype for longjmp since
this may clash with a previously included one.
* except.c (start_dynamic_handler): Add a nonlocal goto label after
library setjmp calls so flow doesn't get confused and set
current_function_calls_setjmp = 1 because gcse can't build an
accurate cfg in functions which call setjmp.
--- libgcc2.c.orig Sat Oct 21 14:00:41 2000
+++ libgcc2.c Wed Oct 25 19:17:12 2000
@@ -3438,7 +3438,7 @@
method. */
#ifdef DONT_USE_BUILTIN_SETJMP
-extern void longjmp (void *, int);
+extern void longjmp ();
#endif
/* Routine to get the head of the current thread's dynamic handler chain
--- except.c.orig Fri Oct 13 15:58:55 2000
+++ except.c Thu Oct 26 19:50:34 2000
@@ -1351,9 +1351,15 @@
buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
#ifdef DONT_USE_BUILTIN_SETJMP
+ /* Generate a nonlocal goto label so flow doesn't get confused. */
+ rtx lab1 = gen_label_rtx();
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST,
TYPE_MODE (integer_type_node), 1,
buf, Pmode);
+ emit_label (lab1);
+ current_function_has_nonlocal_label = 1;
+ nonlocal_goto_handler_labels
+ = gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
/* If we come back here for a catch, transfer control to the handler. */
jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
#else
@@ -1366,6 +1372,9 @@
}
#endif
+ /* Tell the world that this function calls setjmp. */
+ current_function_calls_setjmp = 1;
+
/* We are committed to this, so update the handler chain. */
emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));
More information about the Gcc-bugs
mailing list