... which, I acknowledge, might be very hard work, possibly involving every such function having 2 polymorphic variants, one generic boxed form and one unboxed form, automatically selected and call-site-cached like OO dispatch.

That's pretty much what Common Lisp compilers do. The compiler (or your own compiler macro, if you so choose) can examine the input forms and the compiler environment to decide what code to produce.

The following is from Allegro Common Lisp, but all of the input is ANSI CL -- part of the spec.

Observe how the compiler switches between different implementations of trivial addition as it gets a progressively looser or tighter bound on x. (I've elided some of the irrelevant preamble.)

What would be nice is if Clojure and/or the JVM could produce safe code/bytecode that wouldn't overflow, but could also be JIT-optimized into unboxed primitive arithmetic for known input ranges.



  ;; Range known, optimizing for speed: assembly add instruction.
  cl-user(7): (disassemble
    (compile nil
      (lambda (x)
        (declare (type (integer 0 255) x)
                 (optimize (speed 3)))
        (+ x 2))))
  ...
    15: 48 83 c7 10  add        rdi,$16
    19: f8             clc
    20: 4c 8b 74 24 10 movq     r14,[rsp+16]
    25: c3             ret


;; We know that x is a fixnum: the arithmetic doesn't need a function call, but ;; the result will be a boxed bignum, because fixnum + 2 won't fit in a fixnum. ;; If this function were inlined elsewhere, the compiler might avoid that decision.
  cl-user(8): (disassemble
    (compile nil
      (lambda (x)
        (declare (type fixnum x)
                 (optimize (speed 3)))
        (+ x 2))))
  ...
    21: 74 01          jz       24
    23: 17             (pop ss)        ; sys::trap-signal-hit
    24: 48 c1 ff 03  sar        rdi,$3
    28: 49 c7 c5 02 00 movq     r13,$2
        00 00
    35: 49 03 fd       addq     rdi,r13
    38: 4c 8b ef       movq     r13,rdi
    41: 49 d1 e5       sall     r13,$1
    44: 70 19          jo       71
    46: 49 d1 e5       sall     r13,$1
    49: 70 14          jo       71
    51: 49 d1 e5       sall     r13,$1
    54: 70 0f          jo       71
    56: 49 8b fd       movq     rdi,r13
    59: f8             clc
    60: 48 8d 64 24 78 leaq     rsp,[rsp+120]
    65: 4c 8b 74 24 10 movq     r14,[rsp+16]
    70: c3             ret
    71: 41 ff 57 47  call       *[r15+71]    ; sys::box-to-new-bignum
    75: eb ef          jmp      60
    77: 90             nop


  ;; Nothing known: call to excl::+_2op, the two-arg addition function.
  cl-user(9): (disassemble
     (compile nil
       (lambda (x)
         (declare (optimize (speed 3)))
         (+ x 2))))
  ...
    21: 74 01          jz       24
    23: 17             (pop ss)        ; sys::trap-signal-hit
    24: 40 f6 c7 07  testb      dil,$7
    28: 75 12          jnz      48
    30: 48 83 c7 10  add        rdi,$16
    34: f8             clc
    35: 70 1e          jo       67
    37: 48 8d 64 24 78 leaq     rsp,[rsp+120]
    42: 4c 8b 74 24 10 movq     r14,[rsp+16]
    47: c3             ret
    48: 49 8b af 2f ff movq     rbp,[r15-209]    ; excl::+_2op
        ff ff
    55: 48 c7 c6 10 00 movq     rsi,$16     ; 2
        00 00
    62: ff 53 d0       call     *[rbx-48]  ; sys::tramp-two
    65: eb e2          jmp      37
    67: 49 c7 c5 10 00 movq     r13,$16     ; 2
        00 00
    74: 49 2b fd       subq     rdi,r13
    77: eb e1          jmp      48
    79: 90             nop



--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to