// File: attractivechaos[P]udb2/tommyds/./tommyhashlin.c
// Function: hashlin_shrink_step
tommy_inline void hashlin_shrink_step(tommy_hashlin* hashlin)
{
	/* shrink if less than 12.5% full */
	if (hashlin->state != TOMMY_HASHLIN_STATE_SHRINK
		&& hashlin->count < hashlin->bucket_max / 8
	) {
		/* avoid to shrink the first bucket */
		if (hashlin->bucket_bit > TOMMY_HASHLIN_BIT) {
			/* if we are stable, setup a new shrink state */
			/* otherwise continue with the already setup grow one */
			/* but in backward direction */
			if (hashlin->state == TOMMY_HASHLIN_STATE_STABLE) {
				/* set the lower size */
				hashlin->low_max = hashlin->bucket_max / 2;
				hashlin->low_mask = hashlin->bucket_mask / 2;

				/* start from the half going backward */
				hashlin->split = hashlin->low_max;
			}

			/* start reallocation */
			hashlin->state = TOMMY_HASHLIN_STATE_SHRINK;
		}
	}

	/* if we are shrinking */
	if (hashlin->state == TOMMY_HASHLIN_STATE_SHRINK) {
		/* compute the split target required to finish the reallocation before the next resize */
		tommy_count_t split_target = 8 * hashlin->count;

		/* reallocate buckets until the split target */
		while (hashlin->split + hashlin->low_max > split_target) {
			tommy_hashlin_node** split[2];

			/* go backward position */
			--hashlin->split;

			/* get the low bucket */
			split[0] = tommy_hashlin_pos(hashlin, hashlin->split);

			/* get the high bucket */
			split[1] = tommy_hashlin_pos(hashlin, hashlin->split + hashlin->low_max);

			/* concat the high bucket into the low one */
			tommy_list_concat(split[0], split[1]);

			/* if we have finished, clean up and change the state */
			if (hashlin->split == 0) {
				tommy_hashlin_node** segment;

				/* shrink the hash size */
				--hashlin->bucket_bit;
				hashlin->bucket_max = 1 << hashlin->bucket_bit;
				hashlin->bucket_mask = hashlin->bucket_max - 1;

				/* free the last segment */
				segment = hashlin->bucket[hashlin->bucket_bit];
				tommy_free(&segment[((tommy_ptrdiff_t)1) << hashlin->bucket_bit]);

				/* go in stable mode */
				tommy_hashlin_stable(hashlin);
				break;
			}
		}
	}
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x30(%rsp)
movq 0x30(%rsp), %rax
cmpl $0x2, 0x11c(%rax)
je 0x570b
movq 0x30(%rsp), %rax
movl 0x118(%rax), %eax
movq 0x30(%rsp), %rcx
movl 0x104(%rcx), %ecx
shrl $0x3, %ecx
cmpl %ecx, %eax
jae 0x570b
movq 0x30(%rsp), %rax
cmpl $0x6, 0x100(%rax)
jbe 0x5709
movq 0x30(%rsp), %rax
cmpl $0x0, 0x11c(%rax)
jne 0x56fa
movq 0x30(%rsp), %rax
movl 0x104(%rax), %ecx
shrl %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x10c(%rax)
movq 0x30(%rsp), %rax
movl 0x108(%rax), %ecx
shrl %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x110(%rax)
movq 0x30(%rsp), %rax
movl 0x10c(%rax), %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x114(%rax)
movq 0x30(%rsp), %rax
movl $0x2, 0x11c(%rax)
jmp 0x570b
movq 0x30(%rsp), %rax
cmpl $0x2, 0x11c(%rax)
jne 0x5861
movq 0x30(%rsp), %rax
movl 0x118(%rax), %eax
shll $0x3, %eax
movl %eax, 0x2c(%rsp)
movq 0x30(%rsp), %rax
movl 0x114(%rax), %eax
movq 0x30(%rsp), %rcx
addl 0x10c(%rcx), %eax
cmpl 0x2c(%rsp), %eax
jbe 0x585f
movq 0x30(%rsp), %rax
movl 0x114(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x114(%rax)
movq 0x30(%rsp), %rdi
movq 0x30(%rsp), %rax
movl 0x114(%rax), %esi
callq 0x59d0
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %rdi
movq 0x30(%rsp), %rax
movl 0x114(%rax), %esi
movq 0x30(%rsp), %rax
addl 0x10c(%rax), %esi
callq 0x59d0
movq %rax, 0x18(%rsp)
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rsi
callq 0x6410
movq 0x30(%rsp), %rax
cmpl $0x0, 0x114(%rax)
jne 0x585a
movq 0x30(%rsp), %rax
movl 0x100(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x100(%rax)
movq 0x30(%rsp), %rax
movl 0x100(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x104(%rax)
movq 0x30(%rsp), %rax
movl 0x104(%rax), %ecx
subl $0x1, %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x108(%rax)
movq 0x30(%rsp), %rax
movq 0x30(%rsp), %rcx
movl 0x100(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x8(%rsp)
movq 0x8(%rsp), %rdi
movq 0x30(%rsp), %rax
movl 0x100(%rax), %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
shlq $0x3, %rax
addq %rax, %rdi
callq 0x1030
movq 0x30(%rsp), %rdi
callq 0x51d0
jmp 0x585f
jmp 0x572f
jmp 0x5861
addq $0x38, %rsp
retq
nopw %cs:(%rax,%rax)