// File: /workspace/github_c_makefile_star2_O2/jflatow[P]jfdb/src/trie.c
// Function: splice_new
static JFT_Status splice_new(JFT_Cursor *cursors,
                             JFT_MergeContext *ctx,
                             JFT_Phase phase) {
  // determine what to do based on the most recent / highest precedence cursor
  // (cursors should be given in order of recency / precedence)
  JFT_MergeFrame *frame = ctx->frame;
  JFT_Mask active = frame->active;
  JFT_Amount b = ffsll(active);
  JFT_Cursor *cursor = cursors + b - 1;
  JFT_Cons *cons = (JFT_Cons *)ctx->acc;
  JFT_Buffer *buf = cons->buffer;
  JFT_NodeType type = JFT_node_type(cursor->node);

  if (phase == Out) {
    // do nothing during phase out, except finishing touches
    // copy the changed root data back into the buffer
    if (type == Root) {
      JFT_Root *root = (JFT_Root *)buf->data;
      root->extent = buf->mark;
      root->numPrimary = cons->root.numPrimary;
      root->numIndices = cons->root.numIndices;
      root->maxIndices = cons->root.maxIndices;
      root->maxKeySize = ctx->maxKeySize;
    }
    return Ok;
  }

  if (type == Root) {
    // on the root: make space for the new root in buffer
    // root is a parent, mark it's offset before writing
    frame->offset = buf->mark;
    if (!make_root(buf))
      return ENoMem;

    // keep a root in cons and update it later (NB: cannot rely on buf pointers)
    // allocate memory to store the compressed stem before we write it
    cons->root.head = JFT_head(Root, False, 0, 0, 0);
    cons->stem = (JFT_Stem) {.data = malloc(ctx->maxKeySize)};
    if (cons->stem.data == NULL)
      return ENoMem;

    // allocate the iterators for indices
    cons->iters = malloc(ctx->numCursors * sizeof(JFT_Iter));

    // allocate the offset translation tables for indices (if we are translating)
    if (!(ctx->flags & JFT_FLAGS_ATOM)) {
      cons->TLBs = malloc(ctx->numCursors * sizeof(JFT_Offset *));
      cons->TLBSizes = calloc(ctx->numCursors, sizeof(JFT_Count));
      for (JFT_Amount k = 0; k < ctx->numCursors; k++)
        cons->TLBs[k] = malloc(2 * ((JFT_Root *)cursors[k].root)->numPrimary * sizeof(JFT_Offset));
    }

    // step into the tree
    return Step;
  }

  // add the symbol to the budding stem
  // if its a keyspace, mark the keyspace in the cons
  if (cursor->symbol == JFT_SYMBOL_PRIMARY ||
      cursor->symbol == JFT_SYMBOL_INDICES) {
      cons->stem.pre = cons->keySpace = cursor->symbol;
      cons->stem.size++;
  } else {
      cons->stem.data[cons->stem.size - (cons->stem.pre ? 1 : 0)] = cursor->symbol;
      cons->stem.size++;
  }

  // if cursor is on a terminal node: overwrite
  if (JFT_cursor_at_terminal(cursor)) {
    int doTranslate = !(ctx->flags & JFT_FLAGS_ATOM);
    JFT_Leaf leaf = JFT_leaf(cursor->node);
    // simply skip empty leaves: the offset in parent will remain zero and thus will not branch
    // eventually (next merge), the node will get phased out of the trie completely
    if ((ctx->flags & JFT_FLAGS_PRUNE) && leaf.size == 0)
      return Next;

    if (cons->keySpace == JFT_SYMBOL_PRIMARY) {
      // at value node
      // if we are translating, store the translation of old value offset to new
      if (doTranslate) {
        cons->TLBs[b - 1][cons->TLBSizes[b - 1]++] = cursor->node - cursor->root;
        cons->TLBs[b - 1][cons->TLBSizes[b - 1]++] = buf->mark;
      }

      // emit the leaf node
      frame->offset = buf->mark;
      if (!make_leaf(buf, (frame - 1)->offset, &cons->stem, &leaf))
        return ENoMem;

      cons->root.numPrimary++;
    } else {
      // at index node
      // wrap each cursors' words in an iterator
      // which yields batches of sorted (maybe translated) words
      JFT_Count maxWords = 0, numWords = 0;
      do {
        cursor = cursors + b - 1;
        leaf = JFT_leaf(cursor->node);
        if (!(JFT_cursor_at_terminal(cursor)))
          break;
        if (doTranslate) {
          // use a translation iterator, translates a static size batch at a time
          cons->iters[b - 1] = JFT_iter_trans(leaf, cons->TLBs[b - 1], cons->TLBSizes[b - 1]);
        } else {
          // use an iterator that just returns the raw leaf words in one batch
          cons->iters[b - 1] = JFT_iter_leaf(leaf);
        }
        maxWords += leaf.size;
      } while ((b = ffsll(active &= active - 1)));

      // emit the leaf node using an upper bound on the number of words
      frame->offset = buf->mark;
      if (!(prep_leaf(buf, (frame - 1)->offset, &cons->stem, maxWords)))
        return ENoMem;

      // write the indices, count the actual words
      JFT_Iter i = JFT_iter_any(cons->iters, frame->active ^ active);
      do {
        JFT_buffer_paste(buf, i.batch.data, i.batch.size * sizeof(JFT_Word));
        numWords += i.batch.size;
      } while (JFT_iter_next(&i));

      // correct the leaf node using the actual number of words
      edit_leaf(buf, frame->offset, &cons->stem, maxWords, numWords);

      if (numWords > cons->root.maxIndices)
        cons->root.maxIndices = numWords;
      cons->root.numIndices++;
    }

    // reset the bud
    cons->stem.pre = 0;
    cons->stem.size = 0;

    // done with this subtree
    return Next;
  }

  // cursor is non-terminal, maybe emit a branch
  // look at the other cursors and count # unique subsequent symbols
  JFT_Range range = {.min = 255, .max = 0};
  JFT_SymbolSet set = {};
  int count;
  do {
    if (cursor->symbol != JFT_SYMBOL_ANY)
      JFT_cursor_mark_subsequent(cursor, &range, &set);
    b = ffsll(active &= active - 1);
  } while (b && !JFT_cursor_at_terminal(cursor = cursors + b - 1));

  if ((count = JFT_symbol_set_count(&set)) > 1) {
    // more than one possible symbol: emit a branch node
    frame->offset = buf->mark;
    if (!make_branch(buf, (frame - 1)->offset, &cons->stem, &range, &set, count))
      return ENoMem;

    // reset the bud
    cons->stem.pre = 0;
    cons->stem.size = 0;
  }
  return Step;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x118, %rsp            # imm = 0x118
movq %rsi, %r15
movq %rdi, %r13
movq 0x8(%rsi), %rsi
movq 0x20(%r15), %rbp
movq 0x8(%rsi), %rbx
bsfq %rbx, %rax
pushq $-0x1
popq %r14
cmovneq %rax, %r14
incq %r14
imulq $0x38, %r14, %rax
movq (%rbp), %rdi
movq -0x30(%r13,%rax), %rcx
movq (%rcx), %rcx
cmpl $-0x1, %edx
je 0x38ed
shrq $0x3e, %rcx
jne 0x3922
movq 0x10(%rdi), %rax
movq %rax, 0x18(%rsi)
callq 0x4229
pushq $0x5
popq %r12
testq %rax, %rax
je 0x3ef0
andq $0x0, 0x10(%rbp)
movzwl 0x10(%r15), %edi
callq 0x1150
andq $0x0, 0x40(%rbp)
andw $0x0, 0x48(%rbp)
movq %rax, 0x50(%rbp)
testq %rax, %rax
je 0x3ef0
movq 0x18(%r15), %rbx
imulq $0xc8, %rbx, %rdi
callq 0x1150
movq %rax, 0x58(%rbp)
pushq $0x1
popq %r12
testb $0x4, 0x28(%r15)
jne 0x3ef0
leaq (,%rbx,8), %rdi
callq 0x1150
movq %rax, 0x60(%rbp)
pushq $0x4
popq %rsi
movq %rbx, %rdi
callq 0x1120
movq %rax, 0x68(%rbp)
xorl %r14d, %r14d
cmpq %r14, %rbx
je 0x3ef0
movq (%r13), %rax
movl 0x20(%rax), %edi
addl %edi, %edi
shlq $0x3, %rdi
callq 0x1150
movq 0x60(%rbp), %rcx
movq %rax, (%rcx,%r14,8)
incq %r14
addq $0x38, %r13
jmp 0x38c1
xorl %r12d, %r12d
shrq $0x3e, %rcx
jne 0x3ef0
movq 0x10(%rdi), %rax
movq 0x18(%rdi), %rcx
movq %rax, 0x18(%rcx)
movq 0x30(%rbp), %rax
movq %rax, 0x20(%rcx)
movl 0x38(%rbp), %eax
movl %eax, 0x28(%rcx)
movzwl 0x10(%r15), %eax
movw %ax, 0x2c(%rcx)
jmp 0x3ef0
movq %rsi, 0x20(%rsp)
movq %rdi, 0x18(%rsp)
leaq (%rax,%r13), %r12
movq %r13, 0x28(%rsp)
addq %rax, %r13
addq $-0x38, %r13
movq -0x8(%r12), %rax
leaq 0x5(%rax), %rcx
cmpq $0x1, %rcx
ja 0x3955
movq %rax, 0x8(%rbp)
movq %rax, 0x40(%rbp)
jmp 0x3969
movq 0x50(%rbp), %rcx
cmpq $0x1, 0x40(%rbp)
movzwl 0x48(%rbp), %edx
adcq $-0x1, %rcx
movb %al, (%rcx,%rdx)
incw 0x48(%rbp)
movq %r13, %rdi
callq 0x49f1
testl %eax, %eax
movq %rbp, 0x8(%rsp)
je 0x39bb
movl 0x28(%r15), %r15d
movq -0x30(%r12), %r12
movq %r12, %rdi
callq 0x4a14
movl %eax, 0x30(%rsp)
movq %rdx, 0x38(%rsp)
pushq $0x2
popq %r9
movl %r15d, 0x14(%rsp)
testb $0x2, %r15b
je 0x3c17
testl %eax, %eax
jne 0x3c17
movl %r9d, %r12d
jmp 0x3ef0
movups 0x1ace(%rip), %xmm0     # 0x5490
leaq 0x30(%rsp), %r15
movaps %xmm0, (%r15)
xorps %xmm0, %xmm0
leaq 0x50(%rsp), %r12
movaps %xmm0, 0x10(%r12)
movaps %xmm0, (%r12)
cmpq $-0x1, 0x30(%r13)
je 0x3a80
movq 0x28(%r13), %rax
movzwl 0x18(%r13), %ecx
decq %rcx
cmpq %rcx, %rax
jne 0x3a51
movq 0x8(%r13), %rax
movq (%rax), %rcx
movq %rcx, %rdx
shrq $0x3e, %rdx
cmpq $0x2, %rdx
je 0x3aa8
cmpl $0x1, %edx
jne 0x3a80
movq %rcx, %rdx
shrq $0x28, %rdx
movzbl %dl, %r14d
shrq $0x30, %rcx
andl $0xfff, %ecx            # imm = 0xFFF
leaq (%rax,%rcx), %r13
addq $0x8, %r13
xorl %ebp, %ebp
cmpq %rbp, %r14
je 0x3a80
movzbl (%r13,%rbp), %edx
movq %r15, %rdi
movq %r12, %rsi
callq 0x4c16
incq %rbp
jmp 0x3a36
incq %rax
movq 0x10(%r13), %rdx
testq %rdx, %rdx
je 0x3a6e
testq %rax, %rax
je 0x3a75
movq 0x20(%r13), %rcx
addq %rcx, %rax
decq %rax
jmp 0x3a72
addq 0x20(%r13), %rax
movzbl (%rax), %edx
movq %r15, %rdi
movq %r12, %rsi
callq 0x4c16
leaq -0x1(%rbx), %rax
andq %rax, %rbx
je 0x3af9
bsfq %rbx, %rax
imulq $0x38, %rax, %r13
addq 0x28(%rsp), %r13
movq %r13, %rdi
callq 0x49f1
testl %eax, %eax
je 0x39de
jmp 0x3af9
movq %rcx, %rdx
shrq $0x28, %rdx
movzbl %dl, %edx
shrq $0x30, %rcx
andl $0xfff, %ecx            # imm = 0xFFF
leaq (%rax,%rcx), %r14
addq $0x8, %r14
shll $0x4, %edx
leaq 0x18e2(%rip), %rax      # 0x53b0
movq (%rdx,%rax), %r13
movq 0x8(%rdx,%rax), %rbp
cmpq %rbp, %r13
ja 0x3a80
cmpq $0x0, (%r14)
je 0x3af0
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x4c16
incq %r13
addq $0x8, %r14
jmp 0x3ad7
movdqa 0x50(%rsp), %xmm0
movdqa 0x60(%rsp), %xmm1
movdqa %xmm1, %xmm2
psrlw $0x1, %xmm2
movdqa 0x194a(%rip), %xmm3     # 0x5460
pand %xmm3, %xmm2
psubb %xmm2, %xmm1
movdqa 0x194a(%rip), %xmm2     # 0x5470
movdqa %xmm1, %xmm4
pand %xmm2, %xmm4
psrlw $0x2, %xmm1
pand %xmm2, %xmm1
paddb %xmm4, %xmm1
movdqa %xmm1, %xmm4
psrlw $0x4, %xmm4
paddb %xmm1, %xmm4
movdqa 0x1930(%rip), %xmm1     # 0x5480
pand %xmm1, %xmm4
movdqa %xmm0, %xmm5
psrlw $0x1, %xmm5
pand %xmm3, %xmm5
psubb %xmm5, %xmm0
movdqa %xmm0, %xmm3
pand %xmm2, %xmm3
psrlw $0x2, %xmm0
pand %xmm2, %xmm0
paddb %xmm3, %xmm0
movdqa %xmm0, %xmm2
psrlw $0x4, %xmm2
paddb %xmm0, %xmm2
pand %xmm1, %xmm2
paddb %xmm4, %xmm2
pxor %xmm0, %xmm0
psadbw %xmm2, %xmm0
pshufd $0xee, %xmm0, %xmm1     # xmm1 = xmm0[2,3,2,3]
paddq %xmm0, %xmm1
movd %xmm1, %r8d
pushq $0x1
popq %r12
cmpl $0x2, %r8d
jb 0x3ef0
movq 0x18(%rsp), %rdi
movq 0x10(%rdi), %rax
movq 0x20(%rsp), %rcx
movq %rax, 0x18(%rcx)
movq -0x8(%rcx), %rsi
movq 0x8(%rsp), %rbx
leaq 0x40(%rbx), %rdx
cmpl $0x10, %r8d
jb 0x3e7d
movq 0x30(%rsp), %rax
movq 0x38(%rsp), %r10
pushq $0x1
popq %rcx
xorl %r9d, %r9d
leaq 0x17bd(%rip), %r11      # 0x53b0
cmpq $0x40, %r9
je 0x3e77
cmpq 0x10(%r9,%r11), %rax
jb 0x3c0f
cmpq 0x18(%r9,%r11), %r10
jbe 0x3ed6
incl %ecx
addq $0x10, %r9
jmp 0x3bf3
cmpq $-0x5, 0x8(%rbp)
jne 0x3c61
testb $0x4, 0x14(%rsp)
jne 0x3e46
subq (%r13), %r12
movq 0x60(%rbp), %rax
movq 0x68(%rbp), %rcx
movq -0x8(%rax,%r14,8), %rdx
movl -0x4(%rcx,%r14,4), %esi
leal 0x1(%rsi), %r8d
movq %r12, (%rdx,%rsi,8)
movq 0x18(%rsp), %rdi
movq 0x10(%rdi), %rax
addl $0x2, %esi
movl %esi, -0x4(%rcx,%r14,4)
movq %rax, (%rdx,%r8,8)
jmp 0x3e4f
xorl %r15d, %r15d
movq 0x28(%rsp), %rcx
imulq $0x38, %r14, %rax
leaq (%rcx,%rax), %rbp
addq $-0x38, %rbp
movq 0x8(%rbp), %rdi
callq 0x4a14
movl %eax, %r12d
movq %rdx, %r13
movq %rbp, %rdi
callq 0x49f1
testl %eax, %eax
je 0x3d74
movq 0x8(%rsp), %rsi
movq 0x58(%rsi), %rax
testb $0x4, 0x14(%rsp)
jne 0x3d1e
leaq -0x1(%r14), %rcx
imulq $0xc8, %rcx, %rcx
movq 0x60(%rsi), %rdx
movq 0x68(%rsi), %rsi
movq -0x8(%rdx,%r14,8), %rdx
movq %rdx, 0x48(%rsp)
movl -0x4(%rsi,%r14,4), %r14d
leaq 0x8(%rax,%rcx), %rbp
leaq 0x5d8(%rip), %rax       # 0x42aa
movq %rax, -0x8(%rbp)
movl $0x98, %edx
movq %rbp, %rdi
xorl %esi, %esi
callq 0x10f0
movl %r12d, 0x98(%rbp)
andl $0x0, 0x9c(%rbp)
movq %r13, 0xa0(%rbp)
movq 0x48(%rsp), %rax
movq %rax, 0xa8(%rbp)
movl %r14d, 0xb0(%rbp)
andq $0x0, 0xb4(%rbp)
orl $-0x1, 0xbc(%rbp)
jmp 0x3d53
imulq $0xc8, %r14, %rcx
leaq (%rax,%rcx), %rdi
addq $-0xb0, %rdi
leaq 0x570(%rip), %rax       # 0x42a7
movq %rax, -0x18(%rdi)
andl $0x0, -0x10(%rdi)
movl %r12d, -0xc(%rdi)
movq %r13, -0x8(%rdi)
movl $0xb0, %edx
xorl %esi, %esi
callq 0x10f0
addl %r12d, %r15d
leaq -0x1(%rbx), %rax
andq %rax, %rbx
bsfq %rbx, %r14
incq %r14
testq %rbx, %rbx
movq 0x28(%rsp), %rcx
jne 0x3c69
xorl %ebx, %ebx
movq 0x8(%rsp), %r14
movq 0x18(%rsp), %r13
movq 0x10(%r13), %rax
movq 0x20(%rsp), %r12
movq %rax, 0x18(%r12)
movq -0x8(%r12), %rsi
leaq 0x40(%r14), %rdx
movq %r13, %rdi
movl %r15d, %ecx
callq 0x4a42
testq %rax, %rax
je 0x3eec
movq %r12, %rax
movq 0x58(%r14), %r12
xorq 0x8(%rax), %rbx
leaq 0x58(%rsp), %r14
xorl %ebp, %ebp
movl $0xc0, %edx
movq %r14, %rdi
xorl %esi, %esi
callq 0x10f0
leaq 0x5e6(%rip), %rax       # 0x43b7
movq %rax, -0x8(%r14)
movq %r12, 0x98(%r14)
movq %rbx, 0xa0(%r14)
movq %rbx, 0xa8(%r14)
leaq 0x50(%rsp), %r14
movq 0x60(%rsp), %rsi
movl 0x5c(%rsp), %r12d
shlq $0x3, %r12
movq 0x18(%r13), %rdi
addq 0x10(%r13), %rdi
movq %r12, %rdx
callq 0x1140
addq %r12, 0x10(%r13)
addl 0x5c(%rsp), %ebp
andl $0x0, 0x58(%rsp)
movq %r14, %rdi
callq *0x50(%rsp)
testl %eax, %eax
jne 0x3def
movq 0x18(%r13), %rax
movq 0x20(%rsp), %rcx
addq 0x18(%rcx), %rax
cmpl $0xfe, %r15d
ja 0x3e89
movb %bpl, 0x5(%rax)
movq 0x8(%rsp), %rdx
jmp 0x3e96
movq 0x18(%rsp), %rdi
movq 0x10(%rdi), %rax
movl %r9d, %r12d
movq 0x20(%rsp), %rcx
movq %rax, 0x18(%rcx)
movq -0x8(%rcx), %rsi
leaq 0x40(%rbp), %rdx
leaq 0x30(%rsp), %rcx
callq 0x4267
testq %rax, %rax
je 0x3eec
incl 0x30(%rbp)
jmp 0x3ea8
cmpl $0x20, %r8d
jae 0x3eb4
leaq 0x50(%rsp), %rcx
callq 0x4c3a
jmp 0x3edb
movq 0x8(%rsp), %rdx
movzwl 0x48(%rdx), %ecx
movl %ebp, 0x8(%rax,%rcx)
pushq $0x2
popq %r12
cmpl 0x38(%rdx), %ebp
jbe 0x3ea2
movl %ebp, 0x38(%rdx)
incl 0x34(%rdx)
movq %rdx, %rbp
andq $0x0, 0x40(%rbp)
andw $0x0, 0x48(%rbp)
jmp 0x3ef0
pushq $0x5
popq %rcx
xorl %r9d, %r9d
cmpq $0x60, %r9
je 0x3e7d
cmpq 0x50(%r9,%r11), %rax
jb 0x3ece
cmpq 0x58(%r9,%r11), %r10
jbe 0x3ed6
incl %ecx
addq $0x10, %r9
jmp 0x3eba
callq 0x4d27
testq %rax, %rax
je 0x3eec
andq $0x0, 0x40(%rbx)
andw $0x0, 0x48(%rbx)
jmp 0x3ef0
pushq $0x5
popq %r12
movl %r12d, %eax
addq $0x118, %rsp            # imm = 0x118
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq