comparison lisp/byte-optimize.el @ 5656:e9c3fe82127d

Co-operate with the byte-optimizer in the bytecomp.el labels implementation. lisp/ChangeLog addition: 2012-05-05 Aidan Kehoe <kehoea@parhasard.net> Co-operate with the byte-optimizer in the bytecomp.el labels implementation, don't work against it. * byte-optimize.el: * byte-optimize.el (byte-compile-inline-expand): Call #'byte-compile-unfold-lambda explicitly here, don't assume that the byte-optimizer will do it. * byte-optimize.el (byte-compile-unfold-lambda): Call #'byte-optimize-body on the body, don't just mapcar #'byte-optimize-form along it. * byte-optimize.el (byte-optimize-lambda): New. Optimize a lambda form. * byte-optimize.el (byte-optimize-form-code-walker): Descend lambda expressions, defun, and defmacro, relevant for lexically-oriented operators like #'labels. * byte-optimize.el (byte-optimize-body): Only return a non-eq object if we've actually optimized something * bytecomp.el (byte-compile-initial-macro-environment): In the labels implementation, work with the byte optimizer, not against it; warn when labels are defined but not used, automatically inline labels that are used only once. * bytecomp.el (byte-recompile-directory): No need to wrap #'byte-compile-report-error in a lambda with #'call-with-condition-handler here. * bytecomp.el (byte-compile-form): Don't inline compiled-function objects, they're probably labels. * bytecomp.el (byte-compile-funcall): No longer inline lambdas, trust the byte optimizer to have done it properly, even for labels. * cl-extra.el (cl-macroexpand-all): Treat labels established by the byte compiler distinctly from those established by cl-macs.el. * cl-macs.el (cl-do-proclaim): Treat labels established by the byte compiler distinctly from those established by cl-macs.el. * gui.el (make-gui-button): When referring to the #'gui-button-action label, quote it using function, otherwise there's a warning from the byte compiler.
author Aidan Kehoe <kehoea@parhasard.net>
date Sat, 05 May 2012 20:48:24 +0100
parents cc6f0266bc36
children 2a870a7b86bd
comparison
equal deleted inserted replaced
5655:b7ae5f44b950 5656:e9c3fe82127d
282 (and (fboundp name) (symbol-function name)))))) 282 (and (fboundp name) (symbol-function name))))))
283 (if (and (consp fn) (eq (car fn) 'autoload)) 283 (if (and (consp fn) (eq (car fn) 'autoload))
284 (error "file \"%s\" didn't define \"%s\"" (nth 1 fn) name)) 284 (error "file \"%s\" didn't define \"%s\"" (nth 1 fn) name))
285 (if (symbolp fn) 285 (if (symbolp fn)
286 (byte-compile-inline-expand (cons fn (cdr form))) 286 (byte-compile-inline-expand (cons fn (cdr form)))
287 (if (compiled-function-p fn) 287 (if (or (eq (car-safe fn) 'lambda) (compiled-function-p fn))
288 (progn 288 (byte-compile-unfold-lambda (cons fn (cdr form)))
289 (fetch-bytecode fn) 289 ;; Give up on inlining.
290 (cons (list 'lambda (compiled-function-arglist fn) 290 form)))))
291 (list 'byte-code
292 (compiled-function-instructions fn)
293 (compiled-function-constants fn)
294 (compiled-function-stack-depth fn)))
295 (cdr form)))
296 (if (eq (car-safe fn) 'lambda)
297 (cons fn (cdr form))
298 ;; Give up on inlining.
299 form))))))
300 291
301 ;;; ((lambda ...) ...) 292 ;;; ((lambda ...) ...)
302 ;;; 293 ;;;
303 (defun byte-compile-unfold-lambda (form &optional name) 294 (defun byte-compile-unfold-lambda (form &optional name)
304 (or name (setq name "anonymous lambda")) 295 (or name (setq name "anonymous lambda"))
352 (progn 343 (progn
353 (or (eq values 'too-few) 344 (or (eq values 'too-few)
354 (byte-compile-warn 345 (byte-compile-warn
355 "attempt to open-code %s with too many arguments" name)) 346 "attempt to open-code %s with too many arguments" name))
356 form) 347 form)
357 (setq body (mapcar 'byte-optimize-form body)) 348 (setq body (byte-optimize-body body nil))
358 (let ((newform 349 (let ((newform
359 (if bindings 350 (if bindings
360 (cons 'let (cons (nreverse bindings) body)) 351 (cons 'let (cons (nreverse bindings) body))
361 (cons 'progn body)))) 352 (cons 'progn body))))
362 (byte-compile-log " %s\t==>\t%s" form newform) 353 (byte-compile-log " %s\t==>\t%s" form newform)
363 newform))))) 354 newform)))))
364 355
365 356
357 (defun byte-optimize-lambda (form)
358 (let* ((offset 2) (body (nthcdr offset form)))
359 (if (stringp (car body)) (setq body (nthcdr (incf offset) form)))
360 (if (eq 'interactive (car-safe (car body)))
361 (setq body (nthcdr (incf offset) form)))
362 (if (eq body (setq body (byte-optimize-body body nil)))
363 form
364 (nconc (subseq form 0 offset) body))))
365
366 ;;; implementing source-level optimizers 366 ;;; implementing source-level optimizers
367 367
368 (defun byte-optimize-form-code-walker (form for-effect) 368 (defun byte-optimize-form-code-walker (form for-effect)
369 ;; 369 ;;
370 ;; For normal function calls, We can just mapcar the optimizer the cdr. But 370 ;; For normal function calls, We can just mapcar the optimizer the cdr. But
388 ;; map (quote nil) to nil to simplify optimizer logic. 388 ;; map (quote nil) to nil to simplify optimizer logic.
389 ;; map quoted constants to nil if for-effect (just because). 389 ;; map quoted constants to nil if for-effect (just because).
390 (and (nth 1 form) 390 (and (nth 1 form)
391 (not for-effect) 391 (not for-effect)
392 form)) 392 form))
393 ((or (compiled-function-p fn) 393 ((eq fn 'function)
394 (eq 'lambda (car-safe fn))) 394 (when (cddr form)
395 (byte-compile-unfold-lambda form)) 395 (byte-compile-warn "malformed function form: %S" form))
396 (cond
397 (for-effect nil)
398 ((and (eq (car-safe (cadr form)) 'lambda)
399 (not (eq (cadr form) (setq tmp (byte-optimize-lambda
400 (cadr form))))))
401 (list fn tmp))
402 (t form)))
403 ((and (eq 'lambda (car-safe fn))
404 (not (eq form (setq form (byte-compile-unfold-lambda form)))))
405 form)
396 ((memq fn '(let let*)) 406 ((memq fn '(let let*))
397 ;; recursively enter the optimizer for the bindings and body 407 ;; recursively enter the optimizer for the bindings and body
398 ;; of a let or let*. This for depth-firstness: forms that 408 ;; of a let or let*. This for depth-firstness: forms that
399 ;; are more deeply nested are optimized first. 409 ;; are more deeply nested are optimized first.
400 (cons fn 410 (cons fn
488 ((eq fn 'interactive) 498 ((eq fn 'interactive)
489 (byte-compile-warn "misplaced interactive spec: %s" 499 (byte-compile-warn "misplaced interactive spec: %s"
490 (prin1-to-string form)) 500 (prin1-to-string form))
491 nil) 501 nil)
492 502
493 ((memq fn '(defun defmacro function 503 ((memq fn '(defun defmacro))
494 condition-case save-window-excursion)) 504 (if (eq (setq tmp (cons 'lambda (cddr form)))
495 ;; These forms are compiled as constants or by breaking out 505 (setq tmp (byte-optimize-lambda tmp)))
496 ;; all the subexpressions and compiling them separately. 506 (cons fn (cdr tmp))
497 form) 507 form))
508
509 ((eq fn 'condition-case)
510 (list* fn (nth 1 form) (byte-optimize-form (nth 2 form) for-effect)
511 (mapcar #'(lambda (handler)
512 (cons (car handler)
513 (byte-optimize-body (cdr handler)
514 for-effect)))
515 (cdddr form))))
498 516
499 ((eq fn 'unwind-protect) 517 ((eq fn 'unwind-protect)
500 ;; the "protected" part of an unwind-protect is compiled (and thus 518 ;; the "protected" part of an unwind-protect is compiled (and thus
501 ;; optimized) as a top-level form, so don't do it here. But the 519 ;; optimized) as a top-level form, so don't do it here. But the
502 ;; non-protected part has the same for-effect status as the 520 ;; non-protected part has the same for-effect status as the
522 ((not (eq form 540 ((not (eq form
523 (setq form (macroexpand form 541 (setq form (macroexpand form
524 byte-compile-macro-environment)))) 542 byte-compile-macro-environment))))
525 (byte-optimize-form form for-effect)) 543 (byte-optimize-form form for-effect))
526 544
545 ((compiled-function-p fn)
546 (cons fn (mapcar #'byte-optimize-form (cdr form))))
547
527 ((not (symbolp fn)) 548 ((not (symbolp fn))
528 (byte-compile-warn "%s is a malformed function" (prin1-to-string fn)) 549 (byte-compile-warn "%S is a malformed function" fn)
529 form) 550 form)
530 551
531 ;; Support compiler macros as in cl.el. 552 ;; Support compiler macros as in cl.el.
532 ((and (get fn 'cl-compiler-macro) 553 ((and (get fn 'cl-compiler-macro)
533 (not (eq form (setq form (compiler-macroexpand form))))) 554 (not (eq form (setq form (compiler-macroexpand form)))))
591 ;; forms, all but the last of which are optimized with the assumption that 612 ;; forms, all but the last of which are optimized with the assumption that
592 ;; they are being called for effect. The last is for-effect as well if 613 ;; they are being called for effect. The last is for-effect as well if
593 ;; all-for-effect is true. Returns a new list of forms. 614 ;; all-for-effect is true. Returns a new list of forms.
594 (let ((rest forms) 615 (let ((rest forms)
595 (result nil) 616 (result nil)
617 (modified nil)
596 fe new) 618 fe new)
597 (while rest 619 (while rest
598 (setq fe (or all-for-effect (cdr rest))) 620 (setq fe (or all-for-effect (cdr rest)))
599 (setq new (and (car rest) (byte-optimize-form (car rest) fe))) 621 (setq new (and (car rest) (byte-optimize-form (car rest) fe)))
600 (if (or new (not fe)) 622 (if (or new (not fe))
601 (setq result (cons new result))) 623 (setq result (cons new result)
624 modified (or modified (not (eq new (car rest)))))
625 (setq modified t))
602 (setq rest (cdr rest))) 626 (setq rest (cdr rest)))
603 (nreverse result))) 627 (if modified (nreverse result) forms)))
604 628
605 629
606 ;;; some source-level optimizers 630 ;;; some source-level optimizers
607 ;;; 631 ;;;
608 ;;; when writing optimizers, be VERY careful that the optimizer returns 632 ;;; when writing optimizers, be VERY careful that the optimizer returns