// File: /workspace/github_c_makefile_star2_O3/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 0x4bc5(%rip), %r15      # 0xa79c
testq %rbx, %rbx
je 0x5d33
cmpb $0x0, 0x10(%rbx)
jne 0x5d33
movb $0x1, 0x10(%rbx)
movq 0x8(%rbx), %rsi
movq %r14, %rdi
callq 0x5bc2
movl (%rbx), %eax
cmpl $0x1, %eax
jne 0x5c19
cmpl $0x3, 0x20(%rbx)
jne 0x5c13
movq 0x28(%rbx), %rsi
movq %r14, %rdi
callq 0x5bc2
movq 0x30(%rbx), %rbx
jmp 0x5bd7
cmpl $0x8, %eax
ja 0x5d33
movl %eax, %eax
movslq (%r15,%rax,4), %rax
addq %r15, %rax
jmpq *%rax
cmpl $0x3, 0x28(%rbx)
je 0x5c13
jmp 0x5d33
addq $0x20, %rbx
jmp 0x5cec
movq 0x78(%rbx), %rsi
movq %r14, %rdi
callq 0x5bc2
movl 0x70(%rbx), %eax
testl %eax, %eax
jle 0x5d33
movl $0x8, %r15d
xorl %r12d, %r12d
movq 0x68(%rbx), %rcx
cmpl $0x3, -0x8(%rcx,%r15)
jne 0x5c7c
movq (%rcx,%r15), %rsi
movq %r14, %rdi
callq 0x5bc2
movl 0x70(%rbx), %eax
incq %r12
movslq %eax, %rcx
addq $0x10, %r15
cmpq %rcx, %r12
jl 0x5c61
jmp 0x5d33
movl 0x20(%rbx), %eax
testl %eax, %eax
jle 0x5d33
movl $0x8, %r15d
xorl %r12d, %r12d
movq 0x28(%rbx), %rcx
cmpl $0x3, -0x8(%rcx,%r15)
jne 0x5cbf
movq (%rcx,%r15), %rsi
movq %r14, %rdi
callq 0x5bc2
movl 0x20(%rbx), %eax
incq %r12
movslq %eax, %rcx
addq $0x10, %r15
cmpq %rcx, %r12
jl 0x5ca4
jmp 0x5d33
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x5bc2
leaq 0x30(%rbx), %rsi
movq %r14, %rdi
callq 0x5d3f
addq $0x40, %rbx
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x5d3f
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x5bc2
cmpl $0x0, 0x30(%rbx)
jle 0x5d33
xorl %r15d, %r15d
movq 0x28(%rbx), %rax
movq (%rax,%r15,8), %rsi
movq %r14, %rdi
callq 0x5bc2
incq %r15
movslq 0x30(%rbx), %rax
cmpq %rax, %r15
jl 0x5d17
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq