There are basically two differences between the `unsafe-lsb` function
in Racket and the C one:
 - the Racket calling convention vs the C calling convention
 - the instruction used to perform the LSB calculation

For a variety of reasons Racket's function calling convention is more
heavyweight than C's, but if that code is inlined into some larger
function that will go away (as it would in C). The simpler instruction
used by the C compiler is because the C compiler recognizes that
pattern of bitwise and, whereas the Racket JIT does the obvious `and`.
That could of course be fixed in the JIT, although it's not clear how
much of a win it is.

More broadly, whether Racket supports "C-level" programming depends on
what you mean. If it means "can I use the same APIs and access the
same bits I would in C", then you certainly can, although often you
need to use the FFI to do so. That's what the Racket Manifesto means.
If it means "can I generate the same assembly instructions or get the
same maximum performance from pure Racket code as from C code", then
it isn't true, and you'll need to use some other tools, such as
generating code yourself (see https://github.com/rjnw/sham for an
example).

Sam

On Sat, Aug 11, 2018 at 4:15 AM, 'Paulo Matos' via Racket Users
<racket-users@googlegroups.com> wrote:
> Hi,
>
> In http://felleisen.org/matthias/manifesto/, you can read:
> "In support, Racket offers protection mechanisms to implement a full
> language spectrum, from C-level bit manipulation to soundly typed
> extensions."
>
> What are we talking about here when we mention C-level bit manipulation? Is
> this referring to the ffi or some other Racket feature that allows me to
> generate unsafe bit manipulation instructions?
>
> In C, for a bitwise_and of an integer x and 0xff, I get:
> https://godbolt.org/g/gy3ZN9
> bitwise_and:
>   movzx eax, dil
>   ret
>
> In Racket, I tried:
> #lang racket
>
> (require disassemble
>          racket/unsafe/ops)
>
> (define (lsb x)
>   (bitwise-and x #xff))
>
> (disassemble lsb)
>
>        0: 488b4808                       (mov rcx (mem64+ rax #x8))
>        4: 48898bf8ffffff                 (mov (mem64+ rbx #x-8) rcx)
>        b: 488b4810                       (mov rcx (mem64+ rax #x10))
>        f: 48898bf0ffffff                 (mov (mem64+ rbx #x-10) rcx)
>       16: 4881c3f0ffffff                 (add rbx #xfffffffffffffff0)
>       1d: 488b13                         (mov rdx (mem64+ rbx))
>       20: 488b5230                       (mov rdx (mem64+ rdx #x30))
>       24: 488b4208                       (mov rax (mem64+ rdx #x8))
>       28: 488983f8ffffff                 (mov (mem64+ rbx #x-8) rax)
>       2f: 48b8a80e484c00000000           (mov rax #x4c480ea8)
>       39: 488b00                         (mov rax (mem64+ rax))
>       3c: 488983f0ffffff                 (mov (mem64+ rbx #x-10) rax)
>       43: 4881c3f0ffffff                 (add rbx #xfffffffffffffff0)
>       4a: 488b4308                       (mov rax (mem64+ rbx #x8))
>       4e: f6c001                         (test al #x1)
>       51: 0f850f000000                   (jnz (+ rip #xf))
>       57: 66833831                       (cmp (mem16+ rax) #x31)
>       5b: 0f8505000000                   (jnz (+ rip #x5))
>       61: e81e771fb4                     (call (+ rip #x-4be088e2))
>       66: e8bb751fb4                     (call (+ rip #x-4be08a45))
>       6b: 488b4320                       (mov rax (mem64+ rbx #x20))
>       6f: 4883c310                       (add rbx #x10)
>       73: f6c001                         (test al #x1)
>       76: 0f8514000000                   (jnz (+ rip #x14))
>       7c: ba60fba070                     (mov edx #x70a0fb60)
>       81: b9ff010000                     (mov ecx #x1ff)
>       86: e86e001fb4                     (call (+ rip #x-4be0ff92))
>       8b: e907000000                     (jmp (+ rip #x7))
>       90: 4881e0ff010000                 (and rax #x1ff)
>       97: 4c8b75c8                       (mov r14 (mem64+ rbp #x-38))
>       9b: 4883c428                       (add rsp #x28)
>       9f: 5f                             (pop rdi)
>       a0: 5e                             (pop rsi)
>       a1: 5b                             (pop rbx)
>       a2: 5d                             (pop rbp)
>       a3: c3                             (ret)
>
> (define (unsafe-lsb x)
>   (unsafe-fxand x #xff))
>
> (disassemble unsafe-lsb)
>
>        0: 488983f8ffffff                 (mov (mem64+ rbx #x-8) rax)
>        7: 4881c3f8ffffff                 (add rbx #xfffffffffffffff8)
>        e: 488b4308                       (mov rax (mem64+ rbx #x8))
>       12: 4881e0ff010000                 (and rax #x1ff)
>       19: 4c8b75c8                       (mov r14 (mem64+ rbp #x-38))
>       1d: 4883c428                       (add rsp #x28)
>       21: 5f                             (pop rdi)
>       22: 5e                             (pop rsi)
>       23: 5b                             (pop rbx)
>       24: 5d                             (pop rbp)
>       25: c3                             (ret)
>
> This returns two assembly listings and as expected the unsafe-lsb is shorter
> than the one for lsb but not even close to the one you'd get in C. Is there
> something else in Racket that I might be missing that it gives me access to
> the low level C bit manip constructs besides ffi?
>
> Kind regards,
>
> --
> Paulo Matos
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to