// File: /workspace/github_c_makefile_star2_O2/adamjedlicka[P]blu/src/vm/memory.c
// Function: bluGrayObject
void bluGrayObject(bluVM* vm, bluObj* object) {
	if (object == NULL) return;

	if (object->isDark) return;

#ifdef DEBUG_GC_TRACE
	printf("%p gray ", object);
	bluPrintValue(OBJ_VAL(object));
	printf("\n");
#endif

	object->isDark = true;

	bluGrayObject(vm, (bluObj*)object->class);

	switch (object->type) {

	case OBJ_ARRAY: {
		bluObjArray* array = (bluObjArray*)object;
		for (int32_t i = 0; i < array->len; i++) {
			bluGrayValue(vm, array->data[i]);
		}
		break;
	}

	case OBJ_BOUND_METHOD: {
		bluObjBoundMethod* boundMethod = (bluObjBoundMethod*)object;
		bluGrayValue(vm, boundMethod->receiver);
		bluGrayObject(vm, (bluObj*)boundMethod->closure);
		break;
	}

	case OBJ_CLASS: {
		bluObjClass* class = (bluObjClass*)object;
		bluGrayObject(vm, (bluObj*)class->name);
		bluGrayTable(vm, &class->methods);
		bluGrayTable(vm, &class->fields);
		break;
	}

	case OBJ_CLOSURE: {
		bluObjClosure* closure = (bluObjClosure*)object;
		bluGrayObject(vm, (bluObj*)closure->function);
		for (int32_t i = 0; i < closure->upvalues.count; i++) {
			bluGrayObject(vm, &closure->upvalues.data[i]->obj);
		}
		break;
	}

	case OBJ_FUNCTION: {
		bluObjFunction* function = (bluObjFunction*)object;
		bluGrayObject(vm, (bluObj*)function->name);
		bluGrayValueBuffer(vm, &function->chunk.constants);
		break;
	}

	case OBJ_INSTANCE: {
		bluObjInstance* instance = (bluObjInstance*)object;
		bluGrayTable(vm, &instance->fields);
		break;
	}

	case OBJ_NATIVE: {
		break;
	}

	case OBJ_UPVALUE: {
		bluObjUpvalue* upvalue = (bluObjUpvalue*)object;
		bluGrayValue(vm, upvalue->closed);
		break;
	}

	case OBJ_STRING: {
		break;
	}
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x53a5(%rip), %r15      # 0xa75c
testq %rbx, %rbx
je 0x54d7
cmpb $0x0, 0x10(%rbx)
jne 0x54d7
movb $0x1, 0x10(%rbx)
movq 0x8(%rbx), %rsi
movq %r14, %rdi
callq 0x53a2
movl (%rbx), %eax
cmpq $0x8, %rax
ja 0x54d7
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
movl 0x20(%rbx), %esi
movq 0x28(%rbx), %rdx
movq %r14, %rdi
callq 0x5394
movq 0x30(%rbx), %rbx
jmp 0x53b7
movq 0x78(%rbx), %rsi
movq %r14, %rdi
callq 0x53a2
addq $0x68, %rbx
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x5538
addq $0x20, %rbx
jmp 0x544c
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x53a2
leaq 0x30(%rbx), %rsi
movq %r14, %rdi
callq 0x54e3
addq $0x40, %rbx
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x54e3
movl 0x28(%rbx), %esi
movq 0x30(%rbx), %rdx
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x5394
pushq $0x8
popq %r15
xorl %r12d, %r12d
movslq 0x20(%rbx), %rax
cmpq %rax, %r12
jge 0x54d7
movq 0x28(%rbx), %rax
movl -0x8(%rax,%r15), %esi
movq (%rax,%r15), %rdx
movq %r14, %rdi
callq 0x5394
incq %r12
addq $0x10, %r15
jmp 0x5483
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x53a2
xorl %r15d, %r15d
movslq 0x30(%rbx), %rax
cmpq %rax, %r15
jge 0x54d7
movq 0x28(%rbx), %rax
movq (%rax,%r15,8), %rsi
movq %r14, %rdi
callq 0x53a2
incq %r15
jmp 0x54b9
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq