// File: 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:
subq $0x98, %rsp
movq %rdi, 0x40(%rsp)
movq %rdi, %rax
movq %rax, 0x48(%rsp)
movq %rdi, 0x90(%rsp)
movq %rsi, 0x88(%rsp)
cmpq $0x0, 0x88(%rsp)
jne 0x25492
movq 0x40(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x418c0
jmp 0x256e0
movq 0x88(%rsp), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, %rax
jne 0x254aa
callq 0x5370
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq -0x8(%rax), %rdi
leaq 0x73e3b(%rip), %rsi     # 0x992f8
callq 0x418f0
testb $0x1, %al
jne 0x254c8
jmp 0x25535
movq 0x88(%rsp), %rsi
leaq 0x87(%rsp), %rdi
callq 0x41920
movl $0x10, %edi
callq 0x5160
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x30(%rsp)
leaq 0x40416(%rip), %rsi     # 0x6590f
callq 0x5590
jmp 0x25500
movq 0x30(%rsp), %rdi
movq 0x74acc(%rip), %rsi     # 0x99fd8
movq 0x74ab5(%rip), %rdx     # 0x99fc8
callq 0x54d0
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x78(%rsp)
movl %eax, 0x74(%rsp)
callq 0x5250
jmp 0x256ed
cmpb $0x0, 0x7514c(%rip)     # 0x9a688
jne 0x255b7
leaq 0x75143(%rip), %rdi     # 0x9a688
callq 0x5540
cmpl $0x0, %eax
je 0x255b7
leaq 0x72(%rsp), %rdi
callq 0x41950
movq %rax, 0x18(%rsp)
leaq 0x71(%rsp), %rdi
callq 0x41960
movq %rax, 0x20(%rsp)
leaq 0x73(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x41970
movq 0x10(%rsp), %rdi
movq %rax, 0x28(%rsp)
callq 0x41980
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
movq 0x28(%rsp), %rcx
movq %rax, %r8
leaq 0x750c4(%rip), %rdi     # 0x9a668
callq 0x39840
jmp 0x255ab
leaq 0x750d6(%rip), %rdi     # 0x9a688
callq 0x51d0
movl $0x40, %edi
callq 0x39890
movq %rax, 0x8(%rsp)
jmp 0x255c8
movq 0x8(%rsp), %rax
movq %rax, 0x68(%rsp)
jmp 0x25643
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x78(%rsp)
movl %eax, 0x74(%rsp)
leaq 0x7509f(%rip), %rdi     # 0x9a688
callq 0x51c0
jmp 0x256ed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x78(%rsp)
movl %eax, 0x74(%rsp)
movq 0x78(%rsp), %rdi
callq 0x5110
movq 0x88(%rsp), %rsi
leaq 0x67(%rsp), %rdi
callq 0x41920
jmp 0x2561f
callq 0x5450
jmp 0x256ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x78(%rsp)
movl %eax, 0x74(%rsp)
callq 0x54b0
jmp 0x2563e
jmp 0x256ed
movq 0x68(%rsp), %rdi
movq 0x88(%rsp), %rsi
leaq 0x75011(%rip), %rcx     # 0x9a668
movl $0x1, %edx
callq 0x39950
movq 0x68(%rsp), %rax
movq %rax, (%rsp)
leaq -0x1c901(%rip), %rsi    # 0x8d70
leaq 0x58(%rsp), %rdi
callq 0x9580
movq (%rsp), %rdi
movq 0x58(%rsp), %rsi
callq 0x9550
movq 0x40(%rsp), %rdi
movb $0x0, 0x57(%rsp)
movq 0x88(%rsp), %rsi
movq 0x68(%rsp), %rdx
callq 0x41990
callq 0x8e10
jmp 0x256ac
movb $0x1, 0x57(%rsp)
testb $0x1, 0x57(%rsp)
jne 0x256de
jmp 0x256d4
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x78(%rsp)
movl %eax, 0x74(%rsp)
callq 0x25740
jmp 0x256ed
movq 0x40(%rsp), %rdi
callq 0x25740
jmp 0x256e0
movq 0x48(%rsp), %rax
addq $0x98, %rsp
retq
movq 0x78(%rsp), %rdi
callq 0x5510
movq %rax, %rdi
callq 0x9480
nop