// File: /workspace/github_c_makefile_star2_O2/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 %rbx, %r15
cmpq 0x100000(%rbx), %r15
jae 0x560c
movl (%r15), %esi
movq 0x8(%r15), %rdx
movq %rbx, %rdi
callq 0x5394
addq $0x10, %r15
jmp 0x55ee
leaq 0x100008(%rbx), %r15
xorl %r12d, %r12d
movslq 0x101808(%rbx), %rax
cmpq %rax, %r12
jge 0x5636
movq (%r15), %rsi
movq %rbx, %rdi
callq 0x53a2
incq %r12
addq $0x18, %r15
jmp 0x5616
xorl %r15d, %r15d
xorl %r12d, %r12d
movslq 0x101880(%rbx), %rax
cmpq %rax, %r12
jge 0x5664
movq 0x101878(%rbx), %rax
movq (%rax,%r15), %rsi
movq %rbx, %rdi
callq 0x53a2
incq %r12
addq $0x20, %r15
jmp 0x563c
leaq 0x101810(%rbx), %rsi
movq %rbx, %rdi
callq 0x54e3
movq 0x101870(%rbx), %rsi
movq %rbx, %rdi
callq 0x53a2
leaq 0x101820(%rbx), %r15
xorl %r12d, %r12d
xorl %r13d, %r13d
movslq 0x101824(%rbx), %rax
cmpq %rax, %r13
jg 0x56c5
movq 0x101828(%rbx), %rax
movq (%rax,%r12), %rdx
testq %rdx, %rdx
je 0x56bc
cmpb $0x0, 0x10(%rdx)
jne 0x56bc
movq %rbx, %rdi
movq %r15, %rsi
callq 0x65e3
incq %r13
addq $0x18, %r12
jmp 0x568f
leaq 0x101888(%rbx), %r15
movq (%r15), %rsi
testq %rsi, %rsi
je 0x56f8
cmpb $0x0, 0x10(%rsi)
jne 0x56eb
movq 0x18(%rsi), %rax
movq %rax, (%r15)
movq %rbx, %rdi
callq 0x5766
jmp 0x56cc
movb $0x0, 0x10(%rsi)
addq $0x18, %rsi
movq %rsi, %r15
jmp 0x56cc
movq 0x101890(%rbx), %rax
leaq (%rax,%rax), %rcx
movl $0x100000, %edx         # imm = 0x100000
cmpq %rdx, %rax
cmovbq %rdx, %rcx
cvtsi2sd %r14, %xmm0
divsd 0x4f84(%rip), %xmm0     # 0xa6a0
movsd %xmm0, 0x8(%rsp)
movq %rcx, 0x101898(%rbx)
movb $0x0, 0x1018a0(%rbx)
callq 0x20c0
cvtsi2sd %rax, %xmm0
divsd 0x4f5e(%rip), %xmm0     # 0xa6a0
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