// File: /workspace/github_c_makefile_star2_O3/janet-lang[P]janet/src/core/gc.c
// Function: janet_sweep
void janet_sweep() {
    JanetGCObject *previous = NULL;
    JanetGCObject *current = janet_vm.weak_blocks;
    JanetGCObject *next;

    /* Sweep weak heap to drop weak refs */
    while (NULL != current) {
        next = current->data.next;
        if (current->flags & (JANET_MEM_REACHABLE | JANET_MEM_DISABLED)) {
            /* Check for dead references */
            enum JanetMemoryType type = janet_gc_type(current);
            if (type == JANET_MEMORY_ARRAY_WEAK) {
                JanetArray *array = (JanetArray *) current;
                for (uint32_t i = 0; i < (uint32_t) array->count; i++) {
                    if (!janet_check_liveref(array->data[i])) {
                        array->data[i] = janet_wrap_nil();
                    }
                }
            } else {
                JanetTable *table = (JanetTable *) current;
                int check_values = (type == JANET_MEMORY_TABLE_WEAKV) || (type == JANET_MEMORY_TABLE_WEAKKV);
                int check_keys = (type == JANET_MEMORY_TABLE_WEAKK) || (type == JANET_MEMORY_TABLE_WEAKKV);
                JanetKV *end = table->data + table->capacity;
                JanetKV *kvs = table->data;
                while (kvs < end) {
                    int drop = 0;
                    if (check_keys && !janet_check_liveref(kvs->key)) drop = 1;
                    if (check_values && !janet_check_liveref(kvs->value)) drop = 1;
                    if (drop) {
                        /* Inlined from janet_table_remove without search */
                        table->count--;
                        table->deleted++;
                        kvs->key = janet_wrap_nil();
                        kvs->value = janet_wrap_false();
                    }
                    kvs++;
                }
            }
        }
        current = next;
    }

    /* Sweep weak heap to free blocks */
    previous = NULL;
    current = janet_vm.weak_blocks;
    while (NULL != current) {
        next = current->data.next;
        if (current->flags & (JANET_MEM_REACHABLE | JANET_MEM_DISABLED)) {
            previous = current;
            current->flags &= ~JANET_MEM_REACHABLE;
        } else {
            janet_vm.block_count--;
            janet_deinit_block(current);
            if (NULL != previous) {
                previous->data.next = next;
            } else {
                janet_vm.weak_blocks = next;
            }
            janet_free(current);
        }
        current = next;
    }

    /* Sweep main heap to free blocks */
    previous = NULL;
    current = janet_vm.blocks;
    while (NULL != current) {
        next = current->data.next;
        if (current->flags & (JANET_MEM_REACHABLE | JANET_MEM_DISABLED)) {
            previous = current;
            current->flags &= ~JANET_MEM_REACHABLE;
        } else {
            janet_vm.block_count--;
            janet_deinit_block(current);
            if (NULL != previous) {
                previous->data.next = next;
            } else {
                janet_vm.blocks = next;
            }
            janet_free(current);
        }
        current = next;
    }

#ifdef JANET_EV
    /* Sweep threaded abstract types for references to decrement */
    JanetKV *items = janet_vm.threaded_abstracts.data;
    for (int32_t i = 0; i < janet_vm.threaded_abstracts.capacity; i++) {
        if (janet_checktype(items[i].key, JANET_ABSTRACT)) {

            /* If item was not visited during the mark phase, then this
             * abstract type isn't present in the heap and needs its refcount
             * decremented, and shouuld be removed from table. If the refcount is
             * then 0, the item will be collected. This ensures that only one interpreter
             * will clean up the threaded abstract. */

            /* If not visited... */
            if (!janet_truthy(items[i].value)) {
                void *abst = janet_unwrap_abstract(items[i].key);
                if (0 == janet_abstract_decref(abst)) {
                    /* Run finalizer */
                    JanetAbstractHead *head = janet_abstract_head(abst);
                    if (head->type->gc) {
                        janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
                    }
                    /* Free memory */
                    janet_free(janet_abstract_head(abst));
                }

                /* Mark as tombstone in place */
                items[i].key = janet_wrap_nil();
                items[i].value = janet_wrap_false();
                janet_vm.threaded_abstracts.deleted++;
                janet_vm.threaded_abstracts.count--;
            }

            /* Reset for next sweep */
            items[i].value = janet_wrap_false();
        }
    }
#endif
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %fs:0x0, %rax
leaq -0x348(%rax), %rax
movq %rax, -0x38(%rbp)
movq 0x98(%rax), %r12
testq %r12, %r12
je 0x2b377
movq -0x38(%rbp), %rax
addq $0x98, %rax
movq %rax, -0x48(%rbp)
movq 0x8(%r12), %rax
movq %rax, -0x50(%rbp)
movl (%r12), %ebx
testl $0x300, %ebx            # imm = 0x300
je 0x2b30d
movzbl %bl, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x11, %eax
jne 0x2b26e
cmpl $0x0, 0x10(%r12)
je 0x2b30d
xorl %ebx, %ebx
movq 0x18(%r12), %rax
movq (%rax,%rbx,8), %rdi
callq 0x2b525
testl %eax, %eax
jne 0x2b25c
movq 0x18(%r12), %r14
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4ece6
movq %rax, (%r14,%rbx,8)
incq %rbx
movl 0x10(%r12), %eax
cmpq %rax, %rbx
jb 0x2b232
jmp 0x2b30d
movslq 0x14(%r12), %r14
testq %r14, %r14
jle 0x2b30d
addl $-0xf, -0x2c(%rbp)
movq 0x20(%r12), %r13
shlq $0x4, %r14
addq %r13, %r14
movzbl %bl, %eax
movl %eax, -0x3c(%rbp)
cmpb $0x10, %bl
je 0x2b29d
cmpl $0xe, -0x3c(%rbp)
jne 0x2b2b8
movq (%r13), %rdi
callq 0x2b525
testl %eax, %eax
setne %r15b
cmpl $0x2, -0x2c(%rbp)
jb 0x2b2c1
testl %eax, %eax
jne 0x2b304
jmp 0x2b2d4
movb $0x1, %r15b
cmpl $0x1, -0x2c(%rbp)
ja 0x2b304
movq 0x8(%r13), %rdi
callq 0x2b525
testl %eax, %eax
setne %al
testb %r15b, %al
jne 0x2b304
decl 0x10(%r12)
incl 0x18(%r12)
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4ece6
movq %rax, (%r13)
movabsq $-0x7000000000000, %rdi # imm = 0xFFF9000000000000
callq 0x4ece6
movq %rax, 0x8(%r13)
addq $0x10, %r13
cmpq %r14, %r13
jb 0x2b292
movq -0x50(%rbp), %r12
testq %r12, %r12
jne 0x2b200
movq -0x48(%rbp), %r15
movq (%r15), %r12
testq %r12, %r12
je 0x2b377
xorl %ebx, %ebx
movq 0x8(%r12), %r14
movl (%r12), %eax
testl $0x300, %eax            # imm = 0x300
je 0x2b346
andl $0xfffffeff, %eax       # imm = 0xFFFFFEFF
movl %eax, (%r12)
movq %r12, %rbx
jmp 0x2b36f
movq -0x38(%rbp), %rax
decq 0xb0(%rax)
movq %r12, %rdi
callq 0x2b58f
leaq 0x8(%rbx), %rax
testq %rbx, %rbx
cmoveq %r15, %rax
movq %r14, (%rax)
movq %r12, %rdi
callq 0x120b0
movq %r14, %r12
testq %r14, %r14
jne 0x2b328
movq -0x38(%rbp), %rax
movq 0x90(%rax), %r12
testq %r12, %r12
je 0x2b3e4
movq -0x38(%rbp), %rbx
addq $0x90, %rbx
xorl %r14d, %r14d
movq 0x8(%r12), %r15
movl (%r12), %eax
testl $0x300, %eax            # imm = 0x300
je 0x2b3b3
andl $0xfffffeff, %eax       # imm = 0xFFFFFEFF
movl %eax, (%r12)
movq %r12, %r14
jmp 0x2b3dc
movq -0x38(%rbp), %rax
decq 0xb0(%rax)
movq %r12, %rdi
callq 0x2b58f
leaq 0x8(%r14), %rax
testq %r14, %r14
cmoveq %rbx, %rax
movq %r15, (%rax)
movq %r12, %rdi
callq 0x120b0
movq %r15, %r12
testq %r15, %r15
jne 0x2b395
movq -0x38(%rbp), %r14
movl 0x27c(%r14), %eax
testl %eax, %eax
jle 0x2b511
movq 0x288(%r14), %r13
movabsq $-0x800000000000, %rbx  # imm = 0xFFFF800000000000
addq $0x8, %r13
xorl %r15d, %r15d
movabsq $-0x1000000000000, %r12 # imm = 0xFFFF000000000000
movq -0x8(%r13), %rdi
movq %rdi, %rcx
andq %rbx, %rcx
cmpq %r12, %rcx
jne 0x2b4fe
movq (%r13), %rax
movq %rax, %rcx
andq %rbx, %rcx
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
cmpq %rdx, %rcx
je 0x2b460
movabsq $-0x7000000000000, %rdx # imm = 0xFFF9000000000000
cmpq %rdx, %rcx
jne 0x2b4e4
testb $0x1, %al
jne 0x2b4e4
movq %r12, %rbx
callq 0x4ebc4
movq %rax, %r12
movq %rax, %rdi
callq 0x14681
testl %eax, %eax
jne 0x2b4a3
movq -0x10(%r12), %rax
movq 0x8(%rax), %rax
testq %rax, %rax
je 0x2b497
movq -0x8(%r12), %rsi
movq %r12, %rdi
callq *%rax
testl %eax, %eax
jne 0x2b520
addq $-0x20, %r12
movq %r12, %rdi
callq 0x120b0
movabsq $-0x77fffffffffff, %rdi # imm = 0xFFF8800000000001
callq 0x4ece6
movq %rax, -0x8(%r13)
movabsq $-0x7000000000000, %rdi # imm = 0xFFF9000000000000
callq 0x4ece6
movq %rax, (%r13)
incl 0x280(%r14)
decl 0x278(%r14)
movq %rbx, %r12
movabsq $-0x800000000000, %rbx  # imm = 0xFFFF800000000000
movabsq $-0x7000000000000, %rdi # imm = 0xFFF9000000000000
callq 0x4ece6
movq %rax, (%r13)
movl 0x27c(%r14), %eax
incq %r15
movslq %eax, %rcx
addq $0x10, %r13
cmpq %rcx, %r15
jl 0x2b419
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x13844