// File: /workspace/github_c_makefile_star2_O0/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 %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
callq 0x10a0
cvtsi2sd %rax, %xmm0
movsd 0x874a(%rip), %xmm1     # 0xf6d8
divsd %xmm1, %xmm0
movsd %xmm0, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq 0x100000(%rcx), %rax
jae 0x6fd1
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rax
movl (%rax), %esi
movq 0x8(%rax), %rdx
callq 0x6b90
movq -0x18(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x18(%rbp)
jmp 0x6f9f
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x101808(%rcx), %eax
jge 0x7013
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
addq $0x100008, %rax         # imm = 0x100008
movslq -0x1c(%rbp), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq (%rax), %rsi
callq 0x6bc0
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x6fd8
movl $0x0, -0x20(%rbp)
movl -0x20(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x101880(%rcx), %eax
jge 0x7056
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x101878(%rax), %rax
movslq -0x20(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq (%rax), %rsi
callq 0x6bc0
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x701a
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rsi
addq $0x101810, %rsi         # imm = 0x101810
callq 0x6db0
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rax
movq 0x101870(%rax), %rsi
callq 0x6bc0
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rsi
addq $0x101820, %rsi         # imm = 0x101820
callq 0x7180
movq -0x8(%rbp), %rax
addq $0x101888, %rax         # imm = 0x101888
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq $0x0, (%rax)
je 0x70fc
movq -0x28(%rbp), %rax
movq (%rax), %rax
testb $0x1, 0x10(%rax)
jne 0x70e0
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x7200
jmp 0x70fa
movq -0x28(%rbp), %rax
movq (%rax), %rax
movb $0x0, 0x10(%rax)
movq -0x28(%rbp), %rax
movq (%rax), %rax
addq $0x18, %rax
movq %rax, -0x28(%rbp)
jmp 0x70a0
movq -0x8(%rbp), %rax
cmpq $0x100000, 0x101890(%rax) # imm = 0x100000
jae 0x7118
movl $0x100000, %eax         # imm = 0x100000
movq %rax, -0x38(%rbp)
jmp 0x712a
movq -0x8(%rbp), %rax
movq 0x101890(%rax), %rax
shlq %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x101898(%rax)
movq -0x8(%rbp), %rax
movb $0x0, 0x1018a0(%rax)
callq 0x10a0
cvtsi2sd %rax, %xmm0
movsd 0x8582(%rip), %xmm1     # 0xf6d8
divsd %xmm1, %xmm0
subsd -0x10(%rbp), %xmm0
movq -0x8(%rbp), %rax
addsd 0x1018a8(%rax), %xmm0
movsd %xmm0, 0x1018a8(%rax)
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax)