// File: /workspace/github_c_makefile_star2_O3/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 0xe6e3
leaq 0xb0(%r14), %r15
movq 0x50(%r14), %rsi
movq %r15, %rdi
callq 0xe5d8
cmpq %r13, %r12
je 0xe355
movl 0x10(%r12), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0xe34f
movq 0x8(%r12), %rsi
movq %r14, %rdi
callq 0xe41c
movq %rax, 0x8(%r12)
addq $0x18, %r12
jmp 0xe32b
movq 0x90(%r14), %r12
testq %r12, %r12
je 0xe3f3
movzbl 0x19(%r12), %eax
cmpl $0x3, %eax
je 0xe3b0
cmpl $0x2, %eax
jne 0xe3e9
cmpq $0x0, 0x1a(%r12)
je 0xe3e9
leaq 0x3a(%r12), %r13
xorl %ebp, %ebp
movl 0x8(%r13), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0xe3a0
movq (%r13), %rsi
movq %r14, %rdi
callq 0xe41c
movq %rax, (%r13)
incq %rbp
addq $0x20, %r13
cmpq 0x1a(%r12), %rbp
jb 0xe384
jmp 0xe3e9
cmpq $0x0, 0x1a(%r12)
je 0xe3e9
leaq 0x32(%r12), %r13
xorl %ebp, %ebp
movl 0x8(%r13), %eax
andl $-0x2, %eax
cmpl $0x2, %eax
jne 0xe3db
movq (%r13), %rsi
movq %r14, %rdi
callq 0xe41c
movq %rax, (%r13)
incq %rbp
addq $0x18, %r13
cmpq 0x1a(%r12), %rbp
jb 0xe3bf
movq 0x11(%r12), %r12
jmp 0xe35c
testq %rbx, %rbx
je 0xe406
movq (%rbx), %rsi
movq %r14, %rdi
callq 0xe41c
movq %rax, (%rbx)
movq %r15, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xe689