6 ms·
Very interesting read! But could somebody explain why the following piece of code is needed? And why is it defined inline? (defun-inline (setf vref) (new-val
by veddox 9y ago
Very interesting read! But could somebody explain why the following piece of code is needed? And why is it defined inline?
(defun-inline (setf vref) (new-value chip x y)
(setf (aref (chip-video chip) (+ (* +screen-width+ y) x))
new-value))
- Nokinside 9y agovref and (setf vref) define getter and setter functions for manipulating pixel arrays. Since these functions are used a lot, it makes sense to allow compiler to inline them for maximum speed. Normally function must be accessed trough the symbol and it can be redefined on the fly.
- sigjuice 9y agoIt would be interesting to do a measurement of inline vs non-inline to see how much of a speed difference it makes.
- lispm 9y agoFunctions don't need to be accessed through them symbol. A file compiler can assume that a function does not change inside a file, etc. Inlining and being called via a symbol are slightly different things... I would also think that lexical functions are not called via symbols...
- veddox 9y agoI understand what they do, and I appreciate that it helps performance to inline them. What I don't understand is the (setf vref) syntax. I thought that after a defun statement you had to have a symbol, not an S-expression? Something like so: (defun-inline set-vref (new-value chip x y) ...) And how would you actually call the original function to set a pixel? (I'm not very familiar with inlines, maybe that's my problem here.)
- reikonomusha 9y agoThis is special syntax in Common Lisp. (SETF F) actually names a function too. It allows you to define a setter (a setf-expansion) with a normal DEFUN.
- juki 9y agoCommon lisp has this universal setter-macro, SETF, which can be used to set values to all sorts of places. In this case you would use (setf (vref chip x y) new-value) to call the function (just like with AREF above). Using SETF has the advantage that you can define "modify macros" that read and write a place. For example, (incf (vref chip x y) delta) would increment the place by DELTA. Or (rotatef (vref chip x1 y1) (vref chip x2 y2)) would swap two pixels.
- kbp 9y agoWhy is DEFUN-INLINE used over: (declaim (inline (setf vref))) (defun (setf vref) (new-value chip x y) (setf (aref (chip-video chip) (+ (* +screen-width+ y) x)) new-value))
- stevelosh 9y agoLess typing/reading.
- jacquesm 9y agoWouldn't a lookup table be much faster here? That multiply on every screen access can't help the speed.
- stevelosh 9y ago+screen-width+ is 64, which means SBCL can convert the multiply to a left shift if we care about speed and declare types: (defun foo (chip y) (declare (optimize speed) (type chip chip) (type int16 y)) (vref chip 0 y)) (disassemble 'foo) ; disassembly for FOO ; Size: 48 bytes. Origin: #x100EF5E39D ; 9D: 488B423D MOV RAX, [RDX+61] ; no-arg-parsing entry point ;; ---------------------- Look ma, no multiplication! ;; vvvvvvvvvvv ; A1: 48C1E706 SHL RDI, 6 ; A5: B900100000 MOV ECX, 4096 ; AA: 40F6C701 TEST DIL, 1 ; AE: 7513 JNE L0 ; B0: 4839F9 CMP RCX, RDI ; B3: 760E JBE L0 ; B5: 488B54B801 MOV RDX, [RAX+RDI*4+1] ; BA: 488BE5 MOV RSP, RBP ; BD: F8 CLC ; BE: 5D POP RBP ; BF: C3 RET ; C0: 0F0B10 BREAK 16 ; Invalid argument count trap ; C3: L0: 0F0B0A BREAK 10 ; error trap ; C6: 06 BYTE #X06 ; C7: 0C BYTE #X0C ; INVALID-ARRAY-INDEX-ERROR ; C8: 1B BYTE #X1B ; RAX ; C9: 9A BYTE #X9A ; RCX ; CA: FE9A03 BYTE #XFE, #X9A, #X03 ; RDI