// File: /workspace/github_c_makefile_star2_O3/adamjedlicka[P]blu/src/vm/memory.c
// Function: bluCollectGarbage
void bluCollectGarbage(bluVM* vm) {
#ifdef DEBUG_GC_TRACE
	printf("-- gc begin\n");

	size_t before = vm->bytesAllocated;
#endif

	double start = (double)clock() / CLOCKS_PER_SEC;

	for (bluValue* slot = vm->stack; slot < vm->stackTop; slot++) {
		bluGrayValue(vm, *slot);
	}

	for (int32_t i = 0; i < vm->frameCount; i++) {
		bluGrayObject(vm, (bluObj*)vm->frames[i].closure);
	}

	for (int32_t i = 0; i < vm->modules.count; i++) {
		bluGrayObject(vm, (bluObj*)vm->modules.data[i].name);
	}

	bluGrayTable(vm, &vm->globals);

	bluGrayObject(vm, (bluObj*)vm->stringInitializer);

	tableDeleteWhite(vm, &vm->strings);

	// Collect the white objects.
	bluObj** object = &vm->objects;
	while (*object != NULL) {
		if (!((*object)->isDark)) {
			// This object wasn't reached, so remove it from the list and free it.
			bluObj* unreached = *object;
			*object = unreached->next;
			freeObject(vm, unreached);
		} else {
			// This object was reached, so unmark it (for the next GC) and move on to the next.
			(*object)->isDark = false;
			object = &(*object)->next;
		}
	}

	vm->nextGC = vm->bytesAllocated < GC_HEAP_MINIMUM ? GC_HEAP_MINIMUM : vm->bytesAllocated * GC_HEAP_GROW_FACTOR;
	vm->shouldGC = false;
	vm->timeGC += ((double)clock() / CLOCKS_PER_SEC) - start;

#ifdef DEBUG_GC_TRACE
	printf("-- gc collected %ld bytes (from %ld to %ld) next at %ld\n", before - vm->bytesAllocated, before,
		   vm->bytesAllocated, vm->nextGC);
#endif
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x10, %rsp
movq %rdi, %rbx
callq 0x20c0
movq %rax, %r14
movq 0x100000(%rbx), %rax
cmpq %rbx, %rax
jbe 0x5eaf
movq %rbx, %r15
cmpl $0x3, (%r15)
jne 0x5ea6
movq 0x8(%r15), %rsi
movq %rbx, %rdi
callq 0x5bc2
movq 0x100000(%rbx), %rax
addq $0x10, %r15
cmpq %rax, %r15
jb 0x5e8d
cmpl $0x0, 0x101808(%rbx)
jle 0x5ee0
leaq 0x100008(%rbx), %r15
xorl %r12d, %r12d
movq (%r15), %rsi
movq %rbx, %rdi
callq 0x5bc2
incq %r12
movslq 0x101808(%rbx), %rax
addq $0x18, %r15
cmpq %rax, %r12
jl 0x5ec2
cmpl $0x0, 0x101880(%rbx)
jle 0x5f15
xorl %r15d, %r15d
xorl %r12d, %r12d
movq 0x101878(%rbx), %rax
movq (%rax,%r15), %rsi
movq %rbx, %rdi
callq 0x5bc2
incq %r12
movslq 0x101880(%rbx), %rax
addq $0x20, %r15
cmpq %rax, %r12
jl 0x5eef
leaq 0x101810(%rbx), %rsi
movq %rbx, %rdi
callq 0x5d3f
movq 0x101870(%rbx), %rsi
movq %rbx, %rdi
callq 0x5bc2
movl 0x101824(%rbx), %eax
testl %eax, %eax
js 0x5f84
leaq 0x101820(%rbx), %r15
movq $-0x1, %r12
xorl %r13d, %r13d
movq 0x101828(%rbx), %rcx
movq (%rcx,%r13), %rdx
testq %rdx, %rdx
je 0x5f75
cmpb $0x0, 0x10(%rdx)
jne 0x5f75
movq %rbx, %rdi
movq %r15, %rsi
callq 0x7282
movl 0x101824(%rbx), %eax
movslq %eax, %rcx
incq %r12
addq $0x18, %r13
cmpq %rcx, %r12
jl 0x5f4e
movq 0x101888(%rbx), %rsi
testq %rsi, %rsi
je 0x5fc1
leaq 0x101888(%rbx), %r15
cmpb $0x0, 0x10(%rsi)
je 0x5faa
movb $0x0, 0x10(%rsi)
addq $0x18, %rsi
movq %rsi, %r15
jmp 0x5fb9
movq 0x18(%rsi), %rax
movq %rax, (%r15)
movq %rbx, %rdi
callq 0x6032
movq (%r15), %rsi
testq %rsi, %rsi
jne 0x5f97
movq 0x101890(%rbx), %rax
leaq (%rax,%rax), %rcx
movl $0x100000, %edx         # imm = 0x100000
cmpq %rdx, %rax
cmovbq %rdx, %rcx
cvtsi2sd %r14, %xmm0
divsd 0x46fb(%rip), %xmm0     # 0xa6e0
movsd %xmm0, 0x8(%rsp)
movq %rcx, 0x101898(%rbx)
movb $0x0, 0x1018a0(%rbx)
callq 0x20c0
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
divsd 0x46d2(%rip), %xmm0     # 0xa6e0
subsd 0x8(%rsp), %xmm0
addsd 0x1018a8(%rbx), %xmm0
movsd %xmm0, 0x1018a8(%rbx)
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq