LLM4Binary/decompile-bench-makefile huggingface dataset:
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::~disjoint_module()
GC::disjoint_module::~disjoint_module()
{
	// getting here means there's no longer any owning handles for this disjoint module.
	// that means we're about to release control of all our stuff - the only thing that can leak is objects.
	// however we can't perform a collection because this thread no longer as living handle to this module.
	// so all we can do is enforce the fact that there should not be any memory leaks.

	// if we still have objects, bad news - the user probably violated a disjunction barrier
	if (!objs.empty())
	{
		std::cerr << "\n\nYOU MADE A USAGE VIOLATION!!\ndestruction of a disjoint gc module had leftover objects\n\n";
		std::cerr << objs.front() << ' ' << objs.front()->next << '\n' << roots.size() << '\n';
		std::abort();
	}
	// same thing for roots - less important cause this can't leak, but we don't want dangling pointers floating around out there.
	if (!roots.empty())
	{
		std::cerr << "\n\nYOU MADE A USAGE VIOLATION!!\ndestruction of a disjoint gc module had leftover roots\n\n";
		std::cerr << roots.size() << '\n' << *roots.begin() << '\n';
		std::abort();
	}
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
cmpq $0x0, 0x38(%rdi)
jne 0x645c
cmpq $0x0, 0x60(%rbx)
jne 0x64d9
leaq 0x48(%rbx), %r14
leaq 0x1b0(%rbx), %rdi
callq 0x81ae
leaq 0x178(%rbx), %rdi
callq 0x821e
leaq 0x140(%rbx), %rdi
callq 0x821e
leaq 0x108(%rbx), %rdi
callq 0x828e
leaq 0xd0(%rbx), %rdi
callq 0x828e
subq $-0x80, %rbx
movq %rbx, %rdi
callq 0x828e
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x821e
movq 0x2ab8d(%rip), %rdi     # 0x30ff0
leaq 0x18c23(%rip), %rsi     # 0x1f08d
movl $0x59, %edx
callq 0x42e0
movq 0x38(%rbx), %rsi
movq 0x2ab71(%rip), %rdi     # 0x30ff0
callq 0x4210
leaq 0x5(%rsp), %rsi
movb $0x20, (%rsi)
movl $0x1, %edx
movq %rax, %rdi
callq 0x42e0
movq 0x38(%rbx), %rcx
movq 0x38(%rcx), %rsi
movq %rax, %rdi
callq 0x4210
leaq 0x6(%rsp), %rsi
movb $0xa, (%rsi)
movl $0x1, %edx
movq %rax, %rdi
callq 0x42e0
movq 0x60(%rbx), %rsi
movq %rax, %rdi
callq 0x41b0
movq %rax, %rdi
movl $0xa, %esi
callq 0x4300
jmp 0x6533
movq 0x2ab10(%rip), %rdi     # 0x30ff0
leaq 0x18c00(%rip), %rsi     # 0x1f0e7
movl $0x57, %edx
callq 0x42e0
movq 0x60(%rbx), %rsi
movq 0x2aaf4(%rip), %rdi     # 0x30ff0
callq 0x41b0
leaq 0x7(%rsp), %rsi
movb $0xa, (%rsi)
movl $0x1, %edx
movq %rax, %rdi
callq 0x42e0
movq 0x58(%rbx), %rcx
movq 0x8(%rcx), %rsi
movq %rax, %rdi
callq 0x4210
movq %rax, %rdi
movl $0xa, %esi
callq 0x4300
callq 0x4160
movq %rax, %rdi
callq 0x8024
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_create_null(GC::smart_handle&)
void GC::disjoint_module::schedule_handle_create_null(smart_handle &handle)
{
	std::lock_guard<std::mutex> internal_lock(internal_mutex);

	// point it at null
	handle.raw = nullptr;
	
	// root it
	__schedule_handle_root(handle);
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
callq 0x4380
testl %eax, %eax
jne 0x6b74
movq $0x0, (%r14)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6b8e
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x4200
movl %eax, %edi
callq 0x41a0
movq %rax, %r14
movq %rbx, %rdi
callq 0x4200
movq %r14, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::__schedule_handle_root(GC::smart_handle const&)
void GC::disjoint_module::__schedule_handle_root(const smart_handle &handle)
{
	// if there's no collector thread, we MUST apply the change immediately
	if (collector_thread == std::thread::id())
	{
		// if this branch was selected, the caches should be empty
		assert(roots_add_cache.empty());
		assert(roots_remove_cache.empty());

		roots.insert(&handle.raw_handle());
	}
	// otherwise we need to cache the request
	else
	{
		roots_add_cache.insert(&handle.raw);
		roots_remove_cache.erase(&handle.raw); // ensure the sets are disjoint
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rsi, %r14
movq %rdi, %rbx
cmpq $0x0, 0x28(%rdi)
je 0x6bd8
leaq 0x140(%rbx), %rdi
leaq 0x8(%rsp), %rsi
movq %r14, (%rsi)
movq %rsp, %r15
movq %rdi, (%r15)
movq %r15, %rdx
callq 0x8bcc
addq $0x178, %rbx            # imm = 0x178
movq %r14, (%r15)
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x8388
jmp 0x6c06
cmpq $0x0, 0x158(%rbx)
jne 0x6c10
cmpq $0x0, 0x190(%rbx)
jne 0x6c2f
addq $0x48, %rbx
leaq 0x8(%rsp), %rsi
movq %r14, (%rsi)
movq %rsp, %rdx
movq %rbx, (%rdx)
movq %rbx, %rdi
callq 0x8bcc
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x18579(%rip), %rdi     # 0x1f190
leaq 0x18538(%rip), %rsi     # 0x1f156
leaq 0x186c5(%rip), %rcx     # 0x1f2ea
movl $0x274, %edx            # imm = 0x274
callq 0x4190
leaq 0x18572(%rip), %rdi     # 0x1f1a8
leaq 0x18519(%rip), %rsi     # 0x1f156
leaq 0x186a6(%rip), %rcx     # 0x1f2ea
movl $0x275, %edx            # imm = 0x275
callq 0x4190
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_create_bind_new_obj(GC::smart_handle&, GC::info*)
void GC::disjoint_module::schedule_handle_create_bind_new_obj(smart_handle &handle, info *new_obj)
{
	std::lock_guard<std::mutex> internal_lock(internal_mutex);

	// point it at the object
	handle.raw = new_obj;

	// root it
	__schedule_handle_root(handle);

	// -- add the object -- //

	// set its reference count to 1
	new_obj->ref_count = 1;

	// if there's no collector thread, we MUST apply the change immediately
	if (collector_thread == std::thread::id())
	{
		// if this branch was selected, the caches should be empty
		assert(objs_add_cache.empty());

		objs.add(new_obj);
	}
	// otherwise we need to cache the request
	else objs_add_cache.insert(new_obj);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
movq %rdx, (%rsp)
callq 0x4380
testl %eax, %eax
jne 0x6cde
movq %r14, (%r15)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x6b8e
movq $0x1, 0x20(%r14)
cmpq $0x0, 0x28(%rbx)
je 0x6ca3
leaq 0x108(%rbx), %rdi
leaq 0x8(%rsp), %rdx
movq %rdi, (%rdx)
movq %rsp, %rsi
callq 0x8722
jmp 0x6ccc
cmpq $0x0, 0x120(%rbx)
jne 0x6ce5
movq 0x40(%rbx), %rax
movq %rax, 0x30(%r14)
movq $0x0, 0x38(%r14)
testq %rax, %rax
cmoveq %rbx, %rax
movq %r14, 0x38(%rax)
movq %r14, 0x40(%rbx)
movq %rbx, %rdi
callq 0x4200
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
movl %eax, %edi
callq 0x41a0
leaq 0x18453(%rip), %rdi     # 0x1f13f
leaq 0x18463(%rip), %rsi     # 0x1f156
leaq 0x18513(%rip), %rcx     # 0x1f20d
movl $0x1dd, %edx            # imm = 0x1DD
callq 0x4190
movq %rax, %r14
movq %rbx, %rdi
callq 0x4200
movq %r14, %rdi
callq 0x4430
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_create_alias(GC::smart_handle&, GC::smart_handle const&)
void GC::disjoint_module::schedule_handle_create_alias(smart_handle &handle, const smart_handle &src_handle)
{
	std::lock_guard<std::mutex> internal_lock(internal_mutex);

	// get the target
	info *target = __get_current_target(src_handle);

	#if DRAGAZO_GARBAGE_COLLECT_DISJUNCTION_SAFETY_CHECKS

	// if we're going to repoint outside the disjunction of the handle, that's a disjunction violation
	if (target && handle.disjunction != target->disjunction)
	{
		throw GC::disjunction_error("attempt to repoint GC::ptr outside of the current disjunction");
	}

	#endif

	// point it at the source handle's current target
	handle.raw = target;

	// increment the target reference count
	if (handle.raw) ++handle.raw->ref_count;

	// root it
	__schedule_handle_root(handle);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %rbx
callq 0x4380
testl %eax, %eax
jne 0x6d91
leaq 0x1b0(%rbx), %rdi
leaq 0x8(%rsp), %rsi
movq %r15, (%rsi)
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r15, %rcx
movq (%rcx), %rax
testq %rax, %rax
je 0x6d6d
movq 0x8(%r14), %rcx
cmpq 0x18(%rax), %rcx
jne 0x6d98
movq %rax, (%r14)
incq 0x20(%rax)
jmp 0x6d74
movq $0x0, (%r14)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6b8e
movq %rbx, %rdi
callq 0x4200
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
movl %eax, %edi
callq 0x41a0
movl $0x10, %edi
callq 0x4110
movq %rax, %r14
leaq 0x184b7(%rip), %rsi     # 0x1f263
movq %rax, %rdi
callq 0x4460
leaq 0x2956d(%rip), %rax     # 0x30328
movq %rax, (%r14)
leaq 0x2953b(%rip), %rsi     # 0x30300
movq 0x2a1d4(%rip), %rdx     # 0x30fa0
movq %r14, %rdi
callq 0x43f0
movq %rax, %r15
movq %r14, %rdi
callq 0x41f0
jmp 0x6de4
movq %rax, %r15
movq %rbx, %rdi
callq 0x4200
movq %r15, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_destroy(GC::smart_handle const&)
void GC::disjoint_module::schedule_handle_destroy(const smart_handle &handle)
{
	std::unique_lock<std::mutex> internal_lock(internal_mutex);

	// get the old target
	info *old_target = __get_current_target(handle);

	// unroot the handle
	__schedule_handle_unroot(handle);

	// purge the handle from the repoint cache so we don't dereference undefined memory.
	// the const cast is ok because we won't be modifying it - just for lookup.
	handle_repoint_cache.erase(const_cast<info**>(&handle.raw));

	// dec the reference count
	__MUST_BE_LAST_ref_count_dec(old_target, std::move(internal_lock));
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movq %rsp, %r15
movq %rdi, (%r15)
movb $0x0, 0x8(%r15)
movq %r15, %rdi
callq 0x8aa0
movb $0x1, 0x8(%r15)
leaq 0x1b0(%rbx), %r15
leaq 0x10(%rsp), %rsi
movq %r14, (%rsi)
movq %r15, %rdi
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r14, %rcx
movq (%rcx), %r12
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6efa
leaq 0x10(%rsp), %rsi
movq %r14, (%rsi)
movq %r15, %rdi
callq 0x8adc
movq (%rsp), %rax
leaq 0x18(%rsp), %rdx
movq %rax, (%rdx)
movb 0x8(%rsp), %al
movb %al, 0x8(%rdx)
movq $0x0, (%rsp)
movb $0x0, 0x8(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x6faa
leaq 0x18(%rsp), %rdi
callq 0x8030
movq %rsp, %rdi
callq 0x8030
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x8030
jmp 0x6eea
jmp 0x6ee7
movq %rax, %rbx
movq %rsp, %rdi
callq 0x8030
movq %rbx, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::__schedule_handle_unroot(GC::smart_handle const&)
void GC::disjoint_module::__schedule_handle_unroot(const smart_handle &handle)
{
	// if there's no collector thread, we MUST apply the change immediately
	if (collector_thread == std::thread::id())
	{
		// if this branch was selected, the caches should be empty
		assert(roots_add_cache.empty());
		assert(roots_remove_cache.empty());

		roots.erase(&handle.raw);
	}
	// otherwise we need to cache the request
	else
	{
		roots_remove_cache.insert(&handle.raw);
		roots_add_cache.erase(&handle.raw); // ensure the sets are disjoint
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rsi, %r14
movq %rdi, %rbx
cmpq $0x0, 0x28(%rdi)
je 0x6f3c
leaq 0x178(%rbx), %rdi
leaq 0x8(%rsp), %rsi
movq %r14, (%rsi)
movq %rsp, %r15
movq %rdi, (%r15)
movq %r15, %rdx
callq 0x8bcc
addq $0x140, %rbx            # imm = 0x140
movq %r14, (%r15)
movq %rsp, %rsi
jmp 0x6f5a
cmpq $0x0, 0x158(%rbx)
jne 0x6f6c
cmpq $0x0, 0x190(%rbx)
jne 0x6f8b
addq $0x48, %rbx
movq %rsp, %rsi
movq %r14, (%rsi)
movq %rbx, %rdi
callq 0x8388
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x1821d(%rip), %rdi     # 0x1f190
leaq 0x181dc(%rip), %rsi     # 0x1f156
leaq 0x183b0(%rip), %rcx     # 0x1f331
movl $0x286, %edx            # imm = 0x286
callq 0x4190
leaq 0x18216(%rip), %rdi     # 0x1f1a8
leaq 0x181bd(%rip), %rsi     # 0x1f156
leaq 0x18391(%rip), %rcx     # 0x1f331
movl $0x287, %edx            # imm = 0x287
callq 0x4190
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::__MUST_BE_LAST_ref_count_dec(GC::info*, std::unique_lock<std::mutex>)
void GC::disjoint_module::__MUST_BE_LAST_ref_count_dec(info *target, std::unique_lock<std::mutex> internal_lock)
{
	// decrement the reference count
	// if it falls to zero we need to perform ref count deletion logic
	if (target && --target->ref_count == 0)
	{
		// if it's in the obj add cache we can delete it immediately regardless of what's going on.
		// this is because it being in the obj add cache means it's not in the obj list, and is thus not under gc consideration.
		if (objs_add_cache.find(target) != objs_add_cache.end())
		{
			// remove it from the obj add cache
			objs_add_cache.erase(target);

			// unlock the mutex so we can call arbitrary code
			internal_lock.unlock();

			target->destroy();
			target->dealloc();
		}
		// otherwise we know it exists and isn't in the add cache, therefore it's in the obj list.
		// if we're not suppoed to cache ref count deletions, handle it immediately
		else if (!cache_ref_count_del_actions)
		{
			// remove it from the obj list
			objs.remove(target);
			
			// unlock the mutex so we can call arbitrary code
			internal_lock.unlock();

			target->destroy();
			target->dealloc();
		}
		// otherwise we're supposed to cache the ref count deletion action.
		// this also implies we're in a collection action.
		else
		{
			assert(collector_thread != std::thread::id());

			ref_count_del_cache.insert(target);
		}
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
movq %rsi, (%rsp)
testq %rsi, %rsi
je 0x7065
decq 0x20(%rsi)
jne 0x7065
movq %rdx, %rbx
movq %rdi, %r14
leaq 0x108(%rdi), %r15
movq %rsp, %rsi
movq %r15, %rdi
callq 0x8f6e
testq %rax, %rax
je 0x700b
movq %rsp, %r14
movq %r15, %rdi
movq %r14, %rsi
callq 0x89b0
movq %rbx, %rdi
callq 0x8046
movq (%r14), %rdi
movq 0x10(%rdi), %rax
callq *(%rax)
movq (%r14), %rdi
jmp 0x705e
cmpb $0x0, 0xc8(%r14)
je 0x7038
cmpq $0x0, 0x28(%r14)
je 0x706f
addq $0xd0, %r14
leaq 0x8(%rsp), %rdx
movq %r14, (%rdx)
movq %rsp, %rsi
movq %r14, %rdi
callq 0x8722
jmp 0x7065
addq $0x38, %r14
movq (%rsp), %rsi
movq %r14, %rdi
callq 0x634c
movq %rbx, %rdi
callq 0x8046
movq (%rsp), %rdi
movq 0x10(%rdi), %rax
callq *(%rax)
movq (%rsp), %rdi
movq 0x10(%rdi), %rax
callq *0x8(%rax)
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
leaq 0x18354(%rip), %rdi     # 0x1f3ca
leaq 0x180d9(%rip), %rsi     # 0x1f156
leaq 0x1836c(%rip), %rcx     # 0x1f3f0
movl $0x2d1, %edx            # imm = 0x2D1
callq 0x4190
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_repoint_null(GC::smart_handle&)
void GC::disjoint_module::schedule_handle_repoint_null(smart_handle &handle)
{
	std::unique_lock<std::mutex> internal_lock(internal_mutex);

	// get the old target
	info *old_target = __get_current_target(handle);

	// repoint handle to null
	__raw_schedule_handle_repoint(handle, nullptr);

	// decrement old target reference count
	__MUST_BE_LAST_ref_count_dec(old_target, std::move(internal_lock));
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x30, %rsp
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x8(%rsp), %r15
movq %rdi, (%r15)
movb $0x0, 0x8(%r15)
movq %r15, %rdi
callq 0x8aa0
movb $0x1, 0x8(%r15)
leaq 0x1b0(%rbx), %rdi
leaq 0x28(%rsp), %rsi
movq %r14, (%rsi)
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r14, %rcx
movq (%rcx), %r15
movq %rbx, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x719e
movq 0x8(%rsp), %rax
leaq 0x18(%rsp), %rdx
movq %rax, (%rdx)
movb 0x10(%rsp), %al
movb %al, 0x8(%rdx)
movq $0x0, 0x8(%rsp)
movb $0x0, 0x10(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x6faa
leaq 0x18(%rsp), %rdi
callq 0x8030
leaq 0x8(%rsp), %rdi
callq 0x8030
addq $0x30, %rsp
popq %rbx
popq %r14
popq %r15
retq
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x8030
jmp 0x718b
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x8030
movq %rbx, %rdi
callq 0x4430
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::__raw_schedule_handle_repoint(GC::smart_handle&, GC::info*)
void GC::disjoint_module::__raw_schedule_handle_repoint(smart_handle &handle, info *target)
{
	// if there's no collector thread, we MUST apply the change immediately
	if (collector_thread == std::thread::id())
	{
		// if this branch was selected, the caches should be empty
		assert(handle_repoint_cache.empty());

		// immediately repoint handle to target
		handle.raw = target;
	}
	// otherwise we need to cache the request
	else handle_repoint_cache[&handle.raw] = target;
}

// Assembly:
pushq %rbx
subq $0x10, %rsp
movq %rdx, %rbx
cmpq $0x0, 0x28(%rdi)
je 0x71c9
addq $0x1b0, %rdi            # imm = 0x1B0
leaq 0x8(%rsp), %rax
movq %rsi, (%rax)
movq %rax, %rsi
callq 0x8c80
movq %rbx, (%rax)
jmp 0x71d6
cmpq $0x0, 0x1c8(%rdi)
jne 0x71dc
movq %rbx, (%rsi)
addq $0x10, %rsp
popq %rbx
retq
leaq 0x17fe0(%rip), %rdi     # 0x1f1c3
leaq 0x17f6c(%rip), %rsi     # 0x1f156
leaq 0x18189(%rip), %rcx     # 0x1f37a
movl $0x299, %edx            # imm = 0x299
callq 0x4190
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_repoint(GC::smart_handle&, GC::smart_handle const&)
void GC::disjoint_module::schedule_handle_repoint(smart_handle &handle, const smart_handle &new_value)
{
	std::unique_lock<std::mutex> internal_lock(internal_mutex);
	
	// get the old/new targets
	info *old_target = __get_current_target(handle);
	info *new_target = __get_current_target(new_value);

	#if DRAGAZO_GARBAGE_COLLECT_DISJUNCTION_SAFETY_CHECKS

	// if we're going to repoint outside the disjunction of the handle, that's a disjunction violation
	if (new_target && handle.disjunction != new_target->disjunction)
	{
		throw GC::disjunction_error("attempt to repoint GC::ptr outside of the current disjunction");
	}

	#endif

	// only do the remaining logic if it's an actual repoint
	if (old_target != new_target)
	{
		// repoint handle to the new target
		__raw_schedule_handle_repoint(handle, new_target);

		// increment new target reference count
		if (new_target) ++new_target->ref_count;

		// decrement old target reference count
		__MUST_BE_LAST_ref_count_dec(old_target, std::move(internal_lock));
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x30, %rsp
movq %rdx, %r12
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x8(%rsp), %r15
movq %rdi, (%r15)
movb $0x0, 0x8(%r15)
movq %r15, %rdi
callq 0x8aa0
movb $0x1, 0x8(%r15)
leaq 0x1b0(%rbx), %r13
leaq 0x18(%rsp), %rsi
movq %r14, (%rsi)
movq %r13, %rdi
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r14, %rcx
movq (%rcx), %r15
leaq 0x18(%rsp), %rsi
movq %r12, (%rsi)
movq %r13, %rdi
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r12, %rcx
movq (%rcx), %r12
testq %r12, %r12
je 0x727f
movq 0x8(%r14), %rax
cmpq 0x18(%r12), %rax
jne 0x72eb
cmpq %r12, %r15
je 0x72d3
movq %rbx, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x719e
testq %r12, %r12
je 0x729c
incq 0x20(%r12)
movq 0x8(%rsp), %rax
leaq 0x20(%rsp), %rdx
movq %rax, (%rdx)
movb 0x10(%rsp), %al
movb %al, 0x8(%rdx)
movq $0x0, 0x8(%rsp)
movb $0x0, 0x10(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x6faa
leaq 0x20(%rsp), %rdi
callq 0x8030
leaq 0x8(%rsp), %rdi
callq 0x8030
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movl $0x10, %edi
callq 0x4110
movq %rax, %r14
leaq 0x17f64(%rip), %rsi     # 0x1f263
movq %rax, %rdi
callq 0x4460
leaq 0x2901a(%rip), %rax     # 0x30328
movq %rax, (%r14)
leaq 0x28fe8(%rip), %rsi     # 0x30300
movq 0x29c81(%rip), %rdx     # 0x30fa0
movq %r14, %rdi
callq 0x43f0
movq %rax, %rbx
movq %r14, %rdi
callq 0x41f0
jmp 0x7348
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x8030
jmp 0x7348
jmp 0x7345
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x8030
movq %rbx, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::schedule_handle_repoint_swap(GC::smart_handle&, GC::smart_handle&)
void GC::disjoint_module::schedule_handle_repoint_swap(smart_handle &handle_a, smart_handle &handle_b)
{
	std::lock_guard<std::mutex> internal_lock(internal_mutex);

	// get their current repoint targets
	info *target_a = __get_current_target(handle_a);
	info *target_b = __get_current_target(handle_b);

	#if DRAGAZO_GARBAGE_COLLECT_DISJUNCTION_SAFETY_CHECKS

	// if we're going to repoint outside the disjunction of either handle, that's a disjunction violation
	if ((target_b && handle_a.disjunction != target_b->disjunction) || (target_a && handle_b.disjunction != target_a->disjunction))
	{
		throw GC::disjunction_error("attempt to repoint GC::ptr outside of the current disjunction");
	}

	#endif

	// only perform the swap if they point to different things
	if (target_a != target_b)
	{
		// schedule repoint actions to swap them
		__raw_schedule_handle_repoint(handle_a, target_b);
		__raw_schedule_handle_repoint(handle_b, target_a);

		// there's no need for reference counting logic in a swap operation
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x10, %rsp
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
callq 0x4380
testl %eax, %eax
jne 0x744f
leaq 0x1b0(%rbx), %r13
leaq 0x8(%rsp), %rsi
movq %r15, (%rsi)
movq %r13, %rdi
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r15, %rcx
movq (%rcx), %r12
leaq 0x8(%rsp), %rsi
movq %r14, (%rsi)
movq %r13, %rdi
callq 0x8f12
leaq 0x10(%rax), %rcx
testq %rax, %rax
cmoveq %r14, %rcx
movq (%rcx), %rdx
testq %rdx, %rdx
je 0x73cf
movq 0x8(%r15), %rax
cmpq 0x18(%rdx), %rax
jne 0x7413
testq %r12, %r12
je 0x73df
movq 0x8(%r14), %rax
cmpq 0x18(%r12), %rax
jne 0x7413
cmpq %rdx, %r12
je 0x73fd
movq %rbx, %rdi
movq %r15, %rsi
callq 0x719e
movq %rbx, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x719e
movq %rbx, %rdi
callq 0x4200
addq $0x10, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movl $0x10, %edi
callq 0x4110
movq %rax, %r14
leaq 0x17e3c(%rip), %rsi     # 0x1f263
movq %rax, %rdi
callq 0x4460
leaq 0x28ef2(%rip), %rax     # 0x30328
movq %rax, (%r14)
leaq 0x28ec0(%rip), %rsi     # 0x30300
movq 0x29b59(%rip), %rdx     # 0x30fa0
movq %r14, %rdi
callq 0x43f0
movl %eax, %edi
callq 0x41a0
movq %rax, %r15
movq %r14, %rdi
callq 0x41f0
jmp 0x7468
jmp 0x7465
movq %rax, %r15
movq %rbx, %rdi
callq 0x4200
movq %r15, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module::local()
GC::disjoint_module *GC::disjoint_module::local()
{
	// get the local detour
	disjoint_module *detour = local_detour;

	// if we're taking a detour, use that, otherwise the handle is alive and we should read that instead
	return detour ? detour : local_handle().get();
}

// Assembly:
movq 0x29c21(%rip), %rax     # 0x31290
testq %rax, %rax
je 0x7675
retq
pushq %rax
callq 0x75ba
movq (%rax), %rax
addq $0x8, %rsp
retq
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module_container::create_new_disjunction(GC::shared_disjoint_handle&)
void GC::disjoint_module_container::create_new_disjunction(shared_disjoint_handle &dest)
{
	// create a new disjoint module handle data block
	auto m = std::make_unique<handle_data>();
	// and construct its module in-place
	new (m->get()) disjoint_module;

	// repoint dest to the new disjunction
	dest.reset(m.release());

	// add it to the disjunction database
	{
		std::lock_guard<std::mutex> internal_lock(internal_mutex);

		// if we're not collecting, we need to put it immediately in the disjunction list
		if (!collecting) disjunctions.emplace_back(dest);
		// otherwise we need to cache the add action
		else disjunction_add_cache.emplace_back(dest);
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rsi, %r14
movq %rdi, %rbx
movl $0x1f8, %edi            # imm = 0x1F8
callq 0x4290
movq %rax, %r15
movl $0x1f8, %edx            # imm = 0x1F8
movq %rax, %rdi
xorl %esi, %esi
callq 0x4150
movq %r15, %rdi
callq 0x806e
movq %r14, %rdi
movq %r15, %rsi
callq 0x774e
movq %rbx, %rdi
callq 0x4380
testl %eax, %eax
jne 0x7721
cmpb $0x0, 0x28(%rbx)
je 0x76f1
leaq 0x48(%rbx), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x8fca
movq %rax, %rdi
movq %r15, %rsi
callq 0x4060
movl $0x58, %eax
jmp 0x7710
leaq 0x30(%rbx), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x8fca
movq %rax, %rdi
movq %r15, %rsi
callq 0x4060
movl $0x40, %eax
incq (%rbx,%rax)
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x4200
movl %eax, %edi
callq 0x41a0
movq %rax, %r14
movq %rbx, %rdi
callq 0x4200
jmp 0x7745
movq %rax, %r14
movl $0x1f8, %esi            # imm = 0x1F8
movq %r15, %rdi
callq 0x42a0
movq %r14, %rdi
callq 0x4430
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::shared_disjoint_handle::reset(GC::handle_data*)
void GC::shared_disjoint_handle::reset(handle_data *other)
{
	// handle redundant assignment as no-op
	if (data == other) return;

	// if we pointed at something
	if (data)
	{
		// drop a strong reference and get the previous tag
		auto prev = data->tag_sub(handle_data::strong_1, std::memory_order_acq_rel);

		// if we were the last strong reference, there are no longer any strong references - destroy the object
		// we include the lock strong refs because those locks succeeded - i.e. our very existence as a non-lock strong owner proves those locks succeeded.
		if ((prev & handle_data::strong_mask) == handle_data::strong_1)
		{
			__module->blocking_collect(); // perform one final collection to make sure everything's collected
			__module->~disjoint_module(); // then destroy the module itself - its dtor asserts that all objects were collected

			// if there were also no more weak references, delete the handle
			if ((prev & handle_data::weak_mask) == 0) delete data;
			// otherwise we're not deleting it but the weak ref count might have fallen to zero in the meantime and could be waiting - alert that we're done destroying
			else data->destroyed_flag.store(true, std::memory_order_release);
		}
	}

	// repoint and test for null - must come after destruction logic to ensure the collection can potentially alias this handle
	data = other;
	if (data)
	{
		__module = data->get(); // cache the module pointer
		data->tag_add(handle_data::strong_1, std::memory_order_acq_rel); // bump up the strong ref count
	}
	else __module = nullptr; // cache the module pointer (in this case null)
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %r14
movq 0x8(%rdi), %rdi
cmpq %rsi, %rdi
je 0x7800
movq %rsi, %rbx
testq %rdi, %rdi
je 0x77d0
movl $0x1, %esi
movl $0x4, %edx
callq 0x7a96
movq %rax, %r15
movabsq $0xffffffffffffff, %rax # imm = 0xFFFFFFFFFFFFFF
andq %r15, %rax
cmpq $0x1, %rax
jne 0x77d0
movq (%r14), %r12
movq %r12, %rdi
callq 0x6556
testb %al, %al
je 0x7796
movq (%r14), %rdi
callq 0x63e8
movabsq $0xf00000000000000, %rax # imm = 0xF00000000000000
movq 0x8(%r14), %rdi
testq %rax, %r15
je 0x77c6
movb $0x1, 0x1f0(%rdi)
jmp 0x77d0
movl $0x1f8, %esi            # imm = 0x1F8
callq 0x42a0
movq %rbx, 0x8(%r14)
testq %rbx, %rbx
je 0x77f9
movq %rbx, (%r14)
movl $0x1, %esi
movq %rbx, %rdi
movl $0x4, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
jmp 0x79ca
movq $0x0, (%r14)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::weak_disjoint_handle::expired() const
bool GC::weak_disjoint_handle::expired() const noexcept
{
	// get the current tag
	auto tag = data ? data->tag.load(std::memory_order_acq_rel) : 0;

	// this weak ptr is expired if there are no strong refs remaining.
	// we include lock strong refs because otherwise it's possible for a series of atomic steps to result in a successful lock but intermediately no non-lock strong refs.
	// due to locking, however, this approach could report false negatives (but never false positives).
	return (tag & handle_data::strong_mask) == 0;
}

// Assembly:
movq (%rdi), %rax
testq %rax, %rax
je 0x79c7
movq 0x1e8(%rax), %rax
shlq $0x8, %rax
sete %al
retq
movb $0x1, %al
retq
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::handle_data::tag_add(unsigned long, std::memory_order)
GC::handle_data::tag_t GC::handle_data::tag_add(tag_t v, std::memory_order order)
{
	const auto prev = tag.fetch_add(v, order);

	#if DRAGAZO_GARBAGE_COLLECT_DISJUNCTION_HANDLE_DATA_UND_SAFETY

	const auto cur = prev + v; // compute current value from previous

	// make sure we didn't overflow any of the fields
	assert((cur & strong_mask) >= (prev & strong_mask));
	assert((cur & weak_mask) >= (prev & weak_mask));
	assert((cur & lock_mask) >= (prev & lock_mask));

	#endif

	return prev;
}

// Assembly:
pushq %rax
decl %edx
cmpl $0x4, %edx
ja 0x79e2
leaq 0x1762b(%rip), %rax     # 0x1f004
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq %rsi, %rax
lock
xaddq %rax, 0x1e8(%rdi)
addq %rax, %rsi
movabsq $0xffffffffffffff, %rcx # imm = 0xFFFFFFFFFFFFFF
movq %rsi, %rdx
andq %rcx, %rdx
andq %rax, %rcx
cmpq %rcx, %rdx
jb 0x7a38
movabsq $0xf00000000000000, %rcx # imm = 0xF00000000000000
movq %rsi, %rdx
andq %rcx, %rdx
andq %rax, %rcx
cmpq %rcx, %rdx
jb 0x7a57
movabsq $-0x1000000000000000, %rcx # imm = 0xF000000000000000
andq %rcx, %rsi
andq %rax, %rcx
cmpq %rcx, %rsi
jb 0x7a76
popq %rcx
retq
leaq 0x17ae5(%rip), %rdi     # 0x1f524
leaq 0x17710(%rip), %rsi     # 0x1f156
leaq 0x17b03(%rip), %rcx     # 0x1f550
movl $0x39b, %edx            # imm = 0x39B
callq 0x4190
leaq 0x17b3c(%rip), %rdi     # 0x1f59a
leaq 0x176f1(%rip), %rsi     # 0x1f156
leaq 0x17ae4(%rip), %rcx     # 0x1f550
movl $0x39c, %edx            # imm = 0x39C
callq 0x4190
leaq 0x17b45(%rip), %rdi     # 0x1f5c2
leaq 0x176d2(%rip), %rsi     # 0x1f156
leaq 0x17ac5(%rip), %rcx     # 0x1f550
movl $0x39d, %edx            # imm = 0x39D
callq 0x4190
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::handle_data::tag_sub(unsigned long, std::memory_order)
GC::handle_data::tag_t GC::handle_data::tag_sub(tag_t v, std::memory_order order)
{
	const auto prev = tag.fetch_sub(v, order);

	#if DRAGAZO_GARBAGE_COLLECT_DISJUNCTION_HANDLE_DATA_UND_SAFETY

	const auto cur = prev - v; // compute current value from previous

	// make sure we didn't overflow any of the fields
	assert((cur & strong_mask) <= (prev & strong_mask));
	assert((cur & weak_mask) <= (prev & weak_mask));
	assert((cur & lock_mask) <= (prev & lock_mask));

	#endif

	return prev;
}

// Assembly:
pushq %rax
decl %edx
cmpl $0x4, %edx
ja 0x7aae
leaq 0x17573(%rip), %rax     # 0x1f018
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq %rsi, %rax
negq %rax
lock
xaddq %rax, 0x1e8(%rdi)
movq %rax, %rcx
subq %rsi, %rcx
movabsq $0xffffffffffffff, %rdx # imm = 0xFFFFFFFFFFFFFF
movq %rcx, %rsi
andq %rdx, %rsi
andq %rax, %rdx
cmpq %rdx, %rsi
ja 0x7b0a
movabsq $0xf00000000000000, %rdx # imm = 0xF00000000000000
movq %rcx, %rsi
andq %rdx, %rsi
andq %rax, %rdx
cmpq %rdx, %rsi
ja 0x7b29
movabsq $-0x1000000000000000, %rdx # imm = 0xF000000000000000
andq %rdx, %rcx
andq %rax, %rdx
cmpq %rdx, %rcx
ja 0x7b48
popq %rcx
retq
leaq 0x17ad9(%rip), %rdi     # 0x1f5ea
leaq 0x1763e(%rip), %rsi     # 0x1f156
leaq 0x17af7(%rip), %rcx     # 0x1f616
movl $0x3ac, %edx            # imm = 0x3AC
callq 0x4190
leaq 0x17b30(%rip), %rdi     # 0x1f660
leaq 0x1761f(%rip), %rsi     # 0x1f156
leaq 0x17ad8(%rip), %rcx     # 0x1f616
movl $0x3ad, %edx            # imm = 0x3AD
callq 0x4190
leaq 0x17b39(%rip), %rdi     # 0x1f688
leaq 0x17600(%rip), %rsi     # 0x1f156
leaq 0x17ab9(%rip), %rcx     # 0x1f616
movl $0x3ae, %edx            # imm = 0x3AE
callq 0x4190
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::shared_disjoint_handle::lock(GC::handle_data*)
void GC::shared_disjoint_handle::lock(handle_data *other)
{
	// we need to start out null
	reset();

	// if the relock target is non-null
	if (other)
	{
		// bump up the strong and lock counts
		auto prev = other->tag_add(handle_data::lock_1 | handle_data::strong_1, std::memory_order_acq_rel);

		// if there was at least 1 non-lock strong reference, the lock is successful and the object is still alive.
		// we exclude lock strong refs because otherwise 2 locks back-to-back from 2 threads could trick the latter into thinking it succeeded.
		if (handle_data::non_lock_strongs(prev) != 0)
		{
			// unmark the lock ref (success keeps only the strong ref because we're a non-lock strong owner type)
			other->tag_sub(handle_data::lock_1, std::memory_order_acq_rel);

			// we now own a reference - do the raw repoint
			data = other;
			__module = other->get();
		}
		// otherwise the object is expired
		else
		{
			// unmark the lock ref and strong ref (failure to lock a strong ref)
			other->tag_sub(handle_data::lock_1 | handle_data::strong_1, std::memory_order_acq_rel);
		}
	}
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rsi, %rbx
movq %rdi, %r14
xorl %esi, %esi
callq 0x774e
testq %rbx, %rbx
je 0x7bde
movabsq $0x1000000000000001, %r15 # imm = 0x1000000000000001
movq %rbx, %rdi
movq %r15, %rsi
movl $0x4, %edx
callq 0x79ca
movabsq $0xffffffffffffff, %rcx # imm = 0xFFFFFFFFFFFFFF
andq %rax, %rcx
shrq $0x3c, %rax
cmpq %rax, %rcx
jne 0x7bc4
movq %rbx, %rdi
movq %r15, %rsi
movl $0x4, %edx
popq %rbx
popq %r14
popq %r15
jmp 0x7a96
decq %r15
movq %rbx, %rdi
movq %r15, %rsi
movl $0x4, %edx
callq 0x7a96
movq %rbx, 0x8(%r14)
movq %rbx, (%r14)
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::shared_disjoint_handle::operator=(GC::shared_disjoint_handle&&)
GC::shared_disjoint_handle &GC::shared_disjoint_handle::operator=(shared_disjoint_handle &&other)
{
	if (&other != this)
	{
		// repoint to null with the ref count logic
		reset();

		// then steal disjunction ownership - ref count change is net zero
		data = std::exchange(other.data, nullptr);
		__module = std::exchange(other.__module, nullptr);
	}

	return *this;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
cmpq %rdi, %rsi
je 0x7c80
movq %rsi, %r14
xorl %r15d, %r15d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x774e
movq 0x8(%r14), %rax
movq %r15, 0x8(%r14)
movq %rax, 0x8(%rbx)
movq (%r14), %rax
movq %r15, (%r14)
movq %rax, (%rbx)
movq %rbx, %rax
popq %rbx
popq %r14
popq %r15
retq
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::weak_disjoint_handle::reset(GC::handle_data*)
void GC::weak_disjoint_handle::reset(handle_data *other)
{
	// handle redundant assignment as no-op
	if (data == other) return;

	// if we pointed at something
	if (data)
	{
		// drop a weak ref and get the previous tag
		auto prev = data->tag_sub(handle_data::weak_1, std::memory_order_acq_rel);

		// if we were the last weak ref and there were no strong refs, the object is already destroyed and needs to be deleted.
		// being the last weak ref implies there are no locks at the moment because without unsynchronized read/write to the same variable from several threads that's impossible.
		// therefore we don't need to bother about strong vs. non-lock strong references in this context because strong == non-lock strong
		if ((prev & handle_data::weak_mask) == handle_data::weak_1 && (prev & handle_data::strong_mask) == 0)
		{
			// in this case the strong count fell to zero, so the object is potentially being destroyed by the strong ref count logic.
			// however, that strong ref count logic won't delete the data block because our existence proves there was a weak reference prior to the strong ref dec logic.
			// therefore we just need to wait until the object is destroyed so we can delete the data block
			while (!data->destroyed_flag.load(std::memory_order_acquire));
			delete data;
		}
	}

	// repoint - if non-null bump up weak ref count
	data = other;
	if (data) data->tag_add(handle_data::weak_1, std::memory_order_acq_rel);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %r15
movq (%rdi), %rdi
cmpq %rsi, %rdi
je 0x7d02
movq %rsi, %rbx
movabsq $0x100000000000000, %r14 # imm = 0x100000000000000
testq %rdi, %rdi
je 0x7ce5
movq %r14, %rsi
movl $0x4, %edx
callq 0x7a96
movabsq $0xfffffffffffffff, %rcx # imm = 0xFFFFFFFFFFFFFFF
andq %rax, %rcx
cmpq %r14, %rcx
jne 0x7ce5
movq (%r15), %rax
movb 0x1f0(%rax), %al
testb $0x1, %al
je 0x7ccb
movq (%r15), %rdi
movl $0x1f8, %esi            # imm = 0x1F8
callq 0x42a0
movq %rbx, (%r15)
testq %rbx, %rbx
je 0x7d02
movq %rbx, %rdi
movq %r14, %rsi
movl $0x4, %edx
popq %rbx
popq %r14
popq %r15
jmp 0x79ca
popq %rbx
popq %r14
popq %r15
retq
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::weak_disjoint_handle::operator=(GC::weak_disjoint_handle&&)
GC::weak_disjoint_handle &GC::weak_disjoint_handle::operator=(weak_disjoint_handle &&other)
{
	if (&other != this)
	{
		reset(); // repoint to null with the ref count logic
		data = std::exchange(other.data, nullptr); // then unsafe repoint to other and disconnect other - the ref count change is net zero
	}
	return *this;
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
cmpq %rdi, %rsi
je 0x7d82
movq %rsi, %r14
movq %rbx, %rdi
xorl %esi, %esi
callq 0x7c8a
movq (%r14), %rax
movq $0x0, (%r14)
movq %rax, (%rbx)
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/test.cpp
// Function: foo()
void foo()
{
	{
		//GC::collect();
		
		// create the first node
		GC::ptr<ListNode> root = GC::make<ListNode>();

		// we'll make 10 links in the chain
		GC::ptr<ListNode> *prev = &root;
		for (int i = 0; i < 10; ++i)
		{
			(*prev)->next = GC::make<ListNode>();
			(*prev)->next->prev = *prev;

			prev = &(*prev)->next;
		}

		// then we'll merege the ends into a cycle
		root->prev = *prev;
		(*prev)->next = root;

		using std::swap;

		root.swap(*prev);
		swap(root, *prev);

		//GC::collect();
		//std::cerr << "\n\n";
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x30, %rsp
movq %rsp, %rbx
movq %rbx, %rdi
callq 0x10e4e
movl $0xa, %ebp
leaq 0x20(%rsp), %r14
leaq 0x18(%rsp), %r12
movq %r12, %rdi
callq 0x10e4e
movq (%rbx), %rsi
movq 0x18(%rsp), %rax
movq %rax, 0x18(%rsi)
movq 0x28(%rsi), %rdi
addq $0x20, %rsi
movq %r14, %rdx
callq 0x71fc
movq $0x0, 0x18(%rsp)
movq %r14, %rdi
callq 0x17352
movq (%rbx), %rax
movq 0x18(%rax), %rsi
leaq 0x8(%rbx), %rdx
movq %rax, (%rsi)
movq 0x10(%rsi), %rdi
addq $0x8, %rsi
callq 0x71fc
movq (%rbx), %r15
leaq 0x18(%r15), %rbx
decl %ebp
jne 0x905a
movq (%rsp), %rsi
movq 0x18(%r15), %rax
addq $0x20, %r15
movq %rax, (%rsi)
movq 0x10(%rsi), %rdi
addq $0x8, %rsi
movq %r15, %rdx
callq 0x71fc
movq (%rbx), %rsi
leaq 0x8(%rsp), %r14
movq -0x8(%r14), %rax
movq %rax, 0x18(%rsi)
movq 0x28(%rsi), %rdi
addq $0x20, %rsi
movq %r14, %rdx
callq 0x71fc
movq (%rsp), %rax
movq (%rbx), %rcx
movq %rcx, (%rsp)
movq %rax, (%rbx)
movq 0x10(%rsp), %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x735a
movq (%rsp), %rax
movq (%rbx), %rcx
movq %rcx, (%rsp)
movq %rax, (%rbx)
movq 0x10(%rsp), %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x735a
movq $0x0, (%rsp)
movq %r14, %rdi
callq 0x17352
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
jmp 0x9167
jmp 0x9167
movq %rax, %rbx
movq $0x0, 0x18(%rsp)
movq %r14, %rdi
callq 0x17352
jmp 0x916a
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
movq $0x0, -0x8(%rdi)
callq 0x17352
movq %rbx, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/./GarbageCollection.h
// Function: GC::thread::thread<main::$_1>(GC::new_disjunction_t, main::$_1&&)
explicit thread(new_disjunction_t, Function &&f, Args &&...args) : t([](std::decay_t<Function> &&ff, std::decay_t<Args> &&...fargs)
		{
			// now that we're a new thread, repoint our local disjunction handle to a new disjunction
			disjoint_module_container::get().create_new_disjunction(disjoint_module::local_handle());

			// then invoke the user function
			std::invoke(std::move(ff), std::move(fargs)...);

		}, std::forward<Function>(f), std::forward<Args>(args)...)
		{}

// Assembly:
pushq %rbx
subq $0x10, %rsp
movq %rdi, %rbx
movq $0x0, (%rdi)
movl $0x10, %edi
callq 0x4290
leaq 0x2219a(%rip), %rcx     # 0x305b8
movq %rcx, (%rax)
leaq 0x8(%rsp), %rsi
movq %rax, (%rsi)
movq %rbx, %rdi
xorl %edx, %edx
callq 0x4260
movq 0x8(%rsp), %rdi
testq %rdi, %rdi
je 0xe443
movq (%rdi), %rax
callq *0x8(%rax)
addq $0x10, %rsp
popq %rbx
retq
movq %rax, %rbx
movq 0x8(%rsp), %rdi
testq %rdi, %rdi
je 0xe45c
movq (%rdi), %rax
callq *0x8(%rax)
movq %rbx, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/test.cpp
// Function: void GC::router<router_allocator>::route<GC::router_fn>(router_allocator const&, GC::router_fn)
static void route(const router_allocator &r, F func)
	{
		// simulate router locking a mutex and a mutator in the class locking and allocating
		r.p = GC::make<int>(45);

		GC::route(r.p, func);
		GC::route(r.self, func);
	}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0xc(%rsp), %rsi
movl $0x2d, (%rsi)
leaq 0x10(%rsp), %r15
movq %r15, %rdi
callq 0x14712
movq (%r15), %rax
leaq 0x18(%rsp), %r15
movq %rax, (%r14)
leaq 0x8(%r14), %r12
movq 0x10(%r14), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x71fc
movq $0x0, 0x10(%rsp)
movq %r15, %rdi
callq 0x17352
movq %r12, %rdi
callq *%rbx
addq $0x20, %r14
movq %r14, %rdi
callq *%rbx
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movq %rax, %rbx
movq $0x0, 0x10(%rsp)
movq %r15, %rdi
callq 0x17352
movq %rbx, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/./GarbageCollection.h
// Function: GC::ptr<int []> GC::adopt<int, std::default_delete<int []>>(int*, unsigned long)
[[nodiscard]]
	static ptr<T[]> adopt(T obj[], std::size_t count)
	{
		// -- verification -- //

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

		// -- 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) { for (std::size_t i = 0; i < handle.count; ++i) GC::route(reinterpret_cast<T*>(handle.obj)[i], 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, count, &_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 0x16d08
movq %rdx, %r12
movq %rsi, %r14
movb 0x1a78e(%rip), %al      # 0x31430
testb %al, %al
je 0x16d36
movl $0x40, %edi
callq 0x1725a
movq %rax, %r15
movq %r14, (%rax)
movq %r12, 0x8(%rax)
leaq 0x1a74b(%rip), %rax     # 0x31410
movq %rax, 0x10(%r15)
callq 0x7668
movq %rax, 0x18(%r15)
movq 0x10(%r15), %rax
leaq -0xeee7(%rip), %rsi     # 0x7df6
movq %r15, %rdi
callq *0x10(%rax)
movq %r14, (%rbx)
leaq 0x8(%rbx), %r14
callq 0x7668
movq %rax, 0x10(%rbx)
movq %rax, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x6c4e
callq 0x7e22
jmp 0x16d27
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
callq 0x5b6d
jmp 0x16caa
movq %rax, %r15
movq $0x0, (%rbx)
movq %r14, %rdi
callq 0x17352
jmp 0x16d71
movq %rax, %rdi
callq 0x40e0
movq %r14, %rdi
callq 0x4320
callq 0x4370
movq %rax, %r15
callq 0x43d0
movq %r15, %rdi
callq 0x4430
movq %rax, %rdi
callq 0x8024
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/./GarbageCollection.h
// Function: GC::checked_allocator<GC::raw_aligned_allocator<8ul>>::alloc(unsigned long)
static void *alloc(std::size_t size)
		{
			// allocate the space
			void *buf = allocator_t::alloc(size);

			// if that failed but we have allocfail collect mode enabled
			if (!buf && (int)strategy() & (int)strategies::allocfail)
			{
				// collect and retry the allocation
				GC::collect();
				buf = allocator_t::alloc(size);
			}

			// if that failed, throw bad alloc
			if (!buf) throw std::bad_alloc();

			return buf;
		}

// Assembly:
pushq %rbx
movq %rdi, %rbx
callq 0x4340
testq %rax, %rax
jne 0x17283
callq 0x7e02
testb $0x2, %al
je 0x17285
callq 0x7dd4
movq %rbx, %rdi
callq 0x4340
testq %rax, %rax
je 0x17285
popq %rbx
retq
movl $0x8, %edi
callq 0x4110
movq 0x19cfa(%rip), %rcx     # 0x30f90
addq $0x10, %rcx
movq %rcx, (%rax)
movq 0x19d14(%rip), %rsi     # 0x30fb8
movq 0x19cd5(%rip), %rdx     # 0x30f80
movq %rax, %rdi
callq 0x43f0
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/test.cpp
// Function: void GC::router<atomic_container>::route<GC::router_fn>(atomic_container const&, GC::router_fn)
static void route(const atomic_container &atomic, F func)
	{
		GC::route(atomic.atomic_1, func);
		GC::route(atomic.atomic_2, func);
		GC::route(atomic.atomic_3, func);
		GC::route(atomic.atomic_4, func);
	}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %rbx
movq %rdi, %r14
callq 0x18548
leaq 0x40(%r14), %rdi
movq %rbx, %rsi
callq 0x18548
leaq 0x80(%r14), %rdi
movq %rbx, %rsi
callq 0x18548
addq $0xc0, %r14
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x18548
nop
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/test.cpp
// Function: SymbolTable::operator=(SymbolTable const&)
SymbolTable &operator=(const SymbolTable &other)
	{
		if (this != &other)
		{
			{
				std::lock_guard lock(symbols_mutex);
				symbols = other.symbols;
			}
			better_symbols = other.better_symbols;
		}
		return *this;
	}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
movq %rdi, %rbx
cmpq %rsi, %rdi
je 0x1a7fd
movq %rsi, %r14
leaq 0x38(%rbx), %r15
movq %r15, %rdi
callq 0x4380
testl %eax, %eax
jne 0x1a806
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1a876
movq %r15, %rdi
callq 0x4200
addq $0x60, %r14
leaq 0x60(%rbx), %rdi
movq %r14, %rsi
callq 0x1a820
movq %rbx, %rax
popq %rbx
popq %r14
popq %r15
retq
movl %eax, %edi
callq 0x41a0
movq %rax, %rbx
movq %r15, %rdi
callq 0x4200
movq %rbx, %rdi
callq 0x4430
// File: /workspace/github_cpp_makefile_star2_O3/dragazo[P]cpp-gc/test.cpp
// Function: SymbolTable::operator=(SymbolTable&&)
SymbolTable &operator=(SymbolTable &&other)
	{
		if (this != &other)
		{
			{
				std::scoped_lock locks(symbols_mutex, other.symbols_mutex);
				symbols = std::move(other.symbols);
			}
			better_symbols = std::move(other.better_symbols);
		}
		return *this;
	}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
cmpq %rsi, %rdi
je 0x1aced
movq %rsi, %r14
leaq 0x38(%rbx), %r12
leaq 0x38(%rsi), %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0x1ad5c
movq %rbx, %rdi
movq %r14, %rsi
callq 0x471a
movq %r12, %rdi
callq 0x4200
movq %r15, %rdi
callq 0x4200
addq $0x60, %r14
leaq 0x60(%rbx), %rdi
movq %r14, %rsi
callq 0x1ad04
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movq %rax, %rdi
callq 0x8024