// File: /workspace/github_c_makefile_star2_O1/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
cmpq %rbx, 0x100000(%rbx)
jbe 0x8087
movq %rbx, %r15
movl (%r15), %eax
movsd 0x8(%r15), %xmm0
movsd %xmm0, 0x8(%rsp)
cmpl $0x3, %eax
jne 0x807a
movq 0x8(%rsp), %rsi
movq %rbx, %rdi
callq 0x7d31
addq $0x10, %r15
cmpq 0x100000(%rbx), %r15
jb 0x8059
cmpl $0x0, 0x101808(%rbx)
jle 0x80b8
leaq 0x100008(%rbx), %r15
xorl %r12d, %r12d
movq (%r15), %rsi
movq %rbx, %rdi
callq 0x7d31
incq %r12
movslq 0x101808(%rbx), %rax
addq $0x18, %r15
cmpq %rax, %r12
jl 0x809a
cmpl $0x0, 0x101880(%rbx)
jle 0x80ed
xorl %r15d, %r15d
xorl %r12d, %r12d
movq 0x101878(%rbx), %rax
movq (%rax,%r15), %rsi
movq %rbx, %rdi
callq 0x7d31
incq %r12
movslq 0x101880(%rbx), %rax
addq $0x20, %r15
cmpq %rax, %r12
jl 0x80c7
leaq 0x101810(%rbx), %rsi
movq %rbx, %rdi
callq 0x7eed
movq 0x101870(%rbx), %rsi
movq %rbx, %rdi
callq 0x7d31
cmpl $0x0, 0x101824(%rbx)
js 0x8159
leaq 0x101820(%rbx), %r15
movq $-0x1, %r12
xorl %r13d, %r13d
movq 0x101828(%rbx), %rax
movq (%rax,%r13), %rdx
testq %rdx, %rdx
je 0x8146
cmpb $0x0, 0x10(%rdx)
jne 0x8146
movq %rbx, %rdi
movq %r15, %rsi
callq 0x277a
movslq 0x101824(%rbx), %rax
incq %r12
addq $0x18, %r13
cmpq %rax, %r12
jl 0x8125
movq 0x101888(%rbx), %rsi
testq %rsi, %rsi
je 0x8196
leaq 0x101888(%rbx), %r15
cmpb $0x0, 0x10(%rsi)
je 0x817f
movb $0x0, 0x10(%rsi)
addq $0x18, %rsi
movq %rsi, %r15
jmp 0x818e
movq 0x18(%rsi), %rax
movq %rax, (%r15)
movq %rbx, %rdi
callq 0x8208
movq (%r15), %rsi
testq %rsi, %rsi
jne 0x816c
movq 0x101890(%rbx), %rax
leaq (%rax,%rax), %rcx
movl $0x100000, %edx         # imm = 0x100000
cmpq %rdx, %rax
cmovbq %rdx, %rcx
xorps %xmm0, %xmm0
cvtsi2sd %r14, %xmm0
divsd 0x386b(%rip), %xmm0     # 0xba28
movsd %xmm0, (%rsp)
movq %rcx, 0x101898(%rbx)
movb $0x0, 0x1018a0(%rbx)
callq 0x20c0
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
divsd 0x3843(%rip), %xmm0     # 0xba28
subsd (%rsp), %xmm0
addsd 0x1018a8(%rbx), %xmm0
movsd %xmm0, 0x1018a8(%rbx)
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq