diff options
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog.funvec | 10 | ||||
| -rw-r--r-- | lisp/ChangeLog.lexbind | 256 | ||||
| -rw-r--r-- | lisp/Makefile.in | 9 | ||||
| -rw-r--r-- | lisp/emacs-lisp/byte-lexbind.el | 696 | ||||
| -rw-r--r-- | lisp/emacs-lisp/byte-opt.el | 263 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 884 | ||||
| -rw-r--r-- | lisp/emacs-lisp/disass.el | 15 | ||||
| -rw-r--r-- | lisp/emacs-lisp/lisp-mode.el | 10 | ||||
| -rw-r--r-- | lisp/help-fns.el | 65 | ||||
| -rw-r--r-- | lisp/subr.el | 6 |
10 files changed, 1907 insertions, 307 deletions
diff --git a/lisp/ChangeLog.funvec b/lisp/ChangeLog.funvec new file mode 100644 index 00000000000..0a31b9a590f --- /dev/null +++ b/lisp/ChangeLog.funvec | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | 2004-05-20 Miles Bader <miles@gnu.org> | ||
| 2 | |||
| 3 | * subr.el (functionp): Use `funvecp' instead of | ||
| 4 | `byte-compiled-function-p'. | ||
| 5 | * help-fns.el (describe-function-1): Describe curried functions | ||
| 6 | and other funvecs as such. | ||
| 7 | (help-highlight-arguments): Only format things that look like a | ||
| 8 | function. | ||
| 9 | |||
| 10 | ;; arch-tag: 87f75aac-de53-40d7-96c7-3befaa771cb1 | ||
diff --git a/lisp/ChangeLog.lexbind b/lisp/ChangeLog.lexbind new file mode 100644 index 00000000000..ca491f961d7 --- /dev/null +++ b/lisp/ChangeLog.lexbind | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | 2006-12-04 Miles Bader <miles@gnu.org> | ||
| 2 | |||
| 3 | * Makefile.in (COMPILE_FIRST_STACK_DEPTH): New variable. | ||
| 4 | (compile, compile-always): Use it. | ||
| 5 | |||
| 6 | 2005-10-24 Miles Bader <miles@gnu.org> | ||
| 7 | |||
| 8 | * subr.el (functionp): Re-remove. | ||
| 9 | |||
| 10 | * emacs-lisp/bytecomp.el (byte-compile-closure): Add optional | ||
| 11 | ADD-LAMBDA argument, which we just pass to `byte-compile-lambda'. | ||
| 12 | (byte-compile-defun): Use ADD-LAMBDA arg to `byte-compile-closure' | ||
| 13 | instead of adding lambda ourselves. | ||
| 14 | |||
| 15 | 2004-08-09 Miles Bader <miles@gnu.org> | ||
| 16 | |||
| 17 | Changes from merging the funvec patch: | ||
| 18 | |||
| 19 | * emacs-lisp/bytecomp.el (byte-compile-make-closure): Use `curry' | ||
| 20 | instead of `vector' to create compiled closures. | ||
| 21 | |||
| 22 | Merge funvec patch. | ||
| 23 | |||
| 24 | 2004-04-29 Miles Bader <miles@gnu.org> | ||
| 25 | |||
| 26 | * emacs-lisp/bytecomp.el (byte-compile-top-level): Add new entries | ||
| 27 | to `byte-compile-lexical-environment' at the start, not end. | ||
| 28 | (byte-compile-delay-out): Correctly default STACK-ADJUST to zero. | ||
| 29 | |||
| 30 | * emacs-lisp/byte-opt.el (byte-opt-update-stack-params): Don't | ||
| 31 | crash on no-op lapcode entries (car is nil). | ||
| 32 | |||
| 33 | * emacs-lisp/byte-lexbind.el (byte-compile-make-lambda-lexenv): | ||
| 34 | Push a lexvar onto lexenv, not a vinfo! | ||
| 35 | |||
| 36 | 2004-04-11 Miles Bader <miles@gnu.org> | ||
| 37 | |||
| 38 | * emacs-lisp/bytecomp.el (byte-compile-top-level): Correctly | ||
| 39 | analyze lexically-bound arguments. | ||
| 40 | |||
| 41 | * emacs-lisp/byte-lexbind.el (byte-compile-lforminfo-analyze): | ||
| 42 | Use `append' instead of `nconc'. | ||
| 43 | |||
| 44 | * emacs-lisp/byte-lexbind.el (byte-compile-make-lvarinfo): Don't | ||
| 45 | use backquote to make a mutable data-structure. | ||
| 46 | (byte-compile-lvarinfo-num-refs, byte-compile-lvarinfo-num-sets): | ||
| 47 | Renamed to use `num-' instead of `num'. | ||
| 48 | (byte-compile-make-lambda-lexenv): Adjusted accordingly. | ||
| 49 | |||
| 50 | 2004-04-10 Miles Bader <miles@gnu.org> | ||
| 51 | |||
| 52 | * emacs-lisp/byte-lexbind.el (byte-compile-compute-lforminfo): | ||
| 53 | Look at variable's global specialp state too. | ||
| 54 | |||
| 55 | 2004-04-09 Miles Bader <miles@gnu.org> | ||
| 56 | |||
| 57 | * emacs-lisp/byte-opt.el (byte-optimize-lapcode): Default | ||
| 58 | initial-stack-depth to 0. | ||
| 59 | (byte-optimize-lapcode): Discard the right number of values in | ||
| 60 | the stack-set+discard-->discard optimization. | ||
| 61 | |||
| 62 | 2004-04-02 Miles Bader <miles@gnu.org> | ||
| 63 | |||
| 64 | * emacs-lisp/lisp-mode.el (eval-last-sexp-1): Setup the lexical | ||
| 65 | environment if lexical-binding is enabled. | ||
| 66 | |||
| 67 | 2003-10-14 Miles Bader <miles@gnu.org> | ||
| 68 | |||
| 69 | * emacs-lisp/macroexp.el (macroexpand-all-1): Special-case | ||
| 70 | `backquote-list*' to avoid stack overflows. | ||
| 71 | |||
| 72 | 2003-04-04 Miles Bader <miles@gnu.org> | ||
| 73 | |||
| 74 | * help-fns.el (help-function-arglist): Handle interpreted closures. | ||
| 75 | |||
| 76 | 2002-11-20 Miles Bader <miles@gnu.org> | ||
| 77 | |||
| 78 | * emacs-lisp/bytecomp.el (byte-compile-stack-adjustment): | ||
| 79 | Correctly handle discardN* operators. | ||
| 80 | * emacs-lisp/byte-opt.el (byte-optimize-lapcode): Fix stack-depth | ||
| 81 | tracking errors. | ||
| 82 | |||
| 83 | 2002-08-26 Miles Bader <miles@gnu.org> | ||
| 84 | |||
| 85 | * international/mule.el (make-char): Macroexpand call to | ||
| 86 | charset-id constructed by `byte-compile' hook. | ||
| 87 | |||
| 88 | * emacs-lisp/macroexp.el (macroexpand-all-1): Expand defconst value. | ||
| 89 | |||
| 90 | * emacs-lisp/byte-opt.el (byte-opt-update-stack-params): New macro. | ||
| 91 | (byte-optimize-lapcode): Keep track of stack-depth in final pass too. | ||
| 92 | Add more optimizations for lexical binding. | ||
| 93 | (byte-compile-inline-expand): Macroexpand result of inlining. | ||
| 94 | |||
| 95 | * emacs-lisp/bytecomp.el (byte-compile-lambda): Update call to | ||
| 96 | byte-compile-closure-initial-lexenv-p. | ||
| 97 | (byte-discardN-preserve-tos): Alias to byte-discardN. | ||
| 98 | (byte-compile-push-binding-init): Don't push unused variables on | ||
| 99 | init-lexenv. | ||
| 100 | (byte-compile-push-binding-init): Don't use LFORMINFO if it's nil. | ||
| 101 | (byte-compile-lambda): Don't look at lexical environment unless | ||
| 102 | we're using lexical binding. | ||
| 103 | (byte-compile-defmacro): Correctly generate macros. | ||
| 104 | |||
| 105 | * emacs-lisp/byte-lexbind.el (byte-compile-unbind): Optimize the | ||
| 106 | dynamic-bindings-only case. | ||
| 107 | (byte-compile-bind): Don't special-case unused lexical variables. | ||
| 108 | |||
| 109 | * emacs-lisp/disass.el (disassemble-1): Print arg for discardN ops. | ||
| 110 | |||
| 111 | 2002-08-19 Miles Bader <miles@gnu.org> | ||
| 112 | |||
| 113 | * emacs-lisp/byte-opt.el (byte-decompile-bytecode-1): Handle | ||
| 114 | `byte-discardN-preserve-tos' pseudo-op. | ||
| 115 | (byte-compile-side-effect-and-error-free-ops): Add `byte-stack-ref'. | ||
| 116 | (byte-compile-side-effect-free-ops): Add `byte-vec-ref'. | ||
| 117 | (byte-optimize-lapcode): Add some cases for stack-set/ref ops. | ||
| 118 | Add tracking of stack-depth. Unfinished code to collapse | ||
| 119 | lexical-unbinding sequences. | ||
| 120 | |||
| 121 | * emacs-lisp/bytecomp.el (byte-compile-lapcode): Handle | ||
| 122 | `byte-discardN-preserve-tos' pseudo-op. | ||
| 123 | (byte-compile-top-level): If there are lexical args, output a TAG | ||
| 124 | op to record the initial stack-depth for the optimizer. | ||
| 125 | |||
| 126 | 2002-08-17 Miles Bader <miles@gnu.org> | ||
| 127 | |||
| 128 | * emacs-lisp/bytecomp.el (byte-discardN): Add byte-defop. | ||
| 129 | (byte-compile-lapcode): Include byte-discardN. | ||
| 130 | (byte-compile-lambda): Fixup closure detection. | ||
| 131 | (byte-compile-top-level): Handle arguments for a lexical lambda. | ||
| 132 | (byte-compile-lexical-variable-ref, byte-compile-variable-ref) | ||
| 133 | (byte-compile-variable-set): Use byte-compile-stack-set/ref. | ||
| 134 | (byte-compile-discard): Add new parameters NUM and PRESERVE-TOS. | ||
| 135 | (byte-compile-stack-ref, byte-compile-stack-set): New functions. | ||
| 136 | (byte-compile-push-binding-init): Get the variable list properly | ||
| 137 | from LFORMINFO. | ||
| 138 | |||
| 139 | * emacs-lisp/byte-lexbind.el (byte-compile-lforminfo-analyze): | ||
| 140 | Ignore setq'd variables we're not interested in. | ||
| 141 | (byte-compile-make-lambda-lexenv): Add assertion that closed-over | ||
| 142 | variables be heap allocated. | ||
| 143 | (byte-compile-closure-initial-lexenv-p): Renamed from | ||
| 144 | byte-compile-closure-lexenv-p. | ||
| 145 | (byte-compile-non-stack-bindings-p): Get the variable list | ||
| 146 | properly from LFORMINFO. | ||
| 147 | (byte-compile-maybe-push-heap-environment): Handle the | ||
| 148 | no-closed-over-variables case correctly. | ||
| 149 | (byte-compile-bind): Use byte-compile-stack-set/ref. | ||
| 150 | Don't bother modifying INIT-LEXENV as no one will see the changes. | ||
| 151 | (byte-compile-unbind): Call `byte-compile-discard' to handle | ||
| 152 | unbinding lexical bindings. | ||
| 153 | |||
| 154 | * emacs-lisp/disass.el (disassemble-internal): Handle closures. | ||
| 155 | (disassemble-1): Handle new bytecodes. | ||
| 156 | * emacs-lisp/byte-opt.el (disassemble-offset): Handle new bytecodes. | ||
| 157 | |||
| 158 | 2002-06-16 Miles Bader <miles@gnu.org> | ||
| 159 | |||
| 160 | * emacs-lisp/macroexp.el (macroexp-accumulate): New macro. | ||
| 161 | (macroexpand-all-forms, macroexpand-all-clauses): Use it. | ||
| 162 | * Makefile.in (compile): Undo previous change. | ||
| 163 | |||
| 164 | 2002-06-14 Miles Bader <miles@gnu.org> | ||
| 165 | |||
| 166 | * Makefile.in (COMPILE_FIRST): Add `emacs-lisp/macroexp.el'. | ||
| 167 | (compile): Add a special case that compiles `emacs-lisp/macroexp.el' | ||
| 168 | with an increased max-lisp-eval-depth. | ||
| 169 | |||
| 170 | * emacs-lisp/bytecomp.el: Provide `bytecomp-preload', at the | ||
| 171 | beginning of the file. Require `byte-lexbind' at compile time. | ||
| 172 | Add a few doc string. | ||
| 173 | (byte-compile-push-bytecodes) | ||
| 174 | (byte-compile-push-bytecode-const2): New macros. | ||
| 175 | (byte-compile-lapcode): Use them. Do general code cleanup. | ||
| 176 | (byte-compile-initial-macro-environment): Expand macros in | ||
| 177 | byte-compile-eval before passing to byte-compile-top-level. | ||
| 178 | (byte-compile): Use the `byte-compile-initial-macro-environment'. | ||
| 179 | |||
| 180 | * emacs-lisp/byte-lexbind.el: Require `bytecomp-preload' instead of | ||
| 181 | `bytecomp'. | ||
| 182 | (byte-compile-bind): Use `byte-compile-dynamic-variable-bind' to bind | ||
| 183 | dynamic variables. | ||
| 184 | (byte-compile-maybe-push-heap-environment): Fix function name typo. | ||
| 185 | |||
| 186 | 2002-06-13 Miles Bader <miles@gnu.org> | ||
| 187 | |||
| 188 | Byte compiler lexical binding support (not finished yet): | ||
| 189 | * emacs-lisp/bytecomp.el: Require `macroexp'. | ||
| 190 | (byte-compile-lexical-environment) | ||
| 191 | (byte-compile-current-heap-environment) | ||
| 192 | (byte-compile-current-num-closures): New variables. | ||
| 193 | (0, 178, 179, 180, 181): New byte-opcodes. | ||
| 194 | (byte-compile-lapcode): Handle stack-ref/set opcodes. Signal an | ||
| 195 | error if a delay-output placeholder is not filled in yet. | ||
| 196 | (byte-compile-file-form, byte-compile): Expand all macros with | ||
| 197 | `macroexpand-all'. | ||
| 198 | (byte-compile-file-form-defsubst, byte-compile-form): Don't expand | ||
| 199 | macros here. | ||
| 200 | (byte-compile-make-lambda-lexenv): Autoload. | ||
| 201 | (byte-compile-lambda): Initial code for handling lexically-bound | ||
| 202 | arguments and closures; doesn't work yet. | ||
| 203 | (byte-compile-closure-code-p, byte-compile-make-closure) | ||
| 204 | (byte-compile-closure): New functions. | ||
| 205 | (byte-compile-check-variable, byte-compile-dynamic-variable-op) | ||
| 206 | (byte-compile-dynamic-variable-bind) | ||
| 207 | (byte-compile-lexical-variable-ref, byte-compile-variable-set): | ||
| 208 | New functions. | ||
| 209 | (byte-compile-variable-ref): Remove second argument. Now only | ||
| 210 | handles real variable references (not setting or binding). | ||
| 211 | (byte-compile-push-unknown-constant) | ||
| 212 | (byte-compile-resolve-unknown-constant): New functions. | ||
| 213 | (byte-compile-funarg, byte-compile-funarg-2): Functions removed. | ||
| 214 | (byte-compile-function-form): Use either `byte-compile-constant' | ||
| 215 | or `byte-compile-closure'. | ||
| 216 | (byte-compile-setq): Use `byte-compile-variable-set' instead of | ||
| 217 | `byte-compile-variable-ref'. | ||
| 218 | (apply, mapcar, mapatoms, mapconcat, mapc, sort): | ||
| 219 | `byte-defop-compiler-1's removed. | ||
| 220 | (byte-compile-while): Make sure lexically-bound variables inside | ||
| 221 | the loop don't get stored in an environment outside the loop. | ||
| 222 | (byte-compile-compute-lforminfo): Autoload. | ||
| 223 | (byte-compile-push-binding-init): New function. | ||
| 224 | (byte-compile-let, byte-compile-let*): Handle lexical binding. | ||
| 225 | (byte-compile-defun): Use `byte-compile-closure' to do the work. | ||
| 226 | (byte-compile-defmacro): Use `byte-compile-make-closure'. | ||
| 227 | (byte-compile-defvar): Expand the generated call to `push' since | ||
| 228 | we're past macroexpansion already. | ||
| 229 | (byte-compile-stack-adjustment): New function. | ||
| 230 | (byte-compile-out): Make second arg optional. Rewrite for clarity. | ||
| 231 | (byte-compile-delay-out, byte-compile-delayed-out): New functions. | ||
| 232 | |||
| 233 | * emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): Don't | ||
| 234 | expand macros here. | ||
| 235 | |||
| 236 | * emacs-lisp/macroexp.el (macroexpand-all-1): Expand defmacro forms. | ||
| 237 | |||
| 238 | * emacs-lisp/byte-lexbind.el (byte-compile-make-lvarinfo) | ||
| 239 | (byte-compile-lforminfo-add-var) | ||
| 240 | (byte-compile-lforminfo-note-closure) | ||
| 241 | (byte-compile-compute-lforminfo) | ||
| 242 | (byte-compile-lforminfo-from-lambda) | ||
| 243 | (byte-compile-lforminfo-analyze) | ||
| 244 | (byte-compile-heapenv-add-accessible-env) | ||
| 245 | (byte-compile-heapenv-ensure-access) | ||
| 246 | (byte-compile-rearrange-let-clauses, byte-compile-bind) | ||
| 247 | (byte-compile-unbind): Fix a bunch of typos. | ||
| 248 | |||
| 249 | 2002-06-12 Miles Bader <miles@gnu.org> | ||
| 250 | |||
| 251 | * emacs-lisp/byte-lexbind.el, emacs-lisp/macroexp.el: New files. | ||
| 252 | |||
| 253 | * subr.el (functionp): Function removed (now a subr). | ||
| 254 | * help-fns.el (describe-function-1): Handle interpreted closures. | ||
| 255 | |||
| 256 | ;; arch-tag: bd1b5b8b-fdb2-425d-9ac2-20689fb0ee70 | ||
diff --git a/lisp/Makefile.in b/lisp/Makefile.in index 4effdddff6a..25f7b89c9db 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in | |||
| @@ -71,6 +71,13 @@ AUTOGENEL = loaddefs.el \ | |||
| 71 | cedet/ede/loaddefs.el \ | 71 | cedet/ede/loaddefs.el \ |
| 72 | cedet/srecode/loaddefs.el | 72 | cedet/srecode/loaddefs.el |
| 73 | 73 | ||
| 74 | # Value of max-lisp-eval-depth when compiling initially. | ||
| 75 | # During bootstrapping the byte-compiler is run interpreted when compiling | ||
| 76 | # itself, and uses more stack than usual. | ||
| 77 | # | ||
| 78 | BIG_STACK_DEPTH = 1000 | ||
| 79 | BIG_STACK_OPTS = --eval "(setq max-lisp-eval-depth $(BIG_STACK_DEPTH))" | ||
| 80 | |||
| 74 | # Files to compile before others during a bootstrap. This is done to | 81 | # Files to compile before others during a bootstrap. This is done to |
| 75 | # speed up the bootstrap process. | 82 | # speed up the bootstrap process. |
| 76 | 83 | ||
| @@ -195,7 +202,7 @@ compile-onefile: | |||
| 195 | @echo Compiling $(THEFILE) | 202 | @echo Compiling $(THEFILE) |
| 196 | @# Use byte-compile-refresh-preloaded to try and work around some of | 203 | @# Use byte-compile-refresh-preloaded to try and work around some of |
| 197 | @# the most common bootstrapping problems. | 204 | @# the most common bootstrapping problems. |
| 198 | @$(emacs) -l bytecomp -f byte-compile-refresh-preloaded $(BYTE_COMPILE_EXTRA_FLAGS) -f batch-byte-compile $(THEFILE) | 205 | @$(emacs) -l bytecomp.el -f byte-compile-refresh-preloaded $(BIG_STACK_OPTS) $(BYTE_COMPILE_EXTRA_FLAGS) -f batch-byte-compile $(THEFILE) |
| 199 | 206 | ||
| 200 | # Files MUST be compiled one by one. If we compile several files in a | 207 | # Files MUST be compiled one by one. If we compile several files in a |
| 201 | # row (i.e., in the same instance of Emacs) we can't make sure that | 208 | # row (i.e., in the same instance of Emacs) we can't make sure that |
diff --git a/lisp/emacs-lisp/byte-lexbind.el b/lisp/emacs-lisp/byte-lexbind.el new file mode 100644 index 00000000000..a01829abf50 --- /dev/null +++ b/lisp/emacs-lisp/byte-lexbind.el | |||
| @@ -0,0 +1,696 @@ | |||
| 1 | ;;; byte-lexbind.el --- Lexical binding support for byte-compiler | ||
| 2 | ;; | ||
| 3 | ;; Copyright (C) 2001, 2002 Free Software Foundation, Inc. | ||
| 4 | ;; | ||
| 5 | ;; Author: Miles Bader <miles@gnu.org> | ||
| 6 | ;; Keywords: lisp, compiler, lexical binding | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | ;; | ||
| 27 | |||
| 28 | ;;; Code: | ||
| 29 | |||
| 30 | (require 'bytecomp-preload "bytecomp") | ||
| 31 | |||
| 32 | ;; Downward closures aren't implemented yet, so this should always be nil | ||
| 33 | (defconst byte-compile-use-downward-closures nil | ||
| 34 | "If true, use `downward closures', which are closures that don't cons.") | ||
| 35 | |||
| 36 | (defconst byte-compile-save-window-excursion-uses-eval t | ||
| 37 | "If true, the bytecode for `save-window-excursion' uses eval. | ||
| 38 | This means that the body of the form must be put into a closure.") | ||
| 39 | |||
| 40 | (defun byte-compile-arglist-vars (arglist) | ||
| 41 | "Return a list of the variables in the lambda argument list ARGLIST." | ||
| 42 | (remq '&rest (remq '&optional arglist))) | ||
| 43 | |||
| 44 | |||
| 45 | ;;; Variable extent analysis. | ||
| 46 | |||
| 47 | ;; A `lforminfo' holds information about lexical bindings in a form, and some | ||
| 48 | ;; other info for analysis. It is a cons-cell, where the car is a list of | ||
| 49 | ;; `lvarinfo' stuctures, which form an alist indexed by variable name, and the | ||
| 50 | ;; cdr is the number of closures found in the form: | ||
| 51 | ;; | ||
| 52 | ;; LFORMINFO : ((LVARINFO ...) . NUM-CLOSURES)" | ||
| 53 | ;; | ||
| 54 | ;; A `lvarinfo' holds information about a single lexical variable. It is a | ||
| 55 | ;; list whose car is the variable name (so an lvarinfo is suitable as an alist | ||
| 56 | ;; entry), and the rest of the of which holds information about the variable: | ||
| 57 | ;; | ||
| 58 | ;; LVARINFO : (VAR NUM-REFS NUM-SETS CLOSED-OVER) | ||
| 59 | ;; | ||
| 60 | ;; NUM-REFS is the number of times the variable's value is used | ||
| 61 | ;; NUM-SETS is the number of times the variable's value is set | ||
| 62 | ;; CLOSED-OVER is non-nil if the variable is referenced | ||
| 63 | ;; anywhere but in its original function-level" | ||
| 64 | |||
| 65 | ;;; lvarinfo: | ||
| 66 | |||
| 67 | ;; constructor | ||
| 68 | (defsubst byte-compile-make-lvarinfo (var &optional already-set) | ||
| 69 | (list var 0 (if already-set 1 0) 0 nil)) | ||
| 70 | ;; accessors | ||
| 71 | (defsubst byte-compile-lvarinfo-var (vinfo) (car vinfo)) | ||
| 72 | (defsubst byte-compile-lvarinfo-num-refs (vinfo) (cadr vinfo)) | ||
| 73 | (defsubst byte-compile-lvarinfo-num-sets (vinfo) (nth 3 vinfo)) | ||
| 74 | (defsubst byte-compile-lvarinfo-closed-over-p (vinfo) (nth 4 vinfo)) | ||
| 75 | ;; setters | ||
| 76 | (defsubst byte-compile-lvarinfo-note-ref (vinfo) | ||
| 77 | (setcar (cdr vinfo) (1+ (cadr vinfo)))) | ||
| 78 | (defsubst byte-compile-lvarinfo-note-set (vinfo) | ||
| 79 | (setcar (cddr vinfo) (1+ (nth 3 vinfo)))) | ||
| 80 | (defsubst byte-compile-lvarinfo-note-closure (vinfo) | ||
| 81 | (setcar (nthcdr 4 vinfo) t)) | ||
| 82 | |||
| 83 | ;;; lforminfo: | ||
| 84 | |||
| 85 | ;; constructor | ||
| 86 | (defsubst byte-compile-make-lforminfo () | ||
| 87 | (cons nil 0)) | ||
| 88 | ;; accessors | ||
| 89 | (defalias 'byte-compile-lforminfo-vars 'car) | ||
| 90 | (defalias 'byte-compile-lforminfo-num-closures 'cdr) | ||
| 91 | ;; setters | ||
| 92 | (defsubst byte-compile-lforminfo-add-var (finfo var &optional already-set) | ||
| 93 | (setcar finfo (cons (byte-compile-make-lvarinfo var already-set) | ||
| 94 | (car finfo)))) | ||
| 95 | |||
| 96 | (defun byte-compile-lforminfo-make-closure-flag () | ||
| 97 | "Return a new `closure-flag'." | ||
| 98 | (cons nil nil)) | ||
| 99 | |||
| 100 | (defsubst byte-compile-lforminfo-note-closure (lforminfo lvarinfo closure-flag) | ||
| 101 | "If a variable reference or definition is inside a closure, record that fact. | ||
| 102 | LFORMINFO describes the form currently being analyzed, and LVARINFO | ||
| 103 | describes the variable. CLOSURE-FLAG is either nil, if currently _not_ | ||
| 104 | inside a closure, and otherwise a `closure flag' returned by | ||
| 105 | `byte-compile-lforminfo-make-closure-flag'." | ||
| 106 | (when closure-flag | ||
| 107 | (byte-compile-lvarinfo-note-closure lvarinfo) | ||
| 108 | (unless (car closure-flag) | ||
| 109 | (setcdr lforminfo (1+ (cdr lforminfo))) | ||
| 110 | (setcar closure-flag t)))) | ||
| 111 | |||
| 112 | (defun byte-compile-compute-lforminfo (form &optional special) | ||
| 113 | "Return information about variables lexically bound by FORM. | ||
| 114 | SPECIAL is a list of variables that are special, and so shouldn't be | ||
| 115 | bound lexically (in addition to variable that are considered special | ||
| 116 | because they are declared with `defvar', et al). | ||
| 117 | |||
| 118 | The result is an `lforminfo' data structure." | ||
| 119 | (and | ||
| 120 | (consp form) | ||
| 121 | (let ((lforminfo (byte-compile-make-lforminfo))) | ||
| 122 | (cond ((eq (car form) 'let) | ||
| 123 | ;; Find the bound variables | ||
| 124 | (dolist (clause (cadr form)) | ||
| 125 | (let ((var (if (consp clause) (car clause) clause))) | ||
| 126 | (unless (or (specialp var) (memq var special)) | ||
| 127 | (byte-compile-lforminfo-add-var lforminfo var t)))) | ||
| 128 | ;; Analyze the body | ||
| 129 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 130 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 131 | special nil))) | ||
| 132 | ((eq (car form) 'let*) | ||
| 133 | (dolist (clause (cadr form)) | ||
| 134 | (let ((var (if (consp clause) (car clause) clause))) | ||
| 135 | ;; Analyze each initializer based on the previously | ||
| 136 | ;; bound variables. | ||
| 137 | (when (and (consp clause) lforminfo) | ||
| 138 | (byte-compile-lforminfo-analyze lforminfo (cadr clause) | ||
| 139 | special nil)) | ||
| 140 | (unless (or (specialp var) (memq var special)) | ||
| 141 | (byte-compile-lforminfo-add-var lforminfo var t)))) | ||
| 142 | ;; Analyze the body | ||
| 143 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 144 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 145 | special nil))) | ||
| 146 | ((eq (car form) 'condition-case) | ||
| 147 | ;; `condition-case' currently must dynamically bind the | ||
| 148 | ;; error variable, so do nothing. | ||
| 149 | ) | ||
| 150 | ((memq (car form) '(defun defmacro)) | ||
| 151 | (byte-compile-lforminfo-from-lambda lforminfo (cdr form) special)) | ||
| 152 | ((eq (car form) 'lambda) | ||
| 153 | (byte-compile-lforminfo-from-lambda lforminfo form special)) | ||
| 154 | ((and (consp (car form)) (eq (caar form) 'lambda)) | ||
| 155 | ;; An embedded lambda, which is basically just a `let' | ||
| 156 | (byte-compile-lforminfo-from-lambda lforminfo (cdr form) special))) | ||
| 157 | (if (byte-compile-lforminfo-vars lforminfo) | ||
| 158 | lforminfo | ||
| 159 | nil)))) | ||
| 160 | |||
| 161 | (defun byte-compile-lforminfo-from-lambda (lforminfo lambda special) | ||
| 162 | "Initialize LFORMINFO from the lambda expression LAMBDA. | ||
| 163 | SPECIAL is a list of variables to ignore. | ||
| 164 | The first element of LAMBDA is ignored; it need not actually be `lambda'." | ||
| 165 | ;; Add the arguments | ||
| 166 | (dolist (arg (byte-compile-arglist-vars (cadr lambda))) | ||
| 167 | (byte-compile-lforminfo-add-var lforminfo arg t)) | ||
| 168 | ;; Analyze the body | ||
| 169 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 170 | (byte-compile-lforminfo-analyze-forms lforminfo lambda 2 special nil))) | ||
| 171 | |||
| 172 | (defun byte-compile-lforminfo-analyze (lforminfo form &optional ignore closure-flag) | ||
| 173 | "Update variable information in LFORMINFO by analyzing FORM. | ||
| 174 | IGNORE is a list of variables that shouldn't be analyzed (usually because | ||
| 175 | they're special, or because some inner binding shadows the version in | ||
| 176 | LFORMINFO). CLOSURE-FLAG should be either nil or a `closure flag' created | ||
| 177 | with `byte-compile-lforminfo-make-closure-flag'; the latter indicates that | ||
| 178 | FORM is inside a lambda expression that may close over some variable in | ||
| 179 | LFORMINFO." | ||
| 180 | (cond ((symbolp form) | ||
| 181 | ;; variable reference | ||
| 182 | (unless (member form ignore) | ||
| 183 | (let ((vinfo (assq form (byte-compile-lforminfo-vars lforminfo)))) | ||
| 184 | (when vinfo | ||
| 185 | (byte-compile-lvarinfo-note-ref vinfo) | ||
| 186 | (byte-compile-lforminfo-note-closure lforminfo vinfo | ||
| 187 | closure-flag))))) | ||
| 188 | ;; function call/special form | ||
| 189 | ((consp form) | ||
| 190 | (let ((fun (car form))) | ||
| 191 | (cond | ||
| 192 | ((eq fun 'setq) | ||
| 193 | (pop form) | ||
| 194 | (while form | ||
| 195 | (let ((var (pop form))) | ||
| 196 | (byte-compile-lforminfo-analyze lforminfo (pop form) | ||
| 197 | ignore closure-flag) | ||
| 198 | (unless (member var ignore) | ||
| 199 | (let ((vinfo | ||
| 200 | (assq var (byte-compile-lforminfo-vars lforminfo)))) | ||
| 201 | (when vinfo | ||
| 202 | (byte-compile-lvarinfo-note-set vinfo) | ||
| 203 | (byte-compile-lforminfo-note-closure lforminfo vinfo | ||
| 204 | closure-flag))))))) | ||
| 205 | ((eq fun 'catch) | ||
| 206 | ;; tag | ||
| 207 | (byte-compile-lforminfo-analyze lforminfo (cadr form) | ||
| 208 | ignore closure-flag) | ||
| 209 | ;; `catch' uses a closure for the body | ||
| 210 | (byte-compile-lforminfo-analyze-forms | ||
| 211 | lforminfo form 2 | ||
| 212 | ignore | ||
| 213 | (or closure-flag | ||
| 214 | (and (not byte-compile-use-downward-closures) | ||
| 215 | (byte-compile-lforminfo-make-closure-flag))))) | ||
| 216 | ((eq fun 'cond) | ||
| 217 | (byte-compile-lforminfo-analyze-clauses lforminfo (cdr form) 0 | ||
| 218 | ignore closure-flag)) | ||
| 219 | ((eq fun 'condition-case) | ||
| 220 | ;; `condition-case' separates its body/handlers into | ||
| 221 | ;; separate closures. | ||
| 222 | (unless (or closure-flag byte-compile-use-downward-closures) | ||
| 223 | ;; condition case is implemented by calling a function | ||
| 224 | (setq closure-flag (byte-compile-lforminfo-make-closure-flag))) | ||
| 225 | ;; value form | ||
| 226 | (byte-compile-lforminfo-analyze lforminfo (nth 2 form) | ||
| 227 | ignore closure-flag) | ||
| 228 | ;; the error variable is always bound dynamically (because | ||
| 229 | ;; of the implementation) | ||
| 230 | (when (cadr form) | ||
| 231 | (push (cadr form) ignore)) | ||
| 232 | ;; handlers | ||
| 233 | (byte-compile-lforminfo-analyze-clauses lforminfo | ||
| 234 | (nthcdr 2 form) 1 | ||
| 235 | ignore closure-flag)) | ||
| 236 | ((eq fun '(defvar defconst)) | ||
| 237 | (byte-compile-lforminfo-analyze lforminfo (nth 2 form) | ||
| 238 | ignore closure-flag)) | ||
| 239 | ((memq fun '(defun defmacro)) | ||
| 240 | (byte-compile-lforminfo-analyze-forms lforminfo form 3 | ||
| 241 | ignore closure-flag)) | ||
| 242 | ((eq fun 'function) | ||
| 243 | ;; Analyze an embedded lambda expression [note: we only recognize | ||
| 244 | ;; it within (function ...) as the (lambda ...) for is actually a | ||
| 245 | ;; macro returning (function (lambda ...))]. | ||
| 246 | (when (and (consp (cadr form)) (eq (car (cadr form)) 'lambda)) | ||
| 247 | ;; shadow bound variables | ||
| 248 | (setq ignore | ||
| 249 | (append (byte-compile-arglist-vars (cadr (cadr form))) | ||
| 250 | ignore)) | ||
| 251 | ;; analyze body of lambda | ||
| 252 | (byte-compile-lforminfo-analyze-forms | ||
| 253 | lforminfo (cadr form) 2 | ||
| 254 | ignore | ||
| 255 | (or closure-flag | ||
| 256 | (byte-compile-lforminfo-make-closure-flag))))) | ||
| 257 | ((eq fun 'let) | ||
| 258 | ;; analyze variable inits | ||
| 259 | (byte-compile-lforminfo-analyze-clauses lforminfo (cadr form) 1 | ||
| 260 | ignore closure-flag) | ||
| 261 | ;; shadow bound variables | ||
| 262 | (dolist (clause (cadr form)) | ||
| 263 | (push (if (symbolp clause) clause (car clause)) | ||
| 264 | ignore)) | ||
| 265 | ;; analyze body | ||
| 266 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 267 | ignore closure-flag)) | ||
| 268 | ((eq fun 'let*) | ||
| 269 | (dolist (clause (cadr form)) | ||
| 270 | (if (symbolp clause) | ||
| 271 | ;; shadow bound (to nil) variable | ||
| 272 | (push clause ignore) | ||
| 273 | ;; analyze variable init | ||
| 274 | (byte-compile-lforminfo-analyze lforminfo (cadr clause) | ||
| 275 | ignore closure-flag) | ||
| 276 | ;; shadow bound variable | ||
| 277 | (push (car clause) ignore))) | ||
| 278 | ;; analyze body | ||
| 279 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 280 | ignore closure-flag)) | ||
| 281 | ((eq fun 'quote) | ||
| 282 | ;; do nothing | ||
| 283 | ) | ||
| 284 | ((eq fun 'save-window-excursion) | ||
| 285 | ;; `save-window-excursion' currently uses a funny implementation | ||
| 286 | ;; that requires its body forms be put into a closure (it should | ||
| 287 | ;; be fixed to work more like `save-excursion' etc., do). | ||
| 288 | (byte-compile-lforminfo-analyze-forms | ||
| 289 | lforminfo form 2 | ||
| 290 | ignore | ||
| 291 | (or closure-flag | ||
| 292 | (and byte-compile-save-window-excursion-uses-eval | ||
| 293 | (not byte-compile-use-downward-closures) | ||
| 294 | (byte-compile-lforminfo-make-closure-flag))))) | ||
| 295 | ((and (consp fun) (eq (car fun) 'lambda)) | ||
| 296 | ;; Embedded lambda. These are inlined by the compiler, so | ||
| 297 | ;; we don't treat them like a real closure, more like `let'. | ||
| 298 | ;; analyze inits | ||
| 299 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 300 | ignore closure-flag) | ||
| 301 | |||
| 302 | ;; shadow bound variables | ||
| 303 | (setq ignore (nconc (byte-compile-arglist-vars (cadr fun)) | ||
| 304 | ignore)) | ||
| 305 | ;; analyze body | ||
| 306 | (byte-compile-lforminfo-analyze-forms lforminfo fun 2 | ||
| 307 | ignore closure-flag)) | ||
| 308 | (t | ||
| 309 | ;; For everything else, we just expand each argument (for | ||
| 310 | ;; setq/setq-default this works alright because the | ||
| 311 | ;; variable names are symbols). | ||
| 312 | (byte-compile-lforminfo-analyze-forms lforminfo form 1 | ||
| 313 | ignore closure-flag))))))) | ||
| 314 | |||
| 315 | (defun byte-compile-lforminfo-analyze-forms | ||
| 316 | (lforminfo forms skip ignore closure-flag) | ||
| 317 | "Update variable information in LFORMINFO by analyzing each form in FORMS. | ||
| 318 | The first SKIP elements of FORMS are skipped without analysis. IGNORE | ||
| 319 | is a list of variables that shouldn't be analyzed (usually because | ||
| 320 | they're special, or because some inner binding shadows the version in | ||
| 321 | LFORMINFO). CLOSURE-FLAG should be either nil or a `closure flag' created with | ||
| 322 | `byte-compile-lforminfo-make-closure-flag'; the latter indicates that FORM is | ||
| 323 | inside a lambda expression that may close over some variable in LFORMINFO." | ||
| 324 | (when skip | ||
| 325 | (setq forms (nthcdr skip forms))) | ||
| 326 | (while forms | ||
| 327 | (byte-compile-lforminfo-analyze lforminfo (pop forms) | ||
| 328 | ignore closure-flag))) | ||
| 329 | |||
| 330 | (defun byte-compile-lforminfo-analyze-clauses | ||
| 331 | (lforminfo clauses skip ignore closure-flag) | ||
| 332 | "Update variable information in LFORMINFO by analyzing each clause in CLAUSES. | ||
| 333 | Each clause is a list of forms; any clause that's not a list is ignored. The | ||
| 334 | first SKIP elements of each clause are skipped without analysis. IGNORE is a | ||
| 335 | list of variables that shouldn't be analyzed (usually because they're special, | ||
| 336 | or because some inner binding shadows the version in LFORMINFO). | ||
| 337 | CLOSURE-FLAG should be either nil or a `closure flag' created with | ||
| 338 | `byte-compile-lforminfo-make-closure-flag'; the latter indicates that FORM is | ||
| 339 | inside a lambda expression that may close over some variable in LFORMINFO." | ||
| 340 | (while clauses | ||
| 341 | (let ((clause (pop clauses))) | ||
| 342 | (when (consp clause) | ||
| 343 | (byte-compile-lforminfo-analyze-forms lforminfo clause skip | ||
| 344 | ignore closure-flag))))) | ||
| 345 | |||
| 346 | |||
| 347 | ;;; Lexical environments | ||
| 348 | |||
| 349 | ;; A lexical environment is an alist, where each element is of the form | ||
| 350 | ;; (VAR . (OFFSET . ENV)) where VAR is either a symbol, for normal | ||
| 351 | ;; variables, or an `heapenv' descriptor for references to heap environment | ||
| 352 | ;; vectors. ENV is either an atom, meaning a `stack allocated' variable | ||
| 353 | ;; (the particular atom serves to indicate the particular function context | ||
| 354 | ;; on whose stack it's allocated), or an `heapenv' descriptor (see above), | ||
| 355 | ;; meaning a variable allocated in a heap environment vector. For the | ||
| 356 | ;; later case, an anonymous `variable' holding a pointer to the environment | ||
| 357 | ;; vector may be located by recursively looking up ENV in the environment | ||
| 358 | ;; as if it were a variable (so the entry for that `variable' will have a | ||
| 359 | ;; non-symbol VAR). | ||
| 360 | |||
| 361 | ;; We call a lexical environment a `lexenv', and an entry in it a `lexvar'. | ||
| 362 | |||
| 363 | ;; constructor | ||
| 364 | (defsubst byte-compile-make-lexvar (name offset &optional env) | ||
| 365 | (cons name (cons offset env))) | ||
| 366 | ;; accessors | ||
| 367 | (defsubst byte-compile-lexvar-name (lexvar) (car lexvar)) | ||
| 368 | (defsubst byte-compile-lexvar-offset (lexvar) (cadr lexvar)) | ||
| 369 | (defsubst byte-compile-lexvar-environment (lexvar) (cddr lexvar)) | ||
| 370 | (defsubst byte-compile-lexvar-variable-p (lexvar) (symbolp (car lexvar))) | ||
| 371 | (defsubst byte-compile-lexvar-environment-p (lexvar) | ||
| 372 | (not (symbolp (car lexvar)))) | ||
| 373 | (defsubst byte-compile-lexvar-on-stack-p (lexvar) | ||
| 374 | (atom (byte-compile-lexvar-environment lexvar))) | ||
| 375 | (defsubst byte-compile-lexvar-in-heap-p (lexvar) | ||
| 376 | (not (byte-compile-lexvar-on-stack-p lexvar))) | ||
| 377 | |||
| 378 | (defun byte-compile-make-lambda-lexenv (form closed-over-lexenv) | ||
| 379 | "Return a new lexical environment for a lambda expression FORM. | ||
| 380 | CLOSED-OVER-LEXENV is the lexical environment in which FORM occurs. | ||
| 381 | The returned lexical environment contains two sets of variables: | ||
| 382 | * Variables that were in CLOSED-OVER-LEXENV and used by FORM | ||
| 383 | (all of these will be `heap' variables) | ||
| 384 | * Arguments to FORM (all of these will be `stack' variables)." | ||
| 385 | ;; See if this is a closure or not | ||
| 386 | (let ((closure nil) | ||
| 387 | (lforminfo (byte-compile-make-lforminfo)) | ||
| 388 | (args (byte-compile-arglist-vars (cadr form)))) | ||
| 389 | ;; Add variables from surrounding lexical environment to analysis set | ||
| 390 | (dolist (lexvar closed-over-lexenv) | ||
| 391 | (when (and (byte-compile-lexvar-in-heap-p lexvar) | ||
| 392 | (not (memq (car lexvar) args))) | ||
| 393 | ;; The variable is located in a heap-allocated environment | ||
| 394 | ;; vector, so FORM may use it. Add it to the set of variables | ||
| 395 | ;; that we'll search for in FORM. | ||
| 396 | (byte-compile-lforminfo-add-var lforminfo (car lexvar)))) | ||
| 397 | ;; See how FORM uses these potentially closed-over variables. | ||
| 398 | (byte-compile-lforminfo-analyze lforminfo form args) | ||
| 399 | (let ((lexenv nil)) | ||
| 400 | (dolist (vinfo (byte-compile-lforminfo-vars lforminfo)) | ||
| 401 | (when (> (byte-compile-lvarinfo-num-refs vinfo) 0) | ||
| 402 | ;; FORM uses VINFO's variable, so it must be a closure. | ||
| 403 | (setq closure t) | ||
| 404 | ;; Make sure that the environment in which the variable is | ||
| 405 | ;; located is accessible (since we only ever pass the | ||
| 406 | ;; innermost environment to closures, if it's in some other | ||
| 407 | ;; envionment, there must be path to it from the innermost | ||
| 408 | ;; one). | ||
| 409 | (unless (byte-compile-lexvar-in-heap-p vinfo) | ||
| 410 | ;; To access the variable from FORM, it must be in the heap. | ||
| 411 | (error | ||
| 412 | "Compiler error: lexical variable `%s' should be heap-allocated but is not" | ||
| 413 | (car vinfo))) | ||
| 414 | (let ((closed-over-lexvar (assq (car vinfo) closed-over-lexenv))) | ||
| 415 | (byte-compile-heapenv-ensure-access | ||
| 416 | byte-compile-current-heap-environment | ||
| 417 | (byte-compile-lexvar-environment closed-over-lexvar)) | ||
| 418 | ;; Put this variable in the new lexical environment | ||
| 419 | (push closed-over-lexvar lexenv)))) | ||
| 420 | ;; Fill in the initial stack contents | ||
| 421 | (let ((stackpos 0)) | ||
| 422 | (when closure | ||
| 423 | ;; Add the magic first argument that holds the environment pointer | ||
| 424 | (push (byte-compile-make-lexvar byte-compile-current-heap-environment | ||
| 425 | 0) | ||
| 426 | lexenv) | ||
| 427 | (setq stackpos (1+ stackpos))) | ||
| 428 | ;; Add entries for each argument | ||
| 429 | (dolist (arg args) | ||
| 430 | (push (byte-compile-make-lexvar arg stackpos) lexenv) | ||
| 431 | (setq stackpos (1+ stackpos))) | ||
| 432 | ;; Return the new lexical environment | ||
| 433 | lexenv)))) | ||
| 434 | |||
| 435 | (defun byte-compile-closure-initial-lexenv-p (lexenv) | ||
| 436 | "Return non-nil if LEXENV is the initial lexical environment for a closure. | ||
| 437 | This only works correctly when passed a new lexical environment as | ||
| 438 | returned by `byte-compile-make-lambda-lexenv' (it works by checking to | ||
| 439 | see whether there are any heap-allocated lexical variables in LEXENV)." | ||
| 440 | (let ((closure nil)) | ||
| 441 | (while (and lexenv (not closure)) | ||
| 442 | (when (byte-compile-lexvar-environment-p (pop lexenv)) | ||
| 443 | (setq closure t))) | ||
| 444 | closure)) | ||
| 445 | |||
| 446 | |||
| 447 | ;;; Heap environment vectors | ||
| 448 | |||
| 449 | ;; A `heap environment vector' is heap-allocated vector used to store | ||
| 450 | ;; variable that can't be put onto the stack. | ||
| 451 | ;; | ||
| 452 | ;; They are represented in the compiler by a list of the form | ||
| 453 | ;; | ||
| 454 | ;; (SIZE SIZE-CONST-ID INIT-POSITION . ENVS) | ||
| 455 | ;; | ||
| 456 | ;; SIZE is the current size of the vector (which may be | ||
| 457 | ;; incremented if another variable or environment-reference is added to | ||
| 458 | ;; the end). SIZE-CONST-ID is an `unknown constant id' (as returned by | ||
| 459 | ;; `byte-compile-push-unknown-constant') representing the constant used | ||
| 460 | ;; in the vector initialization code, and INIT-POSITION is a position | ||
| 461 | ;; in the byte-code output (as returned by `byte-compile-delay-out') | ||
| 462 | ;; at which more initialization code can be added. | ||
| 463 | ;; ENVS is a list of other environment vectors accessible form this one, | ||
| 464 | ;; where each element is of the form (ENV . OFFSET). | ||
| 465 | |||
| 466 | ;; constructor | ||
| 467 | (defsubst byte-compile-make-heapenv (size-const-id init-position) | ||
| 468 | (list 0 size-const-id init-position)) | ||
| 469 | ;; accessors | ||
| 470 | (defsubst byte-compile-heapenv-size (heapenv) (car heapenv)) | ||
| 471 | (defsubst byte-compile-heapenv-size-const-id (heapenv) (cadr heapenv)) | ||
| 472 | (defsubst byte-compile-heapenv-init-position (heapenv) (nth 2 heapenv)) | ||
| 473 | (defsubst byte-compile-heapenv-accessible-envs (heapenv) (nthcdr 3 heapenv)) | ||
| 474 | |||
| 475 | (defun byte-compile-heapenv-add-slot (heapenv) | ||
| 476 | "Add a slot to the heap environment HEAPENV and return its offset." | ||
| 477 | (prog1 (car heapenv) (setcar heapenv (1+ (car heapenv))))) | ||
| 478 | |||
| 479 | (defun byte-compile-heapenv-add-accessible-env (heapenv env offset) | ||
| 480 | "Add to HEAPENV's list of accessible environments, ENV at OFFSET." | ||
| 481 | (setcdr (nthcdr 2 heapenv) | ||
| 482 | (cons (cons env offset) | ||
| 483 | (byte-compile-heapenv-accessible-envs heapenv)))) | ||
| 484 | |||
| 485 | (defun byte-compile-push-heapenv () | ||
| 486 | "Generate byte-code to push a new heap environment vector. | ||
| 487 | Sets `byte-compile-current-heap-environment' to the compiler descriptor | ||
| 488 | for the new heap environment. | ||
| 489 | Return a `lexvar' descriptor for the new heap environment." | ||
| 490 | (let ((env-stack-pos byte-compile-depth) | ||
| 491 | size-const-id init-position) | ||
| 492 | ;; Generate code to push the vector | ||
| 493 | (byte-compile-push-constant 'make-vector) | ||
| 494 | (setq size-const-id (byte-compile-push-unknown-constant)) | ||
| 495 | (byte-compile-push-constant nil) | ||
| 496 | (byte-compile-out 'byte-call 2) | ||
| 497 | (setq init-position (byte-compile-delay-out 3)) | ||
| 498 | ;; Now make a heap-environment for the compiler to use | ||
| 499 | (setq byte-compile-current-heap-environment | ||
| 500 | (byte-compile-make-heapenv size-const-id init-position)) | ||
| 501 | (byte-compile-make-lexvar byte-compile-current-heap-environment | ||
| 502 | env-stack-pos))) | ||
| 503 | |||
| 504 | (defun byte-compile-heapenv-ensure-access (heapenv other-heapenv) | ||
| 505 | "Make sure that HEAPENV can be used to access OTHER-HEAPENV. | ||
| 506 | If not, then add a new slot to HEAPENV pointing to OTHER-HEAPENV." | ||
| 507 | (unless (memq heapenv (byte-compile-heapenv-accessible-envs heapenv)) | ||
| 508 | (let ((offset (byte-compile-heapenv-add-slot heapenv))) | ||
| 509 | (byte-compile-heapenv-add-accessible-env heapenv other-heapenv offset)))) | ||
| 510 | |||
| 511 | |||
| 512 | ;;; Variable binding/unbinding | ||
| 513 | |||
| 514 | (defun byte-compile-non-stack-bindings-p (clauses lforminfo) | ||
| 515 | "Return non-nil if any lexical bindings in CLAUSES are not stack-allocated. | ||
| 516 | LFORMINFO should be information about lexical variables being bound." | ||
| 517 | (let ((vars (byte-compile-lforminfo-vars lforminfo))) | ||
| 518 | (or (not (= (length clauses) (length vars))) | ||
| 519 | (progn | ||
| 520 | (while (and vars clauses) | ||
| 521 | (when (byte-compile-lvarinfo-closed-over-p (pop vars)) | ||
| 522 | (setq clauses nil))) | ||
| 523 | (not clauses))))) | ||
| 524 | |||
| 525 | (defun byte-compile-let-clauses-trivial-init-p (clauses) | ||
| 526 | "Return true if let binding CLAUSES all have a `trivial' init value. | ||
| 527 | Trivial means either a constant value, or a simple variable initialization." | ||
| 528 | (or (null clauses) | ||
| 529 | (and (or (atom (car clauses)) | ||
| 530 | (atom (cadr (car clauses))) | ||
| 531 | (eq (car (cadr (car clauses))) 'quote)) | ||
| 532 | (byte-compile-let-clauses-trivial-init-p (cdr clauses))))) | ||
| 533 | |||
| 534 | (defun byte-compile-rearrange-let-clauses (clauses lforminfo) | ||
| 535 | "Return CLAUSES rearranged so non-stack variables come last if possible. | ||
| 536 | Care is taken to only do so when it's clear that the meaning is the same. | ||
| 537 | LFORMINFO should be information about lexical variables being bound." | ||
| 538 | ;; We currently do a very simple job by only exchanging clauses when | ||
| 539 | ;; one has a constant init, or one has a variable init and the other | ||
| 540 | ;; doesn't have a function call init (because that could change the | ||
| 541 | ;; value of the variable). This could be more clever and actually | ||
| 542 | ;; attempt to analyze which variables could possible be changed, etc. | ||
| 543 | (let ((unchanged nil) | ||
| 544 | (lex-non-stack nil) | ||
| 545 | (dynamic nil)) | ||
| 546 | (while clauses | ||
| 547 | (let* ((clause (pop clauses)) | ||
| 548 | (var (if (consp clause) (car clause) clause)) | ||
| 549 | (init (and (consp clause) (cadr clause))) | ||
| 550 | (vinfo (assq var (byte-compile-lforminfo-vars lforminfo)))) | ||
| 551 | (cond | ||
| 552 | ((or (and vinfo | ||
| 553 | (not (byte-compile-lvarinfo-closed-over-p vinfo))) | ||
| 554 | (not | ||
| 555 | (or (eq init nil) (eq init t) | ||
| 556 | (and (atom init) (not (symbolp init))) | ||
| 557 | (and (consp init) (eq (car init) 'quote)) | ||
| 558 | (byte-compile-let-clauses-trivial-init-p clauses)))) | ||
| 559 | (push clause unchanged)) | ||
| 560 | (vinfo | ||
| 561 | (push clause lex-non-stack)) | ||
| 562 | (t | ||
| 563 | (push clause dynamic))))) | ||
| 564 | (nconc (nreverse unchanged) (nreverse lex-non-stack) (nreverse dynamic)))) | ||
| 565 | |||
| 566 | (defun byte-compile-maybe-push-heap-environment (&optional lforminfo) | ||
| 567 | "Push a new heap environment if necessary. | ||
| 568 | LFORMINFO should be information about lexical variables being bound. | ||
| 569 | Return a lexical environment containing only the heap vector (or | ||
| 570 | nil if nothing was pushed). | ||
| 571 | Also, `byte-compile-current-heap-environment' and | ||
| 572 | `byte-compile-current-num-closures' are updated to reflect any change (so they | ||
| 573 | should probably be bound by the caller to ensure that the new values have the | ||
| 574 | proper scope)." | ||
| 575 | ;; We decide whether a new heap environment is required by seeing if | ||
| 576 | ;; the number of closures inside the form described by LFORMINFO is | ||
| 577 | ;; the same as the number inside the binding form that created the | ||
| 578 | ;; currently active heap environment. | ||
| 579 | (let ((nclosures | ||
| 580 | (and lforminfo (byte-compile-lforminfo-num-closures lforminfo)))) | ||
| 581 | (if (or (null lforminfo) | ||
| 582 | (= nclosures byte-compile-current-num-closures)) | ||
| 583 | ;; No need to push a heap environment. | ||
| 584 | nil | ||
| 585 | ;; Have to push one. A heap environment is really just a vector, so | ||
| 586 | ;; we emit bytecodes to create a vector. However, the size is not | ||
| 587 | ;; fixed yet (the vector can grow if subforms use it to store | ||
| 588 | ;; values, and if `access points' to parent heap environments are | ||
| 589 | ;; added), so we use `byte-compile-push-unknown-constant' to push the | ||
| 590 | ;; vector size. | ||
| 591 | (setq byte-compile-current-num-closures nclosures) | ||
| 592 | (list (byte-compile-push-heapenv))))) | ||
| 593 | |||
| 594 | (defun byte-compile-bind (var init-lexenv &optional lforminfo) | ||
| 595 | "Emit byte-codes to bind VAR and update `byte-compile-lexical-environment'. | ||
| 596 | INIT-LEXENV should be a lexical-environment alist describing the | ||
| 597 | positions of the init value that have been pushed on the stack, and | ||
| 598 | LFORMINFO should be information about lexical variables being bound. | ||
| 599 | Return non-nil if the TOS value was popped." | ||
| 600 | ;; The presence of lexical bindings mean that we may have to | ||
| 601 | ;; juggle things on the stack, either to move them to TOS for | ||
| 602 | ;; dynamic binding, or to put them in a non-stack environment | ||
| 603 | ;; vector. | ||
| 604 | (let ((vinfo (assq var (byte-compile-lforminfo-vars lforminfo)))) | ||
| 605 | (cond ((and (null vinfo) (eq var (caar init-lexenv))) | ||
| 606 | ;; VAR is dynamic and is on the top of the | ||
| 607 | ;; stack, so we can just bind it like usual | ||
| 608 | (byte-compile-dynamic-variable-bind var) | ||
| 609 | t) | ||
| 610 | ((null vinfo) | ||
| 611 | ;; VAR is dynamic, but we have to get its | ||
| 612 | ;; value out of the middle of the stack | ||
| 613 | (let ((stack-pos (cdr (assq var init-lexenv)))) | ||
| 614 | (byte-compile-stack-ref stack-pos) | ||
| 615 | (byte-compile-dynamic-variable-bind var) | ||
| 616 | ;; Now we have to store nil into its temporary | ||
| 617 | ;; stack position to avoid problems with GC | ||
| 618 | (byte-compile-push-constant nil) | ||
| 619 | (byte-compile-stack-set stack-pos)) | ||
| 620 | nil) | ||
| 621 | ((byte-compile-lvarinfo-closed-over-p vinfo) | ||
| 622 | ;; VAR is lexical, but needs to be in a | ||
| 623 | ;; heap-allocated environment. | ||
| 624 | (unless byte-compile-current-heap-environment | ||
| 625 | (error "No current heap-environment to allocate `%s' in!" var)) | ||
| 626 | (let ((init-stack-pos | ||
| 627 | ;; nil if the init value is on the top of the stack, | ||
| 628 | ;; otherwise the position of the init value on the stack. | ||
| 629 | (and (not (eq var (caar init-lexenv))) | ||
| 630 | (byte-compile-lexvar-offset (assq var init-lexenv)))) | ||
| 631 | (env-vec-pos | ||
| 632 | ;; Position of VAR in the environment vector | ||
| 633 | (byte-compile-lexvar-offset | ||
| 634 | (assq var byte-compile-lexical-environment))) | ||
| 635 | (env-vec-stack-pos | ||
| 636 | ;; Position of the the environment vector on the stack | ||
| 637 | ;; (the heap-environment must _always_ be available on | ||
| 638 | ;; the stack!) | ||
| 639 | (byte-compile-lexvar-offset | ||
| 640 | (assq byte-compile-current-heap-environment | ||
| 641 | byte-compile-lexical-environment)))) | ||
| 642 | (unless env-vec-stack-pos | ||
| 643 | (error "Couldn't find location of current heap environment!")) | ||
| 644 | (when init-stack-pos | ||
| 645 | ;; VAR is not on the top of the stack, so get it | ||
| 646 | (byte-compile-stack-ref init-stack-pos)) | ||
| 647 | (byte-compile-stack-ref env-vec-stack-pos) | ||
| 648 | ;; Store the variable into the vector | ||
| 649 | (byte-compile-out 'byte-vec-set env-vec-pos) | ||
| 650 | (when init-stack-pos | ||
| 651 | ;; Store nil into VAR's temporary stack | ||
| 652 | ;; position to avoid problems with GC | ||
| 653 | (byte-compile-push-constant nil) | ||
| 654 | (byte-compile-stack-set init-stack-pos)) | ||
| 655 | ;; Push a record of VAR's new lexical binding | ||
| 656 | (push (byte-compile-make-lexvar | ||
| 657 | var env-vec-pos byte-compile-current-heap-environment) | ||
| 658 | byte-compile-lexical-environment) | ||
| 659 | (not init-stack-pos))) | ||
| 660 | (t | ||
| 661 | ;; VAR is a simple stack-allocated lexical variable | ||
| 662 | (push (assq var init-lexenv) | ||
| 663 | byte-compile-lexical-environment) | ||
| 664 | nil)))) | ||
| 665 | |||
| 666 | (defun byte-compile-unbind (clauses init-lexenv | ||
| 667 | &optional lforminfo preserve-body-value) | ||
| 668 | "Emit byte-codes to unbind the variables bound by CLAUSES. | ||
| 669 | CLAUSES is a `let'-style variable binding list. INIT-LEXENV should be a | ||
| 670 | lexical-environment alist describing the positions of the init value that | ||
| 671 | have been pushed on the stack, and LFORMINFO should be information about | ||
| 672 | the lexical variables that were bound. If PRESERVE-BODY-VALUE is true, | ||
| 673 | then an additional value on the top of the stack, above any lexical binding | ||
| 674 | slots, is preserved, so it will be on the top of the stack after all | ||
| 675 | binding slots have been popped." | ||
| 676 | ;; Unbind dynamic variables | ||
| 677 | (let ((num-dynamic-bindings 0)) | ||
| 678 | (if lforminfo | ||
| 679 | (dolist (clause clauses) | ||
| 680 | (unless (assq (if (consp clause) (car clause) clause) | ||
| 681 | (byte-compile-lforminfo-vars lforminfo)) | ||
| 682 | (setq num-dynamic-bindings (1+ num-dynamic-bindings)))) | ||
| 683 | (setq num-dynamic-bindings (length clauses))) | ||
| 684 | (unless (zerop num-dynamic-bindings) | ||
| 685 | (byte-compile-out 'byte-unbind num-dynamic-bindings))) | ||
| 686 | ;; Pop lexical variables off the stack, possibly preserving the | ||
| 687 | ;; return value of the body. | ||
| 688 | (when init-lexenv | ||
| 689 | ;; INIT-LEXENV contains all init values left on the stack | ||
| 690 | (byte-compile-discard (length init-lexenv) preserve-body-value))) | ||
| 691 | |||
| 692 | |||
| 693 | (provide 'byte-lexbind) | ||
| 694 | |||
| 695 | ;;; arch-tag: b8f1dff6-9edb-4430-a96f-323d42a681a9 | ||
| 696 | ;;; byte-lexbind.el ends here | ||
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index e461010a6ce..4c0094dd78b 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el | |||
| @@ -186,8 +186,8 @@ | |||
| 186 | (eval-when-compile (require 'cl)) | 186 | (eval-when-compile (require 'cl)) |
| 187 | 187 | ||
| 188 | (defun byte-compile-log-lap-1 (format &rest args) | 188 | (defun byte-compile-log-lap-1 (format &rest args) |
| 189 | (if (aref byte-code-vector 0) | 189 | ;; (if (aref byte-code-vector 0) |
| 190 | (error "The old version of the disassembler is loaded. Reload new-bytecomp as well")) | 190 | ;; (error "The old version of the disassembler is loaded. Reload new-bytecomp as well")) |
| 191 | (byte-compile-log-1 | 191 | (byte-compile-log-1 |
| 192 | (apply 'format format | 192 | (apply 'format format |
| 193 | (let (c a) | 193 | (let (c a) |
| @@ -281,7 +281,8 @@ | |||
| 281 | (byte-code ,string ,(aref fn 2) ,(aref fn 3))) | 281 | (byte-code ,string ,(aref fn 2) ,(aref fn 3))) |
| 282 | (cdr form))) | 282 | (cdr form))) |
| 283 | (if (eq (car-safe fn) 'lambda) | 283 | (if (eq (car-safe fn) 'lambda) |
| 284 | (cons fn (cdr form)) | 284 | (macroexpand-all (cons fn (cdr form)) |
| 285 | byte-compile-macro-environment) | ||
| 285 | ;; Give up on inlining. | 286 | ;; Give up on inlining. |
| 286 | form)))))) | 287 | form)))))) |
| 287 | 288 | ||
| @@ -1332,14 +1333,15 @@ | |||
| 1332 | ((>= op byte-constant) | 1333 | ((>= op byte-constant) |
| 1333 | (prog1 (- op byte-constant) ;offset in opcode | 1334 | (prog1 (- op byte-constant) ;offset in opcode |
| 1334 | (setq op byte-constant))) | 1335 | (setq op byte-constant))) |
| 1335 | ((and (>= op byte-constant2) | 1336 | ((or (and (>= op byte-constant2) |
| 1336 | (<= op byte-goto-if-not-nil-else-pop)) | 1337 | (<= op byte-goto-if-not-nil-else-pop)) |
| 1338 | (= op byte-stack-set2)) | ||
| 1337 | (setq ptr (1+ ptr)) ;offset in next 2 bytes | 1339 | (setq ptr (1+ ptr)) ;offset in next 2 bytes |
| 1338 | (+ (aref bytes ptr) | 1340 | (+ (aref bytes ptr) |
| 1339 | (progn (setq ptr (1+ ptr)) | 1341 | (progn (setq ptr (1+ ptr)) |
| 1340 | (lsh (aref bytes ptr) 8)))) | 1342 | (lsh (aref bytes ptr) 8)))) |
| 1341 | ((and (>= op byte-listN) | 1343 | ((and (>= op byte-listN) |
| 1342 | (<= op byte-insertN)) | 1344 | (<= op byte-discardN)) |
| 1343 | (setq ptr (1+ ptr)) ;offset in next byte | 1345 | (setq ptr (1+ ptr)) ;offset in next byte |
| 1344 | (aref bytes ptr)))) | 1346 | (aref bytes ptr)))) |
| 1345 | 1347 | ||
| @@ -1400,7 +1402,16 @@ | |||
| 1400 | (if (= ptr (1- length)) | 1402 | (if (= ptr (1- length)) |
| 1401 | (setq op nil) | 1403 | (setq op nil) |
| 1402 | (setq offset (or endtag (setq endtag (byte-compile-make-tag))) | 1404 | (setq offset (or endtag (setq endtag (byte-compile-make-tag))) |
| 1403 | op 'byte-goto)))) | 1405 | op 'byte-goto))) |
| 1406 | ((eq op 'byte-stack-set2) | ||
| 1407 | (setq op 'byte-stack-set)) | ||
| 1408 | ((and (eq op 'byte-discardN) (>= offset #x80)) | ||
| 1409 | ;; The top bit of the operand for byte-discardN is a flag, | ||
| 1410 | ;; saying whether the top-of-stack is preserved. In | ||
| 1411 | ;; lapcode, we represent this by using a different opcode | ||
| 1412 | ;; (with the flag removed from the operand). | ||
| 1413 | (setq op 'byte-discardN-preserve-tos) | ||
| 1414 | (setq offset (- offset #x80)))) | ||
| 1404 | ;; lap = ( [ (pc . (op . arg)) ]* ) | 1415 | ;; lap = ( [ (pc . (op . arg)) ]* ) |
| 1405 | (setq lap (cons (cons optr (cons op (or offset 0))) | 1416 | (setq lap (cons (cons optr (cons op (or offset 0))) |
| 1406 | lap)) | 1417 | lap)) |
| @@ -1456,7 +1467,7 @@ | |||
| 1456 | byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max | 1467 | byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max |
| 1457 | byte-point-min byte-following-char byte-preceding-char | 1468 | byte-point-min byte-following-char byte-preceding-char |
| 1458 | byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp | 1469 | byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp |
| 1459 | byte-current-buffer byte-interactive-p)) | 1470 | byte-current-buffer byte-interactive-p byte-stack-ref)) |
| 1460 | 1471 | ||
| 1461 | (defconst byte-compile-side-effect-free-ops | 1472 | (defconst byte-compile-side-effect-free-ops |
| 1462 | (nconc | 1473 | (nconc |
| @@ -1465,7 +1476,7 @@ | |||
| 1465 | byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate | 1476 | byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate |
| 1466 | byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax | 1477 | byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax |
| 1467 | byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt | 1478 | byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt |
| 1468 | byte-member byte-assq byte-quo byte-rem) | 1479 | byte-member byte-assq byte-quo byte-rem byte-vec-ref) |
| 1469 | byte-compile-side-effect-and-error-free-ops)) | 1480 | byte-compile-side-effect-and-error-free-ops)) |
| 1470 | 1481 | ||
| 1471 | ;; This crock is because of the way DEFVAR_BOOL variables work. | 1482 | ;; This crock is because of the way DEFVAR_BOOL variables work. |
| @@ -1498,12 +1509,50 @@ | |||
| 1498 | ;; The variable `byte-boolean-vars' is now primitive and updated | 1509 | ;; The variable `byte-boolean-vars' is now primitive and updated |
| 1499 | ;; automatically by DEFVAR_BOOL. | 1510 | ;; automatically by DEFVAR_BOOL. |
| 1500 | 1511 | ||
| 1512 | (defmacro byte-opt-update-stack-params (stack-adjust stack-depth lap0 rest lap) | ||
| 1513 | "...macro used by byte-optimize-lapcode..." | ||
| 1514 | `(progn | ||
| 1515 | (byte-compile-log-lap "Before %s [depth = %s]" ,lap0 ,stack-depth) | ||
| 1516 | (cond ((eq (car ,lap0) 'TAG) | ||
| 1517 | ;; A tag can encode the expected stack depth. | ||
| 1518 | (when (cddr ,lap0) | ||
| 1519 | ;; First, check to see if our notion of the current stack | ||
| 1520 | ;; depth agrees with this tag. We don't check at the | ||
| 1521 | ;; beginning of the function, because the presence of | ||
| 1522 | ;; lexical arguments means the first tag will have a | ||
| 1523 | ;; non-zero offset. | ||
| 1524 | (when (and (not (eq ,rest ,lap)) ; not at first insn | ||
| 1525 | ,stack-depth ; not just after a goto | ||
| 1526 | (not (= (cddr ,lap0) ,stack-depth))) | ||
| 1527 | (error "Compiler error: optimizer is confused about %s: | ||
| 1528 | %s != %s at lapcode %s" ',stack-depth (cddr ,lap0) ,stack-depth ,lap0)) | ||
| 1529 | ;; Now set out current depth from this tag | ||
| 1530 | (setq ,stack-depth (cddr ,lap0))) | ||
| 1531 | (setq ,stack-adjust 0)) | ||
| 1532 | ((memq (car ,lap0) '(byte-goto byte-return)) | ||
| 1533 | ;; These insns leave us in an unknown state | ||
| 1534 | (setq ,stack-adjust nil)) | ||
| 1535 | ((car ,lap0) | ||
| 1536 | ;; Not a no-op, set ,stack-adjust for lap0. ,stack-adjust will | ||
| 1537 | ;; be added to ,stack-depth at the end of the loop, so any code | ||
| 1538 | ;; that modifies the instruction sequence must adjust this too. | ||
| 1539 | (setq ,stack-adjust | ||
| 1540 | (byte-compile-stack-adjustment (car ,lap0) (cdr ,lap0))))) | ||
| 1541 | (byte-compile-log-lap "Before %s [depth => %s, adj = %s]" ,lap0 ,stack-depth ,stack-adjust) | ||
| 1542 | )) | ||
| 1543 | |||
| 1501 | (defun byte-optimize-lapcode (lap &optional for-effect) | 1544 | (defun byte-optimize-lapcode (lap &optional for-effect) |
| 1502 | "Simple peephole optimizer. LAP is both modified and returned. | 1545 | "Simple peephole optimizer. LAP is both modified and returned. |
| 1503 | If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | 1546 | If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." |
| 1504 | (let (lap0 | 1547 | (let (lap0 |
| 1505 | lap1 | 1548 | lap1 |
| 1506 | lap2 | 1549 | lap2 |
| 1550 | stack-adjust | ||
| 1551 | stack-depth | ||
| 1552 | (initial-stack-depth | ||
| 1553 | (if (and lap (eq (car (car lap)) 'TAG)) | ||
| 1554 | (cdr (cdr (car lap))) | ||
| 1555 | 0)) | ||
| 1507 | (keep-going 'first-time) | 1556 | (keep-going 'first-time) |
| 1508 | (add-depth 0) | 1557 | (add-depth 0) |
| 1509 | rest tmp tmp2 tmp3 | 1558 | rest tmp tmp2 tmp3 |
| @@ -1514,12 +1563,15 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1514 | (or (eq keep-going 'first-time) | 1563 | (or (eq keep-going 'first-time) |
| 1515 | (byte-compile-log-lap " ---- next pass")) | 1564 | (byte-compile-log-lap " ---- next pass")) |
| 1516 | (setq rest lap | 1565 | (setq rest lap |
| 1566 | stack-depth initial-stack-depth | ||
| 1517 | keep-going nil) | 1567 | keep-going nil) |
| 1518 | (while rest | 1568 | (while rest |
| 1519 | (setq lap0 (car rest) | 1569 | (setq lap0 (car rest) |
| 1520 | lap1 (nth 1 rest) | 1570 | lap1 (nth 1 rest) |
| 1521 | lap2 (nth 2 rest)) | 1571 | lap2 (nth 2 rest)) |
| 1522 | 1572 | ||
| 1573 | (byte-opt-update-stack-params stack-adjust stack-depth lap0 rest lap) | ||
| 1574 | |||
| 1523 | ;; You may notice that sequences like "dup varset discard" are | 1575 | ;; You may notice that sequences like "dup varset discard" are |
| 1524 | ;; optimized but sequences like "dup varset TAG1: discard" are not. | 1576 | ;; optimized but sequences like "dup varset TAG1: discard" are not. |
| 1525 | ;; You may be tempted to change this; resist that temptation. | 1577 | ;; You may be tempted to change this; resist that temptation. |
| @@ -1533,22 +1585,22 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1533 | ((and (eq 'byte-discard (car lap1)) | 1585 | ((and (eq 'byte-discard (car lap1)) |
| 1534 | (memq (car lap0) side-effect-free)) | 1586 | (memq (car lap0) side-effect-free)) |
| 1535 | (setq keep-going t) | 1587 | (setq keep-going t) |
| 1536 | (setq tmp (aref byte-stack+-info (symbol-value (car lap0)))) | ||
| 1537 | (setq rest (cdr rest)) | 1588 | (setq rest (cdr rest)) |
| 1538 | (cond ((= tmp 1) | 1589 | (cond ((= stack-adjust 1) |
| 1539 | (byte-compile-log-lap | 1590 | (byte-compile-log-lap |
| 1540 | " %s discard\t-->\t<deleted>" lap0) | 1591 | " %s discard\t-->\t<deleted>" lap0) |
| 1541 | (setq lap (delq lap0 (delq lap1 lap)))) | 1592 | (setq lap (delq lap0 (delq lap1 lap)))) |
| 1542 | ((= tmp 0) | 1593 | ((= stack-adjust 0) |
| 1543 | (byte-compile-log-lap | 1594 | (byte-compile-log-lap |
| 1544 | " %s discard\t-->\t<deleted> discard" lap0) | 1595 | " %s discard\t-->\t<deleted> discard" lap0) |
| 1545 | (setq lap (delq lap0 lap))) | 1596 | (setq lap (delq lap0 lap))) |
| 1546 | ((= tmp -1) | 1597 | ((= stack-adjust -1) |
| 1547 | (byte-compile-log-lap | 1598 | (byte-compile-log-lap |
| 1548 | " %s discard\t-->\tdiscard discard" lap0) | 1599 | " %s discard\t-->\tdiscard discard" lap0) |
| 1549 | (setcar lap0 'byte-discard) | 1600 | (setcar lap0 'byte-discard) |
| 1550 | (setcdr lap0 0)) | 1601 | (setcdr lap0 0)) |
| 1551 | ((error "Optimizer error: too much on the stack")))) | 1602 | ((error "Optimizer error: too much on the stack"))) |
| 1603 | (setq stack-adjust (1- stack-adjust))) | ||
| 1552 | ;; | 1604 | ;; |
| 1553 | ;; goto*-X X: --> X: | 1605 | ;; goto*-X X: --> X: |
| 1554 | ;; | 1606 | ;; |
| @@ -1573,10 +1625,14 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1573 | ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup | 1625 | ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup |
| 1574 | ;; The latter two can enable other optimizations. | 1626 | ;; The latter two can enable other optimizations. |
| 1575 | ;; | 1627 | ;; |
| 1576 | ((and (eq 'byte-varref (car lap2)) | 1628 | ((or (and (eq 'byte-varref (car lap2)) |
| 1577 | (eq (cdr lap1) (cdr lap2)) | 1629 | (eq (cdr lap1) (cdr lap2)) |
| 1578 | (memq (car lap1) '(byte-varset byte-varbind))) | 1630 | (memq (car lap1) '(byte-varset byte-varbind))) |
| 1579 | (if (and (setq tmp (memq (car (cdr lap2)) byte-boolean-vars)) | 1631 | (and (eq (car lap2) 'byte-stack-ref) |
| 1632 | (eq (car lap1) 'byte-stack-set) | ||
| 1633 | (eq (cdr lap1) (cdr lap2)))) | ||
| 1634 | (if (and (eq 'byte-varref (car lap2)) | ||
| 1635 | (setq tmp (memq (car (cdr lap2)) byte-boolean-vars)) | ||
| 1580 | (not (eq (car lap0) 'byte-constant))) | 1636 | (not (eq (car lap0) 'byte-constant))) |
| 1581 | nil | 1637 | nil |
| 1582 | (setq keep-going t) | 1638 | (setq keep-going t) |
| @@ -1608,10 +1664,11 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1608 | ;; | 1664 | ;; |
| 1609 | ((and (eq 'byte-dup (car lap0)) | 1665 | ((and (eq 'byte-dup (car lap0)) |
| 1610 | (eq 'byte-discard (car lap2)) | 1666 | (eq 'byte-discard (car lap2)) |
| 1611 | (memq (car lap1) '(byte-varset byte-varbind))) | 1667 | (memq (car lap1) '(byte-varset byte-varbind byte-stack-set byte-vec-set))) |
| 1612 | (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1) | 1668 | (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1) |
| 1613 | (setq keep-going t | 1669 | (setq keep-going t |
| 1614 | rest (cdr rest)) | 1670 | rest (cdr rest) |
| 1671 | stack-adjust -1) | ||
| 1615 | (setq lap (delq lap0 (delq lap2 lap)))) | 1672 | (setq lap (delq lap0 (delq lap2 lap)))) |
| 1616 | ;; | 1673 | ;; |
| 1617 | ;; not goto-X-if-nil --> goto-X-if-non-nil | 1674 | ;; not goto-X-if-nil --> goto-X-if-non-nil |
| @@ -1633,7 +1690,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1633 | 'byte-goto-if-not-nil | 1690 | 'byte-goto-if-not-nil |
| 1634 | 'byte-goto-if-nil)) | 1691 | 'byte-goto-if-nil)) |
| 1635 | (setq lap (delq lap0 lap)) | 1692 | (setq lap (delq lap0 lap)) |
| 1636 | (setq keep-going t)) | 1693 | (setq keep-going t |
| 1694 | stack-adjust 0)) | ||
| 1637 | ;; | 1695 | ;; |
| 1638 | ;; goto-X-if-nil goto-Y X: --> goto-Y-if-non-nil X: | 1696 | ;; goto-X-if-nil goto-Y X: --> goto-Y-if-non-nil X: |
| 1639 | ;; goto-X-if-non-nil goto-Y X: --> goto-Y-if-nil X: | 1697 | ;; goto-X-if-non-nil goto-Y X: --> goto-Y-if-nil X: |
| @@ -1649,7 +1707,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1649 | (byte-compile-log-lap " %s %s %s:\t-->\t%s %s:" | 1707 | (byte-compile-log-lap " %s %s %s:\t-->\t%s %s:" |
| 1650 | lap0 lap1 lap2 | 1708 | lap0 lap1 lap2 |
| 1651 | (cons inverse (cdr lap1)) lap2) | 1709 | (cons inverse (cdr lap1)) lap2) |
| 1652 | (setq lap (delq lap0 lap)) | 1710 | (setq lap (delq lap0 lap) |
| 1711 | stack-adjust 0) | ||
| 1653 | (setcar lap1 inverse) | 1712 | (setcar lap1 inverse) |
| 1654 | (setq keep-going t))) | 1713 | (setq keep-going t))) |
| 1655 | ;; | 1714 | ;; |
| @@ -1666,15 +1725,14 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1666 | (setq rest (cdr rest) | 1725 | (setq rest (cdr rest) |
| 1667 | lap (delq lap0 (delq lap1 lap)))) | 1726 | lap (delq lap0 (delq lap1 lap)))) |
| 1668 | (t | 1727 | (t |
| 1669 | (if (memq (car lap1) byte-goto-always-pop-ops) | 1728 | (byte-compile-log-lap " %s %s\t-->\t%s" |
| 1670 | (progn | 1729 | lap0 lap1 |
| 1671 | (byte-compile-log-lap " %s %s\t-->\t%s" | 1730 | (cons 'byte-goto (cdr lap1))) |
| 1672 | lap0 lap1 (cons 'byte-goto (cdr lap1))) | 1731 | (when (memq (car lap1) byte-goto-always-pop-ops) |
| 1673 | (setq lap (delq lap0 lap))) | 1732 | (setq lap (delq lap0 lap))) |
| 1674 | (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 | ||
| 1675 | (cons 'byte-goto (cdr lap1)))) | ||
| 1676 | (setcar lap1 'byte-goto))) | 1733 | (setcar lap1 'byte-goto))) |
| 1677 | (setq keep-going t)) | 1734 | (setq keep-going t |
| 1735 | stack-adjust 0)) | ||
| 1678 | ;; | 1736 | ;; |
| 1679 | ;; varref-X varref-X --> varref-X dup | 1737 | ;; varref-X varref-X --> varref-X dup |
| 1680 | ;; varref-X [dup ...] varref-X --> varref-X [dup ...] dup | 1738 | ;; varref-X [dup ...] varref-X --> varref-X [dup ...] dup |
| @@ -1682,14 +1740,14 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1682 | ;; because that would inhibit some goto optimizations; we | 1740 | ;; because that would inhibit some goto optimizations; we |
| 1683 | ;; optimize the const-X case after all other optimizations. | 1741 | ;; optimize the const-X case after all other optimizations. |
| 1684 | ;; | 1742 | ;; |
| 1685 | ((and (eq 'byte-varref (car lap0)) | 1743 | ((and (memq (car lap0) '(byte-varref byte-stack-ref)) |
| 1686 | (progn | 1744 | (progn |
| 1687 | (setq tmp (cdr rest)) | 1745 | (setq tmp (cdr rest) tmp2 0) |
| 1688 | (while (eq (car (car tmp)) 'byte-dup) | 1746 | (while (eq (car (car tmp)) 'byte-dup) |
| 1689 | (setq tmp (cdr tmp))) | 1747 | (setq tmp (cdr tmp) tmp2 (1+ tmp2))) |
| 1690 | t) | 1748 | t) |
| 1691 | (eq (cdr lap0) (cdr (car tmp))) | 1749 | (eq (car lap0) (car (car tmp))) |
| 1692 | (eq 'byte-varref (car (car tmp)))) | 1750 | (eq (cdr lap0) (cdr (car tmp)))) |
| 1693 | (if (memq byte-optimize-log '(t byte)) | 1751 | (if (memq byte-optimize-log '(t byte)) |
| 1694 | (let ((str "")) | 1752 | (let ((str "")) |
| 1695 | (setq tmp2 (cdr rest)) | 1753 | (setq tmp2 (cdr rest)) |
| @@ -1701,7 +1759,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1701 | (setq keep-going t) | 1759 | (setq keep-going t) |
| 1702 | (setcar (car tmp) 'byte-dup) | 1760 | (setcar (car tmp) 'byte-dup) |
| 1703 | (setcdr (car tmp) 0) | 1761 | (setcdr (car tmp) 0) |
| 1704 | (setq rest tmp)) | 1762 | (setq rest tmp |
| 1763 | stack-adjust (+ 2 tmp2))) | ||
| 1705 | ;; | 1764 | ;; |
| 1706 | ;; TAG1: TAG2: --> TAG1: <deleted> | 1765 | ;; TAG1: TAG2: --> TAG1: <deleted> |
| 1707 | ;; (and other references to TAG2 are replaced with TAG1) | 1766 | ;; (and other references to TAG2 are replaced with TAG1) |
| @@ -1768,7 +1827,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1768 | (byte-compile-log-lap " %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0) | 1827 | (byte-compile-log-lap " %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0) |
| 1769 | (setcar rest lap1) | 1828 | (setcar rest lap1) |
| 1770 | (setcar (cdr rest) lap0) | 1829 | (setcar (cdr rest) lap0) |
| 1771 | (setq keep-going t)) | 1830 | (setq keep-going t |
| 1831 | stack-adjust 0)) | ||
| 1772 | ;; | 1832 | ;; |
| 1773 | ;; varbind-X unbind-N --> discard unbind-(N-1) | 1833 | ;; varbind-X unbind-N --> discard unbind-(N-1) |
| 1774 | ;; save-excursion unbind-N --> unbind-(N-1) | 1834 | ;; save-excursion unbind-N --> unbind-(N-1) |
| @@ -1794,6 +1854,14 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1794 | "")) | 1854 | "")) |
| 1795 | (setq keep-going t)) | 1855 | (setq keep-going t)) |
| 1796 | ;; | 1856 | ;; |
| 1857 | ;; stack-ref-N --> dup ; where N is TOS | ||
| 1858 | ;; | ||
| 1859 | ((and (eq (car lap0) 'byte-stack-ref) | ||
| 1860 | (= (cdr lap0) (1- stack-depth))) | ||
| 1861 | (setcar lap0 'byte-dup) | ||
| 1862 | (setcdr lap0 nil) | ||
| 1863 | (setq keep-going t)) | ||
| 1864 | ;; | ||
| 1797 | ;; goto*-X ... X: goto-Y --> goto*-Y | 1865 | ;; goto*-X ... X: goto-Y --> goto*-Y |
| 1798 | ;; goto-X ... X: return --> return | 1866 | ;; goto-X ... X: return --> return |
| 1799 | ;; | 1867 | ;; |
| @@ -1870,20 +1938,22 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1870 | (cdr tmp)))) | 1938 | (cdr tmp)))) |
| 1871 | (setcdr lap1 (car (cdr tmp))) | 1939 | (setcdr lap1 (car (cdr tmp))) |
| 1872 | (setq lap (delq lap0 lap)))) | 1940 | (setq lap (delq lap0 lap)))) |
| 1873 | (setq keep-going t)) | 1941 | (setq keep-going t |
| 1942 | stack-adjust 0)) | ||
| 1874 | ;; | 1943 | ;; |
| 1875 | ;; X: varref-Y ... varset-Y goto-X --> | 1944 | ;; X: varref-Y ... varset-Y goto-X --> |
| 1876 | ;; X: varref-Y Z: ... dup varset-Y goto-Z | 1945 | ;; X: varref-Y Z: ... dup varset-Y goto-Z |
| 1877 | ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.) | 1946 | ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.) |
| 1878 | ;; (This is so usual for while loops that it is worth handling). | 1947 | ;; (This is so usual for while loops that it is worth handling). |
| 1879 | ;; | 1948 | ;; |
| 1880 | ((and (eq (car lap1) 'byte-varset) | 1949 | ((and (memq (car lap1) '(byte-varset byte-stack-set)) |
| 1881 | (eq (car lap2) 'byte-goto) | 1950 | (eq (car lap2) 'byte-goto) |
| 1882 | (not (memq (cdr lap2) rest)) ;Backwards jump | 1951 | (not (memq (cdr lap2) rest)) ;Backwards jump |
| 1883 | (eq (car (car (setq tmp (cdr (memq (cdr lap2) lap))))) | 1952 | (eq (car (car (setq tmp (cdr (memq (cdr lap2) lap))))) |
| 1884 | 'byte-varref) | 1953 | (if (eq (car lap1) 'byte-varset) 'byte-varref 'byte-stack-ref)) |
| 1885 | (eq (cdr (car tmp)) (cdr lap1)) | 1954 | (eq (cdr (car tmp)) (cdr lap1)) |
| 1886 | (not (memq (car (cdr lap1)) byte-boolean-vars))) | 1955 | (not (and (eq (car lap1) 'byte-varref) |
| 1956 | (memq (car (cdr lap1)) byte-boolean-vars)))) | ||
| 1887 | ;;(byte-compile-log-lap " Pulled %s to end of loop" (car tmp)) | 1957 | ;;(byte-compile-log-lap " Pulled %s to end of loop" (car tmp)) |
| 1888 | (let ((newtag (byte-compile-make-tag))) | 1958 | (let ((newtag (byte-compile-make-tag))) |
| 1889 | (byte-compile-log-lap | 1959 | (byte-compile-log-lap |
| @@ -1940,10 +2010,15 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1940 | byte-goto-if-not-nil | 2010 | byte-goto-if-not-nil |
| 1941 | byte-goto byte-goto)))) | 2011 | byte-goto byte-goto)))) |
| 1942 | ) | 2012 | ) |
| 1943 | (setq keep-going t)) | 2013 | (setq keep-going t |
| 2014 | stack-adjust (and (not (eq (car lap0) 'byte-goto)) -1))) | ||
| 1944 | ) | 2015 | ) |
| 2016 | |||
| 2017 | (setq stack-depth | ||
| 2018 | (and stack-depth stack-adjust (+ stack-depth stack-adjust))) | ||
| 1945 | (setq rest (cdr rest))) | 2019 | (setq rest (cdr rest))) |
| 1946 | ) | 2020 | ) |
| 2021 | |||
| 1947 | ;; Cleanup stage: | 2022 | ;; Cleanup stage: |
| 1948 | ;; Rebuild byte-compile-constants / byte-compile-variables. | 2023 | ;; Rebuild byte-compile-constants / byte-compile-variables. |
| 1949 | ;; Simple optimizations that would inhibit other optimizations if they | 2024 | ;; Simple optimizations that would inhibit other optimizations if they |
| @@ -1951,10 +2026,13 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1951 | ;; need to do more than once. | 2026 | ;; need to do more than once. |
| 1952 | (setq byte-compile-constants nil | 2027 | (setq byte-compile-constants nil |
| 1953 | byte-compile-variables nil) | 2028 | byte-compile-variables nil) |
| 1954 | (setq rest lap) | 2029 | (setq rest lap |
| 2030 | stack-depth initial-stack-depth) | ||
| 2031 | (byte-compile-log-lap " ---- final pass") | ||
| 1955 | (while rest | 2032 | (while rest |
| 1956 | (setq lap0 (car rest) | 2033 | (setq lap0 (car rest) |
| 1957 | lap1 (nth 1 rest)) | 2034 | lap1 (nth 1 rest)) |
| 2035 | (byte-opt-update-stack-params stack-adjust stack-depth lap0 rest lap) | ||
| 1958 | (if (memq (car lap0) byte-constref-ops) | 2036 | (if (memq (car lap0) byte-constref-ops) |
| 1959 | (if (or (eq (car lap0) 'byte-constant) | 2037 | (if (or (eq (car lap0) 'byte-constant) |
| 1960 | (eq (car lap0) 'byte-constant2)) | 2038 | (eq (car lap0) 'byte-constant2)) |
| @@ -2001,11 +2079,108 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 2001 | (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 | 2079 | (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 |
| 2002 | (cons 'byte-unbind | 2080 | (cons 'byte-unbind |
| 2003 | (+ (cdr lap0) (cdr lap1)))) | 2081 | (+ (cdr lap0) (cdr lap1)))) |
| 2004 | (setq keep-going t) | ||
| 2005 | (setq lap (delq lap0 lap)) | 2082 | (setq lap (delq lap0 lap)) |
| 2006 | (setcdr lap1 (+ (cdr lap1) (cdr lap0)))) | 2083 | (setcdr lap1 (+ (cdr lap1) (cdr lap0)))) |
| 2084 | |||
| 2085 | ;; | ||
| 2086 | ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos | ||
| 2087 | ;; stack-set-M [discard/discardN ...] --> discardN | ||
| 2088 | ;; | ||
| 2089 | ((and (eq (car lap0) 'byte-stack-set) | ||
| 2090 | (memq (car lap1) '(byte-discard byte-discardN)) | ||
| 2091 | (progn | ||
| 2092 | ;; See if enough discard operations follow to expose or | ||
| 2093 | ;; destroy the value stored by the stack-set. | ||
| 2094 | (setq tmp (cdr rest)) | ||
| 2095 | (setq tmp2 (- stack-depth 2 (cdr lap0))) | ||
| 2096 | (setq tmp3 0) | ||
| 2097 | (while (memq (car (car tmp)) '(byte-discard byte-discardN)) | ||
| 2098 | (if (eq (car (car tmp)) 'byte-discard) | ||
| 2099 | (setq tmp3 (1+ tmp3)) | ||
| 2100 | (setq tmp3 (+ tmp3 (cdr (car tmp))))) | ||
| 2101 | (setq tmp (cdr tmp))) | ||
| 2102 | (>= tmp3 tmp2))) | ||
| 2103 | ;; Do the optimization | ||
| 2104 | (setq lap (delq lap0 lap)) | ||
| 2105 | (cond ((= tmp2 tmp3) | ||
| 2106 | ;; The value stored is the new TOS, so pop one more value | ||
| 2107 | ;; (to get rid of the old value) using the TOS-preserving | ||
| 2108 | ;; discard operator. | ||
| 2109 | (setcar lap1 'byte-discardN-preserve-tos) | ||
| 2110 | (setcdr lap1 (1+ tmp3))) | ||
| 2111 | (t | ||
| 2112 | ;; Otherwise, the value stored is lost, so just use a | ||
| 2113 | ;; normal discard. | ||
| 2114 | (setcar lap1 'byte-discardN) | ||
| 2115 | (setcdr lap1 tmp3))) | ||
| 2116 | (setcdr (cdr rest) tmp) | ||
| 2117 | (setq stack-adjust 0) | ||
| 2118 | (byte-compile-log-lap " %s [discard/discardN]...\t-->\t%s" | ||
| 2119 | lap0 lap1)) | ||
| 2120 | |||
| 2121 | ;; | ||
| 2122 | ;; discard/discardN/discardN-preserve-tos-X discard/discardN-Y --> | ||
| 2123 | ;; discardN-(X+Y) | ||
| 2124 | ;; | ||
| 2125 | ((and (memq (car lap0) | ||
| 2126 | '(byte-discard | ||
| 2127 | byte-discardN | ||
| 2128 | byte-discardN-preserve-tos)) | ||
| 2129 | (memq (car lap1) '(byte-discard byte-discardN))) | ||
| 2130 | (setq lap (delq lap0 lap)) | ||
| 2131 | (byte-compile-log-lap | ||
| 2132 | " %s %s\t-->\t(discardN %s)" | ||
| 2133 | lap0 lap1 | ||
| 2134 | (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0)) | ||
| 2135 | (if (eq (car lap1) 'byte-discard) 1 (cdr lap1)))) | ||
| 2136 | (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0)) | ||
| 2137 | (if (eq (car lap1) 'byte-discard) 1 (cdr lap1)))) | ||
| 2138 | (setcar lap1 'byte-discardN) | ||
| 2139 | (setq stack-adjust 0)) | ||
| 2140 | |||
| 2141 | ;; | ||
| 2142 | ;; discardN-preserve-tos-X discardN-preserve-tos-Y --> | ||
| 2143 | ;; discardN-preserve-tos-(X+Y) | ||
| 2144 | ;; | ||
| 2145 | ((and (eq (car lap0) 'byte-discardN-preserve-tos) | ||
| 2146 | (eq (car lap1) 'byte-discardN-preserve-tos)) | ||
| 2147 | (setq lap (delq lap0 lap)) | ||
| 2148 | (setcdr lap1 (+ (cdr lap0) (cdr lap1))) | ||
| 2149 | (setq stack-adjust 0) | ||
| 2150 | (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 (car rest))) | ||
| 2151 | |||
| 2152 | ;; | ||
| 2153 | ;; discardN-preserve-tos return --> return | ||
| 2154 | ;; dup return --> return | ||
| 2155 | ;; stack-set-N return --> return ; where N is TOS-1 | ||
| 2156 | ;; | ||
| 2157 | ((and (eq (car lap1) 'byte-return) | ||
| 2158 | (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup)) | ||
| 2159 | (and (eq (car lap0) 'byte-stack-set) | ||
| 2160 | (= (cdr lap0) (- stack-depth 2))))) | ||
| 2161 | ;; the byte-code interpreter will pop the stack for us, so | ||
| 2162 | ;; we can just leave stuff on it | ||
| 2163 | (setq lap (delq lap0 lap)) | ||
| 2164 | (setq stack-adjust 0) | ||
| 2165 | (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 lap1)) | ||
| 2166 | |||
| 2167 | ;; | ||
| 2168 | ;; dup stack-set-N return --> return ; where N is TOS | ||
| 2169 | ;; | ||
| 2170 | ((and (eq (car lap0) 'byte-dup) | ||
| 2171 | (eq (car lap1) 'byte-stack-set) | ||
| 2172 | (eq (car (car (cdr (cdr rest)))) 'byte-return) | ||
| 2173 | (= (cdr lap1) (1- stack-depth))) | ||
| 2174 | (setq lap (delq lap0 (delq lap1 lap))) | ||
| 2175 | (setq rest (cdr rest)) | ||
| 2176 | (setq stack-adjust 0) | ||
| 2177 | (byte-compile-log-lap " dup %s return\t-->\treturn" lap1)) | ||
| 2007 | ) | 2178 | ) |
| 2179 | |||
| 2180 | (setq stack-depth | ||
| 2181 | (and stack-depth stack-adjust (+ stack-depth stack-adjust))) | ||
| 2008 | (setq rest (cdr rest))) | 2182 | (setq rest (cdr rest))) |
| 2183 | |||
| 2009 | (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) | 2184 | (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) |
| 2010 | lap) | 2185 | lap) |
| 2011 | 2186 | ||
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 217afea9f8a..c80bcd49b82 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -116,12 +116,55 @@ | |||
| 116 | ;; Some versions of `file' can be customized to recognize that. | 116 | ;; Some versions of `file' can be customized to recognize that. |
| 117 | 117 | ||
| 118 | (require 'backquote) | 118 | (require 'backquote) |
| 119 | (require 'macroexp) | ||
| 119 | (eval-when-compile (require 'cl)) | 120 | (eval-when-compile (require 'cl)) |
| 120 | 121 | ||
| 121 | (or (fboundp 'defsubst) | 122 | (or (fboundp 'defsubst) |
| 122 | ;; This really ought to be loaded already! | 123 | ;; This really ought to be loaded already! |
| 123 | (load "byte-run")) | 124 | (load "byte-run")) |
| 124 | 125 | ||
| 126 | ;; We want to do (require 'byte-lexbind) when compiling, to avoid compilation | ||
| 127 | ;; errors; however that file also wants to do (require 'bytecomp) for the | ||
| 128 | ;; same reason. Since we know it's OK to load byte-lexbind.el second, we | ||
| 129 | ;; have that file require a feature that's provided before at the beginning | ||
| 130 | ;; of this file, to avoid an infinite require loop. | ||
| 131 | ;; `eval-when-compile' is defined in byte-run.el, so it must come after the | ||
| 132 | ;; preceding load expression. | ||
| 133 | (provide 'bytecomp-preload) | ||
| 134 | (eval-when-compile (require 'byte-lexbind)) | ||
| 135 | |||
| 136 | ;; The feature of compiling in a specific target Emacs version | ||
| 137 | ;; has been turned off because compile time options are a bad idea. | ||
| 138 | (defmacro byte-compile-single-version () nil) | ||
| 139 | (defmacro byte-compile-version-cond (cond) cond) | ||
| 140 | |||
| 141 | ;; The crud you see scattered through this file of the form | ||
| 142 | ;; (or (and (boundp 'epoch::version) epoch::version) | ||
| 143 | ;; (string-lessp emacs-version "19")) | ||
| 144 | ;; is because the Epoch folks couldn't be bothered to follow the | ||
| 145 | ;; normal emacs version numbering convention. | ||
| 146 | |||
| 147 | ;; (if (byte-compile-version-cond | ||
| 148 | ;; (or (and (boundp 'epoch::version) epoch::version) | ||
| 149 | ;; (string-lessp emacs-version "19"))) | ||
| 150 | ;; (progn | ||
| 151 | ;; ;; emacs-18 compatibility. | ||
| 152 | ;; (defvar baud-rate (baud-rate)) ;Define baud-rate if it's undefined | ||
| 153 | ;; | ||
| 154 | ;; (if (byte-compile-single-version) | ||
| 155 | ;; (defmacro byte-code-function-p (x) "Emacs 18 doesn't have these." nil) | ||
| 156 | ;; (defun byte-code-function-p (x) "Emacs 18 doesn't have these." nil)) | ||
| 157 | ;; | ||
| 158 | ;; (or (and (fboundp 'member) | ||
| 159 | ;; ;; avoid using someone else's possibly bogus definition of this. | ||
| 160 | ;; (subrp (symbol-function 'member))) | ||
| 161 | ;; (defun member (elt list) | ||
| 162 | ;; "like memq, but uses equal instead of eq. In v19, this is a subr." | ||
| 163 | ;; (while (and list (not (equal elt (car list)))) | ||
| 164 | ;; (setq list (cdr list))) | ||
| 165 | ;; list)))) | ||
| 166 | |||
| 167 | |||
| 125 | (defgroup bytecomp nil | 168 | (defgroup bytecomp nil |
| 126 | "Emacs Lisp byte-compiler." | 169 | "Emacs Lisp byte-compiler." |
| 127 | :group 'lisp) | 170 | :group 'lisp) |
| @@ -398,7 +441,17 @@ specify different fields to sort on." | |||
| 398 | :type '(choice (const name) (const callers) (const calls) | 441 | :type '(choice (const name) (const callers) (const calls) |
| 399 | (const calls+callers) (const nil))) | 442 | (const calls+callers) (const nil))) |
| 400 | 443 | ||
| 401 | (defvar byte-compile-debug nil) | 444 | ;(defvar byte-compile-debug nil) |
| 445 | (defvar byte-compile-debug t) | ||
| 446 | |||
| 447 | ;; (defvar byte-compile-overwrite-file t | ||
| 448 | ;; "If nil, old .elc files are deleted before the new is saved, and .elc | ||
| 449 | ;; files will have the same modes as the corresponding .el file. Otherwise, | ||
| 450 | ;; existing .elc files will simply be overwritten, and the existing modes | ||
| 451 | ;; will not be changed. If this variable is nil, then an .elc file which | ||
| 452 | ;; is a symbolic link will be turned into a normal file, instead of the file | ||
| 453 | ;; which the link points to being overwritten.") | ||
| 454 | |||
| 402 | (defvar byte-compile-constants nil | 455 | (defvar byte-compile-constants nil |
| 403 | "List of all constants encountered during compilation of this form.") | 456 | "List of all constants encountered during compilation of this form.") |
| 404 | (defvar byte-compile-variables nil | 457 | (defvar byte-compile-variables nil |
| @@ -418,11 +471,18 @@ This list lives partly on the stack.") | |||
| 418 | ;; (byte-compiler-options . (lambda (&rest forms) | 471 | ;; (byte-compiler-options . (lambda (&rest forms) |
| 419 | ;; (apply 'byte-compiler-options-handler forms))) | 472 | ;; (apply 'byte-compiler-options-handler forms))) |
| 420 | (eval-when-compile . (lambda (&rest body) | 473 | (eval-when-compile . (lambda (&rest body) |
| 421 | (list 'quote | 474 | (list |
| 422 | (byte-compile-eval (byte-compile-top-level | 475 | 'quote |
| 423 | (cons 'progn body)))))) | 476 | (byte-compile-eval |
| 477 | (byte-compile-top-level | ||
| 478 | (macroexpand-all | ||
| 479 | (cons 'progn body) | ||
| 480 | byte-compile-initial-macro-environment)))))) | ||
| 424 | (eval-and-compile . (lambda (&rest body) | 481 | (eval-and-compile . (lambda (&rest body) |
| 425 | (byte-compile-eval-before-compile (cons 'progn body)) | 482 | (byte-compile-eval-before-compile |
| 483 | (macroexpand-all | ||
| 484 | (cons 'progn body) | ||
| 485 | byte-compile-initial-macro-environment)) | ||
| 426 | (cons 'progn body)))) | 486 | (cons 'progn body)))) |
| 427 | "The default macro-environment passed to macroexpand by the compiler. | 487 | "The default macro-environment passed to macroexpand by the compiler. |
| 428 | Placing a macro here will cause a macro to have different semantics when | 488 | Placing a macro here will cause a macro to have different semantics when |
| @@ -453,6 +513,14 @@ defined with incorrect args.") | |||
| 453 | Used for warnings about calling a function that is defined during compilation | 513 | Used for warnings about calling a function that is defined during compilation |
| 454 | but won't necessarily be defined when the compiled file is loaded.") | 514 | but won't necessarily be defined when the compiled file is loaded.") |
| 455 | 515 | ||
| 516 | ;; Variables for lexical binding | ||
| 517 | (defvar byte-compile-lexical-environment nil | ||
| 518 | "The current lexical environment.") | ||
| 519 | (defvar byte-compile-current-heap-environment nil | ||
| 520 | "If non-nil, a descriptor for the current heap-allocated lexical environment.") | ||
| 521 | (defvar byte-compile-current-num-closures 0 | ||
| 522 | "The number of lexical closures that close over `byte-compile-current-heap-environment'.") | ||
| 523 | |||
| 456 | (defvar byte-compile-tag-number 0) | 524 | (defvar byte-compile-tag-number 0) |
| 457 | (defvar byte-compile-output nil | 525 | (defvar byte-compile-output nil |
| 458 | "Alist describing contents to put in byte code string. | 526 | "Alist describing contents to put in byte code string. |
| @@ -498,11 +566,10 @@ Each element is (INDEX . VALUE)") | |||
| 498 | (put 'byte-stack+-info 'tmp-compile-time-value nil))) | 566 | (put 'byte-stack+-info 'tmp-compile-time-value nil))) |
| 499 | 567 | ||
| 500 | 568 | ||
| 501 | ;; unused: 0-7 | ||
| 502 | |||
| 503 | ;; These opcodes are special in that they pack their argument into the | 569 | ;; These opcodes are special in that they pack their argument into the |
| 504 | ;; opcode word. | 570 | ;; opcode word. |
| 505 | ;; | 571 | ;; |
| 572 | (byte-defop 0 1 byte-stack-ref "for stack reference") | ||
| 506 | (byte-defop 8 1 byte-varref "for variable reference") | 573 | (byte-defop 8 1 byte-varref "for variable reference") |
| 507 | (byte-defop 16 -1 byte-varset "for setting a variable") | 574 | (byte-defop 16 -1 byte-varset "for setting a variable") |
| 508 | (byte-defop 24 -1 byte-varbind "for binding a variable") | 575 | (byte-defop 24 -1 byte-varbind "for binding a variable") |
| @@ -664,11 +731,28 @@ otherwise pop it") | |||
| 664 | (byte-defop 168 0 byte-integerp) | 731 | (byte-defop 168 0 byte-integerp) |
| 665 | 732 | ||
| 666 | ;; unused: 169-174 | 733 | ;; unused: 169-174 |
| 734 | |||
| 667 | (byte-defop 175 nil byte-listN) | 735 | (byte-defop 175 nil byte-listN) |
| 668 | (byte-defop 176 nil byte-concatN) | 736 | (byte-defop 176 nil byte-concatN) |
| 669 | (byte-defop 177 nil byte-insertN) | 737 | (byte-defop 177 nil byte-insertN) |
| 670 | 738 | ||
| 671 | ;; unused: 178-191 | 739 | (byte-defop 178 -1 byte-stack-set) ; stack offset in following one byte |
| 740 | (byte-defop 179 -1 byte-stack-set2) ; stack offset in following two bytes | ||
| 741 | (byte-defop 180 1 byte-vec-ref) ; vector offset in following one byte | ||
| 742 | (byte-defop 181 -1 byte-vec-set) ; vector offset in following one byte | ||
| 743 | |||
| 744 | ;; if (following one byte & 0x80) == 0 | ||
| 745 | ;; discard (following one byte & 0x7F) stack entries | ||
| 746 | ;; else | ||
| 747 | ;; discard (following one byte & 0x7F) stack entries _underneath_ the top of stack | ||
| 748 | ;; (that is, if the operand = 0x83, ... X Y Z T => ... T) | ||
| 749 | (byte-defop 182 nil byte-discardN) | ||
| 750 | ;; `byte-discardN-preserve-tos' is a pseudo-op that gets turned into | ||
| 751 | ;; `byte-discardN' with the high bit in the operand set (by | ||
| 752 | ;; `byte-compile-lapcode'). | ||
| 753 | (defconst byte-discardN-preserve-tos byte-discardN) | ||
| 754 | |||
| 755 | ;; unused: 182-191 | ||
| 672 | 756 | ||
| 673 | (byte-defop 192 1 byte-constant "for reference to a constant") | 757 | (byte-defop 192 1 byte-constant "for reference to a constant") |
| 674 | ;; codes 193-255 are consumed by byte-constant. | 758 | ;; codes 193-255 are consumed by byte-constant. |
| @@ -715,71 +799,108 @@ otherwise pop it") | |||
| 715 | ;; front of the constants-vector than the constant-referencing instructions. | 799 | ;; front of the constants-vector than the constant-referencing instructions. |
| 716 | ;; Also, this lets us notice references to free variables. | 800 | ;; Also, this lets us notice references to free variables. |
| 717 | 801 | ||
| 802 | (defmacro byte-compile-push-bytecodes (&rest args) | ||
| 803 | "Push BYTE... onto BYTES, and increment PC by the number of bytes pushed. | ||
| 804 | ARGS is of the form (BYTE... BYTES PC), where BYTES and PC are variable names. | ||
| 805 | BYTES and PC are updated after evaluating all the arguments." | ||
| 806 | (let ((byte-exprs (butlast args 2)) | ||
| 807 | (bytes-var (car (last args 2))) | ||
| 808 | (pc-var (car (last args)))) | ||
| 809 | `(setq ,bytes-var ,(if (null (cdr byte-exprs)) | ||
| 810 | `(cons ,@byte-exprs ,bytes-var) | ||
| 811 | `(nconc (list ,@(reverse byte-exprs)) ,bytes-var)) | ||
| 812 | ,pc-var (+ ,(length byte-exprs) ,pc-var)))) | ||
| 813 | |||
| 814 | (defmacro byte-compile-push-bytecode-const2 (opcode const2 bytes pc) | ||
| 815 | "Push OPCODE and the two-byte constant CONST2 onto BYTES, and add 3 to PC. | ||
| 816 | CONST2 may be evaulated multiple times." | ||
| 817 | `(byte-compile-push-bytecodes ,opcode (logand ,const2 255) (lsh ,const2 -8) | ||
| 818 | ,bytes ,pc)) | ||
| 819 | |||
| 718 | (defun byte-compile-lapcode (lap) | 820 | (defun byte-compile-lapcode (lap) |
| 719 | "Turns lapcode into bytecode. The lapcode is destroyed." | 821 | "Turns lapcode into bytecode. The lapcode is destroyed." |
| 720 | ;; Lapcode modifications: changes the ID of a tag to be the tag's PC. | 822 | ;; Lapcode modifications: changes the ID of a tag to be the tag's PC. |
| 721 | (let ((pc 0) ; Program counter | 823 | (let ((pc 0) ; Program counter |
| 722 | op off ; Operation & offset | 824 | op off ; Operation & offset |
| 825 | opcode ; numeric value of OP | ||
| 723 | (bytes '()) ; Put the output bytes here | 826 | (bytes '()) ; Put the output bytes here |
| 724 | (patchlist nil)) ; List of tags and goto's to patch | 827 | (patchlist nil)) ; List of gotos to patch |
| 725 | (while lap | 828 | (dolist (lap-entry lap) |
| 726 | (setq op (car (car lap)) | 829 | (setq op (car lap-entry) |
| 727 | off (cdr (car lap))) | 830 | off (cdr lap-entry)) |
| 728 | (cond ((not (symbolp op)) | 831 | (cond ((not (symbolp op)) |
| 729 | (error "Non-symbolic opcode `%s'" op)) | 832 | (error "Non-symbolic opcode `%s'" op)) |
| 730 | ((eq op 'TAG) | 833 | ((eq op 'TAG) |
| 731 | (setcar off pc) | 834 | (setcar off pc)) |
| 732 | (setq patchlist (cons off patchlist))) | 835 | ((null op) |
| 733 | ((memq op byte-goto-ops) | 836 | ;; a no-op added by `byte-compile-delay-out' |
| 734 | (setq pc (+ pc 3)) | 837 | (unless (zerop off) |
| 735 | (setq bytes (cons (cons pc (cdr off)) | 838 | (error |
| 736 | (cons nil | 839 | "Placeholder added by `byte-compile-delay-out' not filled in.") |
| 737 | (cons (symbol-value op) bytes)))) | 840 | )) |
| 738 | (setq patchlist (cons bytes patchlist))) | ||
| 739 | (t | 841 | (t |
| 740 | (setq bytes | 842 | (if (eq op 'byte-discardN-preserve-tos) |
| 741 | (cond ((cond ((consp off) | 843 | ;; byte-discardN-preserve-tos is a psuedo op, which is actually |
| 742 | ;; Variable or constant reference | 844 | ;; the same as byte-discardN with a modified argument |
| 743 | (setq off (cdr off)) | 845 | (setq opcode byte-discardN) |
| 744 | (eq op 'byte-constant))) | 846 | (setq opcode (symbol-value op))) |
| 745 | (cond ((< off byte-constant-limit) | 847 | (cond ((memq op byte-goto-ops) |
| 746 | (setq pc (1+ pc)) | 848 | ;; goto |
| 747 | (cons (+ byte-constant off) bytes)) | 849 | (byte-compile-push-bytecodes opcode nil (cdr off) bytes pc) |
| 748 | (t | 850 | (push bytes patchlist)) |
| 749 | (setq pc (+ 3 pc)) | 851 | ((and (consp off) |
| 750 | (cons (lsh off -8) | 852 | ;; Variable or constant reference |
| 751 | (cons (logand off 255) | 853 | (progn (setq off (cdr off)) |
| 752 | (cons byte-constant2 bytes)))))) | 854 | (eq op 'byte-constant))) |
| 753 | ((<= byte-listN (symbol-value op)) | 855 | ;; constant ref |
| 754 | (setq pc (+ 2 pc)) | 856 | (if (< off byte-constant-limit) |
| 755 | (cons off (cons (symbol-value op) bytes))) | 857 | (byte-compile-push-bytecodes (+ byte-constant off) |
| 756 | ((< off 6) | 858 | bytes pc) |
| 757 | (setq pc (1+ pc)) | 859 | (byte-compile-push-bytecode-const2 byte-constant2 off |
| 758 | (cons (+ (symbol-value op) off) bytes)) | 860 | bytes pc))) |
| 759 | ((< off 256) | 861 | ((and (= opcode byte-stack-set) |
| 760 | (setq pc (+ 2 pc)) | 862 | (> off 255)) |
| 761 | (cons off (cons (+ (symbol-value op) 6) bytes))) | 863 | ;; Use the two-byte version of byte-stack-set if the |
| 762 | (t | 864 | ;; offset is too large for the normal version. |
| 763 | (setq pc (+ 3 pc)) | 865 | (byte-compile-push-bytecode-const2 byte-stack-set2 off |
| 764 | (cons (lsh off -8) | 866 | bytes pc)) |
| 765 | (cons (logand off 255) | 867 | ((and (>= opcode byte-listN) |
| 766 | (cons (+ (symbol-value op) 7) | 868 | (< opcode byte-discardN)) |
| 767 | bytes)))))))) | 869 | ;; These insns all put their operand into one extra byte. |
| 768 | (setq lap (cdr lap))) | 870 | (byte-compile-push-bytecodes opcode off bytes pc)) |
| 871 | ((= opcode byte-discardN) | ||
| 872 | ;; byte-discardN is wierd in that it encodes a flag in the | ||
| 873 | ;; top bit of its one-byte argument. If the argument is | ||
| 874 | ;; too large to fit in 7 bits, the opcode can be repeated. | ||
| 875 | (let ((flag (if (eq op 'byte-discardN-preserve-tos) #x80 0))) | ||
| 876 | (while (> off #x7f) | ||
| 877 | (byte-compile-push-bytecodes opcode (logior #x7f flag) bytes pc) | ||
| 878 | (setq off (- off #x7f))) | ||
| 879 | (byte-compile-push-bytecodes opcode (logior off flag) bytes pc))) | ||
| 880 | ((null off) | ||
| 881 | ;; opcode that doesn't use OFF | ||
| 882 | (byte-compile-push-bytecodes opcode bytes pc)) | ||
| 883 | ;; The following three cases are for the special | ||
| 884 | ;; insns that encode their operand into 0, 1, or 2 | ||
| 885 | ;; extra bytes depending on its magnitude. | ||
| 886 | ((< off 6) | ||
| 887 | (byte-compile-push-bytecodes (+ opcode off) bytes pc)) | ||
| 888 | ((< off 256) | ||
| 889 | (byte-compile-push-bytecodes (+ opcode 6) off bytes pc)) | ||
| 890 | (t | ||
| 891 | (byte-compile-push-bytecode-const2 (+ opcode 7) off | ||
| 892 | bytes pc)))))) | ||
| 769 | ;;(if (not (= pc (length bytes))) | 893 | ;;(if (not (= pc (length bytes))) |
| 770 | ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes))) | 894 | ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes))) |
| 771 | ;; Patch PC into jumps | 895 | |
| 772 | (let (bytes) | 896 | ;; Patch tag PCs into absolute jumps |
| 773 | (while patchlist | 897 | (dolist (bytes-tail patchlist) |
| 774 | (setq bytes (car patchlist)) | 898 | (setq pc (caar bytes-tail)) ; Pick PC from goto's tag |
| 775 | (cond ((atom (car bytes))) ; Tag | 899 | (setcar (cdr bytes-tail) (logand pc 255)) |
| 776 | (t ; Absolute jump | 900 | (setcar bytes-tail (lsh pc -8)) |
| 777 | (setq pc (car (cdr (car bytes)))) ; Pick PC from tag | 901 | ;; FIXME: Replace this by some workaround. |
| 778 | (setcar (cdr bytes) (logand pc 255)) | 902 | (if (> (car bytes) 255) (error "Bytecode overflow"))) |
| 779 | (setcar bytes (lsh pc -8)) | 903 | |
| 780 | ;; FIXME: Replace this by some workaround. | ||
| 781 | (if (> (car bytes) 255) (error "Bytecode overflow")))) | ||
| 782 | (setq patchlist (cdr patchlist)))) | ||
| 783 | (apply 'unibyte-string (nreverse bytes)))) | 904 | (apply 'unibyte-string (nreverse bytes)))) |
| 784 | 905 | ||
| 785 | 906 | ||
| @@ -2073,18 +2194,16 @@ list that represents a doc string reference. | |||
| 2073 | (defun byte-compile-file-form (form) | 2194 | (defun byte-compile-file-form (form) |
| 2074 | (let ((byte-compile-current-form nil) ; close over this for warnings. | 2195 | (let ((byte-compile-current-form nil) ; close over this for warnings. |
| 2075 | bytecomp-handler) | 2196 | bytecomp-handler) |
| 2076 | (cond | 2197 | (setq form (macroexpand-all form byte-compile-macro-environment)) |
| 2077 | ((not (consp form)) | 2198 | (cond ((not (consp form)) |
| 2078 | (byte-compile-keep-pending form)) | 2199 | (byte-compile-keep-pending form)) |
| 2079 | ((and (symbolp (car form)) | 2200 | ((and (symbolp (car form)) |
| 2080 | (setq bytecomp-handler (get (car form) 'byte-hunk-handler))) | 2201 | (setq bytecomp-handler (get (car form) 'byte-hunk-handler))) |
| 2081 | (cond ((setq form (funcall bytecomp-handler form)) | 2202 | (cond ((setq form (funcall bytecomp-handler form)) |
| 2082 | (byte-compile-flush-pending) | 2203 | (byte-compile-flush-pending) |
| 2083 | (byte-compile-output-file-form form)))) | 2204 | (byte-compile-output-file-form form)))) |
| 2084 | ((eq form (setq form (macroexpand form byte-compile-macro-environment))) | 2205 | (t |
| 2085 | (byte-compile-keep-pending form)) | 2206 | (byte-compile-keep-pending form))))) |
| 2086 | (t | ||
| 2087 | (byte-compile-file-form form))))) | ||
| 2088 | 2207 | ||
| 2089 | ;; Functions and variables with doc strings must be output separately, | 2208 | ;; Functions and variables with doc strings must be output separately, |
| 2090 | ;; so make-docfile can recognise them. Most other things can be output | 2209 | ;; so make-docfile can recognise them. Most other things can be output |
| @@ -2096,8 +2215,7 @@ list that represents a doc string reference. | |||
| 2096 | (setq byte-compile-current-form (nth 1 form)) | 2215 | (setq byte-compile-current-form (nth 1 form)) |
| 2097 | (byte-compile-warn "defsubst `%s' was used before it was defined" | 2216 | (byte-compile-warn "defsubst `%s' was used before it was defined" |
| 2098 | (nth 1 form))) | 2217 | (nth 1 form))) |
| 2099 | (byte-compile-file-form | 2218 | (byte-compile-file-form form) |
| 2100 | (macroexpand form byte-compile-macro-environment)) | ||
| 2101 | ;; Return nil so the form is not output twice. | 2219 | ;; Return nil so the form is not output twice. |
| 2102 | nil) | 2220 | nil) |
| 2103 | 2221 | ||
| @@ -2418,6 +2536,12 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2418 | (if macro | 2536 | (if macro |
| 2419 | (setq fun (cdr fun))) | 2537 | (setq fun (cdr fun))) |
| 2420 | (cond ((eq (car-safe fun) 'lambda) | 2538 | (cond ((eq (car-safe fun) 'lambda) |
| 2539 | ;; expand macros | ||
| 2540 | (setq fun | ||
| 2541 | (macroexpand-all fun | ||
| 2542 | byte-compile-initial-macro-environment)) | ||
| 2543 | ;; get rid of the `function' quote added by the `lambda' macro | ||
| 2544 | (setq fun (cadr fun)) | ||
| 2421 | (setq fun (if macro | 2545 | (setq fun (if macro |
| 2422 | (cons 'macro (byte-compile-lambda fun)) | 2546 | (cons 'macro (byte-compile-lambda fun)) |
| 2423 | (byte-compile-lambda fun))) | 2547 | (byte-compile-lambda fun))) |
| @@ -2505,6 +2629,8 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2505 | (setq list (cdr list))))) | 2629 | (setq list (cdr list))))) |
| 2506 | 2630 | ||
| 2507 | 2631 | ||
| 2632 | (autoload 'byte-compile-make-lambda-lexenv "byte-lexbind") | ||
| 2633 | |||
| 2508 | ;; Byte-compile a lambda-expression and return a valid function. | 2634 | ;; Byte-compile a lambda-expression and return a valid function. |
| 2509 | ;; The value is usually a compiled function but may be the original | 2635 | ;; The value is usually a compiled function but may be the original |
| 2510 | ;; lambda-expression. | 2636 | ;; lambda-expression. |
| @@ -2561,20 +2687,43 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2561 | (byte-compile-warn "malformed interactive spec: %s" | 2687 | (byte-compile-warn "malformed interactive spec: %s" |
| 2562 | (prin1-to-string bytecomp-int))))) | 2688 | (prin1-to-string bytecomp-int))))) |
| 2563 | ;; Process the body. | 2689 | ;; Process the body. |
| 2564 | (let ((compiled (byte-compile-top-level | 2690 | (let* ((byte-compile-lexical-environment |
| 2565 | (cons 'progn bytecomp-body) nil 'lambda))) | 2691 | ;; If doing lexical binding, push a new lexical environment |
| 2692 | ;; containing the args and any closed-over variables. | ||
| 2693 | (and lexical-binding | ||
| 2694 | (byte-compile-make-lambda-lexenv | ||
| 2695 | fun | ||
| 2696 | byte-compile-lexical-environment))) | ||
| 2697 | (is-closure | ||
| 2698 | ;; This is true if we should be making a closure instead of | ||
| 2699 | ;; a simple lambda (because some variables from the | ||
| 2700 | ;; containing lexical environment are closed over). | ||
| 2701 | (and lexical-binding | ||
| 2702 | (byte-compile-closure-initial-lexenv-p | ||
| 2703 | byte-compile-lexical-environment))) | ||
| 2704 | (byte-compile-current-heap-environment nil) | ||
| 2705 | (byte-compile-current-num-closures 0) | ||
| 2706 | (compiled | ||
| 2707 | (byte-compile-top-level (cons 'progn bytecomp-body) nil 'lambda))) | ||
| 2566 | ;; Build the actual byte-coded function. | 2708 | ;; Build the actual byte-coded function. |
| 2567 | (if (eq 'byte-code (car-safe compiled)) | 2709 | (if (eq 'byte-code (car-safe compiled)) |
| 2568 | (apply 'make-byte-code | 2710 | (let ((code |
| 2569 | (append (list bytecomp-arglist) | 2711 | (apply 'make-byte-code |
| 2570 | ;; byte-string, constants-vector, stack depth | 2712 | (append (list bytecomp-arglist) |
| 2571 | (cdr compiled) | 2713 | ;; byte-string, constants-vector, stack depth |
| 2572 | ;; optionally, the doc string. | 2714 | (cdr compiled) |
| 2573 | (if (or bytecomp-doc bytecomp-int) | 2715 | ;; optionally, the doc string. |
| 2574 | (list bytecomp-doc)) | 2716 | (if (or bytecomp-doc bytecomp-int |
| 2575 | ;; optionally, the interactive spec. | 2717 | lexical-binding) |
| 2576 | (if bytecomp-int | 2718 | (list bytecomp-doc)) |
| 2577 | (list (nth 1 bytecomp-int))))) | 2719 | ;; optionally, the interactive spec. |
| 2720 | (if (or bytecomp-int lexical-binding) | ||
| 2721 | (list (nth 1 bytecomp-int))) | ||
| 2722 | (if lexical-binding | ||
| 2723 | '(t)))))) | ||
| 2724 | (if is-closure | ||
| 2725 | (cons 'closure code) | ||
| 2726 | code)) | ||
| 2578 | (setq compiled | 2727 | (setq compiled |
| 2579 | (nconc (if bytecomp-int (list bytecomp-int)) | 2728 | (nconc (if bytecomp-int (list bytecomp-int)) |
| 2580 | (cond ((eq (car-safe compiled) 'progn) (cdr compiled)) | 2729 | (cond ((eq (car-safe compiled) 'progn) (cdr compiled)) |
| @@ -2585,6 +2734,26 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2585 | (bytecomp-body (list nil)))) | 2734 | (bytecomp-body (list nil)))) |
| 2586 | compiled)))))) | 2735 | compiled)))))) |
| 2587 | 2736 | ||
| 2737 | (defun byte-compile-closure-code-p (code) | ||
| 2738 | (eq (car-safe code) 'closure)) | ||
| 2739 | |||
| 2740 | (defun byte-compile-make-closure (code) | ||
| 2741 | ;; A real closure requires that the constant be curried with an | ||
| 2742 | ;; environment vector to make a closure object. | ||
| 2743 | (if for-effect | ||
| 2744 | (setq for-effect nil) | ||
| 2745 | (byte-compile-push-constant 'curry) | ||
| 2746 | (byte-compile-push-constant code) | ||
| 2747 | (byte-compile-lexical-variable-ref byte-compile-current-heap-environment) | ||
| 2748 | (byte-compile-out 'byte-call 2))) | ||
| 2749 | |||
| 2750 | (defun byte-compile-closure (form &optional add-lambda) | ||
| 2751 | (let ((code (byte-compile-lambda form add-lambda))) | ||
| 2752 | (if (byte-compile-closure-code-p code) | ||
| 2753 | (byte-compile-make-closure code) | ||
| 2754 | ;; A simple lambda is just a constant | ||
| 2755 | (byte-compile-constant code)))) | ||
| 2756 | |||
| 2588 | (defun byte-compile-constants-vector () | 2757 | (defun byte-compile-constants-vector () |
| 2589 | ;; Builds the constants-vector from the current variables and constants. | 2758 | ;; Builds the constants-vector from the current variables and constants. |
| 2590 | ;; This modifies the constants from (const . nil) to (const . offset). | 2759 | ;; This modifies the constants from (const . nil) to (const . offset). |
| @@ -2629,17 +2798,51 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2629 | (byte-compile-depth 0) | 2798 | (byte-compile-depth 0) |
| 2630 | (byte-compile-maxdepth 0) | 2799 | (byte-compile-maxdepth 0) |
| 2631 | (byte-compile-output nil)) | 2800 | (byte-compile-output nil)) |
| 2632 | (if (memq byte-optimize '(t source)) | 2801 | (if (memq byte-optimize '(t source)) |
| 2633 | (setq form (byte-optimize-form form for-effect))) | 2802 | (setq form (byte-optimize-form form for-effect))) |
| 2634 | (while (and (eq (car-safe form) 'progn) (null (cdr (cdr form)))) | 2803 | (while (and (eq (car-safe form) 'progn) (null (cdr (cdr form)))) |
| 2635 | (setq form (nth 1 form))) | 2804 | (setq form (nth 1 form))) |
| 2636 | (if (and (eq 'byte-code (car-safe form)) | 2805 | (if (and (eq 'byte-code (car-safe form)) |
| 2637 | (not (memq byte-optimize '(t byte))) | 2806 | (not (memq byte-optimize '(t byte))) |
| 2638 | (stringp (nth 1 form)) (vectorp (nth 2 form)) | 2807 | (stringp (nth 1 form)) (vectorp (nth 2 form)) |
| 2639 | (natnump (nth 3 form))) | 2808 | (natnump (nth 3 form))) |
| 2640 | form | 2809 | form |
| 2641 | (byte-compile-form form for-effect) | 2810 | ;; Set up things for a lexically-bound function |
| 2642 | (byte-compile-out-toplevel for-effect output-type)))) | 2811 | (when (and lexical-binding (eq output-type 'lambda)) |
| 2812 | ;; See how many arguments there are, and set the current stack depth | ||
| 2813 | ;; accordingly | ||
| 2814 | (dolist (var byte-compile-lexical-environment) | ||
| 2815 | (when (byte-compile-lexvar-on-stack-p var) | ||
| 2816 | (setq byte-compile-depth (1+ byte-compile-depth)))) | ||
| 2817 | ;; If there are args, output a tag to record the initial | ||
| 2818 | ;; stack-depth for the optimizer | ||
| 2819 | (when (> byte-compile-depth 0) | ||
| 2820 | (byte-compile-out-tag (byte-compile-make-tag))) | ||
| 2821 | ;; If this is the top-level of a lexically bound lambda expression, | ||
| 2822 | ;; perhaps some parameters on stack need to be copied into a heap | ||
| 2823 | ;; environment, so check for them, and do so if necessary. | ||
| 2824 | (let ((lforminfo (byte-compile-make-lforminfo))) | ||
| 2825 | ;; Add any lexical variable that's on the stack to the analysis set. | ||
| 2826 | (dolist (var byte-compile-lexical-environment) | ||
| 2827 | (when (byte-compile-lexvar-on-stack-p var) | ||
| 2828 | (byte-compile-lforminfo-add-var lforminfo (car var) t))) | ||
| 2829 | ;; Analyze the body | ||
| 2830 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 2831 | (byte-compile-lforminfo-analyze lforminfo form nil nil)) | ||
| 2832 | ;; If the analysis revealed some argument need to be in a heap | ||
| 2833 | ;; environment (because they're closed over by an embedded | ||
| 2834 | ;; lambda), put them there. | ||
| 2835 | (setq byte-compile-lexical-environment | ||
| 2836 | (nconc (byte-compile-maybe-push-heap-environment lforminfo) | ||
| 2837 | byte-compile-lexical-environment)) | ||
| 2838 | (dolist (arginfo (byte-compile-lforminfo-vars lforminfo)) | ||
| 2839 | (when (byte-compile-lvarinfo-closed-over-p arginfo) | ||
| 2840 | (byte-compile-bind (car arginfo) | ||
| 2841 | byte-compile-lexical-environment | ||
| 2842 | lforminfo))))) | ||
| 2843 | ;; Now compile FORM | ||
| 2844 | (byte-compile-form form for-effect) | ||
| 2845 | (byte-compile-out-toplevel for-effect output-type)))) | ||
| 2643 | 2846 | ||
| 2644 | (defun byte-compile-out-toplevel (&optional for-effect output-type) | 2847 | (defun byte-compile-out-toplevel (&optional for-effect output-type) |
| 2645 | (if for-effect | 2848 | (if for-effect |
| @@ -2761,7 +2964,6 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2761 | ;; (Use byte-compile-form-do-effect to reset the for-effect flag too.) | 2964 | ;; (Use byte-compile-form-do-effect to reset the for-effect flag too.) |
| 2762 | ;; | 2965 | ;; |
| 2763 | (defun byte-compile-form (form &optional for-effect) | 2966 | (defun byte-compile-form (form &optional for-effect) |
| 2764 | (setq form (macroexpand form byte-compile-macro-environment)) | ||
| 2765 | (cond ((not (consp form)) | 2967 | (cond ((not (consp form)) |
| 2766 | (cond ((or (not (symbolp form)) (byte-compile-const-symbol-p form)) | 2968 | (cond ((or (not (symbolp form)) (byte-compile-const-symbol-p form)) |
| 2767 | (when (symbolp form) | 2969 | (when (symbolp form) |
| @@ -2771,7 +2973,8 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2771 | (when (symbolp form) | 2973 | (when (symbolp form) |
| 2772 | (byte-compile-set-symbol-position form)) | 2974 | (byte-compile-set-symbol-position form)) |
| 2773 | (setq for-effect nil)) | 2975 | (setq for-effect nil)) |
| 2774 | (t (byte-compile-variable-ref 'byte-varref form)))) | 2976 | (t |
| 2977 | (byte-compile-variable-ref form)))) | ||
| 2775 | ((symbolp (car form)) | 2978 | ((symbolp (car form)) |
| 2776 | (let* ((bytecomp-fn (car form)) | 2979 | (let* ((bytecomp-fn (car form)) |
| 2777 | (bytecomp-handler (get bytecomp-fn 'byte-compile))) | 2980 | (bytecomp-handler (get bytecomp-fn 'byte-compile))) |
| @@ -2822,44 +3025,98 @@ That command is designed for interactive use only" bytecomp-fn)) | |||
| 2822 | (mapc 'byte-compile-form (cdr form)) ; wasteful, but faster. | 3025 | (mapc 'byte-compile-form (cdr form)) ; wasteful, but faster. |
| 2823 | (byte-compile-out 'byte-call (length (cdr form)))) | 3026 | (byte-compile-out 'byte-call (length (cdr form)))) |
| 2824 | 3027 | ||
| 2825 | (defun byte-compile-variable-ref (base-op bytecomp-var) | 3028 | (defun byte-compile-check-variable (var &optional binding) |
| 2826 | (when (symbolp bytecomp-var) | 3029 | "Do various error checks before a use of the variable VAR. |
| 2827 | (byte-compile-set-symbol-position bytecomp-var)) | 3030 | If BINDING is non-nil, VAR is being bound." |
| 2828 | (if (or (not (symbolp bytecomp-var)) | 3031 | (when (symbolp var) |
| 2829 | (byte-compile-const-symbol-p bytecomp-var | 3032 | (byte-compile-set-symbol-position var)) |
| 2830 | (not (eq base-op 'byte-varref)))) | 3033 | (cond ((or (not (symbolp var)) (byte-compile-const-symbol-p var)) |
| 2831 | (if (byte-compile-warning-enabled-p 'constants) | 3034 | (when (byte-compile-warning-enabled-p 'constants) |
| 2832 | (byte-compile-warn | 3035 | (byte-compile-warn (if binding |
| 2833 | (cond ((eq base-op 'byte-varbind) "attempt to let-bind %s `%s'") | 3036 | "attempt to let-bind %s `%s`" |
| 2834 | ((eq base-op 'byte-varset) "variable assignment to %s `%s'") | 3037 | "variable reference to %s `%s'") |
| 2835 | (t "variable reference to %s `%s'")) | 3038 | (if (symbolp var) "constant" "nonvariable") |
| 2836 | (if (symbolp bytecomp-var) "constant" "nonvariable") | 3039 | (prin1-to-string var)))) |
| 2837 | (prin1-to-string bytecomp-var))) | 3040 | ((and (get var 'byte-obsolete-variable) |
| 2838 | (and (get bytecomp-var 'byte-obsolete-variable) | 3041 | (not (eq var byte-compile-not-obsolete-var))) |
| 2839 | (not (memq bytecomp-var byte-compile-not-obsolete-vars)) | 3042 | (byte-compile-warn-obsolete var)))) |
| 2840 | (byte-compile-warn-obsolete bytecomp-var)) | 3043 | |
| 2841 | (if (eq base-op 'byte-varbind) | 3044 | (defsubst byte-compile-dynamic-variable-op (base-op var) |
| 2842 | (push bytecomp-var byte-compile-bound-variables) | 3045 | (let ((tmp (assq var byte-compile-variables))) |
| 2843 | (or (not (byte-compile-warning-enabled-p 'free-vars)) | ||
| 2844 | (boundp bytecomp-var) | ||
| 2845 | (memq bytecomp-var byte-compile-bound-variables) | ||
| 2846 | (if (eq base-op 'byte-varset) | ||
| 2847 | (or (memq bytecomp-var byte-compile-free-assignments) | ||
| 2848 | (progn | ||
| 2849 | (byte-compile-warn "assignment to free variable `%s'" | ||
| 2850 | bytecomp-var) | ||
| 2851 | (push bytecomp-var byte-compile-free-assignments))) | ||
| 2852 | (or (memq bytecomp-var byte-compile-free-references) | ||
| 2853 | (progn | ||
| 2854 | (byte-compile-warn "reference to free variable `%s'" | ||
| 2855 | bytecomp-var) | ||
| 2856 | (push bytecomp-var byte-compile-free-references))))))) | ||
| 2857 | (let ((tmp (assq bytecomp-var byte-compile-variables))) | ||
| 2858 | (unless tmp | 3046 | (unless tmp |
| 2859 | (setq tmp (list bytecomp-var)) | 3047 | (setq tmp (list var)) |
| 2860 | (push tmp byte-compile-variables)) | 3048 | (push tmp byte-compile-variables)) |
| 2861 | (byte-compile-out base-op tmp))) | 3049 | (byte-compile-out base-op tmp))) |
| 2862 | 3050 | ||
| 3051 | (defun byte-compile-dynamic-variable-bind (var) | ||
| 3052 | "Generate code to bind the lexical variable VAR to the top-of-stack value." | ||
| 3053 | (byte-compile-check-variable var t) | ||
| 3054 | (when (byte-compile-warning-enabled-p 'free-vars) | ||
| 3055 | (push var byte-compile-bound-variables)) | ||
| 3056 | (byte-compile-dynamic-variable-op 'byte-varbind var)) | ||
| 3057 | |||
| 3058 | ;; This is used when it's know that VAR _definitely_ has a lexical | ||
| 3059 | ;; binding, and no error-checking should be done. | ||
| 3060 | (defun byte-compile-lexical-variable-ref (var) | ||
| 3061 | "Generate code to push the value of the lexical variable VAR on the stack." | ||
| 3062 | (let ((binding (assq var byte-compile-lexical-environment))) | ||
| 3063 | (when (null binding) | ||
| 3064 | (error "Lexical binding not found for `%s'" var)) | ||
| 3065 | (if (byte-compile-lexvar-on-stack-p binding) | ||
| 3066 | ;; On the stack | ||
| 3067 | (byte-compile-stack-ref (byte-compile-lexvar-offset binding)) | ||
| 3068 | ;; In a heap environment vector; first push the vector on the stack | ||
| 3069 | (byte-compile-lexical-variable-ref | ||
| 3070 | (byte-compile-lexvar-environment binding)) | ||
| 3071 | ;; Now get the value from it | ||
| 3072 | (byte-compile-out 'byte-vec-ref (byte-compile-lexvar-offset binding))))) | ||
| 3073 | |||
| 3074 | (defun byte-compile-variable-ref (var) | ||
| 3075 | "Generate code to push the value of the variable VAR on the stack." | ||
| 3076 | (byte-compile-check-variable var) | ||
| 3077 | (let ((lex-binding (assq var byte-compile-lexical-environment))) | ||
| 3078 | (if lex-binding | ||
| 3079 | ;; VAR is lexically bound | ||
| 3080 | (if (byte-compile-lexvar-on-stack-p lex-binding) | ||
| 3081 | ;; On the stack | ||
| 3082 | (byte-compile-stack-ref (byte-compile-lexvar-offset lex-binding)) | ||
| 3083 | ;; In a heap environment vector | ||
| 3084 | (byte-compile-lexical-variable-ref | ||
| 3085 | (byte-compile-lexvar-environment lex-binding)) | ||
| 3086 | (byte-compile-out 'byte-vec-ref | ||
| 3087 | (byte-compile-lexvar-offset lex-binding))) | ||
| 3088 | ;; VAR is dynamically bound | ||
| 3089 | (unless (or (not (byte-compile-warning-enabled-p 'free-vars)) | ||
| 3090 | (boundp var) | ||
| 3091 | (memq var byte-compile-bound-variables) | ||
| 3092 | (memq var byte-compile-free-references)) | ||
| 3093 | (byte-compile-warn "reference to free variable `%s'" var) | ||
| 3094 | (push var byte-compile-free-references)) | ||
| 3095 | (byte-compile-dynamic-variable-op 'byte-varref var)))) | ||
| 3096 | |||
| 3097 | (defun byte-compile-variable-set (var) | ||
| 3098 | "Generate code to set the variable VAR from the top-of-stack value." | ||
| 3099 | (byte-compile-check-variable var) | ||
| 3100 | (let ((lex-binding (assq var byte-compile-lexical-environment))) | ||
| 3101 | (if lex-binding | ||
| 3102 | ;; VAR is lexically bound | ||
| 3103 | (if (byte-compile-lexvar-on-stack-p lex-binding) | ||
| 3104 | ;; On the stack | ||
| 3105 | (byte-compile-stack-set (byte-compile-lexvar-offset lex-binding)) | ||
| 3106 | ;; In a heap environment vector | ||
| 3107 | (byte-compile-lexical-variable-ref | ||
| 3108 | (byte-compile-lexvar-environment lex-binding)) | ||
| 3109 | (byte-compile-out 'byte-vec-set | ||
| 3110 | (byte-compile-lexvar-offset lex-binding))) | ||
| 3111 | ;; VAR is dynamically bound | ||
| 3112 | (unless (or (not (byte-compile-warning-enabled-p 'free-vars)) | ||
| 3113 | (boundp var) | ||
| 3114 | (memq var byte-compile-bound-variables) | ||
| 3115 | (memq var byte-compile-free-assignments)) | ||
| 3116 | (byte-compile-warn "assignment to free variable `%s'" var) | ||
| 3117 | (push var byte-compile-free-assignments)) | ||
| 3118 | (byte-compile-dynamic-variable-op 'byte-varset var)))) | ||
| 3119 | |||
| 2863 | (defmacro byte-compile-get-constant (const) | 3120 | (defmacro byte-compile-get-constant (const) |
| 2864 | `(or (if (stringp ,const) | 3121 | `(or (if (stringp ,const) |
| 2865 | ;; In a string constant, treat properties as significant. | 3122 | ;; In a string constant, treat properties as significant. |
| @@ -2886,6 +3143,25 @@ That command is designed for interactive use only" bytecomp-fn)) | |||
| 2886 | (let ((for-effect nil)) | 3143 | (let ((for-effect nil)) |
| 2887 | (inline (byte-compile-constant const)))) | 3144 | (inline (byte-compile-constant const)))) |
| 2888 | 3145 | ||
| 3146 | (defun byte-compile-push-unknown-constant (&optional id) | ||
| 3147 | "Generate code to push a `constant' who's value isn't known yet. | ||
| 3148 | A tag is returned which may then later be passed to | ||
| 3149 | `byte-compile-resolve-unknown-constant' to finalize the value. | ||
| 3150 | The optional argument ID is a tag returned by an earlier call to | ||
| 3151 | `byte-compile-push-unknown-constant', in which case the same constant is | ||
| 3152 | pushed again." | ||
| 3153 | (unless id | ||
| 3154 | (setq id (list (make-symbol "unknown"))) | ||
| 3155 | (push id byte-compile-constants)) | ||
| 3156 | (byte-compile-out 'byte-constant id) | ||
| 3157 | id) | ||
| 3158 | |||
| 3159 | (defun byte-compile-resolve-unknown-constant (id value) | ||
| 3160 | "Give an `unknown constant' a value. | ||
| 3161 | ID is the tag returned by `byte-compile-push-unknown-constant'. and VALUE | ||
| 3162 | is the value it should have." | ||
| 3163 | (setcar id value)) | ||
| 3164 | |||
| 2889 | 3165 | ||
| 2890 | ;; Compile those primitive ordinary functions | 3166 | ;; Compile those primitive ordinary functions |
| 2891 | ;; which have special byte codes just for speed. | 3167 | ;; which have special byte codes just for speed. |
| @@ -3089,8 +3365,39 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\"" | |||
| 3089 | (defun byte-compile-noop (form) | 3365 | (defun byte-compile-noop (form) |
| 3090 | (byte-compile-constant nil)) | 3366 | (byte-compile-constant nil)) |
| 3091 | 3367 | ||
| 3092 | (defun byte-compile-discard () | 3368 | (defun byte-compile-discard (&optional num preserve-tos) |
| 3093 | (byte-compile-out 'byte-discard 0)) | 3369 | "Output byte codes to discard the NUM entries at the top of the stack (NUM defaults to 1). |
| 3370 | If PRESERVE-TOS is non-nil, preserve the top-of-stack value, as if it were | ||
| 3371 | popped before discarding the num values, and then pushed back again after | ||
| 3372 | discarding." | ||
| 3373 | (if (and (null num) (not preserve-tos)) | ||
| 3374 | ;; common case | ||
| 3375 | (byte-compile-out 'byte-discard) | ||
| 3376 | ;; general case | ||
| 3377 | (unless num | ||
| 3378 | (setq num 1)) | ||
| 3379 | (when (and preserve-tos (> num 0)) | ||
| 3380 | ;; Preserve the top-of-stack value by writing it directly to the stack | ||
| 3381 | ;; location which will be at the top-of-stack after popping. | ||
| 3382 | (byte-compile-stack-set (1- (- byte-compile-depth num))) | ||
| 3383 | ;; Now we actually discard one less value, since we want to keep | ||
| 3384 | ;; the eventual TOS | ||
| 3385 | (setq num (1- num))) | ||
| 3386 | (while (> num 0) | ||
| 3387 | (byte-compile-out 'byte-discard) | ||
| 3388 | (setq num (1- num))))) | ||
| 3389 | |||
| 3390 | (defun byte-compile-stack-ref (stack-pos) | ||
| 3391 | "Output byte codes to push the value at position STACK-POS in the stack, on the top of the stack." | ||
| 3392 | (if (= byte-compile-depth (1+ stack-pos)) | ||
| 3393 | ;; A simple optimization | ||
| 3394 | (byte-compile-out 'byte-dup) | ||
| 3395 | ;; normal case | ||
| 3396 | (byte-compile-out 'byte-stack-ref stack-pos))) | ||
| 3397 | |||
| 3398 | (defun byte-compile-stack-set (stack-pos) | ||
| 3399 | "Output byte codes to store the top-of-stack value at position STACK-POS in the stack." | ||
| 3400 | (byte-compile-out 'byte-stack-set stack-pos)) | ||
| 3094 | 3401 | ||
| 3095 | 3402 | ||
| 3096 | ;; Compile a function that accepts one or more args and is right-associative. | 3403 | ;; Compile a function that accepts one or more args and is right-associative. |
| @@ -3249,40 +3556,14 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\"" | |||
| 3249 | the syntax (function (lambda (...) ...)) instead."))))) | 3556 | the syntax (function (lambda (...) ...)) instead."))))) |
| 3250 | (byte-compile-two-args form)) | 3557 | (byte-compile-two-args form)) |
| 3251 | 3558 | ||
| 3252 | (defun byte-compile-funarg (form) | ||
| 3253 | ;; (mapcar '(lambda (x) ..) ..) ==> (mapcar (function (lambda (x) ..)) ..) | ||
| 3254 | ;; for cases where it's guaranteed that first arg will be used as a lambda. | ||
| 3255 | (byte-compile-normal-call | ||
| 3256 | (let ((fn (nth 1 form))) | ||
| 3257 | (if (and (eq (car-safe fn) 'quote) | ||
| 3258 | (eq (car-safe (nth 1 fn)) 'lambda)) | ||
| 3259 | (cons (car form) | ||
| 3260 | (cons (cons 'function (cdr fn)) | ||
| 3261 | (cdr (cdr form)))) | ||
| 3262 | form)))) | ||
| 3263 | |||
| 3264 | (defun byte-compile-funarg-2 (form) | ||
| 3265 | ;; (sort ... '(lambda (x) ..)) ==> (sort ... (function (lambda (x) ..))) | ||
| 3266 | ;; for cases where it's guaranteed that second arg will be used as a lambda. | ||
| 3267 | (byte-compile-normal-call | ||
| 3268 | (let ((fn (nth 2 form))) | ||
| 3269 | (if (and (eq (car-safe fn) 'quote) | ||
| 3270 | (eq (car-safe (nth 1 fn)) 'lambda)) | ||
| 3271 | (cons (car form) | ||
| 3272 | (cons (nth 1 form) | ||
| 3273 | (cons (cons 'function (cdr fn)) | ||
| 3274 | (cdr (cdr (cdr form)))))) | ||
| 3275 | form)))) | ||
| 3276 | |||
| 3277 | ;; (function foo) must compile like 'foo, not like (symbol-function 'foo). | 3559 | ;; (function foo) must compile like 'foo, not like (symbol-function 'foo). |
| 3278 | ;; Otherwise it will be incompatible with the interpreter, | 3560 | ;; Otherwise it will be incompatible with the interpreter, |
| 3279 | ;; and (funcall (function foo)) will lose with autoloads. | 3561 | ;; and (funcall (function foo)) will lose with autoloads. |
| 3280 | 3562 | ||
| 3281 | (defun byte-compile-function-form (form) | 3563 | (defun byte-compile-function-form (form) |
| 3282 | (byte-compile-constant | 3564 | (if (symbolp (nth 1 form)) |
| 3283 | (cond ((symbolp (nth 1 form)) | 3565 | (byte-compile-constant (nth 1 form)) |
| 3284 | (nth 1 form)) | 3566 | (byte-compile-closure (nth 1 form)))) |
| 3285 | ((byte-compile-lambda (nth 1 form)))))) | ||
| 3286 | 3567 | ||
| 3287 | (defun byte-compile-indent-to (form) | 3568 | (defun byte-compile-indent-to (form) |
| 3288 | (let ((len (length form))) | 3569 | (let ((len (length form))) |
| @@ -3326,7 +3607,7 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\"" | |||
| 3326 | (byte-compile-form (car (cdr bytecomp-args))) | 3607 | (byte-compile-form (car (cdr bytecomp-args))) |
| 3327 | (or for-effect (cdr (cdr bytecomp-args)) | 3608 | (or for-effect (cdr (cdr bytecomp-args)) |
| 3328 | (byte-compile-out 'byte-dup 0)) | 3609 | (byte-compile-out 'byte-dup 0)) |
| 3329 | (byte-compile-variable-ref 'byte-varset (car bytecomp-args)) | 3610 | (byte-compile-variable-set (car bytecomp-args)) |
| 3330 | (setq bytecomp-args (cdr (cdr bytecomp-args)))) | 3611 | (setq bytecomp-args (cdr (cdr bytecomp-args)))) |
| 3331 | ;; (setq), with no arguments. | 3612 | ;; (setq), with no arguments. |
| 3332 | (byte-compile-form nil for-effect)) | 3613 | (byte-compile-form nil for-effect)) |
| @@ -3392,16 +3673,6 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\"" | |||
| 3392 | (byte-defop-compiler-1 or) | 3673 | (byte-defop-compiler-1 or) |
| 3393 | (byte-defop-compiler-1 while) | 3674 | (byte-defop-compiler-1 while) |
| 3394 | (byte-defop-compiler-1 funcall) | 3675 | (byte-defop-compiler-1 funcall) |
| 3395 | (byte-defop-compiler-1 apply byte-compile-funarg) | ||
| 3396 | (byte-defop-compiler-1 mapcar byte-compile-funarg) | ||
| 3397 | (byte-defop-compiler-1 mapatoms byte-compile-funarg) | ||
| 3398 | (byte-defop-compiler-1 mapconcat byte-compile-funarg) | ||
| 3399 | (byte-defop-compiler-1 mapc byte-compile-funarg) | ||
| 3400 | (byte-defop-compiler-1 maphash byte-compile-funarg) | ||
| 3401 | (byte-defop-compiler-1 map-char-table byte-compile-funarg) | ||
| 3402 | (byte-defop-compiler-1 map-char-table byte-compile-funarg-2) | ||
| 3403 | ;; map-charset-chars should be funarg but has optional third arg | ||
| 3404 | (byte-defop-compiler-1 sort byte-compile-funarg-2) | ||
| 3405 | (byte-defop-compiler-1 let) | 3676 | (byte-defop-compiler-1 let) |
| 3406 | (byte-defop-compiler-1 let*) | 3677 | (byte-defop-compiler-1 let*) |
| 3407 | 3678 | ||
| @@ -3583,7 +3854,14 @@ that suppresses all warnings during execution of BODY." | |||
| 3583 | 3854 | ||
| 3584 | (defun byte-compile-while (form) | 3855 | (defun byte-compile-while (form) |
| 3585 | (let ((endtag (byte-compile-make-tag)) | 3856 | (let ((endtag (byte-compile-make-tag)) |
| 3586 | (looptag (byte-compile-make-tag))) | 3857 | (looptag (byte-compile-make-tag)) |
| 3858 | ;; Heap environments can't be shared between a loop and its | ||
| 3859 | ;; enclosing environment (because any lexical variables bound | ||
| 3860 | ;; inside the loop should have an independent value for each | ||
| 3861 | ;; iteration). Setting `byte-compile-current-num-closures' to | ||
| 3862 | ;; an invalid value causes the code that tries to merge | ||
| 3863 | ;; environments to not do so. | ||
| 3864 | (byte-compile-current-num-closures -1)) | ||
| 3587 | (byte-compile-out-tag looptag) | 3865 | (byte-compile-out-tag looptag) |
| 3588 | (byte-compile-form (car (cdr form))) | 3866 | (byte-compile-form (car (cdr form))) |
| 3589 | (byte-compile-goto-if nil for-effect endtag) | 3867 | (byte-compile-goto-if nil for-effect endtag) |
| @@ -3596,34 +3874,116 @@ that suppresses all warnings during execution of BODY." | |||
| 3596 | (mapc 'byte-compile-form (cdr form)) | 3874 | (mapc 'byte-compile-form (cdr form)) |
| 3597 | (byte-compile-out 'byte-call (length (cdr (cdr form))))) | 3875 | (byte-compile-out 'byte-call (length (cdr (cdr form))))) |
| 3598 | 3876 | ||
| 3877 | |||
| 3878 | ;; let binding | ||
| 3879 | |||
| 3880 | ;; All other lexical-binding functions are guarded by a non-nil return | ||
| 3881 | ;; value from `byte-compile-compute-lforminfo', so they needn't be | ||
| 3882 | ;; autoloaded. | ||
| 3883 | (autoload 'byte-compile-compute-lforminfo "byte-lexbind") | ||
| 3884 | |||
| 3885 | (defun byte-compile-push-binding-init (clause init-lexenv lforminfo) | ||
| 3886 | "Emit byte-codes to push the initialization value for CLAUSE on the stack. | ||
| 3887 | INIT-LEXENV is the lexical environment created for initializations | ||
| 3888 | already done for this form. | ||
| 3889 | LFORMINFO should be information about lexical variables being bound. | ||
| 3890 | Return INIT-LEXENV updated to include the newest initialization, or nil | ||
| 3891 | if LFORMINFO is nil (meaning all bindings are dynamic)." | ||
| 3892 | (let* ((var (if (consp clause) (car clause) clause)) | ||
| 3893 | (vinfo | ||
| 3894 | (and lforminfo (assq var (byte-compile-lforminfo-vars lforminfo)))) | ||
| 3895 | (unused (and vinfo (zerop (cadr vinfo))))) | ||
| 3896 | (unless (and unused (symbolp clause)) | ||
| 3897 | (when (and lforminfo (not unused)) | ||
| 3898 | ;; We record the stack position even of dynamic bindings and | ||
| 3899 | ;; variables in non-stack lexical environments; we'll put | ||
| 3900 | ;; them in the proper place below. | ||
| 3901 | (push (byte-compile-make-lexvar var byte-compile-depth) init-lexenv)) | ||
| 3902 | (if (consp clause) | ||
| 3903 | (byte-compile-form (cadr clause) unused) | ||
| 3904 | (byte-compile-push-constant nil)))) | ||
| 3905 | init-lexenv) | ||
| 3599 | 3906 | ||
| 3600 | (defun byte-compile-let (form) | 3907 | (defun byte-compile-let (form) |
| 3601 | ;; First compute the binding values in the old scope. | 3908 | "Generate code for the `let' form FORM." |
| 3602 | (let ((varlist (car (cdr form)))) | 3909 | (let ((clauses (cadr form)) |
| 3603 | (dolist (var varlist) | 3910 | (lforminfo (and lexical-binding (byte-compile-compute-lforminfo form))) |
| 3604 | (if (consp var) | 3911 | (init-lexenv nil) |
| 3605 | (byte-compile-form (car (cdr var))) | 3912 | ;; bind these to restrict the scope of any changes |
| 3606 | (byte-compile-push-constant nil)))) | 3913 | (byte-compile-current-heap-environment |
| 3607 | (let ((byte-compile-bound-variables byte-compile-bound-variables) ;new scope | 3914 | byte-compile-current-heap-environment) |
| 3608 | (varlist (reverse (car (cdr form))))) | 3915 | (byte-compile-current-num-closures byte-compile-current-num-closures)) |
| 3609 | (dolist (var varlist) | 3916 | (when (and lforminfo (byte-compile-non-stack-bindings-p clauses lforminfo)) |
| 3610 | (byte-compile-variable-ref 'byte-varbind | 3917 | ;; Some of the variables we're binding are lexical variables on |
| 3611 | (if (consp var) (car var) var))) | 3918 | ;; the stack, but not all. As much as we can, rearrange the list |
| 3612 | (byte-compile-body-do-effect (cdr (cdr form))) | 3919 | ;; so that non-stack lexical variables and dynamically bound |
| 3613 | (byte-compile-out 'byte-unbind (length (car (cdr form)))))) | 3920 | ;; variables come last, which allows slightly more optimal |
| 3921 | ;; byte-code for binding them. | ||
| 3922 | (setq clauses (byte-compile-rearrange-let-clauses clauses lforminfo))) | ||
| 3923 | ;; If necessary, create a new heap environment to hold some of the | ||
| 3924 | ;; variables bound here. | ||
| 3925 | (when lforminfo | ||
| 3926 | (setq init-lexenv (byte-compile-maybe-push-heap-environment lforminfo))) | ||
| 3927 | ;; First compute the binding values in the old scope. | ||
| 3928 | (dolist (clause clauses) | ||
| 3929 | (setq init-lexenv | ||
| 3930 | (byte-compile-push-binding-init clause init-lexenv lforminfo))) | ||
| 3931 | ;; Now do the bindings, execute the body, and undo the bindings | ||
| 3932 | (let ((byte-compile-bound-variables byte-compile-bound-variables) | ||
| 3933 | (byte-compile-lexical-environment byte-compile-lexical-environment) | ||
| 3934 | (preserve-body-value (not for-effect))) | ||
| 3935 | (dolist (clause (reverse clauses)) | ||
| 3936 | (let ((var (if (consp clause) (car clause) clause))) | ||
| 3937 | (cond ((null lforminfo) | ||
| 3938 | ;; If there are no lexical bindings, we can do things simply. | ||
| 3939 | (byte-compile-dynamic-variable-bind var)) | ||
| 3940 | ((byte-compile-bind var init-lexenv lforminfo) | ||
| 3941 | (pop init-lexenv))))) | ||
| 3942 | ;; Emit the body | ||
| 3943 | (byte-compile-body-do-effect (cdr (cdr form))) | ||
| 3944 | ;; Unbind the variables | ||
| 3945 | (if lforminfo | ||
| 3946 | ;; Unbind both lexical and dynamic variables | ||
| 3947 | (byte-compile-unbind clauses init-lexenv lforminfo preserve-body-value) | ||
| 3948 | ;; Unbind dynamic variables | ||
| 3949 | (byte-compile-out 'byte-unbind (length clauses)))))) | ||
| 3614 | 3950 | ||
| 3615 | (defun byte-compile-let* (form) | 3951 | (defun byte-compile-let* (form) |
| 3616 | (let ((byte-compile-bound-variables byte-compile-bound-variables) ;new scope | 3952 | "Generate code for the `let*' form FORM." |
| 3617 | (varlist (copy-sequence (car (cdr form))))) | 3953 | (let ((clauses (cadr form)) |
| 3618 | (dolist (var varlist) | 3954 | (lforminfo (and lexical-binding (byte-compile-compute-lforminfo form))) |
| 3619 | (if (atom var) | 3955 | (init-lexenv nil) |
| 3620 | (byte-compile-push-constant nil) | 3956 | (preserve-body-value (not for-effect)) |
| 3621 | (byte-compile-form (car (cdr var))) | 3957 | ;; bind these to restrict the scope of any changes |
| 3622 | (setq var (car var))) | 3958 | (byte-compile-bound-variables byte-compile-bound-variables) |
| 3623 | (byte-compile-variable-ref 'byte-varbind var)) | 3959 | (byte-compile-lexical-environment byte-compile-lexical-environment) |
| 3960 | (byte-compile-current-heap-environment | ||
| 3961 | byte-compile-current-heap-environment) | ||
| 3962 | (byte-compile-current-num-closures byte-compile-current-num-closures)) | ||
| 3963 | ;; If necessary, create a new heap environment to hold some of the | ||
| 3964 | ;; variables bound here. | ||
| 3965 | (when lforminfo | ||
| 3966 | (setq init-lexenv (byte-compile-maybe-push-heap-environment lforminfo))) | ||
| 3967 | ;; Bind the variables | ||
| 3968 | (dolist (clause clauses) | ||
| 3969 | (setq init-lexenv | ||
| 3970 | (byte-compile-push-binding-init clause init-lexenv lforminfo)) | ||
| 3971 | (let ((var (if (consp clause) (car clause) clause))) | ||
| 3972 | (cond ((null lforminfo) | ||
| 3973 | ;; If there are no lexical bindings, we can do things simply. | ||
| 3974 | (byte-compile-dynamic-variable-bind var)) | ||
| 3975 | ((byte-compile-bind var init-lexenv lforminfo) | ||
| 3976 | (pop init-lexenv))))) | ||
| 3977 | ;; Emit the body | ||
| 3624 | (byte-compile-body-do-effect (cdr (cdr form))) | 3978 | (byte-compile-body-do-effect (cdr (cdr form))) |
| 3625 | (byte-compile-out 'byte-unbind (length (car (cdr form)))))) | 3979 | ;; Unbind the variables |
| 3980 | (if lforminfo | ||
| 3981 | ;; Unbind both lexical and dynamic variables | ||
| 3982 | (byte-compile-unbind clauses init-lexenv lforminfo preserve-body-value) | ||
| 3983 | ;; Unbind dynamic variables | ||
| 3984 | (byte-compile-out 'byte-unbind (length clauses))))) | ||
| 3626 | 3985 | ||
| 3986 | |||
| 3627 | 3987 | ||
| 3628 | (byte-defop-compiler-1 /= byte-compile-negated) | 3988 | (byte-defop-compiler-1 /= byte-compile-negated) |
| 3629 | (byte-defop-compiler-1 atom byte-compile-negated) | 3989 | (byte-defop-compiler-1 atom byte-compile-negated) |
| @@ -3646,6 +4006,7 @@ that suppresses all warnings during execution of BODY." | |||
| 3646 | "Compiler error: `%s' has no `byte-compile-negated-op' property" | 4006 | "Compiler error: `%s' has no `byte-compile-negated-op' property" |
| 3647 | (car form))) | 4007 | (car form))) |
| 3648 | (cdr form)))) | 4008 | (cdr form)))) |
| 4009 | |||
| 3649 | 4010 | ||
| 3650 | ;;; other tricky macro-like special-forms | 4011 | ;;; other tricky macro-like special-forms |
| 3651 | 4012 | ||
| @@ -3766,28 +4127,28 @@ that suppresses all warnings during execution of BODY." | |||
| 3766 | (byte-compile-set-symbol-position (car form)) | 4127 | (byte-compile-set-symbol-position (car form)) |
| 3767 | (byte-compile-set-symbol-position 'defun) | 4128 | (byte-compile-set-symbol-position 'defun) |
| 3768 | (error "defun name must be a symbol, not %s" (car form))) | 4129 | (error "defun name must be a symbol, not %s" (car form))) |
| 3769 | ;; We prefer to generate a defalias form so it will record the function | 4130 | (let ((for-effect nil)) |
| 3770 | ;; definition just like interpreting a defun. | 4131 | (byte-compile-push-constant 'defalias) |
| 3771 | (byte-compile-form | 4132 | (byte-compile-push-constant (nth 1 form)) |
| 3772 | (list 'defalias | 4133 | (byte-compile-closure (cdr (cdr form)) t)) |
| 3773 | (list 'quote (nth 1 form)) | 4134 | (byte-compile-out 'byte-call 2)) |
| 3774 | (byte-compile-byte-code-maker | ||
| 3775 | (byte-compile-lambda (cdr (cdr form)) t))) | ||
| 3776 | t) | ||
| 3777 | (byte-compile-constant (nth 1 form))) | ||
| 3778 | 4135 | ||
| 3779 | (defun byte-compile-defmacro (form) | 4136 | (defun byte-compile-defmacro (form) |
| 3780 | ;; This is not used for file-level defmacros with doc strings. | 4137 | ;; This is not used for file-level defmacros with doc strings. |
| 3781 | (byte-compile-body-do-effect | 4138 | ;; FIXME handle decls, use defalias? |
| 3782 | (let ((decls (byte-compile-defmacro-declaration form)) | 4139 | (let ((decls (byte-compile-defmacro-declaration form)) |
| 3783 | (code (byte-compile-byte-code-maker | 4140 | (code (byte-compile-lambda (cdr (cdr form)) t)) |
| 3784 | (byte-compile-lambda (cdr (cdr form)) t)))) | 4141 | (for-effect nil)) |
| 3785 | `((defalias ',(nth 1 form) | 4142 | (byte-compile-push-constant (nth 1 form)) |
| 3786 | ,(if (eq (car-safe code) 'make-byte-code) | 4143 | (if (not (byte-compile-closure-code-p code)) |
| 3787 | `(cons 'macro ,code) | 4144 | ;; simple lambda |
| 3788 | `'(macro . ,(eval code)))) | 4145 | (byte-compile-push-constant (cons 'macro code)) |
| 3789 | ,@decls | 4146 | (byte-compile-push-constant 'macro) |
| 3790 | ',(nth 1 form))))) | 4147 | (byte-compile-make-closure code) |
| 4148 | (byte-compile-out 'byte-cons)) | ||
| 4149 | (byte-compile-out 'byte-fset) | ||
| 4150 | (byte-compile-discard)) | ||
| 4151 | (byte-compile-constant (nth 1 form))) | ||
| 3791 | 4152 | ||
| 3792 | (defun byte-compile-defvar (form) | 4153 | (defun byte-compile-defvar (form) |
| 3793 | ;; This is not used for file-level defvar/consts with doc strings. | 4154 | ;; This is not used for file-level defvar/consts with doc strings. |
| @@ -3813,7 +4174,7 @@ that suppresses all warnings during execution of BODY." | |||
| 3813 | ;; Put the defined variable in this library's load-history entry | 4174 | ;; Put the defined variable in this library's load-history entry |
| 3814 | ;; just as a real defvar would, but only in top-level forms. | 4175 | ;; just as a real defvar would, but only in top-level forms. |
| 3815 | (when (and (cddr form) (null byte-compile-current-form)) | 4176 | (when (and (cddr form) (null byte-compile-current-form)) |
| 3816 | `(push ',var current-load-list)) | 4177 | `(setq current-load-list (cons ',var current-load-list))) |
| 3817 | (when (> (length form) 3) | 4178 | (when (> (length form) 3) |
| 3818 | (when (and string (not (stringp string))) | 4179 | (when (and string (not (stringp string))) |
| 3819 | (byte-compile-warn "third arg to `%s %s' is not a string: %s" | 4180 | (byte-compile-warn "third arg to `%s %s' is not a string: %s" |
| @@ -3935,23 +4296,74 @@ that suppresses all warnings during execution of BODY." | |||
| 3935 | (setq byte-compile-depth (and (not (eq opcode 'byte-goto)) | 4296 | (setq byte-compile-depth (and (not (eq opcode 'byte-goto)) |
| 3936 | (1- byte-compile-depth)))) | 4297 | (1- byte-compile-depth)))) |
| 3937 | 4298 | ||
| 3938 | (defun byte-compile-out (opcode offset) | 4299 | (defun byte-compile-stack-adjustment (op operand) |
| 3939 | (push (cons opcode offset) byte-compile-output) | 4300 | "Return the amount by which an operation adjusts the stack. |
| 3940 | (cond ((eq opcode 'byte-call) | 4301 | OP and OPERAND are as passed to `byte-compile-out'." |
| 3941 | (setq byte-compile-depth (- byte-compile-depth offset))) | 4302 | (if (memq op '(byte-call byte-discardN byte-discardN-preserve-tos)) |
| 3942 | ((eq opcode 'byte-return) | 4303 | ;; For calls, OPERAND is the number of args, so we pop OPERAND + 1 |
| 3943 | ;; This is actually an unnecessary case, because there should be | 4304 | ;; elements, and the push the result, for a total of -OPERAND. |
| 3944 | ;; no more opcodes behind byte-return. | 4305 | ;; For discardN*, of course, we just pop OPERAND elements. |
| 3945 | (setq byte-compile-depth nil)) | 4306 | (- operand) |
| 3946 | (t | 4307 | (or (aref byte-stack+-info (symbol-value op)) |
| 3947 | (setq byte-compile-depth (+ byte-compile-depth | 4308 | ;; Ops with a nil entry in `byte-stack+-info' are byte-codes |
| 3948 | (or (aref byte-stack+-info | 4309 | ;; that take OPERAND values off the stack and push a result, for |
| 3949 | (symbol-value opcode)) | 4310 | ;; a total of 1 - OPERAND |
| 3950 | (- (1- offset)))) | 4311 | (- 1 operand)))) |
| 3951 | byte-compile-maxdepth (max byte-compile-depth | 4312 | |
| 3952 | byte-compile-maxdepth)))) | 4313 | (defun byte-compile-out (op &optional operand) |
| 3953 | ;;(if (< byte-compile-depth 0) (error "Compiler error: stack underflow")) | 4314 | (push (cons op operand) byte-compile-output) |
| 3954 | ) | 4315 | (if (eq op 'byte-return) |
| 4316 | ;; This is actually an unnecessary case, because there should be no | ||
| 4317 | ;; more ops behind byte-return. | ||
| 4318 | (setq byte-compile-depth nil) | ||
| 4319 | (setq byte-compile-depth | ||
| 4320 | (+ byte-compile-depth (byte-compile-stack-adjustment op operand))) | ||
| 4321 | (setq byte-compile-maxdepth (max byte-compile-depth byte-compile-maxdepth)) | ||
| 4322 | ;;(if (< byte-compile-depth 0) (error "Compiler error: stack underflow")) | ||
| 4323 | )) | ||
| 4324 | |||
| 4325 | (defun byte-compile-delay-out (&optional stack-used stack-adjust) | ||
| 4326 | "Add a placeholder to the output, which can be used to later add byte-codes. | ||
| 4327 | Return a position tag that can be passed to `byte-compile-delayed-out' | ||
| 4328 | to add the delayed byte-codes. STACK-USED is the maximum amount of | ||
| 4329 | stack-spaced used by the delayed byte-codes (defaulting to 0), and | ||
| 4330 | STACK-ADJUST is the amount by which the later-added code will adjust the | ||
| 4331 | stack (defaulting to 0); the byte-codes added later _must_ adjust the | ||
| 4332 | stack by this amount! If STACK-ADJUST is 0, then it's not necessary to | ||
| 4333 | actually add anything later; the effect as if nothing was added at all." | ||
| 4334 | ;; We just add a no-op to `byte-compile-output', and return a pointer to | ||
| 4335 | ;; the tail of the list; `byte-compile-delayed-out' uses list surgery | ||
| 4336 | ;; to add the byte-codes. | ||
| 4337 | (when stack-used | ||
| 4338 | (setq byte-compile-maxdepth | ||
| 4339 | (max byte-compile-depth (+ byte-compile-depth (or stack-used 0))))) | ||
| 4340 | (when stack-adjust | ||
| 4341 | (setq byte-compile-depth | ||
| 4342 | (+ byte-compile-depth stack-adjust))) | ||
| 4343 | (push (cons nil (or stack-adjust 0)) byte-compile-output)) | ||
| 4344 | |||
| 4345 | (defun byte-compile-delayed-out (position op &optional operand) | ||
| 4346 | "Add at POSITION the byte-operation OP, with optional numeric arg OPERAND. | ||
| 4347 | POSITION should a position returned by `byte-compile-delay-out'. | ||
| 4348 | Return a new position, which can be used to add further operations." | ||
| 4349 | (unless (null (caar position)) | ||
| 4350 | (error "Bad POSITION arg to `byte-compile-delayed-out'")) | ||
| 4351 | ;; This is kind of like `byte-compile-out', but we splice into the list | ||
| 4352 | ;; where POSITION is. We don't bother updating `byte-compile-maxdepth' | ||
| 4353 | ;; because that was already done by `byte-compile-delay-out', but we do | ||
| 4354 | ;; update the relative operand stored in the no-op marker currently at | ||
| 4355 | ;; POSITION; since we insert before that marker, this means that if the | ||
| 4356 | ;; caller doesn't insert a sequence of byte-codes that matches the expected | ||
| 4357 | ;; operand passed to `byte-compile-delay-out', then the nop will still have | ||
| 4358 | ;; a non-zero operand when `byte-compile-lapcode' is called, which will | ||
| 4359 | ;; cause an error to be signaled. | ||
| 4360 | |||
| 4361 | ;; Adjust the cumulative stack-adjustment stored in the cdr of the no-op | ||
| 4362 | (setcdr (car position) | ||
| 4363 | (- (cdar position) (byte-compile-stack-adjustment op operand))) | ||
| 4364 | ;; Add the new operation onto the list tail at POSITION | ||
| 4365 | (setcdr position (cons (cons op operand) (cdr position))) | ||
| 4366 | position) | ||
| 3955 | 4367 | ||
| 3956 | 4368 | ||
| 3957 | ;;; call tree stuff | 4369 | ;;; call tree stuff |
diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el index 9899e991e3f..18aa5fde0c8 100644 --- a/lisp/emacs-lisp/disass.el +++ b/lisp/emacs-lisp/disass.el | |||
| @@ -73,19 +73,22 @@ redefine OBJECT if it is a symbol." | |||
| 73 | (let ((macro 'nil) | 73 | (let ((macro 'nil) |
| 74 | (name 'nil) | 74 | (name 'nil) |
| 75 | (doc 'nil) | 75 | (doc 'nil) |
| 76 | (lexical-binding nil) | ||
| 76 | args) | 77 | args) |
| 77 | (while (symbolp obj) | 78 | (while (symbolp obj) |
| 78 | (setq name obj | 79 | (setq name obj |
| 79 | obj (symbol-function obj))) | 80 | obj (symbol-function obj))) |
| 80 | (if (subrp obj) | 81 | (if (subrp obj) |
| 81 | (error "Can't disassemble #<subr %s>" name)) | 82 | (error "Can't disassemble #<subr %s>" name)) |
| 82 | (if (and (listp obj) (eq (car obj) 'autoload)) | 83 | (when (and (listp obj) (eq (car obj) 'autoload)) |
| 83 | (progn | 84 | (load (nth 1 obj)) |
| 84 | (load (nth 1 obj)) | 85 | (setq obj (symbol-function name))) |
| 85 | (setq obj (symbol-function name)))) | ||
| 86 | (if (eq (car-safe obj) 'macro) ;handle macros | 86 | (if (eq (car-safe obj) 'macro) ;handle macros |
| 87 | (setq macro t | 87 | (setq macro t |
| 88 | obj (cdr obj))) | 88 | obj (cdr obj))) |
| 89 | (when (and (listp obj) (eq (car obj) 'closure)) | ||
| 90 | (setq lexical-binding t) | ||
| 91 | (setq obj (cddr obj))) | ||
| 89 | (if (and (listp obj) (eq (car obj) 'byte-code)) | 92 | (if (and (listp obj) (eq (car obj) 'byte-code)) |
| 90 | (setq obj (list 'lambda nil obj))) | 93 | (setq obj (list 'lambda nil obj))) |
| 91 | (if (and (listp obj) (not (eq (car obj) 'lambda))) | 94 | (if (and (listp obj) (not (eq (car obj) 'lambda))) |
| @@ -216,7 +219,9 @@ OBJ should be a call to BYTE-CODE generated by the byte compiler." | |||
| 216 | (cond ((memq op byte-goto-ops) | 219 | (cond ((memq op byte-goto-ops) |
| 217 | (insert (int-to-string (nth 1 arg)))) | 220 | (insert (int-to-string (nth 1 arg)))) |
| 218 | ((memq op '(byte-call byte-unbind | 221 | ((memq op '(byte-call byte-unbind |
| 219 | byte-listN byte-concatN byte-insertN)) | 222 | byte-listN byte-concatN byte-insertN |
| 223 | byte-stack-ref byte-stack-set byte-stack-set2 | ||
| 224 | byte-discardN byte-discardN-preserve-tos)) | ||
| 220 | (insert (int-to-string arg))) | 225 | (insert (int-to-string arg))) |
| 221 | ((memq op '(byte-varref byte-varset byte-varbind)) | 226 | ((memq op '(byte-varref byte-varset byte-varbind)) |
| 222 | (prin1 (car arg) (current-buffer))) | 227 | (prin1 (car arg) (current-buffer))) |
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 02477baf74f..1185f79806f 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el | |||
| @@ -701,7 +701,15 @@ If CHAR is not a character, return nil." | |||
| 701 | (defun eval-last-sexp-1 (eval-last-sexp-arg-internal) | 701 | (defun eval-last-sexp-1 (eval-last-sexp-arg-internal) |
| 702 | "Evaluate sexp before point; print value in minibuffer. | 702 | "Evaluate sexp before point; print value in minibuffer. |
| 703 | With argument, print output into current buffer." | 703 | With argument, print output into current buffer." |
| 704 | (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))) | 704 | (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t)) |
| 705 | ;; preserve the current lexical environment | ||
| 706 | (internal-interpreter-environment internal-interpreter-environment)) | ||
| 707 | ;; Setup the lexical environment if lexical-binding is enabled. | ||
| 708 | ;; Note that `internal-interpreter-environment' _can't_ be both | ||
| 709 | ;; assigned and let-bound above -- it's treated specially (and | ||
| 710 | ;; oddly) by the interpreter! | ||
| 711 | (when lexical-binding | ||
| 712 | (setq internal-interpreter-environment '(t))) | ||
| 705 | (eval-last-sexp-print-value (eval (preceding-sexp))))) | 713 | (eval-last-sexp-print-value (eval (preceding-sexp))))) |
| 706 | 714 | ||
| 707 | 715 | ||
diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 86e9411b140..9a505b214c8 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el | |||
| @@ -100,6 +100,8 @@ ARGLIST can also be t or a string of the form \"(FUN ARG1 ARG2 ...)\"." | |||
| 100 | (if (and (symbolp def) (fboundp def)) (setq def (indirect-function def))) | 100 | (if (and (symbolp def) (fboundp def)) (setq def (indirect-function def))) |
| 101 | ;; If definition is a macro, find the function inside it. | 101 | ;; If definition is a macro, find the function inside it. |
| 102 | (if (eq (car-safe def) 'macro) (setq def (cdr def))) | 102 | (if (eq (car-safe def) 'macro) (setq def (cdr def))) |
| 103 | ;; and do the same for interpreted closures | ||
| 104 | (if (eq (car-safe def) 'closure) (setq def (cddr def))) | ||
| 103 | (cond | 105 | (cond |
| 104 | ((byte-code-function-p def) (aref def 0)) | 106 | ((byte-code-function-p def) (aref def 0)) |
| 105 | ((eq (car-safe def) 'lambda) (nth 1 def)) | 107 | ((eq (car-safe def) 'lambda) (nth 1 def)) |
| @@ -190,7 +192,7 @@ if the variable `help-downcase-arguments' is non-nil." | |||
| 190 | doc t t 1))))) | 192 | doc t t 1))))) |
| 191 | 193 | ||
| 192 | (defun help-highlight-arguments (usage doc &rest args) | 194 | (defun help-highlight-arguments (usage doc &rest args) |
| 193 | (when usage | 195 | (when (and usage (string-match "^(" usage)) |
| 194 | (with-temp-buffer | 196 | (with-temp-buffer |
| 195 | (insert usage) | 197 | (insert usage) |
| 196 | (goto-char (point-min)) | 198 | (goto-char (point-min)) |
| @@ -347,8 +349,7 @@ suitable file is found, return nil." | |||
| 347 | (pt1 (with-current-buffer (help-buffer) (point))) | 349 | (pt1 (with-current-buffer (help-buffer) (point))) |
| 348 | errtype) | 350 | errtype) |
| 349 | (setq string | 351 | (setq string |
| 350 | (cond ((or (stringp def) | 352 | (cond ((or (stringp def) (vectorp def)) |
| 351 | (vectorp def)) | ||
| 352 | "a keyboard macro") | 353 | "a keyboard macro") |
| 353 | ((subrp def) | 354 | ((subrp def) |
| 354 | (if (eq 'unevalled (cdr (subr-arity def))) | 355 | (if (eq 'unevalled (cdr (subr-arity def))) |
| @@ -356,6 +357,13 @@ suitable file is found, return nil." | |||
| 356 | (concat beg "built-in function"))) | 357 | (concat beg "built-in function"))) |
| 357 | ((byte-code-function-p def) | 358 | ((byte-code-function-p def) |
| 358 | (concat beg "compiled Lisp function")) | 359 | (concat beg "compiled Lisp function")) |
| 360 | ((and (funvecp def) (eq (aref def 0) 'curry)) | ||
| 361 | (if (symbolp (aref def 1)) | ||
| 362 | (format "a curried function calling `%s'" (aref def 1)) | ||
| 363 | "a curried function")) | ||
| 364 | ((funvecp def) | ||
| 365 | (format "a function-vector (funvec) of type `%s'" | ||
| 366 | (aref def 0))) | ||
| 359 | ((symbolp def) | 367 | ((symbolp def) |
| 360 | (while (and (fboundp def) | 368 | (while (and (fboundp def) |
| 361 | (symbolp (symbol-function def))) | 369 | (symbolp (symbol-function def))) |
| @@ -367,6 +375,8 @@ suitable file is found, return nil." | |||
| 367 | (concat beg "Lisp function")) | 375 | (concat beg "Lisp function")) |
| 368 | ((eq (car-safe def) 'macro) | 376 | ((eq (car-safe def) 'macro) |
| 369 | "a Lisp macro") | 377 | "a Lisp macro") |
| 378 | ((eq (car-safe def) 'closure) | ||
| 379 | (concat beg "Lisp closure")) | ||
| 370 | ((eq (car-safe def) 'autoload) | 380 | ((eq (car-safe def) 'autoload) |
| 371 | (format "%s autoloaded %s" | 381 | (format "%s autoloaded %s" |
| 372 | (if (commandp def) "an interactive" "an") | 382 | (if (commandp def) "an interactive" "an") |
| @@ -494,27 +504,42 @@ suitable file is found, return nil." | |||
| 494 | ((or (stringp def) | 504 | ((or (stringp def) |
| 495 | (vectorp def)) | 505 | (vectorp def)) |
| 496 | (format "\nMacro: %s" (format-kbd-macro def))) | 506 | (format "\nMacro: %s" (format-kbd-macro def))) |
| 507 | ((and (funvecp def) (eq (aref def 0) 'curry)) | ||
| 508 | ;; Describe a curried-function's function and args | ||
| 509 | (let ((slot 0)) | ||
| 510 | (mapconcat (lambda (arg) | ||
| 511 | (setq slot (1+ slot)) | ||
| 512 | (cond | ||
| 513 | ((= slot 1) "") | ||
| 514 | ((= slot 2) | ||
| 515 | (format " Function: %S" arg)) | ||
| 516 | (t | ||
| 517 | (format "Argument %d: %S" | ||
| 518 | (- slot 3) arg)))) | ||
| 519 | def | ||
| 520 | "\n"))) | ||
| 521 | ((funvecp def) nil) | ||
| 497 | (t "[Missing arglist. Please make a bug report.]"))) | 522 | (t "[Missing arglist. Please make a bug report.]"))) |
| 498 | (high (help-highlight-arguments use doc))) | 523 | (high (help-highlight-arguments use doc))) |
| 499 | (let ((fill-begin (point))) | 524 | (let ((fill-begin (point))) |
| 500 | (insert (car high) "\n") | 525 | (insert (car high) "\n") |
| 501 | (fill-region fill-begin (point))) | 526 | (fill-region fill-begin (point)))) |
| 502 | (setq doc (cdr high)))) | 527 | (setq doc (cdr high)))) |
| 503 | (let* ((obsolete (and | 528 | (let* ((obsolete (and |
| 504 | ;; function might be a lambda construct. | 529 | ;; function might be a lambda construct. |
| 505 | (symbolp function) | 530 | (symbolp function) |
| 506 | (get function 'byte-obsolete-info))) | 531 | (get function 'byte-obsolete-info))) |
| 507 | (use (car obsolete))) | 532 | (use (car obsolete))) |
| 508 | (when obsolete | 533 | (when obsolete |
| 509 | (princ "\nThis function is obsolete") | 534 | (princ "\nThis function is obsolete") |
| 510 | (when (nth 2 obsolete) | 535 | (when (nth 2 obsolete) |
| 511 | (insert (format " since %s" (nth 2 obsolete)))) | 536 | (insert (format " since %s" (nth 2 obsolete)))) |
| 512 | (insert (cond ((stringp use) (concat ";\n" use)) | 537 | (insert (cond ((stringp use) (concat ";\n" use)) |
| 513 | (use (format ";\nuse `%s' instead." use)) | 538 | (use (format ";\nuse `%s' instead." use)) |
| 514 | (t ".")) | 539 | (t ".")) |
| 515 | "\n")) | 540 | "\n")) |
| 516 | (insert "\n" | 541 | (insert "\n" |
| 517 | (or doc "Not documented.")))))))) | 542 | (or doc "Not documented."))))))) |
| 518 | 543 | ||
| 519 | 544 | ||
| 520 | ;; Variables | 545 | ;; Variables |
diff --git a/lisp/subr.el b/lisp/subr.el index 16ba45f1c74..61a226c20ff 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -427,6 +427,12 @@ Non-strings in LIST are ignored." | |||
| 427 | (setq list (cdr list))) | 427 | (setq list (cdr list))) |
| 428 | list) | 428 | list) |
| 429 | 429 | ||
| 430 | (defmacro with-lexical-binding (&rest body) | ||
| 431 | "Execute the statements in BODY using lexical binding." | ||
| 432 | `(let ((internal-interpreter-environment internal-interpreter-environment)) | ||
| 433 | (setq internal-interpreter-environment '(t)) | ||
| 434 | ,@body)) | ||
| 435 | |||
| 430 | (defun assq-delete-all (key alist) | 436 | (defun assq-delete-all (key alist) |
| 431 | "Delete from ALIST all elements whose car is `eq' to KEY. | 437 | "Delete from ALIST all elements whose car is `eq' to KEY. |
| 432 | Return the modified alist. | 438 | Return the modified alist. |