// File: /workspace/github_c_makefile_star2_O2/Tarsnap[P]kivaloo/kvlds/btree_balance.c
// Function: domergenode
static int
domergenode(struct balance_cookie * B, struct node * N)
{
	size_t nmerges, i, j;
	size_t nmerge;
	int failed = 0;		/* We haven't failed yet. */
	int merging;
	struct node * NC;

	/*
	 * As far as we know, we've done all possibly merges under this
	 * subtree.  (We'll adjust this later if necessary).
	 */
	N->needmerge = 0;

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

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

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

		/* If this child needs to be remerged, so do we. */
		if (N->v.children[i]->needmerge)
			N->needmerge = 1;
	}

	/* Count how many of our children will be merged. */
	for (nmerges = i = 0; i <= N->nkeys; i++) {
		if (N->v.children[i]->merging) {
			/* We have a merge required. */
			nmerges++;

			/* We might need to do a merge in the new child. */
			N->needmerge = 1;
		}
	}

	/* If we don't need to do any merges, we're done. */
	if (nmerges == 0)
		goto done;

	/* Iterate through the children, dirtying and unlocking them. */
	for (merging = 0, i = 0;
	    i <= N->nkeys;
	    merging = N->v.children[i]->merging, i++) {
		/*
		 * Grab a pointer to the node.  Note that if we dirty NC, it
		 * will no longer be the same as N->v.children[i].
		 */
		NC = N->v.children[i];

		/* If this node isn't being merged, move on. */
		if ((NC->merging == 0) && (merging == 0))
			continue;

		/* If this node isn't dirty, make it dirty. */
		if (NC->state != NODE_STATE_DIRTY) {
			if (btree_node_dirty(B->T, NC) == NULL)
				failed = 1;

			/* The dirty node is being merged, not the shadow. */
			N->v.children[i]->merging = NC->merging;
			NC->merging = 0;
		}

		/*
		 * Release the lock we picked up in planmergenode or which
		 * was picked up for us by btree_node_fetch.
		 */
		btree_node_unlock(B->T, NC);
	}

	/* If we failed to dirty a node, give up now. */
	if (failed)
		goto err0;

	/* Iterate through the children, merging them as necessary. */
	for (nmerge = 0, j = i = 0; i <= N->nkeys; i++) {
		/* If this node is being merged into the next, move on. */
		if (N->v.children[i]->merging) {
			nmerge++;
			continue;
		}

		/* If we're not merging, just copy the child and key. */
		if (nmerge == 0) {
			N->v.children[j] = N->v.children[i];
			if (i < N->nkeys)
				N->u.keys[j] = N->u.keys[i];
			j += 1;
			continue;
		}

		/* Merge children. */
		if (btree_node_merge(B->T,
		    &N->v.children[i - nmerge], &N->u.keys[i - nmerge],
		    &N->v.children[j], &N->u.keys[j], nmerge)) {
			j += nmerge;
			failed = 1;
		}

		/* Copy the separator key. */
		if (i < N->nkeys)
			N->u.keys[j] = N->u.keys[i];
		j += 1;

		/* We've merged this batch; start over. */
		nmerge = 0;
	}

	/* Store number of keys. */
	N->nkeys = j - 1;

	/* The size of this node has changed. */
	N->pagesize = (uint32_t)(-1);

	/* Did we fail? */
	if (failed)
		goto err0;

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

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

// Assembly:
movb 0x1c(%rsi), %al
movl %eax, %ecx
andb $-0x41, %cl
movb %cl, 0x1c(%rsi)
andb $0xf, %al
cmpb $0x8, %al
jne 0x5d66
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
xorl %r15d, %r15d
movq 0x38(%rbx), %rax
movq 0x48(%rbx), %rcx
cmpq %rax, %r15
ja 0x5d69
movq (%rcx,%r15,8), %rsi
movq %r14, %rdi
callq 0x5d09
testl %eax, %eax
jne 0x5eea
movq 0x48(%rbx), %rax
movq (%rax,%r15,8), %rax
testb $0x40, 0x1c(%rax)
je 0x5d61
orb $0x40, 0x1c(%rbx)
incq %r15
jmp 0x5d2e
xorl %eax, %eax
retq
pushq $-0x1
popq %rsi
xorl %edx, %edx
cmpq %rsi, %rax
je 0x5d8a
movq 0x8(%rcx,%rsi,8), %rdi
testb $0x20, 0x1c(%rdi)
je 0x5d85
incq %rdx
orb $0x40, 0x1c(%rbx)
incq %rsi
jmp 0x5d6e
testq %rdx, %rdx
je 0x5eef
xorl %r12d, %r12d
pushq $0x1
popq %r13
xorl %ebp, %ebp
xorl %esi, %esi
cmpq %rax, %r12
ja 0x5e16
movq (%rcx,%r12,8), %r15
movb 0x1c(%r15), %dl
testb $0x20, %dl
jne 0x5db4
testl %esi, %esi
je 0x5e08
andb $0xc, %dl
cmpb $0x8, %dl
je 0x5ded
movq 0x10(%r14), %rdi
movq %r15, %rsi
callq 0x7abe
testq %rax, %rax
cmovel %r13d, %ebp
movb 0x1c(%r15), %al
andb $0x20, %al
movq 0x48(%rbx), %rcx
movq (%rcx,%r12,8), %rcx
movb 0x1c(%rcx), %dl
andb $-0x21, %dl
orb %al, %dl
movb %dl, 0x1c(%rcx)
andb $-0x21, 0x1c(%r15)
movq 0x10(%r14), %rdi
movq %r15, %rsi
callq 0x59ff
movq 0x38(%rbx), %rax
movq 0x48(%rbx), %rcx
movq (%rcx,%r12,8), %rdx
movb 0x1c(%rdx), %dl
shrb $0x5, %dl
andb $0x1, %dl
movzbl %dl, %esi
incq %r12
jmp 0x5d9e
testl %ebp, %ebp
jne 0x5eea
xorl %r12d, %r12d
xorl %ebp, %ebp
xorl %r13d, %r13d
xorl %r15d, %r15d
xorl %edi, %edi
cmpq %rax, %rbp
ja 0x5edb
movq 0x48(%rbx), %rcx
movq (%rcx,%r12), %rdx
testb $0x20, 0x1c(%rdx)
jne 0x5eaf
testq %r15, %r15
je 0x5eb4
movl %edi, 0x4(%rsp)
movq 0x10(%r14), %rdi
leaq (,%r15,8), %rax
movq %r12, %rsi
subq %rax, %rsi
addq %rcx, %rsi
movq 0x40(%rbx), %rdx
leaq (%rdx,%r13,8), %r8
subq %rax, %rdx
addq %r12, %rdx
leaq (%rcx,%r13,8), %rcx
movq %r15, %r9
callq 0x863c
movl 0x4(%rsp), %edi
testl %eax, %eax
movl $0x0, %ecx
cmovneq %r15, %rcx
pushq $0x1
popq %rax
cmovnel %eax, %edi
addq %r13, %rcx
movq 0x38(%rbx), %rax
cmpq %rax, %rbp
jae 0x5ea7
movq 0x40(%rbx), %rdx
movq (%rdx,%r12), %rsi
movq %rsi, (%rdx,%rcx,8)
incq %rcx
movq %rcx, %r13
jmp 0x5ecc
incq %r15
jmp 0x5ecf
movq %rdx, (%rcx,%r13,8)
cmpq %rax, %rbp
jae 0x5ec9
movq 0x40(%rbx), %rcx
movq (%rcx,%r12), %rdx
movq %rdx, (%rcx,%r13,8)
incq %r13
xorl %r15d, %r15d
incq %rbp
addq $0x8, %r12
jmp 0x5e2b
decq %r13
movq %r13, 0x38(%rbx)
orl $-0x1, 0x18(%rbx)
testl %edi, %edi
je 0x5eef
pushq $-0x1
popq %rax
jmp 0x5ef1
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq