aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2012-06-27 23:31:27 -0400
committerStefan Monnier2012-06-27 23:31:27 -0400
commitc207708c86ab04f4bb1d78789be0d116e77ba9bb (patch)
treead5da6a992628f001c7c5dce39b847a94575c4c4
parent059e4fb5ed71639f16162e559c9f68f8b5889b9c (diff)
downloademacs-c207708c86ab04f4bb1d78789be0d116e77ba9bb.tar.gz
emacs-c207708c86ab04f4bb1d78789be0d116e77ba9bb.zip
Make inlining of other-mode interpreted functions work.
* lisp/emacs-lisp/bytecomp.el (byte-compile--refiy-function): New fun. (byte-compile): Use it to fix compilation of lexical-binding closures. * lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Compile the function, if needed. Fixes: debbugs:11799
-rw-r--r--lisp/ChangeLog8
-rw-r--r--lisp/emacs-lisp/byte-opt.el50
-rw-r--r--lisp/emacs-lisp/bytecomp.el41
3 files changed, 60 insertions, 39 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 566dad73cf0..bb7fca91126 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,11 @@
12012-06-28 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 Make inlining of other-mode interpreted functions work (bug#11799).
4 * emacs-lisp/bytecomp.el (byte-compile--refiy-function): New fun.
5 (byte-compile): Use it to fix compilation of lexical-binding closures.
6 * emacs-lisp/byte-opt.el (byte-compile-inline-expand): Compile the
7 function, if needed.
8
12012-06-27 Stefan Monnier <monnier@iro.umontreal.ca> 92012-06-27 Stefan Monnier <monnier@iro.umontreal.ca>
2 10
3 * help-mode.el (help-make-xrefs): Don't just withstand 11 * help-mode.el (help-make-xrefs): Don't just withstand
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 92a10dff774..106946b0037 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -266,42 +266,30 @@
266 ;; (message "Inlining byte-code for %S!" name) 266 ;; (message "Inlining byte-code for %S!" name)
267 ;; The byte-code will be really inlined in byte-compile-unfold-bcf. 267 ;; The byte-code will be really inlined in byte-compile-unfold-bcf.
268 `(,fn ,@(cdr form))) 268 `(,fn ,@(cdr form)))
269 ((or (and `(lambda ,args . ,body) (let env nil)) 269 ((or `(lambda . ,_) `(closure . ,_))
270 `(closure ,env ,args . ,body))
271 (if (not (or (eq fn localfn) ;From the same file => same mode. 270 (if (not (or (eq fn localfn) ;From the same file => same mode.
272 (eq (not lexical-binding) (not env)))) ;Same mode. 271 (eq (car fn) ;Same mode.
272 (if lexical-binding 'closure 'lambda))))
273 ;; While byte-compile-unfold-bcf can inline dynbind byte-code into 273 ;; While byte-compile-unfold-bcf can inline dynbind byte-code into
274 ;; letbind byte-code (or any other combination for that matter), we 274 ;; letbind byte-code (or any other combination for that matter), we
275 ;; can only inline dynbind source into dynbind source or letbind 275 ;; can only inline dynbind source into dynbind source or letbind
276 ;; source into letbind source. 276 ;; source into letbind source.
277 ;; FIXME: we could of course byte-compile the inlined function 277 (progn
278 ;; first, and then inline its byte-code. 278 ;; We can of course byte-compile the inlined function
279 form 279 ;; first, and then inline its byte-code.
280 (let ((renv ())) 280 (byte-compile name)
281 ;; Turn the function's closed vars (if any) into local let bindings. 281 `(,(symbol-function name) ,@(cdr form)))
282 (dolist (binding env) 282 (let ((newfn (if (eq fn localfn)
283 (cond 283 ;; If `fn' is from the same file, it has already
284 ((consp binding) 284 ;; been preprocessed!
285 ;; We check shadowing by the args, so that the `let' can be 285 `(function ,fn)
286 ;; moved within the lambda, which can then be unfolded. 286 (byte-compile-preprocess
287 ;; FIXME: Some of those bindings might be unused in `body'. 287 (byte-compile--refiy-function fn)))))
288 (unless (memq (car binding) args) ;Shadowed. 288 (if (eq (car-safe newfn) 'function)
289 (push `(,(car binding) ',(cdr binding)) renv))) 289 (byte-compile-unfold-lambda `(,(cadr newfn) ,@(cdr form)))
290 ((eq binding t)) 290 (byte-compile-log-warning
291 (t (push `(defvar ,binding) body)))) 291 (format "Inlining closure %S failed" name))
292 (let ((newfn (if (eq fn localfn) 292 form))))
293 ;; If `fn' is from the same file, it has already
294 ;; been preprocessed!
295 `(function ,fn)
296 (byte-compile-preprocess
297 (if (null renv)
298 `(lambda ,args ,@body)
299 `(lambda ,args (let ,(nreverse renv) ,@body)))))))
300 (if (eq (car-safe newfn) 'function)
301 (byte-compile-unfold-lambda `(,(cadr newfn) ,@(cdr form)))
302 (byte-compile-log-warning
303 (format "Inlining closure %S failed" name))
304 form)))))
305 293
306 (t ;; Give up on inlining. 294 (t ;; Give up on inlining.
307 form)))) 295 form))))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 650faec6bf6..af7bc81fef0 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2451,7 +2451,26 @@ If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
2451 (- (position-bytes (point)) (point-min) -1) 2451 (- (position-bytes (point)) (point-min) -1)
2452 (goto-char (point-max)))))) 2452 (goto-char (point-max))))))
2453 2453
2454 2454(defun byte-compile--refiy-function (fun)
2455 "Return an expression which will evaluate to a function value FUN.
2456FUN should be either a `lambda' value or a `closure' value."
2457 (pcase-let* (((or (and `(lambda ,args . ,body) (let env nil))
2458 `(closure ,env ,args . ,body)) fun)
2459 (renv ()))
2460 ;; Turn the function's closed vars (if any) into local let bindings.
2461 (dolist (binding env)
2462 (cond
2463 ((consp binding)
2464 ;; We check shadowing by the args, so that the `let' can be moved
2465 ;; within the lambda, which can then be unfolded. FIXME: Some of those
2466 ;; bindings might be unused in `body'.
2467 (unless (memq (car binding) args) ;Shadowed.
2468 (push `(,(car binding) ',(cdr binding)) renv)))
2469 ((eq binding t))
2470 (t (push `(defvar ,binding) body))))
2471 (if (null renv)
2472 `(lambda ,args ,@body)
2473 `(lambda ,args (let ,(nreverse renv) ,@body)))))
2455 2474
2456;;;###autoload 2475;;;###autoload
2457(defun byte-compile (form) 2476(defun byte-compile (form)
@@ -2459,23 +2478,29 @@ If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
2459If FORM is a lambda or a macro, byte-compile it as a function." 2478If FORM is a lambda or a macro, byte-compile it as a function."
2460 (displaying-byte-compile-warnings 2479 (displaying-byte-compile-warnings
2461 (byte-compile-close-variables 2480 (byte-compile-close-variables
2462 (let* ((fun (if (symbolp form) 2481 (let* ((lexical-binding lexical-binding)
2482 (fun (if (symbolp form)
2463 (and (fboundp form) (symbol-function form)) 2483 (and (fboundp form) (symbol-function form))
2464 form)) 2484 form))
2465 (macro (eq (car-safe fun) 'macro))) 2485 (macro (eq (car-safe fun) 'macro)))
2466 (if macro 2486 (if macro
2467 (setq fun (cdr fun))) 2487 (setq fun (cdr fun)))
2468 (cond ((eq (car-safe fun) 'lambda) 2488 (when (symbolp form)
2489 (unless (memq (car-safe fun) '(closure lambda))
2490 (error "Don't know how to compile %S" fun))
2491 (setq fun (byte-compile--refiy-function fun))
2492 (setq lexical-binding (eq (car fun) 'closure)))
2493 (unless (eq (car-safe fun) 'lambda)
2494 (error "Don't know how to compile %S" fun))
2469 ;; Expand macros. 2495 ;; Expand macros.
2470 (setq fun (byte-compile-preprocess fun)) 2496 (setq fun (byte-compile-preprocess fun))
2471 ;; Get rid of the `function' quote added by the `lambda' macro. 2497 ;; Get rid of the `function' quote added by the `lambda' macro.
2472 (if (eq (car-safe fun) 'function) (setq fun (cadr fun))) 2498 (if (eq (car-safe fun) 'function) (setq fun (cadr fun)))
2473 (setq fun (if macro 2499 (setq fun (byte-compile-lambda fun))
2474 (cons 'macro (byte-compile-lambda fun)) 2500 (if macro (push 'macro fun))
2475 (byte-compile-lambda fun)))
2476 (if (symbolp form) 2501 (if (symbolp form)
2477 (defalias form fun) 2502 (fset form fun)
2478 fun))))))) 2503 fun)))))
2479 2504
2480(defun byte-compile-sexp (sexp) 2505(defun byte-compile-sexp (sexp)
2481 "Compile and return SEXP." 2506 "Compile and return SEXP."