LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbLoadLzfStringObject
robj *rdbLoadLzfStringObject(rio *rdb) {
    unsigned int len, clen;
    unsigned char *c = NULL;
    sds val = NULL;

    // 读入压缩后的缓存长度
    if ((clen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
    // 读入字符串未压缩前的长度
    if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
    // 压缩缓存空间
    if ((c = zmalloc(clen)) == NULL) goto err;
    // 字符串空间
    if ((val = sdsnewlen(NULL,len)) == NULL) goto err;

    // 读入压缩后的缓存
    if (rioRead(rdb,c,clen) == 0) goto err;

    // 解压缓存，得出字符串
    if (lzf_decompress(c,clen,val,len) == 0) goto err;
    zfree(c);

    // 创建字符串对象
    return createObject(REDIS_STRING,val);
err:
    zfree(c);
    sdsfree(val);
    return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
xorl %esi, %esi
callq 0x3645f
cmpl $-0x1, %eax
je 0x36a4f
movl %eax, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x3645f
cmpl $-0x1, %eax
je 0x36a4f
movl %eax, %r15d
movl %ebp, %r12d
movq %r12, %rdi
callq 0x299b5
movq %rax, %r13
testq %rax, %rax
je 0x36a30
movl %r15d, %esi
xorl %r14d, %r14d
xorl %edi, %edi
callq 0x283f4
movq %rax, 0x10(%rsp)
testq %rax, %rax
je 0x36a3f
movq %r13, 0x8(%rsp)
testl %ebp, %ebp
je 0x369f2
movq 0x8(%rsp), %r14
movq 0x30(%rbx), %rax
cmpq %r12, %rax
movq %r12, %r13
cmovbq %rax, %r13
testq %rax, %rax
cmoveq %r12, %r13
movq %rbx, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq *(%rbx)
testq %rax, %rax
je 0x36a35
movq 0x18(%rbx), %rax
testq %rax, %rax
je 0x369e6
movq %rbx, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq *%rax
addq %r13, %r14
addq %r13, 0x28(%rbx)
subq %r13, %r12
jne 0x369ad
movq 0x8(%rsp), %r13
movq %r13, %rdi
movl %ebp, %esi
movq 0x10(%rsp), %r14
movq %r14, %rdx
movl %r15d, %ecx
callq 0x29dc0
testl %eax, %eax
je 0x36a3f
movq %r13, %rdi
callq 0x29af7
xorl %edi, %edi
movq %r14, %rsi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3059c
xorl %r14d, %r14d
jmp 0x36a3f
movq 0x10(%rsp), %r14
movq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0x29af7
movq %r14, %rdi
callq 0x2850d
xorl %eax, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbSaveRawString
int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
    int enclen;
    int n, nwritten = 0;

    /* Try integer encoding 
     *
     * 尝试进行整数值编码
     */
    if (len <= 11) {
        unsigned char buf[5];
        if ((enclen = rdbTryIntegerEncoding((char*)s,len,buf)) > 0) {
            // 整数转换成功，写入
            if (rdbWriteRaw(rdb,buf,enclen) == -1) return -1;
            // 返回字节数
            return enclen;
        }
    }

    /* Try LZF compression - under 20 bytes it's unable to compress even
     * aaaaaaaaaaaaaaaaaa so skip it 
     *
     * 如果字符串长度大于 20 ，并且服务器开启了 LZF 压缩，
     * 那么在保存字符串到数据库之前，先对字符串进行 LZF 压缩。
     */
    if (server.rdb_compression && len > 20) {

        // 尝试压缩
        n = rdbSaveLzfStringObject(rdb,s,len);

        if (n == -1) return -1;
        if (n > 0) return n;
        /* Return value of 0 means data can't be compressed, save the old way */
    }

    // 执行到这里，说明值 s 既不能编码为整数
    // 也不能被压缩
    // 那么直接将它写入到 rdb 中
    /* Store verbatim */

    // 写入长度
    if ((n = rdbSaveLen(rdb,len)) == -1) return -1;
    nwritten += n;

    // 写入内容
    if (len > 0) {
        if (rdbWriteRaw(rdb,s,len) == -1) return -1;
        nwritten += len;
    }

    return nwritten;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r14
cmpq $0xb, %rdx
ja 0x36a9d
leaq 0x3(%rsp), %rdx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x367cc
testl %eax, %eax
je 0x36acc
movl %eax, %ebp
movl %eax, %edx
leaq 0x3(%rsp), %rsi
movq %r14, %rdi
callq 0x361b8
jmp 0x36af2
cmpq $0x15, %rbx
jb 0x36acc
leaq 0x934fe(%rip), %rax     # 0xc9fa8
cmpl $0x0, 0x590(%rax)
je 0x36acc
movq %r14, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x36857
cmpl $-0x1, %eax
je 0x36afa
movl %eax, %ebp
testl %eax, %eax
jg 0x36aff
movq %r14, %rdi
movl %ebx, %esi
callq 0x363a7
cmpl $-0x1, %eax
je 0x36afa
movl %eax, %ebp
testq %rbx, %rbx
je 0x36aff
movq %r14, %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x361b8
addl %ebx, %ebp
cmpl $-0x1, %eax
cmovel %eax, %ebp
jmp 0x36aff
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbSaveLongLongAsStringObject
int rdbSaveLongLongAsStringObject(rio *rdb, long long value) {
    unsigned char buf[32];
    int n, nwritten = 0;

    // 尝试以节省空间的方式编码整数值 value 
    int enclen = rdbEncodeInteger(value,buf);

    // 编码成功，直接写入编码后的缓存
    // 比如，值 1 可以编码为 11 00 0001
    if (enclen > 0) {
        return rdbWriteRaw(rdb,buf,enclen);

    // 编码失败，将整数值转换成对应的字符串来保存
    // 比如，值 999999999 要编码成 "999999999" ，
    // 因为这个值没办法用节省空间的方式编码
    } else {
        /* Encode as string */
        // 转换成字符串表示
        enclen = ll2string((char*)buf,32,value);
        redisAssert(enclen < 32);
        // 写入字符串长度
        if ((n = rdbSaveLen(rdb,enclen)) == -1) return -1;
        nwritten += n;
        // 写入字符串
        if ((n = rdbWriteRaw(rdb,buf,enclen)) == -1) return -1;
        nwritten += n;
    }

    // 返回长度
    return nwritten;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x20, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movq %rsp, %rsi
movq %r14, %rdi
callq 0x365d5
testl %eax, %eax
je 0x36b3a
movl %eax, %edx
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x361b8
movl %eax, %ebp
jmp 0x36b80
movq %rsp, %rdi
movl $0x20, %esi
movq %r14, %rdx
callq 0x300c7
cmpl $0x20, %eax
jge 0x36b8b
movl %eax, %r14d
movq %rbx, %rdi
movl %eax, %esi
callq 0x363a7
cmpl $-0x1, %eax
je 0x36b7b
movl %eax, %ebp
movslq %r14d, %rdx
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x361b8
addl %eax, %ebp
cmpl $-0x1, %eax
cmovel %eax, %ebp
jmp 0x36b80
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl %ebp, %eax
addq $0x20, %rsp
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x61f0c(%rip), %rdi     # 0x98a9e
leaq 0x61eff(%rip), %rsi     # 0x98a98
movl $0x1e0, %edx            # imm = 0x1E0
callq 0x4ca32
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbSaveStringObject
int rdbSaveStringObject(rio *rdb, robj *obj) {

    /* Avoid to decode the object, then encode it again, if the
     * object is already integer encoded. */
    // 尝试对 INT 编码的字符串进行特殊编码
    if (obj->encoding == REDIS_ENCODING_INT) {
        return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr);

    // 保存 STRING 编码的字符串
    } else {
        redisAssertWithInfo(NULL,obj,sdsEncodedObject(obj));
        return rdbSaveRawString(rdb,obj->ptr,sdslen(obj->ptr));
    }
}

// Assembly:
movl (%rsi), %eax
shrl $0x4, %eax
andl $0xf, %eax
je 0x36bca
cmpl $0x8, %eax
je 0x36bca
cmpl $0x1, %eax
jne 0x36bd7
movq 0x8(%rsi), %rsi
jmp 0x36b0c
movq 0x8(%rsi), %rsi
movslq -0x8(%rsi), %rdx
jmp 0x36a60
pushq %rax
leaq 0x61ecb(%rip), %rdx     # 0x98aaa
leaq 0x61eb2(%rip), %rcx     # 0x98a98
xorl %edi, %edi
movl $0x1ff, %r8d            # imm = 0x1FF
callq 0x4d277
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbGenericLoadStringObject
robj *rdbGenericLoadStringObject(rio *rdb, int encode) {
    int isencoded;
    uint32_t len;
    sds val;

    // 长度
    len = rdbLoadLen(rdb,&isencoded);

    // 这是一个特殊编码字符串
    if (isencoded) {

        switch(len) {

        // 整数编码
        case REDIS_RDB_ENC_INT8:
        case REDIS_RDB_ENC_INT16:
        case REDIS_RDB_ENC_INT32:
            return rdbLoadIntegerObject(rdb,len,encode);

        // LZF 压缩
        case REDIS_RDB_ENC_LZF:
            return rdbLoadLzfStringObject(rdb);

        default:
            redisPanic("Unknown RDB encoding type");
        }
    }

    if (len == REDIS_RDB_LENERR) return NULL;

    // 执行到这里，说明这个字符串即没有被压缩，也不是整数
    // 那么直接从 rdb 中读入它
    val = sdsnewlen(NULL,len);
    if (len && rioRead(rdb,val,len) == 0) {
        sdsfree(val);
        return NULL;
    }

    return createObject(REDIS_STRING,val);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %esi, %r14d
movq %rdi, %rbx
leaq 0x4(%rsp), %r15
movq %r15, %rsi
callq 0x3645f
movl %eax, %ebp
cmpl $0x0, (%r15)
je 0x36c3a
cmpl $0x3, %ebp
jae 0x36ca7
movq %rbx, %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0x3663c
jmp 0x36cbd
cmpl $-0x1, %ebp
je 0x36cbb
movl %ebp, %r14d
xorl %edi, %edi
movq %r14, %rsi
callq 0x283f4
movq %rax, %r15
testl %ebp, %ebp
je 0x36c9b
movq %r15, %r12
movq 0x30(%rbx), %rax
cmpq %r14, %rax
movq %r14, %r13
cmovbq %rax, %r13
testq %rax, %rax
cmoveq %r14, %r13
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *(%rbx)
testq %rax, %rax
je 0x36cb3
movq 0x18(%rbx), %rax
testq %rax, %rax
je 0x36c8f
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *%rax
addq %r13, %r12
addq %r13, 0x28(%rbx)
subq %r13, %r14
jne 0x36c56
xorl %edi, %edi
movq %r15, %rsi
callq 0x3059c
jmp 0x36cbd
jne 0x36ccc
movq %rbx, %rdi
callq 0x36934
jmp 0x36cbd
movq %r15, %rdi
callq 0x2850d
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x61ded(%rip), %rdi     # 0x98ac0
leaq 0x61dbe(%rip), %rsi     # 0x98a98
movl $0x221, %edx            # imm = 0x221
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: startLoading
void startLoading(FILE *fp) {
    struct stat sb;

    /* Load the DB */

    // 正在载入
    server.loading = 1;

    // 开始进行载入的时间
    server.loading_start_time = time(NULL);

    // 文件的大小
    if (fstat(fileno(fp), &sb) == -1) {
        server.loading_total_bytes = 1; /* just to avoid division by zero */
    } else {
        server.loading_total_bytes = sb.st_size;
    }
}

// Assembly:
pushq %r14
pushq %rbx
subq $0x98, %rsp
movq %rdi, %rbx
leaq 0x91e2a(%rip), %r14     # 0xc9fa8
movl $0x1, 0x2f0(%r14)
xorl %edi, %edi
callq 0x1fc50
movq %rax, 0x308(%r14)
movq %rbx, %rdi
callq 0x1f070
leaq 0x8(%rsp), %rsi
movl %eax, %edi
callq 0x1f690
movl $0x1, %ecx
cmpl $-0x1, %eax
je 0x381ba
movq 0x38(%rsp), %rcx
movq %rcx, 0x2f8(%r14)
addq $0x98, %rsp
popq %rbx
popq %r14
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: rdbLoadProgressCallback
void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
    if (server.rdb_checksum)
        rioGenericUpdateChecksum(r, buf, len);
    if (server.loading_process_events_interval_bytes &&
        (r->processed_bytes + len)/server.loading_process_events_interval_bytes > r->processed_bytes/server.loading_process_events_interval_bytes)
    {
        /* The DB can take some non trivial amount of time to load. Update
         * our cached time since it is used to create and update the last
         * interaction time with clients and for other important things. */
        updateCachedTime();
        if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER)
            replicationSendNewlineToMaster();
        loadingProgress(r->processed_bytes);
        processEventsWhileBlocked();
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdx, %r14
movq %rdi, %rbx
leaq 0x91d81(%rip), %r15     # 0xc9fa8
cmpl $0x0, 0x594(%r15)
je 0x3823c
movq %rbx, %rdi
movq %r14, %rdx
callq 0x588d5
movq 0x310(%r15), %rdi
testq %rdi, %rdi
je 0x38298
movq 0x28(%rbx), %rcx
addq %rcx, %r14
movq %r14, %rax
xorl %edx, %edx
divq %rdi
movq %rax, %rsi
movq %rcx, %rax
xorl %edx, %edx
divq %rdi
cmpq %rax, %rsi
jbe 0x38298
callq 0x23e34
cmpq $0x0, 0x650(%r15)
je 0x38285
cmpl $0x4, 0x674(%r15)
jne 0x38285
callq 0x34839
movq 0x28(%rbx), %rdi
callq 0x381cc
popq %rbx
popq %r14
popq %r15
jmp 0x2fc38
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: backgroundSaveDoneHandler
void backgroundSaveDoneHandler(int exitcode, int bysignal) {

    // BGSAVE 成功
    if (!bysignal && exitcode == 0) {
        redisLog(REDIS_NOTICE,
            "Background saving terminated with success");
        server.dirty = server.dirty - server.dirty_before_bgsave;
        server.lastsave = time(NULL);
        server.lastbgsave_status = REDIS_OK;

    // BGSAVE 出错
    } else if (!bysignal && exitcode != 0) {
        redisLog(REDIS_WARNING, "Background saving error");
        server.lastbgsave_status = REDIS_ERR;

    // BGSAVE 被中断
    } else {
        redisLog(REDIS_WARNING,
            "Background saving terminated by signal %d", bysignal);
        // 移除临时文件
        rdbRemoveTempFile(server.rdb_child_pid);
        /* SIGUSR1 is whitelisted, so we have a way to kill a child without
         * tirggering an error conditon. */
        if (bysignal != SIGUSR1)
            server.lastbgsave_status = REDIS_ERR;
    }

    // 更新服务器状态
    server.rdb_child_pid = -1;
    server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start;
    server.rdb_save_time_start = -1;

    /* Possibly there are slaves waiting for a BGSAVE in order to be served
     * (the first stage of SYNC is a bulk transfer of dump.rdb) */
    // 处理正在等待 BGSAVE 完成的那些 slave
    updateSlavesWaitingBgsave(exitcode == 0 ? REDIS_OK : REDIS_ERR);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movl %edi, %ebx
movl %esi, %eax
orl %edi, %eax
je 0x386bb
movl %esi, %ebp
testl %esi, %esi
setne %al
testl %ebx, %ebx
sete %cl
orb %al, %cl
jne 0x386f6
leaq 0x60785(%rip), %rsi     # 0x98e29
movl $0x3, %edi
xorl %eax, %eax
callq 0x23223
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
jmp 0x38744
leaq 0x6073d(%rip), %rsi     # 0x98dff
xorl %r14d, %r14d
movl $0x2, %edi
xorl %eax, %eax
callq 0x23223
leaq 0x918d0(%rip), %r15     # 0xc9fa8
movq 0x568(%r15), %rax
subq %rax, 0x560(%r15)
xorl %edi, %edi
callq 0x1fc50
movq %rax, 0x598(%r15)
jmp 0x38744
leaq 0x60744(%rip), %rsi     # 0x98e41
movl $0x3, %edi
movl %ebp, %edx
xorl %eax, %eax
callq 0x23223
leaq 0x91896(%rip), %rax     # 0xc9fa8
movl 0x570(%rax), %ecx
leaq 0x60412(%rip), %rdx     # 0x98b31
movq %rsp, %r14
movl $0x100, %esi            # imm = 0x100
movq %r14, %rdi
xorl %eax, %eax
callq 0x1f120
movq %r14, %rdi
callq 0x1f3a0
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
cmpl $0xa, %ebp
je 0x38752
leaq 0x9185d(%rip), %rax     # 0xc9fa8
movl %r14d, 0x5b8(%rax)
leaq 0x9184f(%rip), %r15     # 0xc9fa8
movl $0xffffffff, 0x570(%r15) # imm = 0xFFFFFFFF
xorl %r14d, %r14d
xorl %edi, %edi
callq 0x1fc50
subq 0x5b0(%r15), %rax
movq %rax, 0x5a8(%r15)
movq $-0x1, 0x5b0(%r15)
negl %ebx
sbbl %r14d, %r14d
movl %r14d, %edi
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x34599
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: saveCommand
void saveCommand(redisClient *c) {

    // BGSAVE 已经在执行中，不能再执行 SAVE
    // 否则将产生竞争条件
    if (server.rdb_child_pid != -1) {
        addReplyError(c,"Background save already in progress");
        return;
    }

    // 执行 
    if (rdbSave(server.rdb_filename) == REDIS_OK) {
        addReply(c,shared.ok);
    } else {
        addReply(c,shared.err);
    }
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
leaq 0x917fc(%rip), %rax     # 0xc9fa8
cmpl $-0x1, 0x570(%rax)
je 0x387c5
leaq 0x606af(%rip), %rsi     # 0x98e6b
movq %rbx, %rdi
popq %rbx
jmp 0x2dc63
movq 0x588(%rax), %rdi
callq 0x37460
testl %eax, %eax
je 0x387e2
leaq 0x92024(%rip), %rax     # 0xca800
movq 0x10(%rax), %rsi
jmp 0x387ed
leaq 0x92017(%rip), %rax     # 0xca800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2d97c
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/rdb.c
// Function: bgsaveCommand
void bgsaveCommand(redisClient *c) {

    // 不能重复执行 BGSAVE
    if (server.rdb_child_pid != -1) {
        addReplyError(c,"Background save already in progress");

    // 不能在 BGREWRITEAOF 正在运行时执行
    } else if (server.aof_child_pid != -1) {
        addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");

    // 执行 BGSAVE
    } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {
        addReplyStatus(c,"Background saving started");

    } else {
        addReply(c,shared.err);
    }
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
leaq 0x917a7(%rip), %rax     # 0xc9fa8
cmpl $-0x1, 0x570(%rax)
je 0x38813
leaq 0x6065a(%rip), %rsi     # 0x98e6b
jmp 0x38823
cmpl $-0x1, 0x504(%rax)
je 0x3882c
leaq 0x6066c(%rip), %rsi     # 0x98e8f
movq %rbx, %rdi
popq %rbx
jmp 0x2dc63
movq 0x588(%rax), %rdi
callq 0x37828
testl %eax, %eax
je 0x38850
leaq 0x91fbd(%rip), %rax     # 0xca800
movq 0x10(%rax), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x2d97c
leaq 0x6066c(%rip), %rsi     # 0x98ec3
movq %rbx, %rdi
popq %rbx
jmp 0x2ddb7
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: getGenericCommand
int getGenericCommand(redisClient *c) {
    robj *o;

    // 尝试从数据库中取出键 c->argv[1] 对应的值对象
    // 如果键不存在时，向客户端发送回复信息，并返回 NULL
    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)
        return REDIS_OK;

    // 值对象存在，检查它的类型
    if (o->type != REDIS_STRING) {
        // 类型错误
        addReply(c,shared.wrongtypeerr);
        return REDIS_ERR;
    } else {
        // 类型正确，向客户端返回对象的值
        addReplyBulk(c,o);
        return REDIS_OK;
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rsi
leaq 0x91b7f(%rip), %r14     # 0xca800
movq 0x50(%r14), %rdx
callq 0x31745
xorl %ebp, %ebp
testq %rax, %rax
je 0x38cb4
testb $0xf, (%rax)
je 0x38ca9
movq 0x70(%r14), %rsi
movq %rbx, %rdi
callq 0x2d97c
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0x38cb4
movq %rbx, %rdi
movq %rax, %rsi
callq 0x2e204
movl %ebp, %eax
popq %rbx
popq %r14
popq %rbp
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: getsetCommand
void getsetCommand(redisClient *c) {

    // 取出并返回键的值对象
    if (getGenericCommand(c) == REDIS_ERR) return;

    // 编码键的新值 c->argv[2]
    c->argv[2] = tryObjectEncoding(c->argv[2]);

    // 将数据库中关联键 c->argv[1] 和新值对象 c->argv[2]
    setKey(c->db,c->argv[1],c->argv[2]);

    // 发送事件通知
    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"set",c->argv[1],c->db->id);

    // 将服务器设为脏
    server.dirty++;
}

// Assembly:
pushq %rbx
movq %rdi, %rbx
callq 0x38c6b
cmpl $-0x1, %eax
je 0x38d26
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rdi
callq 0x30c49
movq 0x38(%rbx), %rcx
movq %rax, 0x10(%rcx)
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq 0x10(%rax), %rdx
callq 0x318fc
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
leaq 0x5c820(%rip), %rsi     # 0x9552e
movl $0x8, %edi
callq 0x60371
leaq 0x91289(%rip), %rax     # 0xc9fa8
incq 0x560(%rax)
popq %rbx
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: getrangeCommand
void getrangeCommand(redisClient *c) {
    robj *o;
    long start, end;
    char *str, llbuf[32];
    size_t strlen;

    // 取出 start 参数
    if (getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != REDIS_OK)
        return;

    // 取出 end 参数
    if (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != REDIS_OK)
        return;

    // 从数据库中查找键 c->argv[1] 
    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptybulk)) == NULL ||
        checkType(c,o,REDIS_STRING)) return;

    // 根据编码，对对象的值进行处理
    if (o->encoding == REDIS_ENCODING_INT) {
        str = llbuf;
        strlen = ll2string(llbuf,sizeof(llbuf),(long)o->ptr);
    } else {
        str = o->ptr;
        strlen = sdslen(str);
    }

    /* Convert negative indexes */
    // 将负数索引转换为整数索引
    if (start < 0) start = strlen+start;
    if (end < 0) end = strlen+end;
    if (start < 0) start = 0;
    if (end < 0) end = 0;
    if ((unsigned)end >= strlen) end = strlen-1;

    /* Precondition: end >= 0 && end < strlen, so the only condition where
     * nothing can be returned is: start > end. */
    if (start > end) {
        // 处理索引范围为空的情况
        addReply(c,shared.emptybulk);
    } else {
        // 向客户端返回给定范围内的字符串内容
        addReplyBulkCBuffer(c,(char*)str+start,end-start+1);
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x30, %rsp
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x10(%rax), %rsi
leaq 0x8(%rsp), %rdx
xorl %ecx, %ecx
callq 0x313b2
testl %eax, %eax
jne 0x38f08
movq 0x38(%rbx), %rax
movq 0x18(%rax), %rsi
movq %rsp, %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
callq 0x313b2
testl %eax, %eax
je 0x38f12
addq $0x30, %rsp
popq %rbx
popq %r14
popq %r15
retq
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
leaq 0x918df(%rip), %r15     # 0xca800
movq 0x18(%r15), %rdx
movq %rbx, %rdi
callq 0x31745
testq %rax, %rax
je 0x38f08
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x30bbf
testl %eax, %eax
jne 0x38f08
movl $0xf0, %eax
andl (%r14), %eax
movq 0x8(%r14), %rdx
cmpl $0x10, %eax
jne 0x38f6e
leaq 0x10(%rsp), %r14
movl $0x20, %esi
movq %r14, %rdi
callq 0x300c7
movq %r14, %rdx
jmp 0x38f71
movl -0x8(%rdx), %eax
movslq %eax, %rsi
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
jns 0x38f86
addq %rsi, %rcx
movq %rcx, 0x8(%rsp)
movq (%rsp), %rax
testq %rax, %rax
jns 0x38f96
addq %rsi, %rax
movq %rax, (%rsp)
testq %rcx, %rcx
jns 0x38fa6
movq $0x0, 0x8(%rsp)
xorl %ecx, %ecx
xorl %edi, %edi
testq %rax, %rax
cmovgq %rax, %rdi
setns %r8b
movl %edi, %r9d
leaq -0x1(%rsi), %rax
cmpq %rsi, %r9
setb %sil
cmovbq %rdi, %rax
testb %sil, %r8b
jne 0x38fce
movq %rax, (%rsp)
subq %rcx, %rax
jge 0x38fe4
movq 0x18(%r15), %rsi
movq %rbx, %rdi
callq 0x2d97c
jmp 0x38f08
addq %rcx, %rdx
incq %rax
movq %rbx, %rdi
movq %rdx, %rsi
movq %rax, %rdx
callq 0x2e237
jmp 0x38f08
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: mgetCommand
void mgetCommand(redisClient *c) {
    int j;

    addReplyMultiBulkLen(c,c->argc-1);
    // 查找并返回所有输入键的值
    for (j = 1; j < c->argc; j++) {
        // 查找键 c->argc[j] 的值
        robj *o = lookupKeyRead(c->db,c->argv[j]);
        if (o == NULL) {
            // 值不存在，向客户端发送空回复
            addReply(c,shared.nullbulk);
        } else {
            if (o->type != REDIS_STRING) {
                // 值存在，但不是字符串类型
                addReply(c,shared.nullbulk);
            } else {
                // 值存在，并且是字符串
                addReplyBulk(c,o);
            }
        }
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
movslq 0x30(%rdi), %rsi
decq %rsi
callq 0x2e168
cmpl $0x2, 0x30(%rbx)
jl 0x39064
movl $0x1, %r14d
leaq 0x917dc(%rip), %r15     # 0xca800
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r14,8), %rsi
callq 0x3163a
testq %rax, %rax
je 0x3903f
testb $0xf, (%rax)
je 0x3904d
movq 0x50(%r15), %rsi
movq %rbx, %rdi
callq 0x2d97c
jmp 0x39058
movq %rbx, %rdi
movq %rax, %rsi
callq 0x2e204
incq %r14
movslq 0x30(%rbx), %rax
cmpq %rax, %r14
jl 0x39024
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: msetGenericCommand
void msetGenericCommand(redisClient *c, int nx) {
    int j, busykeys = 0;

    // 键值参数不是成相成对出现的，格式不正确
    if ((c->argc % 2) == 0) {
        addReplyError(c,"wrong number of arguments for MSET");
        return;
    }
    /* Handle the NX flag. The MSETNX semantic is to return zero and don't
     * set nothing at all if at least one already key exists. */
    // 如果 nx 参数为真，那么检查所有输入键在数据库中是否存在
    // 只要有一个键是存在的，那么就向客户端发送空回复
    // 并放弃执行接下来的设置操作
    if (nx) {
        for (j = 1; j < c->argc; j += 2) {
            if (lookupKeyWrite(c->db,c->argv[j]) != NULL) {
                busykeys++;
            }
        }
        // 键存在
        // 发送空白回复，并放弃执行接下来的设置操作
        if (busykeys) {
            addReply(c, shared.czero);
            return;
        }
    }

    // 设置所有键值对
    for (j = 1; j < c->argc; j += 2) {

        // 对值对象进行解码
        c->argv[j+1] = tryObjectEncoding(c->argv[j+1]);

        // 将键值对关联到数据库
        // c->argc[j] 为键
        // c->argc[j+1] 为值
        setKey(c->db,c->argv[j],c->argv[j+1]);

        // 发送事件通知
        notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"set",c->argv[j],c->db->id);
    }

    // 将服务器设为脏
    server.dirty += (c->argc-1)/2;

    // 设置成功
    // MSET 返回 OK ，而 MSETNX 返回 1
    addReply(c, nx ? shared.cone : shared.ok);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movl 0x30(%rdi), %eax
testb $0x1, %al
jne 0x39094
leaq 0x5fe8f(%rip), %rsi     # 0x98f11
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x2dc63
movl %esi, %ebp
testl %esi, %esi
je 0x390e6
cmpl $0x2, %eax
jl 0x3914d
xorl %r14d, %r14d
movl $0x1, %r15d
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r15,8), %rsi
callq 0x31724
cmpq $0x1, %rax
sbbl $-0x1, %r14d
addq $0x2, %r15
movl 0x30(%rbx), %eax
cmpl %r15d, %eax
jg 0x390ac
testl %r14d, %r14d
je 0x390e6
leaq 0x91723(%rip), %rax     # 0xca800
movq 0x20(%rax), %rsi
jmp 0x39180
cmpl $0x2, %eax
jl 0x3914d
movl $0x1, %r15d
leaq 0x5c436(%rip), %r14     # 0x9552e
movq 0x38(%rbx), %rax
movq 0x8(%rax,%r15,8), %rdi
callq 0x30c49
movq 0x38(%rbx), %rcx
movq %rax, 0x8(%rcx,%r15,8)
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq (%rax,%r15,8), %rsi
movq 0x8(%rax,%r15,8), %rdx
callq 0x318fc
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq (%rcx,%r15,8), %rdx
movl 0x30(%rax), %ecx
movl $0x8, %edi
movq %r14, %rsi
callq 0x60371
addq $0x2, %r15
movl 0x30(%rbx), %eax
cmpl %r15d, %eax
jg 0x390f8
xorl %ecx, %ecx
testl %ebp, %ebp
setne %cl
movl %eax, %edx
decl %edx
shrl $0x1f, %edx
addl %edx, %eax
decl %eax
sarl %eax
cltq
leaq 0x90e3e(%rip), %rdx     # 0xc9fa8
addq %rax, 0x560(%rdx)
leaq 0x91688(%rip), %rax     # 0xca800
shll $0x5, %ecx
movq 0x8(%rax,%rcx), %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x2d97c
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: incrDecrCommand
void incrDecrCommand(redisClient *c, long long incr) {
    long long value, oldvalue;
    robj *o, *new;

    // 取出值对象
    o = lookupKeyWrite(c->db,c->argv[1]);

    // 检查对象是否存在，以及类型是否正确
    if (o != NULL && checkType(c,o,REDIS_STRING)) return;

    // 取出对象的整数值，并保存到 value 参数中
    if (getLongLongFromObjectOrReply(c,o,&value,NULL) != REDIS_OK) return;

    // 检查加法操作执行之后值释放会溢出
    // 如果是的话，就向客户端发送一个出错回复，并放弃设置操作
    oldvalue = value;
    if ((incr < 0 && oldvalue < 0 && incr < (LLONG_MIN-oldvalue)) ||
        (incr > 0 && oldvalue > 0 && incr > (LLONG_MAX-oldvalue))) {
        addReplyError(c,"increment or decrement would overflow");
        return;
    }

    // 进行加法计算，并将值保存到新的值对象中
    // 然后用新的值对象替换原来的值对象
    value += incr;
    new = createStringObjectFromLongLong(value);
    if (o)
        dbOverwrite(c->db,c->argv[1],new);
    else
        dbAdd(c->db,c->argv[1],new);

    // 向数据库发送键被修改的信号
    signalModifiedKey(c->db,c->argv[1]);

    // 发送事件通知
    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"incrby",c->argv[1],c->db->id);

    // 将服务器设为脏
    server.dirty++;

    // 返回回复
    addReply(c,shared.colon);
    addReply(c,new);
    addReply(c,shared.crlf);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rsi, %r15
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x31724
movq %rax, %r14
testq %rax, %rax
je 0x391e0
movq %rbx, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x30bbf
testl %eax, %eax
jne 0x392e5
leaq 0x8(%rsp), %rdx
movq %rbx, %rdi
movq %r14, %rsi
xorl %ecx, %ecx
callq 0x31355
testl %eax, %eax
jne 0x392e5
movabsq $0x7fffffffffffffff, %rax # imm = 0x7FFFFFFFFFFFFFFF
movq 0x8(%rsp), %rdi
subq %rdi, %rax
testq %r15, %r15
jns 0x3921f
testq %rdi, %rdi
jns 0x3921f
leaq 0x1(%rax), %rcx
cmpq %r15, %rcx
jg 0x39239
testq %r15, %r15
setg %cl
testq %rdi, %rdi
setg %dl
andb %cl, %dl
cmpq %r15, %rax
setl %al
andb %dl, %al
cmpb $0x1, %al
jne 0x3924d
leaq 0x5fcf4(%rip), %rsi     # 0x98f34
movq %rbx, %rdi
callq 0x2dc63
jmp 0x392e5
addq %r15, %rdi
movq %rdi, 0x8(%rsp)
callq 0x3069e
movq %rax, %r15
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq %r15, %rdx
testq %r14, %r14
je 0x39278
callq 0x318a1
jmp 0x3927d
callq 0x317f0
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x319b8
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
leaq 0x5b224(%rip), %rsi     # 0x944c8
movl $0x8, %edi
callq 0x60371
leaq 0x90cf3(%rip), %rax     # 0xc9fa8
incq 0x560(%rax)
leaq 0x9153d(%rip), %r14     # 0xca800
movq 0x48(%r14), %rsi
movq %rbx, %rdi
callq 0x2d97c
movq %rbx, %rdi
movq %r15, %rsi
callq 0x2d97c
movq (%r14), %rsi
movq %rbx, %rdi
callq 0x2d97c
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: appendCommand
void appendCommand(redisClient *c) {
    size_t totlen;
    robj *o, *append;

    // 取出键相应的值对象
    o = lookupKeyWrite(c->db,c->argv[1]);
    if (o == NULL) {

        // 键值对不存在。。。

        /* Create the key */
        // 键值对不存在，创建一个新的
        c->argv[2] = tryObjectEncoding(c->argv[2]);
        dbAdd(c->db,c->argv[1],c->argv[2]);
        incrRefCount(c->argv[2]);
        totlen = stringObjectLen(c->argv[2]);
    } else {

        // 键值对存在。。。

        /* Key exists, check type */
        // 检查类型
        if (checkType(c,o,REDIS_STRING))
            return;

        /* "append" is an argument, so always an sds */
        // 检查追加操作之后，字符串的长度是否符合 Redis 的限制
        append = c->argv[2];
        totlen = stringObjectLen(o)+sdslen(append->ptr);
        if (checkStringLength(c,totlen) != REDIS_OK)
            return;

        /* Append the value */
        // 执行追加操作
        o = dbUnshareStringValue(c->db,c->argv[1],o);
        o->ptr = sdscatlen(o->ptr,append->ptr,sdslen(append->ptr));
        totlen = sdslen(o->ptr);
    }

    // 向数据库发送键被修改的信号
    signalModifiedKey(c->db,c->argv[1]);

    // 发送事件通知
    notifyKeyspaceEvent(REDIS_NOTIFY_STRING,"append",c->argv[1],c->db->id);

    // 将服务器设为脏
    server.dirty++;

    // 发送回复
    addReplyLongLong(c,totlen);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
movq 0x8(%rdi), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x31724
testq %rax, %rax
je 0x3952a
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x30bbf
testl %eax, %eax
je 0x39573
popq %rbx
popq %r14
popq %r15
retq
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rdi
callq 0x30c49
movq 0x38(%rbx), %rcx
movq %rax, 0x10(%rcx)
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq 0x10(%rax), %rdx
callq 0x317f0
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rdi
callq 0x306f3
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rdi
callq 0x30f42
movq %rax, %r14
jmp 0x395db
movq 0x38(%rbx), %rax
movq 0x10(%rax), %r15
movq %r14, %rdi
callq 0x30f42
movq 0x8(%r15), %rcx
movslq -0x8(%rcx), %rcx
addq %rax, %rcx
cmpq $0x20000001, %rcx       # imm = 0x20000001
jl 0x395ab
leaq 0x5f9e4(%rip), %rsi     # 0x98f82
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x2dc63
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
movq %r14, %rdx
callq 0x31ac2
movq %rax, %r14
movq 0x8(%rax), %rdi
movq 0x8(%r15), %rsi
movslq -0x8(%rsi), %rdx
callq 0x28689
movq %rax, 0x8(%r14)
movslq -0x8(%rax), %r14
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x319b8
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
leaq 0x5acc1(%rip), %rsi     # 0x942c3
movl $0x8, %edi
callq 0x60371
leaq 0x90995(%rip), %rax     # 0xc9fa8
incq 0x560(%rax)
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x2e133
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_string.c
// Function: strlenCommand
void strlenCommand(redisClient *c) {
    robj *o;

    // 取出值对象，并进行类型检查
    if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
        checkType(c,o,REDIS_STRING)) return;

    // 返回字符串值的长度
    addReplyLongLong(c,stringObjectLen(o));
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rsi
leaq 0x911c0(%rip), %rax     # 0xca800
movq 0x20(%rax), %rdx
callq 0x31745
testq %rax, %rax
je 0x39662
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x30bbf
testl %eax, %eax
je 0x3966a
addq $0x8, %rsp
popq %rbx
popq %r14
retq
movq %r14, %rdi
callq 0x30f42
movq %rbx, %rdi
movq %rax, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2e133
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypeTryConversion
void listTypeTryConversion(robj *subject, robj *value) {

    // 确保 subject 为 ZIPLIST 编码
    if (subject->encoding != REDIS_ENCODING_ZIPLIST) return;

    if (sdsEncodedObject(value) &&
        // 看字符串是否过长
        sdslen(value->ptr) > server.list_max_ziplist_value)
            // 将编码转换为双端链表
            listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
}

// Assembly:
movl $0xf0, %eax
andl (%rdi), %eax
cmpl $0x50, %eax
jne 0x396bb
movl (%rsi), %eax
shrl $0x4, %eax
testb $0x7, %al
jne 0x396bb
movq 0x8(%rsi), %rax
movslq -0x8(%rax), %rax
leaq 0x90900(%rip), %rcx     # 0xc9fa8
cmpq %rax, 0x770(%rcx)
jae 0x396bb
movl $0x4, %esi
jmp 0x396bc
retq
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypeConvert
void listTypeConvert(robj *subject, int enc) {

    listTypeIterator *li;

    listTypeEntry entry;

    redisAssertWithInfo(NULL,subject,subject->type == REDIS_LIST);

    // 转换成双端链表
    if (enc == REDIS_ENCODING_LINKEDLIST) {

        list *l = listCreate();

        listSetFreeMethod(l,decrRefCountVoid);

        /* listTypeGet returns a robj with incremented refcount */
        // 遍历 ziplist ，并将里面的值全部添加到双端链表中
        li = listTypeInitIterator(subject,0,REDIS_TAIL);
        while (listTypeNext(li,&entry)) listAddNodeTail(l,listTypeGet(&entry));
        listTypeReleaseIterator(li);

        // 更新编码
        subject->encoding = REDIS_ENCODING_LINKEDLIST;

        // 释放原来的 ziplist
        zfree(subject->ptr);

        // 更新对象值指针
        subject->ptr = l;

    } else {
        redisPanic("Unsupported list conversion");
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movl (%rdi), %eax
andl $0xf, %eax
cmpl $0x1, %eax
jne 0x39767
cmpl $0x4, %esi
jne 0x39787
callq 0x203fc
movq %rax, %r14
leaq -0x8e8c(%rip), %rax     # 0x30864
movq %rax, 0x18(%r14)
movq %rbx, %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x399c5
movq %rax, %r15
movq %rsp, %rsi
movq %rax, %rdi
callq 0x39a5a
testl %eax, %eax
je 0x3973a
movq %rsp, %r12
movq %r12, %rdi
callq 0x39b0f
movq %r14, %rdi
movq %rax, %rsi
callq 0x204cb
movq %r15, %rdi
movq %r12, %rsi
callq 0x39a5a
testl %eax, %eax
jne 0x39718
movq %r15, %rdi
callq 0x29af7
movl $0xffffff0f, %eax       # imm = 0xFFFFFF0F
andl (%rbx), %eax
orl $0x40, %eax
movl %eax, (%rbx)
movq 0x8(%rbx), %rdi
callq 0x29af7
movq %r14, 0x8(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x5f8a7(%rip), %rdx     # 0x99015
leaq 0x5f839(%rip), %rcx     # 0x98fae
xorl %edi, %edi
movq %rbx, %rsi
movl $0x1c8, %r8d            # imm = 0x1C8
callq 0x4d277
jmp 0x3979f
leaq 0x5f8a3(%rip), %rdi     # 0x99031
leaq 0x5f819(%rip), %rsi     # 0x98fae
movl $0x1e1, %edx            # imm = 0x1E1
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypePush
void listTypePush(robj *subject, robj *value, int where) {

    /* Check if we need to convert the ziplist */
    // 是否需要转换编码？
    listTypeTryConversion(subject,value);

    if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
        ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)
            listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);

    // ZIPLIST
    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
        int pos = (where == REDIS_HEAD) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
        // 取出对象的值，因为 ZIPLIST 只能保存字符串或整数
        value = getDecodedObject(value);
        subject->ptr = ziplistPush(subject->ptr,value->ptr,sdslen(value->ptr),pos);
        decrRefCount(value);

    // 双端链表
    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
        if (where == REDIS_HEAD) {
            listAddNodeHead(subject->ptr,value);
        } else {
            listAddNodeTail(subject->ptr,value);
        }
        incrRefCount(value);

    // 未知编码
    } else {
        redisPanic("Unknown list encoding");
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r14
callq 0x39684
movl $0xf0, %eax
andl (%r14), %eax
cmpl $0x50, %eax
jne 0x397f2
movq 0x8(%r14), %rdi
callq 0x2cc17
movl %eax, %eax
leaq 0x907cc(%rip), %rcx     # 0xc9fa8
cmpq %rax, 0x768(%rcx)
ja 0x397f2
movq %r14, %rdi
movl $0x4, %esi
callq 0x396bc
movl (%r14), %eax
shrl $0x4, %eax
andl $0xf, %eax
cmpl $0x4, %eax
je 0x39842
cmpl $0x5, %eax
jne 0x3986b
xorl %r15d, %r15d
testl %ebp, %ebp
setne %r15b
movq %rbx, %rdi
callq 0x30d93
movq %rax, %rbx
movq 0x8(%r14), %rdi
movq 0x8(%rax), %rsi
movl -0x8(%rsi), %edx
movl %r15d, %ecx
callq 0x2be64
movq %rax, 0x8(%r14)
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x30b0c
movq 0x8(%r14), %rdi
movq %rbx, %rsi
testl %ebp, %ebp
je 0x39854
callq 0x204cb
jmp 0x39859
callq 0x2046c
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x306f3
leaq 0x5f26e(%rip), %rdi     # 0x98ae0
leaq 0x5f735(%rip), %rsi     # 0x98fae
movl $0x69, %edx
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypePop
robj *listTypePop(robj *subject, int where) {

    robj *value = NULL;

    // ZIPLIST
    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *p;
        unsigned char *vstr;
        unsigned int vlen;
        long long vlong;

        // 决定弹出元素的位置
        int pos = (where == REDIS_HEAD) ? 0 : -1;

        p = ziplistIndex(subject->ptr,pos);
        if (ziplistGet(p,&vstr,&vlen,&vlong)) {
            // 为被弹出元素创建对象
            if (vstr) {
                value = createStringObject((char*)vstr,vlen);
            } else {
                value = createStringObjectFromLongLong(vlong);
            }
            /* We only need to delete an element when it exists */
            // 从 ziplist 中删除被弹出元素
            subject->ptr = ziplistDelete(subject->ptr,&p);
        }

    // 双端链表
    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {

        list *list = subject->ptr;

        listNode *ln;

        if (where == REDIS_HEAD) {
            ln = listFirst(list);
        } else {
            ln = listLast(list);
        }

        // 删除被弹出节点
        if (ln != NULL) {
            value = listNodeValue(ln);
            incrRefCount(value);
            listDelNode(list,ln);
        }

    // 未知编码
    } else {
        redisPanic("Unknown list encoding");
    }

    // 返回节点对象
    return value;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x20, %rsp
movq %rdi, %rbx
movl (%rdi), %eax
shrl $0x4, %eax
andl $0xf, %eax
cmpl $0x4, %eax
je 0x398f9
cmpl $0x5, %eax
jne 0x39957
xorl %r14d, %r14d
negl %esi
movl $0x0, %esi
sbbl %esi, %esi
movq 0x8(%rbx), %rdi
callq 0x2c28b
movq %rax, 0x18(%rsp)
leaq 0x10(%rsp), %rsi
leaq 0x4(%rsp), %rdx
leaq 0x8(%rsp), %rcx
movq %rax, %rdi
callq 0x2c5f6
testl %eax, %eax
je 0x3994a
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x3992b
movl 0x4(%rsp), %esi
callq 0x3068f
jmp 0x39935
movq 0x8(%rbx), %rbx
xorl %eax, %eax
testl %esi, %esi
setne %al
movq (%rbx,%rax,8), %r15
testq %r15, %r15
je 0x39926
movq 0x10(%r15), %r14
movq %r14, %rdi
callq 0x306f3
movq %rbx, %rdi
movq %r15, %rsi
callq 0x205b1
jmp 0x3994a
xorl %r14d, %r14d
jmp 0x3994a
movq 0x8(%rsp), %rdi
callq 0x3069e
movq %rax, %r14
movq 0x8(%rbx), %rdi
leaq 0x18(%rsp), %rsi
callq 0x2c713
movq %rax, 0x8(%rbx)
movq %r14, %rax
addq $0x20, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x5f182(%rip), %rdi     # 0x98ae0
leaq 0x5f649(%rip), %rsi     # 0x98fae
movl $0xa7, %edx
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypeLength
unsigned long listTypeLength(robj *subject) {

    // ZIPLIST
    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
        return ziplistLen(subject->ptr);

    // 双端链表
    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
        return listLength((list*)subject->ptr);

    // 未知编码
    } else {
        redisPanic("Unknown list encoding");
    }
}

// Assembly:
pushq %rax
movl (%rdi), %eax
shrl $0x4, %eax
andl $0xf, %eax
cmpl $0x4, %eax
je 0x39999
cmpl $0x5, %eax
jne 0x399a3
movq 0x8(%rdi), %rdi
callq 0x2cc17
movl %eax, %eax
jmp 0x399a1
movq 0x8(%rdi), %rax
movq 0x28(%rax), %rax
popq %rcx
retq
leaq 0x5f136(%rip), %rdi     # 0x98ae0
leaq 0x5f5fd(%rip), %rsi     # 0x98fae
movl $0xbd, %edx
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypeInitIterator
listTypeIterator *listTypeInitIterator(robj *subject, long index, unsigned char direction) {

    listTypeIterator *li = zmalloc(sizeof(listTypeIterator));

    li->subject = subject;

    li->encoding = subject->encoding;

    li->direction = direction;

    // ZIPLIST
    if (li->encoding == REDIS_ENCODING_ZIPLIST) {
        li->zi = ziplistIndex(subject->ptr,index);

    // 双端链表
    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {
        li->ln = listIndex(subject->ptr,index);

    // 未知编码
    } else {
        redisPanic("Unknown list encoding");
    }

    return li;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %r15
movl $0x20, %edi
callq 0x299b5
movq %rax, %rbx
movq %r15, (%rax)
movb (%r15), %al
shrb $0x4, %al
movb %al, 0x8(%rbx)
movb %bpl, 0x9(%rbx)
cmpb $0x4, %al
je 0x39a10
movzbl %al, %eax
cmpl $0x5, %eax
jne 0x39a33
movq 0x8(%r15), %rdi
movl %r14d, %esi
callq 0x2c28b
movl $0x10, %ecx
jmp 0x39a21
movq 0x8(%r15), %rdi
movq %r14, %rsi
callq 0x207b0
movl $0x18, %ecx
movq %rax, (%rbx,%rcx)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5f0a6(%rip), %rdi     # 0x98ae0
leaq 0x5f56d(%rip), %rsi     # 0x98fae
movl $0xdf, %edx
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypeNext
int listTypeNext(listTypeIterator *li, listTypeEntry *entry) {
    /* Protect from converting when iterating */
    redisAssert(li->subject->encoding == li->encoding);

    entry->li = li;

    // 迭代 ZIPLIST
    if (li->encoding == REDIS_ENCODING_ZIPLIST) {

        // 记录当前节点到 entry
        entry->zi = li->zi;

        // 移动迭代器的指针
        if (entry->zi != NULL) {
            if (li->direction == REDIS_TAIL)
                li->zi = ziplistNext(li->subject->ptr,li->zi);
            else
                li->zi = ziplistPrev(li->subject->ptr,li->zi);
            return 1;
        }

    // 迭代双端链表
    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {

        // 记录当前节点到 entry
        entry->ln = li->ln;

        // 移动迭代器的指针
        if (entry->ln != NULL) {
            if (li->direction == REDIS_TAIL)
                li->ln = li->ln->next;
            else
                li->ln = li->ln->prev;
            return 1;
        }

    // 未知编码
    } else {
        redisPanic("Unknown list encoding");
    }

    // 列表元素已经全部迭代完
    return 0;
}

// Assembly:
pushq %rbx
movq (%rdi), %rcx
movl (%rcx), %edx
shrl $0x4, %edx
andl $0xf, %edx
movzbl 0x8(%rdi), %eax
cmpl %eax, %edx
jne 0x39ad3
movq %rdi, %rbx
movq %rdi, (%rsi)
cmpl $0x4, %eax
je 0x39a9f
cmpl $0x5, %eax
jne 0x39aed
movq 0x10(%rbx), %rax
movq %rax, 0x8(%rsi)
testq %rax, %rax
je 0x39abf
cmpb $0x1, 0x9(%rbx)
movq 0x8(%rcx), %rdi
movq %rax, %rsi
jne 0x39ac3
callq 0x2c558
jmp 0x39ac8
movq 0x18(%rbx), %rax
movq %rax, 0x10(%rsi)
testq %rax, %rax
je 0x39abf
xorl %ecx, %ecx
cmpb $0x1, 0x9(%rbx)
sete %cl
movq (%rax,%rcx,8), %rax
movq %rax, 0x18(%rbx)
jmp 0x39acc
xorl %eax, %eax
jmp 0x39ad1
callq 0x2c57e
movq %rax, 0x10(%rbx)
movl $0x1, %eax
popq %rbx
retq
leaq 0x5f4dd(%rip), %rdi     # 0x98fb7
leaq 0x5f4cd(%rip), %rsi     # 0x98fae
movl $0xf7, %edx
callq 0x4ca32
jmp 0x39b05
leaq 0x5efec(%rip), %rdi     # 0x98ae0
leaq 0x5f4b3(%rip), %rsi     # 0x98fae
movl $0x11b, %edx            # imm = 0x11B
callq 0x4cae0
movl $0x1, %edi
callq 0x1f3b0
// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: listTypeGet
robj *listTypeGet(listTypeEntry *entry) {

    listTypeIterator *li = entry->li;

    robj *value = NULL;

    // 根据索引，从 ZIPLIST 中取出节点的值
    if (li->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *vstr;
        unsigned int vlen;
        long long vlong;
        redisAssert(entry->zi != NULL);
        if (ziplistGet(entry->zi,&vstr,&vlen,&vlong)) {
            if (vstr) {
                value = createStringObject((char*)vstr,vlen);
            } else {
                value = createStringObjectFromLongLong(vlong);
            }
        }

    // 从双端链表中取出节点的值
    } else if (li->encoding == REDIS_ENCODING_LINKEDLIST) {
        redisAssert(entry->ln != NULL);
        value = listNodeValue(entry->ln);
        incrRefCount(value);

    } else {
        redisPanic("Unknown list encoding");
    }

    return value;
}

// Assembly:
pushq %rbx
subq $0x20, %rsp
movq (%rdi), %rax
movzbl 0x8(%rax), %eax
cmpl $0x4, %eax
je 0x39b5f
cmpl $0x5, %eax
jne 0x39b90
movq 0x8(%rdi), %rdi
testq %rdi, %rdi
je 0x39bbf
leaq 0x18(%rsp), %rsi
leaq 0xc(%rsp), %rdx
leaq 0x10(%rsp), %rcx
callq 0x2c5f6
testl %eax, %eax
je 0x39b76
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
je 0x39b7a
movl 0xc(%rsp), %esi
callq 0x3068f
jmp 0x39b84
movq 0x10(%rdi), %rax
testq %rax, %rax
je 0x39baa
movq 0x10(%rax), %rbx
movq %rbx, %rdi
callq 0x306f3
jmp 0x39b87
xorl %ebx, %ebx
jmp 0x39b87
movq 0x10(%rsp), %rdi
callq 0x3069e
movq %rax, %rbx
movq %rbx, %rax
addq $0x20, %rsp
popq %rbx
retq
leaq 0x5ef49(%rip), %rdi     # 0x98ae0
leaq 0x5f410(%rip), %rsi     # 0x98fae
movl $0x143, %edx            # imm = 0x143
callq 0x4cae0
jmp 0x39bd7
leaq 0x5f43e(%rip), %rdi     # 0x98fef
leaq 0x5f3f6(%rip), %rsi     # 0x98fae
movl $0x13e, %edx            # imm = 0x13E
jmp 0x39bd2
leaq 0x5f417(%rip), %rdi     # 0x98fdd
leaq 0x5f3e1(%rip), %rsi     # 0x98fae
movl $0x133, %edx            # imm = 0x133
callq 0x4ca32
movl $0x1, %edi
callq 0x1f3b0