From: Martin A. <ma...@at...> - 2001-07-16 16:24:34
|
I've looked into the wait-for-floating-point-exceptions issue in handler-case, brought up on cmucl-imp around 2001-03-28. This was also on the TODO list for pre-0.7-SBCL (referring to Bill's mail on 2001-05-09). There was a problem in CMUCL, that caused a floating-point-exception, and for that the patch for handler-case was made (more onto that, below). Attached is a patch that has the float-wait instruction in the handler-case macro, ported from CMUCL. It turned out, that CMUCL was using another version of the macro, that was commented out in the CMUCL-sources, but was reinstated around 2000-07. A comment in the CVS logs for SBCL (sbcl-0.6.7.2), said that the older-version of handler-case was deleted. Hmm, I'm not sure, which one the older one was ... ;) The new code looks a bit more "modern" and cleaner, since it uses a TAGBODY for directing the control-flow, but that's merely a matter of style. Well, more importantly, since the original code to trigger the bug, given by Christophe Rhodes, does yield no error in SBCL, neither with the old/new handler-case: I'm not sure, if we should include the patch, but we could do it as CMUCL did, with the old code commented out. :-| The patch may still be relevant for SBCL, but I haven't found a way to trigger the bug, yet. Here are some important pieces from cmucl-imp for that matter: The code that triggered the problem: * (defun make-single-float (bits) (if (zerop bits) ; IEEE float special case 0.0 (let ((sign (ecase (ldb (byte 1 31) bits) (0 1.0) (1 -1.0))) (expt (- (ldb (byte 8 23) bits) 127)) (mant (* (logior (ldb (byte 23 0) bits) (ash 1 23)) (expt 0.5 23)))) (* sign (expt 2.0 expt) mant)))) MAKE-SINGLE-FLOAT * (make-single-float 1) 5.8774716e-39 * (compile 'make-single-float) Compiling LAMBDA (BITS): Arithmetic error FLOATING-POINT-OVERFLOW signalled. -- Subject: Re: Compiler bug? From: Raymond Toy <to...@rt...> Date: 19 Apr 2001 10:49:06 -0400 [...] Raymond> 1. The underlying problem is in safe-expt, despite what the backtrace Raymond> says. The computation is (safe-expt 2.0 128), which causes an Raymond> overflow. Raymond> 2. The real cause of 1 is that handler-case in safe-expt doesn't Raymond> correctly handle the floating-point overflow. Raymond> 3. The backtrace is totally wrong. TWO-ARG-= can't possibly cause an Raymond> overflow. Figured out what the problem is. If you macroexpand the handler-case and handler-bind in safe-expt, you get something like: (LET ((CONDITIONS::*HANDLER-CLUSTERS* (CONS (LIST (CONS 'ERROR #'(LAMBDA (CONDITIONS::TEMP) (DECLARE (IGNORE CONDITIONS::TEMP)) (GO #:G948)))) CONDITIONS::*HANDLER-CLUSTERS*))) (MULTIPLE-VALUE-PROG1 (PROGN (RETURN-FROM #:G946 (EXPT X Y))) (KERNEL:FLOAT-WAIT))) Since FP exceptions aren't signaled until the *next* FP instruction, the expt returns and bypasses the float-wait. I think handler-bind needs the float-wait call. The appended patch does this by adding a float-wait for handler-case. With this change, FP errors should be handled at the appropriate time. [...] -------- Cheers, Martin -- Martin Atzmueller <ma...@at...> |