// File: /workspace/github_c_makefile_star2_O2/Tarsnap[P]kivaloo/kvlds/btree_balance.c
// Function: planmergenode
static int
planmergenode(struct balance_cookie * B, struct node * N)
{
	size_t maxplen = (B->T->pagelen * 2) / 3;
	size_t i;
	size_t plen;
	int gotdirty;
	int leafchild;
	int merging;

	/* If this node has no children, do nothing. */
	if (N->type != NODE_TYPE_PARENT)
		goto done;

	/* If this node is not dirty, it doesn't need splitting. */
	if (N->state != NODE_STATE_DIRTY)
		goto done;

	/* Plan merges under our children first. */
	for (i = 0; i <= N->nkeys; i++) {
		if (planmergenode(B, N->v.children[i]))
			goto err0;
	}

	/* Scan this node to see if we can merge any of its children. */
	/*
	 * Child number N->nkeys can't be merged into a higher-numbered child
	 * so we jump directly to nomerge.  This could be done using an
	 * "are we on the first pass through the loop" test inside the loop,
	 * but this confuses gcc.
	 */
	i = N->nkeys;
	goto nomerge;
	for (/* i = N->nkeys; */; i <= N->nkeys; i--) {
		/* Have we seen a dirty node yet? */
		if (N->v.children[i]->state == NODE_STATE_DIRTY) {
			gotdirty = 1;
			leafchild = (N->v.children[i]->type == NODE_TYPE_LEAF);
		}

		/*
		 * If we haven't seen a dirty node, we can't possibly need to
		 * merge this into the previous node.
		 */
		if (!gotdirty)
			goto nomerge;

		/*
		 * Figure out how large a node we'll produce if we merge this
		 * node into the next one.
		 */
		if (!leafchild)
			plen += kvldskey_serial_size(N->u.keys[i]);
		plen += serialize_merge_size(N->v.children[i]);

		/* Would the resulting node be too big? */
		if (plen > maxplen)
			goto nomerge;

		/* Mark this node as requiring merging. */
		N->v.children[i]->merging = 1;

		/* Move on to considering the next child. */
		continue;

nomerge:
		/*
		 * We're not merging this node into the next one.  Reset the
		 * state we're tracking so we can check if other nodes should
		 * be merged into this one.
		 */
		plen = serialize_size(N->v.children[i]);
		gotdirty = (N->v.children[i]->state == NODE_STATE_DIRTY);
		leafchild = (N->v.children[i]->type == NODE_TYPE_LEAF);
	}

	/* Page in any nodes which are needed for merging. */
	for (merging = i = 0; i <= N->nkeys; i++) {
		/* Do we need this node? */
		if (merging || N->v.children[i]->merging) {
			/* Is it present? */
			if (node_present(N->v.children[i])) {
				/* Make sure it stays present. */
				btree_node_lock(B->T, N->v.children[i]);
			} else {
				/* Fetch it. */
				B->nmergefetch += 1;
				if (btree_node_fetch(B->T, N->v.children[i],
				    merge_fetch, B))
					goto err0;
			}
		}

		/* Are we in the middle of a merging range? */
		merging = N->v.children[i]->merging;
	}

done:
	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq 0x10(%rdi), %rax
movq (%rax), %rax
addq %rax, %rax
xorl %esi, %esi
pushq $0x3
popq %rcx
xorl %edx, %edx
divq %rcx
movq %rax, %r12
movb 0x1c(%r14), %al
andb $0xf, %al
cmpb $0x8, %al
jne 0x5bbe
movq %rdi, %r15
xorl %ebp, %ebp
movq 0x38(%r14), %r13
cmpq %r13, %rbp
ja 0x5aa5
movq 0x48(%r14), %rax
movq (%rax,%rbp,8), %rsi
movq %r15, %rdi
callq 0x5a45
incq %rbp
testl %eax, %eax
je 0x5a7d
pushq $-0x1
popq %rsi
jmp 0x5bbe
movq 0x48(%r14), %rax
movq (%rax,%r13,8), %rdi
callq 0x8e4b
movq 0x48(%r14), %rcx
movq (%rcx,%r13,8), %rcx
movb 0x1c(%rcx), %dl
movl %edx, %ecx
andb $0xc, %cl
cmpb $0x8, %cl
setne %cl
andb $0x3, %dl
xorl %ebp, %ebp
cmpb $0x1, %dl
sete %bpl
decq %r13
movq 0x38(%r14), %rdx
cmpq %rdx, %r13
ja 0x5b49
movq 0x48(%r14), %rdx
movq (%rdx,%r13,8), %rdi
movb 0x1c(%rdi), %dl
movl %edx, %esi
andb $0xc, %sil
andb $0x3, %dl
xorl %r8d, %r8d
cmpb $0x1, %dl
sete %r8b
cmpb $0x8, %sil
setne %dl
cmovel %r8d, %ebp
testb %cl, %dl
jne 0x5aa5
testl %ebp, %ebp
jne 0x5b22
movq 0x40(%r14), %rcx
movq (%rcx,%r13,8), %rcx
movzbl (%rcx), %ecx
addq %rcx, %rax
incq %rax
movq %rax, %rbx
callq 0x9330
addq %rbx, %rax
cmpq %r12, %rax
ja 0x5aa5
movq 0x48(%r14), %rcx
movq (%rcx,%r13,8), %rcx
orb $0x20, 0x1c(%rcx)
decq %r13
xorl %ecx, %ecx
jmp 0x5ad7
xorl %r13d, %r13d
leaq 0x18a(%rip), %r12       # 0x5cdd
xorl %eax, %eax
cmpq %rdx, %r13
ja 0x5bbc
movq 0x48(%r14), %rcx
movq (%rcx,%r13,8), %rsi
movb 0x1c(%rsi), %cl
testl %eax, %eax
jne 0x5b6f
movl %ecx, %eax
andb $0x20, %al
je 0x5ba2
testb $0x2, %cl
jne 0x5b7f
movq 0x10(%r15), %rdi
callq 0x59da
jmp 0x5ba2
incq 0x18(%r15)
movq 0x10(%r15), %rdi
movq 0x48(%r14), %rax
movq (%rax,%r13,8), %rsi
movq %r12, %rdx
movq %r15, %rcx
callq 0x77c8
testl %eax, %eax
jne 0x5a9d
movq 0x38(%r14), %rdx
movq 0x48(%r14), %rax
movq (%rax,%r13,8), %rax
movl 0x1c(%rax), %eax
shrl $0x5, %eax
andl $0x1, %eax
incq %r13
jmp 0x5b55
xorl %esi, %esi
movl %esi, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq