// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: pushxGenericCommand
void pushxGenericCommand(redisClient *c, robj *refval, robj *val, int where) {
    robj *subject;
    listTypeIterator *iter;
    listTypeEntry entry;
    int inserted = 0;

    // 取出列表对象
    if ((subject = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
        checkType(c,subject,REDIS_LIST)) return;

    // 执行的是 LINSERT 命令
    if (refval != NULL) {
        /* We're not sure if this value can be inserted yet, but we cannot
         * convert the list inside the iterator. We don't want to loop over
         * the list twice (once to see if the value can be inserted and once
         * to do the actual insert), so we assume this value can be inserted
         * and convert the ziplist to a regular list if necessary. */
        // 看保存值 value 是否需要将列表编码转换为双端链表
        listTypeTryConversion(subject,val);

        /* Seek refval from head to tail */
        // 在列表中查找 refval 对象
        iter = listTypeInitIterator(subject,0,REDIS_TAIL);
        while (listTypeNext(iter,&entry)) {
            if (listTypeEqual(&entry,refval)) {
                // 找到了，将值插入到节点的前面或后面
                listTypeInsert(&entry,val,where);
                inserted = 1;
                break;
            }
        }
        listTypeReleaseIterator(iter);

        if (inserted) {
            /* Check if the length exceeds the ziplist length threshold. */
            // 查看插入之后是否需要将编码转换为双端链表
            if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
                ziplistLen(subject->ptr) > server.list_max_ziplist_entries)
                    listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);

            signalModifiedKey(c->db,c->argv[1]);

            notifyKeyspaceEvent(REDIS_NOTIFY_LIST,"linsert",
                                c->argv[1],c->db->id);
            server.dirty++;
        } else {
            /* Notify client of a failed insert */
            // refval 不存在，插入失败
            addReply(c,shared.cnegone);
            return;
        }

    // 执行的是 LPUSHX 或 RPUSHX 命令
    } else {
        char *event = (where == REDIS_HEAD) ? "lpush" : "rpush";

        listTypePush(subject,val,where);

        signalModifiedKey(c->db,c->argv[1]);

        notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,c->argv[1],c->db->id);

        server.dirty++;
    }

    addReplyLongLong(c,listTypeLength(subject));
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %ecx, %ebp
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rsi
leaq 0x90196(%rip), %rax     # 0xc7800
movq 0x20(%rax), %rdx
callq 0x2f9a9
testq %rax, %rax
je 0x3768d
movq %rax, %r14
pushq $0x1
popq %rdx
movq %rbx, %rdi
movq %rax, %rsi
callq 0x2eec6
testl %eax, %eax
je 0x3769c
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %r12, %r12
je 0x37740
movl %ebp, 0xc(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x36d34
pushq $0x1
popq %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x37058
movq %rax, %r13
leaq 0x10(%rsp), %rbp
movq %r13, %rdi
movq %rbp, %rsi
callq 0x370e4
testl %eax, %eax
je 0x377bb
movq %rbp, %rdi
movq %r12, %rsi
callq 0x3733b
testl %eax, %eax
je 0x376c9
leaq 0x10(%rsp), %rdi
movq %r15, %rsi
movl 0xc(%rsp), %edx
callq 0x37265
movq %r13, %rdi
callq 0x283cd
movl $0xf0, %eax
andl (%r14), %eax
leaq 0x52bbe(%rip), %r12     # 0x8a2d1
cmpl $0x50, %eax
jne 0x37761
movq 0x8(%r14), %rdi
callq 0x2b465
movl %eax, %eax
leaq 0x8f87e(%rip), %rcx     # 0xc6fa8
cmpq %rax, 0x768(%rcx)
jae 0x37761
pushq $0x4
popq %rsi
movq %r14, %rdi
callq 0x36d6a
jmp 0x37761
testl %ebp, %ebp
leaq 0x52b9e(%rip), %rax     # 0x8a2e7
leaq 0x52b6d(%rip), %r12     # 0x8a2bd
cmoveq %rax, %r12
movq %r14, %rdi
movq %r15, %rsi
movl %ebp, %edx
callq 0x36e46
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x2fbc0
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
pushq $0x10
popq %rdi
movq %r12, %rsi
callq 0x5b488
leaq 0x8f815(%rip), %rax     # 0xc6fa8
incq 0x560(%rax)
movq %r14, %rdi
callq 0x3700e
movq %rbx, %rdi
movq %rax, %rsi
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2c794
movq %r13, %rdi
callq 0x283cd
leaq 0x90036(%rip), %rax     # 0xc7800
movq 0x30(%rax), %rsi
movq %rbx, %rdi
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2c10d