// File: /workspace/github_cpp_makefile_star2_O3/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 0x1151d
movq %rsi, %r14
movq (%rsi), %r15
movq -0x8(%r15), %rax
movq 0x8(%rax), %rdi
leaq 0xf2c3(%rip), %rax      # 0x2074e
cmpq %rax, %rdi
je 0x114ad
cmpb $0x2a, (%rdi)
je 0x1154b
leaq 0xf2ae(%rip), %rsi      # 0x2074e
callq 0x4360
testl %eax, %eax
jne 0x1154b
movb 0x20135(%rip), %al      # 0x315e8
testb %al, %al
je 0x11584
movl $0x40, %edi
callq 0x1725a
movq %rax, %r15
movq %r14, (%rax)
movq $0x1, 0x8(%rax)
leaq 0x200ee(%rip), %rax     # 0x315c8
movq %rax, 0x10(%r15)
callq 0x7668
movq %rax, 0x18(%r15)
movq 0x10(%r15), %rax
leaq -0x96fc(%rip), %rsi     # 0x7df6
movq %r15, %rdi
callq *0x10(%rax)
movq %r14, (%rbx)
leaq 0x8(%rbx), %r12
callq 0x7668
movq %rax, 0x10(%rbx)
movq %rax, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x6c4e
callq 0x7e22
jmp 0x1153c
movq $0x0, (%rbx)
leaq 0x8(%rbx), %r14
callq 0x7668
movq %rax, 0x10(%rbx)
movq %rax, %rdi
movq %r14, %rsi
callq 0x6b40
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 0x4110
movq %rax, %rbx
leaq 0xf060(%rip), %rsi      # 0x205c6
movq %rax, %rdi
callq 0x4470
movq 0x1fa5b(%rip), %rsi     # 0x30fd0
movq 0x1fa44(%rip), %rdx     # 0x30fc0
movq %rbx, %rdi
callq 0x43f0
callq 0x49c4
jmp 0x114bb
movq %rax, %r14
movq %rbx, %rdi
callq 0x41f0
jmp 0x115cd
movq %rax, %r14
movq $0x0, (%rbx)
movq %r12, %rdi
callq 0x17352
jmp 0x115cd
movq %rax, %rdi
callq 0x40e0
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
callq 0x4370
movq %rax, %r14
callq 0x43d0
movq %r14, %rdi
callq 0x4430
movq %rax, %rdi
callq 0x8024
nop