// File: /workspace/github_c_makefile_star2_O2/jiribenes[P]scheme/src/vm.c
// Function: mark
static void mark(vm_t *vm, value_t val) {
    if (IS_VAL(val)) {
        return;
    }
    ptrvalue_t *ptr = AS_PTR(val);
    if (ptr == NULL) {
        error_runtime(vm, "|GC: Cannot mark a NULL!");
        return;
    }
    if (ptr->gcmark) {
        return;
    }

    ptr->gcmark = true;

    if (ptr->type == T_CONS) {
        cons_t *cons = (cons_t *) ptr;
        mark(vm, cons->car);
        mark(vm, cons->cdr);
    } else if (ptr->type == T_ENV) {
        env_t *env = (env_t *) ptr;
        mark(vm, env->variables);
        if (!IS_NIL(env->variables)) {
            cons_t *vars = AS_CONS(env->variables);
            while (true) {
                value_t pair = vars->car;
                mark(vm, pair);
                if (IS_NIL(vars->cdr)) {
                    break;
                }
                vars = AS_CONS(vars->cdr);
            }
        }

        if (env->up != NULL) {
            mark(vm, PTR_VAL(env->up));
        }
    } else if (ptr->type == T_PRIMITIVE) {
        primitive_t *prim = (primitive_t *) ptr;
        if (prim->name != NULL) {
            mark(vm, PTR_VAL(prim->name));
        }
    } else if (ptr->type == T_FUNCTION || ptr->type == T_MACRO) {
        function_t *func = (function_t *) ptr;

        if (func->name != NULL) {
            mark(vm, PTR_VAL(func->name));
        }

        mark(vm, func->params);
        mark(vm, func->body);
        mark(vm, PTR_VAL(func->env));
    } else if (ptr->type == T_VECTOR) {
        vector_t *vec = (vector_t *) ptr;

        for (uint32_t i = 0; i < vec->count; i++) {
            mark(vm, vec->data[i]);
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movabsq $-0x4000000000000, %r15 # imm = 0xFFFC000000000000
movabsq $0x7ffc000000000001, %r12 # imm = 0x7FFC000000000001
movabsq $0x3ffffffffffff, %r13  # imm = 0x3FFFFFFFFFFFF
leaq -0x1(%r15), %rbp
cmpq %rbp, %r14
jbe 0x523d
andq %r13, %r14
je 0x51fd
cmpb $0x0, 0x4(%r14)
jne 0x523d
movb $0x1, 0x4(%r14)
movl (%r14), %eax
cmpq $0x7, %rax
ja 0x523d
leaq 0x1936(%rip), %rcx      # 0x6a90
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x10(%r14), %rsi
testq %rsi, %rsi
je 0x5177
orq %r15, %rsi
movq %rbx, %rdi
callq 0x50f1
movq 0x20(%r14), %rsi
movq %rbx, %rdi
callq 0x50f1
movq 0x28(%r14), %rsi
movq %rbx, %rdi
callq 0x50f1
movq 0x18(%r14), %r14
jmp 0x51e0
movq 0x10(%r14), %r14
testq %r14, %r14
jne 0x51e0
jmp 0x523d
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x50f1
movq 0x10(%r14), %r15
cmpq %r12, %r15
je 0x51cd
andq %r13, %r15
movq 0x10(%r15), %rsi
movq %rbx, %rdi
callq 0x50f1
movq 0x18(%r15), %r15
jmp 0x51b3
movq 0x18(%r14), %r14
testq %r14, %r14
movabsq $-0x4000000000000, %r15 # imm = 0xFFFC000000000000
je 0x523d
orq %r15, %r14
jmp 0x5124
movq 0x10(%r14), %rsi
movq %rbx, %rdi
callq 0x50f1
movq 0x18(%r14), %r14
jmp 0x5124
leaq 0x1ac2(%rip), %rsi      # 0x6cc6
movq %rbx, %rdi
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x45ec
xorl %r15d, %r15d
movl 0x14(%r14), %eax
cmpq %rax, %r15
jae 0x523d
movq 0x18(%r14), %rax
movq (%rax,%r15,8), %rsi
movq %rbx, %rdi
callq 0x50f1
incq %r15
jmp 0x521f
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq