Mercurial > emacs
changeset 99544:d0522fd272de
(byte-compile-associative)
(byte-compile-minus, byte-compile-quo): If there are more than two
operands, don't use binary operation code (bug#1334).
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Fri, 14 Nov 2008 18:08:10 +0000 |
parents | f96d00b9bf04 |
children | 5b971b30c85d |
files | lisp/emacs-lisp/bytecomp.el |
diffstat | 1 files changed, 33 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/emacs-lisp/bytecomp.el Fri Nov 14 18:07:52 2008 +0000 +++ b/lisp/emacs-lisp/bytecomp.el Fri Nov 14 18:08:10 2008 +0000 @@ -3217,14 +3217,21 @@ (defun byte-compile-associative (form) (if (cdr form) (let ((opcode (get (car form) 'byte-opcode)) - (args (copy-sequence (cdr form)))) - (byte-compile-form (car args)) - (setq args (cdr args)) - (or args (setq args '(0) - opcode (get '+ 'byte-opcode))) - (dolist (arg args) - (byte-compile-form arg) - (byte-compile-out opcode 0))) + args) + (if (and (< 3 (length form)) + (memq opcode (list (get '+ 'byte-opcode) + (get '* 'byte-opcode)))) + ;; Don't use binary operations for > 2 operands, as that + ;; may cause overflow/truncation in float operations. + (byte-compile-normal-call form) + (setq args (copy-sequence (cdr form))) + (byte-compile-form (car args)) + (setq args (cdr args)) + (or args (setq args '(0) + opcode (get '+ 'byte-opcode))) + (dolist (arg args) + (byte-compile-form arg) + (byte-compile-out opcode 0)))) (byte-compile-constant (eval form)))) @@ -3303,24 +3310,30 @@ ((byte-compile-normal-call form))))) (defun byte-compile-minus (form) - (if (null (setq form (cdr form))) - (byte-compile-constant 0) - (byte-compile-form (car form)) - (if (cdr form) - (while (setq form (cdr form)) - (byte-compile-form (car form)) - (byte-compile-out 'byte-diff 0)) - (byte-compile-out 'byte-negate 0)))) + (let ((len (length form))) + (cond + ((= 1 len) (byte-compile-constant 0)) + ((= 2 len) + (byte-compile-form (cadr form)) + (byte-compile-out 'byte-negate 0)) + ((= 3 len) + (byte-compile-form (nth 1 form)) + (byte-compile-form (nth 2 form)) + (byte-compile-out 'byte-diff 0)) + ;; Don't use binary operations for > 2 operands, as that may + ;; cause overflow/truncation in float operations. + (t (byte-compile-normal-call form))))) (defun byte-compile-quo (form) (let ((len (length form))) (cond ((<= len 2) (byte-compile-subr-wrong-args form "2 or more")) + ((= len 3) + (byte-compile-two-args form)) (t - (byte-compile-form (car (setq form (cdr form)))) - (while (setq form (cdr form)) - (byte-compile-form (car form)) - (byte-compile-out 'byte-quo 0)))))) + ;; Don't use binary operations for > 2 operands, as that + ;; may cause overflow/truncation in float operations. + (byte-compile-normal-call form))))) (defun byte-compile-nconc (form) (let ((len (length form)))