;; If we pass a lambda form to an inline function, ;; this does not get properly optimized by SBCL's compiler.
;; Example code.
(declaim (inline nie)) (defun nie (fn) (declare (function fn)) "A function that calls nie." (funcall fn :nie))
;; ;; NIE is fully inlined here and BAZ becomes (constantly T). (defun baz () (nie #'symbolp))
CL-USER> (disassemble 'baz) ; disassembly for BAZ ; Size: 11 bytes. Origin: #x1021287276 ; 76: BA4F001050 MOV EDX, #x5010004F ; no-arg-parsing entry point ; T ; 7B: 488BE5 MOV RSP, RBP ; 7E: F8 CLC ; 7F: 5D POP RBP ; 80: C3 RET
;; ;; Now the same with a LAMBDA. 12 - bytes more and a JMP. (defun bar () (nie (lambda (s) (symbolp s))))
CL-USER> (disassemble 'bar) ; disassembly for BAR ; Size: 23 bytes. Origin: #x1021287386 ; 86: BA1F729C50 MOV EDX, #x509C721F ; no-arg-parsing entry point ; :NIE ; 8B: 488B05AEFFFFFF MOV RAX, [RIP-82] ; #<FUNCTION (LAMBDA ; # ..)> ; 92: B902000000 MOV ECX, 2 ; 97: FF7508 PUSH QWORD PTR [RBP+8] ; 9A: FF60FD JMP QWORD PTR [RAX-3]
;; Just to check that: ;; (funcall (lambda ...)) still works like in the 60s'
(defun foo () (funcall (lambda (x) (symbolp x)) :nie))
CL-USER> (disassemble 'foo) ; disassembly for FOO ; Size: 11 bytes. Origin: #x10212873F6 ; 3F6: BA4F001050 MOV EDX, #x5010004F ; no-arg-parsing entry point ; T ; 3FB: 488BE5 MOV RSP, RBP ; 3FE: F8 CLC ; 3FF: 5D POP RBP ; 400: C3 RET
;; As a consequence this forces one to use compiler-macros for folding and inlining ;; instead-of the default inline mechanism.
;; If we pass a lambda form to an inline function,
;; this does not get properly optimized by SBCL's compiler.
;; Example code.
(declaim (inline nie))
(defun nie (fn) (declare (function fn))
"A function that calls nie."
(funcall fn :nie))
;;
;; NIE is fully inlined here and BAZ becomes (constantly T).
(defun baz ()
(nie #'symbolp))
CL-USER> (disassemble 'baz)
; T
; disassembly for BAZ
; Size: 11 bytes. Origin: #x1021287276
; 76: BA4F001050 MOV EDX, #x5010004F ; no-arg-parsing entry point
; 7B: 488BE5 MOV RSP, RBP
; 7E: F8 CLC
; 7F: 5D POP RBP
; 80: C3 RET
;;
;; Now the same with a LAMBDA. 12 - bytes more and a JMP.
(defun bar ()
(nie (lambda (s) (symbolp s))))
CL-USER> (disassemble 'bar)
; :NIE
; # ..)>
; disassembly for BAR
; Size: 23 bytes. Origin: #x1021287386
; 86: BA1F729C50 MOV EDX, #x509C721F ; no-arg-parsing entry point
; 8B: 488B05AEFFFFFF MOV RAX, [RIP-82] ; #<FUNCTION (LAMBDA
; 92: B902000000 MOV ECX, 2
; 97: FF7508 PUSH QWORD PTR [RBP+8]
; 9A: FF60FD JMP QWORD PTR [RAX-3]
;; Just to check that:
;; (funcall (lambda ...)) still works like in the 60s'
(defun foo ()
(funcall (lambda (x) (symbolp x)) :nie))
CL-USER> (disassemble 'foo)
; T
; disassembly for FOO
; Size: 11 bytes. Origin: #x10212873F6
; 3F6: BA4F001050 MOV EDX, #x5010004F ; no-arg-parsing entry point
; 3FB: 488BE5 MOV RSP, RBP
; 3FE: F8 CLC
; 3FF: 5D POP RBP
; 400: C3 RET
;; As a consequence this forces one to use compiler-macros for folding and inlining
;; instead-of the default inline mechanism.