// File: /workspace/github_cpp_makefile_star2_O2/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 %rbx
movq %rdi, %rbx
testq %rsi, %rsi
je 0xfc08
movq %rsi, %r14
movq (%rsi), %rax
movq -0x8(%rax), %rdi
leaq 0x237b8(%rip), %rsi     # 0x33358
callq 0x170f0
testb %al, %al
jne 0xfc1b
movb 0x24a49(%rip), %al      # 0x345f8
testb %al, %al
je 0xfc54
pushq $0x40
popq %rdi
callq 0x15e54
movq %rax, %r15
movq %r14, (%rax)
movq $0x1, 0x8(%rax)
leaq 0x24a04(%rip), %rax     # 0x345d8
movq %rax, 0x10(%r15)
callq 0x6860
movq %rax, 0x18(%r15)
movq 0x10(%r15), %rax
leaq -0x8cbe(%rip), %rsi     # 0x6f2e
movq %r15, %rdi
callq *0x10(%rax)
movq %r14, (%rbx)
leaq 0x8(%rbx), %rdi
movq %r15, %rsi
callq 0x15f72
callq 0x6f5a
jmp 0xfc12
movq %rbx, %rdi
xorl %esi, %esi
callq 0x170e0
movq %rbx, %rax
popq %rbx
popq %r14
popq %r15
retq
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
pushq $0x10
popq %rdi
callq 0x5140
movq %rax, %rbx
leaq 0xfa55(%rip), %rsi      # 0x1f68b
movq %rax, %rdi
callq 0x5490
movq 0x2438b(%rip), %rsi     # 0x33fd0
movq 0x24374(%rip), %rdx     # 0x33fc0
movq %rbx, %rdi
callq 0x5410
leaq 0x2499d(%rip), %rdi     # 0x345f8
callq 0x5470
testl %eax, %eax
je 0xfbb7
leaq 0x74b3(%rip), %rax      # 0x17122
movq %rax, 0x24962(%rip)     # 0x345d8
leaq 0x74b5(%rip), %rax      # 0x17132
movq %rax, 0x2495c(%rip)     # 0x345e0
leaq 0x74ad(%rip), %rax      # 0x17138
movq %rax, 0x24956(%rip)     # 0x345e8
leaq 0x74a1(%rip), %rax      # 0x1713a
movq %rax, 0x24950(%rip)     # 0x345f0
leaq 0x24951(%rip), %rdi     # 0x345f8
callq 0x51a0
jmp 0xfbb7
movq %rax, %r14
movq %rbx, %rdi
callq 0x5210
jmp 0xfce9
movq %rax, %r14
movq %rbx, %rdi
callq 0xfd16
jmp 0xfce9
movq %rax, %rdi
callq 0x50f0
movq (%r14), %rax
movq %r14, %rdi
callq *0x8(%rax)
callq 0x5390
movq %rax, %r14
callq 0x53f0
movq %r14, %rdi
callq 0x5450
movq %rax, %rdi
callq 0x70ea
nop