From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.bugs Subject: bug#34757: Invalid bytecode from byte compiler Date: Fri, 15 Mar 2019 10:08:48 -0400 Message-ID: References: <838sxg1rwz.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="253116"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) Cc: 34757@debbugs.gnu.org, Pip Cet , chuntaro@sakura-games.jp To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Fri Mar 15 15:18:20 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1h4nf8-0013gY-5y for geb-bug-gnu-emacs@m.gmane.org; Fri, 15 Mar 2019 15:18:18 +0100 Original-Received: from localhost ([127.0.0.1]:55929 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h4nf6-0005y4-VY for geb-bug-gnu-emacs@m.gmane.org; Fri, 15 Mar 2019 10:18:17 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:42232) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h4nWC-0006bQ-BK for bug-gnu-emacs@gnu.org; Fri, 15 Mar 2019 10:09:06 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h4nWA-00010I-TE for bug-gnu-emacs@gnu.org; Fri, 15 Mar 2019 10:09:04 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:59989) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1h4nWA-00010C-Jt for bug-gnu-emacs@gnu.org; Fri, 15 Mar 2019 10:09:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1h4nWA-0004D5-8L for bug-gnu-emacs@gnu.org; Fri, 15 Mar 2019 10:09:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 15 Mar 2019 14:09:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 34757 X-GNU-PR-Package: emacs Original-Received: via spool by 34757-submit@debbugs.gnu.org id=B34757.155265893616167 (code B ref 34757); Fri, 15 Mar 2019 14:09:02 +0000 Original-Received: (at 34757) by debbugs.gnu.org; 15 Mar 2019 14:08:56 +0000 Original-Received: from localhost ([127.0.0.1]:45300 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h4nW3-0004Cg-Ko for submit@debbugs.gnu.org; Fri, 15 Mar 2019 10:08:56 -0400 Original-Received: from chene.dit.umontreal.ca ([132.204.246.20]:56262) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1h4nW0-0004CW-3v for 34757@debbugs.gnu.org; Fri, 15 Mar 2019 10:08:54 -0400 Original-Received: from pastel.home (lechon.iro.umontreal.ca [132.204.27.242]) by chene.dit.umontreal.ca (8.14.7/8.14.1) with ESMTP id x2FE8mbl031869; Fri, 15 Mar 2019 10:08:49 -0400 Original-Received: by pastel.home (Postfix, from userid 20848) id BA1EC6AB8D; Fri, 15 Mar 2019 10:08:48 -0400 (EDT) In-Reply-To: <838sxg1rwz.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 15 Mar 2019 10:08:12 +0200") X-NAI-Spam-Flag: NO X-NAI-Spam-Threshold: 5 X-NAI-Spam-Score: 0 X-NAI-Spam-Rules: 2 Rules triggered EDT_SA_DN_PASS=0, RV6504=0 X-NAI-Spam-Version: 2.3.0.9418 : core <6504> : inlines <7034> : streams <1815782> : uri <2813266> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:156382 Archived-At: >> diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el >> index 0b8f8824b4c..4e54e08ce14 100644 >> --- a/lisp/emacs-lisp/bytecomp.el >> +++ b/lisp/emacs-lisp/bytecomp.el >> @@ -3025,6 +3025,7 @@ byte-compile-out-toplevel >> (or (null (cdr rest)) >> (and (memq output-type '(file progn t)) >> (cdr (cdr rest)) >> + (eql (length body) (cdr (car rest))) >> (eq (car (nth 1 rest)) 'byte-discard) >> (progn (setq rest (cdr rest)) t)))) >> (setq maycall nil) ; Only allow one real function call. > > Stefan, any comments? Looks good to me, thanks. I'm personally running with the following patch instead, which is much more risky and hasn't been sufficiently tested yet. Stefan diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index f46cab2c17..573b0489d4 100644 *** a/lisp/emacs-lisp/bytecomp.el --- b/lisp/emacs-lisp/bytecomp.el *************** *** 2990,3059 **** (setq byte-compile-output (byte-optimize-lapcode byte-compile-output))) ! ;; Decompile trivial functions: ! ;; only constants and variables, or a single funcall except in lambdas. ! ;; Except for Lisp_Compiled objects, forms like (foo "hi") ! ;; are still quicker than (byte-code "..." [foo "hi"] 2). ! ;; Note that even (quote foo) must be parsed just as any subr by the ! ;; interpreter, so quote should be compiled into byte-code in some contexts. ! ;; What to leave uncompiled: ! ;; lambda -> never. we used to leave it uncompiled if the body was ! ;; a single atom, but that causes confusion if the docstring ! ;; uses the (file . pos) syntax. Besides, now that we have ! ;; the Lisp_Compiled type, the compiled form is faster. ! ;; eval -> atom, quote or (function atom atom atom) ! ;; progn -> as <> or (progn <> atom) ! ;; file -> as progn, but takes both quotes and atoms, and longer forms. ! (let (rest ! (maycall (not (eq output-type 'lambda))) ; t if we may make a funcall. ! tmp body) ! (cond ! ;; #### This should be split out into byte-compile-nontrivial-function-p. ! ((or (eq output-type 'lambda) ! (nthcdr (if (eq output-type 'file) 50 8) byte-compile-output) ! (assq 'TAG byte-compile-output) ; Not necessary, but speeds up a bit. ! (not (setq tmp (assq 'byte-return byte-compile-output))) ! (progn ! (setq rest (nreverse ! (cdr (memq tmp (reverse byte-compile-output))))) ! (while ! (cond ! ((memq (car (car rest)) '(byte-varref byte-constant)) ! (setq tmp (car (cdr (car rest)))) ! (if (if (eq (car (car rest)) 'byte-constant) ! (or (consp tmp) ! (and (symbolp tmp) ! (not (macroexp--const-symbol-p tmp))))) ! (if maycall ! (setq body (cons (list 'quote tmp) body))) ! (setq body (cons tmp body)))) ! ((and maycall ! ;; Allow a funcall if at most one atom follows it. ! (null (nthcdr 3 rest)) ! (setq tmp (get (car (car rest)) 'byte-opcode-invert)) ! (or (null (cdr rest)) ! (and (memq output-type '(file progn t)) ! (cdr (cdr rest)) ! (eq (car (nth 1 rest)) 'byte-discard) ! (progn (setq rest (cdr rest)) t)))) ! (setq maycall nil) ; Only allow one real function call. ! (setq body (nreverse body)) ! (setq body (list ! (if (and (eq tmp 'funcall) ! (eq (car-safe (car body)) 'quote) ! (symbolp (nth 1 (car body)))) ! (cons (nth 1 (car body)) (cdr body)) ! (cons tmp body)))) ! (or (eq output-type 'file) ! (not (delq nil (mapcar 'consp (cdr (car body)))))))) ! (setq rest (cdr rest))) ! rest)) ! (let ((byte-compile-vector (byte-compile-constants-vector))) ! (list 'byte-code (byte-compile-lapcode byte-compile-output) ! byte-compile-vector byte-compile-maxdepth))) ! ;; it's a trivial function ! ((cdr body) (cons 'progn (nreverse body))) ! ((car body))))) ;; Given BODY, compile it and return a new body. (defun byte-compile-top-level-body (body &optional for-effect) --- 2993,3013 ---- (setq byte-compile-output (byte-optimize-lapcode byte-compile-output))) ! (cond ! ((and (not (eq output-type 'lambda)) ;;The caller really wants (byte-code ...) ! (null (cddr byte-compile-output)) ! (eq (car (nth 0 byte-compile-output)) 'byte-constant) ! (eq (car (nth 1 byte-compile-output)) 'byte-return)) ! ;; Special case for trivial code returning a function. ! ;; This is so that when compiling #'(lambda ...) we return ! ;; a #[...] byte-code object instead of a (byte-code "...") ! ;; expression that returns this object. It's not indispensable, ! ;; but it's cleaner. ! (macroexp-quote (cadr (nth 0 byte-compile-output)))) ! (t ! (let ((byte-compile-vector (byte-compile-constants-vector))) ! (list 'byte-code (byte-compile-lapcode byte-compile-output) ! byte-compile-vector byte-compile-maxdepth))))) ;; Given BODY, compile it and return a new body. (defun byte-compile-top-level-body (body &optional for-effect)