// File: /workspace/github_c_makefile_star2_O2/masyagin1998[P]GCI/src/garbage-collector/garbage-collector.c
// Function: run_gc_inner
static void run_gc_inner(garbage_collector_type_t gc, void**ptr)
{
    struct VALUE*stack = (*(gc->stack));
    struct VALUE*stack_top = (*(gc->stack_top));
    
    struct VALUE*val;
    void*unscanned_ptr;

    allocator_clean_pool(&(gc->b));

    /* Cheneys GC from Aho-Ullman. */

    /* 2) for (All o in FROM) NewLocation(o) = NULL; */
    ptrs_map_conf(&(gc->ptrs_map), gc->a.busy_list.count);

    /* 3) unscanned = free = start TO address. */
    /* Nothing to do */

    /* 4-5) for (every link R in root subset) R = LookupNewLocation(r) */
    for (val = stack; val != stack_top; val++) {
        if (val->type == VALUE_TYPE_OBJ) {
            val->obj_val = lookup_new_location(gc, val->obj_val);
        } else if (val->type == VALUE_TYPE_ARR) {
            val->arr_val = lookup_new_location(gc, val->arr_val);
        }
    }

    /* 6-7-8-9-10) */
    unscanned_ptr = gc->b.busy_list.first;
    while (unscanned_ptr != NULL) {
        char*ptr = BLOCK_DATA(unscanned_ptr);
        if (ptr[0] == VALUE_TYPE_OBJ) {
            size_t i;
            struct OBJECT*obj = (struct OBJECT*) (ptr + 1);
            for (i = 0; i < obj->properties_len; i++) {
                if (obj->properties[i].val.type == VALUE_TYPE_OBJ) {
                    obj->properties[i].val.obj_val = lookup_new_location(gc, obj->properties[i].val.obj_val);
                } else if (obj->properties[i].val.type == VALUE_TYPE_ARR) {
                    obj->properties[i].val.arr_val = lookup_new_location(gc, obj->properties[i].val.arr_val);
                }
            }
        } else if (ptr[0] == VALUE_TYPE_ARR) {
            size_t i;
            struct ARRAY*arr = (struct ARRAY*) (ptr + 1);
            for (i = 0; i < arr->len; i++) {
                if (arr->values[i].type == VALUE_TYPE_OBJ) {
                    arr->values[i].obj_val = lookup_new_location(gc, arr->values[i].obj_val);
                } else if (arr->values[i].type == VALUE_TYPE_ARR) {
                    arr->values[i].arr_val = lookup_new_location(gc, arr->values[i].arr_val);
                }
            }
        }
        unscanned_ptr = BLOCK_LIST_NEXT(unscanned_ptr);
    }

    if (ptr != NULL) {
        (*ptr) = lookup_new_location(gc, *ptr);
    }

    ptrs_map_free(&(gc->ptrs_map));
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
movq (%rdi), %rax
movq 0x8(%rdi), %rcx
movq (%rax), %r12
movq (%rcx), %r13
addq $0x60, %rdi
callq 0xcf0c
leaq 0xb0(%r14), %rdi
movq 0x50(%r14), %rsi
movq %rdi, (%rsp)
callq 0xcd44
cmpq %r13, %r12
je 0xcb46
movl 0x10(%r12), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0xcb40
movq 0x8(%r12), %rsi
movq %r14, %rdi
callq 0xcbf5
movq %rax, 0x8(%r12)
addq $0x18, %r12
jmp 0xcb1c
leaq 0x90(%r14), %r12
movq (%r12), %r13
testq %r13, %r13
je 0xcbcb
leaq 0x11(%r13), %r12
movzbl 0x19(%r13), %eax
cmpl $0x3, %eax
je 0xcb9a
cmpl $0x2, %eax
jne 0xcb4d
leaq 0x3a(%r13), %rbp
xorl %r15d, %r15d
cmpq 0x1a(%r13), %r15
jae 0xcb4d
movl 0x8(%rbp), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0xcb91
movq (%rbp), %rsi
movq %r14, %rdi
callq 0xcbf5
movq %rax, (%rbp)
incq %r15
addq $0x20, %rbp
jmp 0xcb70
leaq 0x32(%r13), %rbp
xorl %r15d, %r15d
cmpq 0x1a(%r13), %r15
jae 0xcb4d
movl 0x8(%rbp), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0xcbc2
movq (%rbp), %rsi
movq %r14, %rdi
callq 0xcbf5
movq %rax, (%rbp)
incq %r15
addq $0x18, %rbp
jmp 0xcba1
testq %rbx, %rbx
je 0xcbde
movq (%rbx), %rsi
movq %r14, %rdi
callq 0xcbf5
movq %rax, (%rbx)
movq (%rsp), %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xce3d