// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/dict.c
// Function: dictRehash
int dictRehash(dict *d, int n) {

    // 只可以在 rehash 进行中时执行
    if (!dictIsRehashing(d)) return 0;

    // 进行 N 步迁移
    // T = O(N)
    while(n--) {
        dictEntry *de, *nextde;

        /* Check if we already rehashed the whole table... */
        // 如果 0 号哈希表为空，那么表示 rehash 执行完毕
        // T = O(1)
        if (d->ht[0].used == 0) {
            // 释放 0 号哈希表
            zfree(d->ht[0].table);
            // 将原来的 1 号哈希表设置为新的 0 号哈希表
            d->ht[0] = d->ht[1];
            // 重置旧的 1 号哈希表
            _dictReset(&d->ht[1]);
            // 关闭 rehash 标识
            d->rehashidx = -1;
            // 返回 0 ，向调用者表示 rehash 已经完成
            return 0;
        }

        /* Note that rehashidx can't overflow as we are sure there are more
         * elements because ht[0].used != 0 */
        // 确保 rehashidx 没有越界
        assert(d->ht[0].size > (unsigned)d->rehashidx);

        // 略过数组中为空的索引，找到下一个非空索引
        while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++;

        // 指向该索引的链表表头节点
        de = d->ht[0].table[d->rehashidx];
        /* Move all the keys in this bucket from the old to the new hash HT */
        // 将链表中的所有节点迁移到新哈希表
        // T = O(1)
        while(de) {
            unsigned int h;

            // 保存下个节点的指针
            nextde = de->next;

            /* Get the index in the new hash table */
            // 计算新哈希表的哈希值，以及节点插入的索引位置
            h = dictHashKey(d, de->key) & d->ht[1].sizemask;

            // 插入节点到新哈希表
            de->next = d->ht[1].table[h];
            d->ht[1].table[h] = de;

            // 更新计数器
            d->ht[0].used--;
            d->ht[1].used++;

            // 继续处理下个节点
            de = nextde;
        }
        // 将刚迁移完的哈希表索引的指针设为空
        d->ht[0].table[d->rehashidx] = NULL;
        // 更新 rehash 索引
        d->rehashidx++;
    }

    return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
xorl %eax, %eax
cmpl $-0x1, 0x50(%rdi)
je 0x22192
movl %esi, %ebp
movq %rdi, %r14
leaq 0x10(%rdi), %rax
movq %rax, (%rsp)
leaq 0x30(%rdi), %r12
subl $0x1, %ebp
jb 0x2218d
movq 0x28(%r14), %r13
testq %r13, %r13
je 0x2214b
movl 0x50(%r14), %eax
cmpq %rax, 0x18(%r14)
jbe 0x221a1
movq 0x10(%r14), %rcx
movl 0x50(%r14), %eax
movslq %eax, %rdx
movq (%rcx,%rdx,8), %rbx
testq %rbx, %rbx
jne 0x22106
leaq (%rcx,%rdx,8), %rcx
addq $0x8, %rcx
movq (%rcx), %rbx
incl %eax
addq $0x8, %rcx
testq %rbx, %rbx
je 0x220f4
movl %eax, 0x50(%r14)
movq (%rbx), %rdi
movq 0x10(%rbx), %r15
movq (%r14), %rax
callq *(%rax)
andl 0x40(%r14), %eax
movq 0x30(%r14), %rcx
movq (%rcx,%rax,8), %rdx
movq %rdx, 0x10(%rbx)
movq %rbx, (%rcx,%rax,8)
decq 0x28(%r14)
incq 0x48(%r14)
movq %r15, %rbx
testq %r15, %r15
jne 0x22106
movq 0x10(%r14), %rax
movslq 0x50(%r14), %rcx
movq $0x0, (%rax,%rcx,8)
leal 0x1(%rcx), %eax
jmp 0x2217c
movq (%rsp), %rbx
movq (%rbx), %rdi
callq 0x2984b
movups (%r12), %xmm0
movups 0x10(%r12), %xmm1
movups %xmm1, 0x10(%rbx)
movups %xmm0, (%rbx)
xorps %xmm0, %xmm0
movups %xmm0, (%r12)
movups %xmm0, 0x10(%r12)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, 0x50(%r14)
testq %r13, %r13
jne 0x220b4
xorl %eax, %eax
jmp 0x22192
movl $0x1, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x71fba(%rip), %rdi     # 0x94162
leaq 0x7e39f(%rip), %rsi     # 0xa054e
movl $0x17f, %edx            # imm = 0x17F
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0