Ten Cache Misses

Crushing Haskell like a Tin Can

Ragel primops and the GHC stack

Quite a few people have been asking about a follow up to an old post, specifically on dealing with passing return values on the stack from our C/LLVM based primop. I ended up with some unexpected free time today on the Caltrain waiting for a crushed tractor-trailer to get cleared off the tracks and dusted off a semi-functional feed parser in the style of Tsuru’s code sample. Sample data for is much easier to find than NASDAQ’s ITCH feed, I hope it’s also easier for you to get started with.

As with C, allocating from GHC’s stack is almost as simple as bumping a pointer. Unlike (most) C code, Haskell applications must explicitly check the stack to verify there is space available before performing the allocation. This is quite a bit more of a pain to deal with in C compared to C– or Haskell because stack allocations are done via tail-calls, we will ignore this detail for now and just assume the stack is large enough.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extern void
QuoteParser_run(
    int64_t* restrict baseReg,
    int64_t* restrict sp,
    ...)
{
    // TODO: check to see if sp has room for 4 more values

    // allocate space for 4 values on the stack
    int64_t* nextSp = &sp[-4];

    // assign some value to each unboxed primitive
    sp[-1] = 0xfdfdfdfdfdfdfdfd;
    sp[-2] = 0xabababababababab;
    sp[-3] = 0x1717171717177171;
    sp[-4] = 0x3535353535353535;

    // pass the updated stack pointer along to a function
    // expecting 10 integers to be returned from this primop:
    // 6 in registers R1-R6 and 4 on the stack
    nextFunction(baseReg, nextSp, ...);
}

The full code is available on Github for your forking pleasure.

Comments