// File: /workspace/github_cpp_makefile_star2_O1/dragazo[P]cpp-gc/./GarbageCollection.h
// Function: GC::ptr<derived> GC::adopt<derived, std::default_delete<derived>>(derived*)
[[nodiscard]]
	static ptr<T> adopt(T *obj)
	{
		// -- verification -- //

		// if obj is null, return an null ptr
		if (!obj) return {};

		// und for obj to not be of type T - this is because we need the object's real router functions.
		// otherwise we'd be using the wrong router functions and lead to undefined behavior.
		// if T is polymorphic we can check that now - otherwise is left as undefined behavior.
		#if DRAGAZO_GARBAGE_COLLECT_EXTRA_UND_CHECKS
		
		if constexpr (std::is_polymorphic<T>::value)
		{
			if (typeid(*obj) != typeid(T))
			{
				Deleter()(obj);
				throw std::invalid_argument("UND: obj was pointer to base");
			}
		}

		#endif

		// -- normalize T -- //

		// get the allocator
		typedef checked_aligned_allocator_for<info> allocator_t;

		// -- create the vtable -- //

		// use lambda to conveniently create the set of all router functions for type T
		auto router_set = [](info &handle, auto func) { GC::route(*reinterpret_cast<T*>(handle.obj), func); };

		static const info_vtable _vtable(
			[](info &handle) { Deleter()(reinterpret_cast<T*>(handle.obj)); },
			[](info &handle) { allocator_t::dealloc(&handle); },
			router_set,
			router_set
		);

		// -- create the info object for management -- //

		info *handle;

		// allocate the buffer space for the info object
		try { handle = reinterpret_cast<info*>(allocator_t::alloc(sizeof(info))); }
		// on failure, delete the object and rethrow whatever killed us
		catch (...) { Deleter()(obj); throw; }

		// construct the info object
		new (handle) info(obj, 1, &_vtable);

		// -- do the garbage collection aspects -- //

		// claim its children
		handle->route(GC::router_unroot);

		// create the ptr first - this roots obj
		ptr<T> res(obj, handle, GC::bind_new_obj);

		// begin timed collection (if it's not already)
		GC::start_timed_collect();

		// return the now-initialized ptr
		return res;
	}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
testq %rsi, %rsi
je 0x127ab
movq %rsi, %r14
movq (%rsi), %r15
movq -0x8(%r15), %rax
movq 0x8(%rax), %rdi
leaq 0xf069(%rip), %rax      # 0x21782
cmpq %rax, %rdi
je 0x1273b
cmpb $0x2a, (%rdi)
je 0x127d9
leaq 0xf054(%rip), %rsi      # 0x21782
callq 0x5360
testl %eax, %eax
jne 0x127d9
movb 0x20ea7(%rip), %al      # 0x335e8
testb %al, %al
je 0x12812
movl $0x40, %edi
callq 0x185a6
movq %rax, %r15
movq %r14, (%rax)
movq $0x1, 0x8(%rax)
leaq 0x20e60(%rip), %rax     # 0x335c8
movq %rax, 0x10(%r15)
callq 0x8708
movq %rax, 0x18(%r15)
movq 0x10(%r15), %rax
leaq -0x98ce(%rip), %rsi     # 0x8eb2
movq %r15, %rdi
callq *0x10(%rax)
movq %r14, (%rbx)
leaq 0x8(%rbx), %r12
callq 0x8708
movq %rax, 0x10(%rbx)
movq %rax, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x7ce0
callq 0x8ede
jmp 0x127ca
movq $0x0, (%rbx)
leaq 0x8(%rbx), %r14
callq 0x8708
movq %rax, 0x10(%rbx)
movq %rax, %rdi
movq %r14, %rsi
callq 0x7bd2
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movq %r14, %rdi
callq *0x8(%r15)
movl $0x10, %edi
callq 0x5110
movq %rax, %rbx
leaq 0xee06(%rip), %rsi      # 0x215fa
movq %rax, %rdi
callq 0x5470
movq 0x207cd(%rip), %rsi     # 0x32fd0
movq 0x207b6(%rip), %rdx     # 0x32fc0
movq %rbx, %rdi
callq 0x53f0
callq 0x59dc
jmp 0x12749
movq %rax, %r14
movq %rbx, %rdi
callq 0x51f0
jmp 0x1285b
movq %rax, %r14
movq $0x0, (%rbx)
movq %r12, %rdi
callq 0x186a4
jmp 0x1285b
movq %rax, %rdi
callq 0x50e0
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
callq 0x5370
movq %rax, %r14
callq 0x53d0
movq %r14, %rdi
callq 0x5430
movq %rax, %rdi
callq 0x90ea
nop