// File: /workspace/github_c_makefile_star2_O3/mflatt[P]gc-demo/gen2space/gen2space.c
// Function: collect_garbage
void collect_garbage()
{
  size_t need_size = space_end - space_start;
  if (need_size < (gen1_space_end - gen1_space_next)) {
    /* Minor collection, since we have room in the gen1 space */
    struct gc_node *alloc_pos;
    alloc_pos = (struct gc_node *)gen1_space_next;

    /* A minor collection (still) relies on having no references from
       old object to new objects; this is not a general-purpose GC. If
       such references were allowed, we'd have to add them as
       roots. */

    is_major = 0;
    copy_from_roots(&alloc_pos);

    /* Record updated allocation pointer */
    gen1_space_next = (uintptr_t)alloc_pos;
  } else {
    /* Major collection; make a space big enough for both the old and
       new generation: */
    size_t new_size = need_size + (gen1_space_next - gen1_space_start);
    if (new_size < (gen1_prev_size * 2))
      new_size = gen1_prev_size * 2;

    struct gc_node *alloc_pos;
    void *new_space = raw_malloc(new_size);
    alloc_pos = (struct gc_node *)new_space;
    
    is_major = 1;
    copy_from_roots(&alloc_pos);

    /* Clean up old space */
    if (gen1_space_start != 0)
      raw_free((void *)gen1_space_start, gen1_space_end - gen1_space_start);

    /* Continue allocating into new old-generation space */
    gen1_space_start = (uintptr_t)new_space;
    gen1_space_end = gen1_space_start + new_size;
    gen1_space_next = (uintptr_t)alloc_pos;

    gen1_prev_size = gen1_space_next - gen1_space_start;
  }

  /* Create a fresh new-generation space: */
  void *new_space = raw_malloc(GEN0_SIZE);

  /* Clean up old new-generation space */
  if (space_start != 0)
    raw_free((void *)space_start, GEN0_SIZE);

  /* Continue allocating into new space */
  space_start = (uintptr_t)new_space;
  space_end = space_start + GEN0_SIZE;
  space_next = space_start;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
leaq 0x2d39(%rip), %r15      # 0x4098
movq (%r15), %rcx
leaq 0x3147(%rip), %r12      # 0x44b0
subq (%r12), %rcx
movq 0x2cf4(%rip), %rdx      # 0x4068
movq 0x2cf5(%rip), %rax      # 0x4070
subq %rax, %rdx
cmpq %rdx, %rcx
jae 0x13a4
movq %rsp, %rbx
movq %rax, (%rbx)
movb $0x0, 0x2ce8(%rip)      # 0x4078
movq %rbx, %rdi
callq 0x14e2
movq (%rbx), %rax
movq %rax, 0x2cce(%rip)      # 0x4070
jmp 0x141d
addq %rcx, %rax
subq 0x2cd2(%rip), %rax      # 0x4080
movq 0x2c8b(%rip), %rbx      # 0x4040
addq %rbx, %rbx
cmpq %rbx, %rax
cmovaq %rax, %rbx
movq %rbx, %rdi
callq 0x1318
movq %rax, %r14
movq %rsp, %rdi
movq %rax, (%rdi)
movb $0x1, 0x2ca1(%rip)      # 0x4078
callq 0x14e2
movq 0x2c9d(%rip), %rdi      # 0x4080
testq %rdi, %rdi
je 0x13f7
movq 0x2c79(%rip), %rsi      # 0x4068
subq %rdi, %rsi
callq 0x1342
movq %r14, 0x2c82(%rip)      # 0x4080
addq %r14, %rbx
movq %rbx, 0x2c60(%rip)      # 0x4068
movq (%rsp), %rax
movq %rax, 0x2c5d(%rip)      # 0x4070
subq %r14, %rax
movq %rax, 0x2c23(%rip)      # 0x4040
movl $0x1000, %edi           # imm = 0x1000
callq 0x1318
movq %rax, %rbx
movq (%r12), %rdi
testq %rdi, %rdi
je 0x143d
movl $0x1000, %esi           # imm = 0x1000
callq 0x1342
movq %rbx, (%r12)
movq %rbx, %rax
addq $0x1000, %rax           # imm = 0x1000
movq %rax, (%r15)
leaq 0x2c3c(%rip), %rax      # 0x4090
movq %rbx, (%rax)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq