// File: /workspace/github_cpp_makefile_star2_O3/UTSASRG[P]Guarder/./bibopheap.hh
// Function: BibopHeap::freeSmallObject(void*)
void freeSmallObject(void * addr) {
		void * objectStartAddr;
		PerThreadBag * bag;
		#ifdef USE_CANARY
		PerThreadBag * ownerBag;
		shadowObjectInfo * shadowinfo = getShadowObjectInfo(addr, &bag, &objectStartAddr, &ownerBag);
		#else
		shadowObjectInfo * shadowinfo = getShadowObjectInfo(addr, &bag, &objectStartAddr);
		#endif

		BibopFreeCache * freeCache = bag->freeCache;

		PRDBG("\tfree(%p): smAddr %p (value=%d), threadIndex=%d, bagNum=%d, classSize=%zu, objectStart=%p",
						addr, shadowinfo, *shadowinfo, bag->threadIndex, bag->bagNum, bag->classSize, objectStartAddr);

		if(isObjectFree(shadowinfo)) {
			PRERR("Double free or invalid free problem found on object %p (sm %p)", addr, shadowinfo);
      printCallStack();
      exit(EXIT_FAILURE);
		} 

		#ifdef DESTROY_ON_FREE
		#ifdef USE_CANARY
		size_t objectSizeNoCanary = bag->classSize - 1;
		#else
		size_t objectSizeNoCanary = bag->classSize;
		#endif
		#endif

		#ifdef USE_CANARY
		char * canary = (char *)objectStartAddr + bag->classSize - 1;
		if(*canary != CANARY_SENTINEL) {
				FATAL("canary value for object %p not intact; canary @ %p, value=0x%x",
								addr, canary, (unsigned)*canary);
		}
		#if (NUM_MORE_CANARIES_TO_CHECK > 0)
		for(int move = LEFT; move <= RIGHT; move++) {
				shadowObjectInfo * canaryShadow = shadowinfo;
				for(int pos = 0; pos < NUM_MORE_CANARIES_TO_CHECK; pos++) {
						if((canaryShadow = getNextCanaryNeighbor(canaryShadow, ownerBag, (direction)move))) {
								char * neighborAddr = (char *)getAddrFromShadowInfo(canaryShadow, ownerBag);
								char * canary = neighborAddr + bag->classSize - 1;
								// We will only inspect the canary of objects currently in-use; if the
								// object is free, then it has already been checked previously.
								PRDBG("checking canary value for object %p (neighbor of %p); classSize=%zu, canary @ %p",
												neighborAddr, objectStartAddr, bag->classSize, canary);
								if(!isObjectFree(canaryShadow) && (*canary != CANARY_SENTINEL)) {
										FATAL("canary value for object %p (neighbor of %p) not intact; canary @ %p, value=0x%x",
														neighborAddr, objectStartAddr, canary, (unsigned)*canary);
								}
						} else {
								// getNextCanaryNeighbor will only return null when we attempt to move
								// left or right from the first or last object in a bag.
								break;
						}
				}
		}
		#endif
		#endif
		#ifdef DESTROY_ON_FREE
		destroyObject(objectStartAddr, objectSizeNoCanary);
		#endif

		markObjectFree(shadowinfo);

		//#pragma message "madvise turned off"
		if(bag->classSize >= 16 * PAGESIZE) {
				madvise(objectStartAddr, bag->classSize, MADV_DONTNEED);
		}

		freeCache->add(objectStartAddr);
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, 0x30(%rsp)
movq %rdi, %r15
movq (%rdi), %rbp
movq %rsi, %rax
subq %rbp, %rax
movq 0x71ac(%rip), %rcx      # 0xcfe8
movq (%rcx), %rcx
andq %rax, %rcx
movq %rcx, 0x8(%rsp)
movq 0x711a(%rip), %rcx      # 0xcf68
movb (%rcx), %cl
movq %rax, %r14
shrq %cl, %r14
movb 0x38(%rdi), %cl
shrq %cl, %rax
andq 0x40(%rdi), %r14
imulq $0x32, %rax, %rcx
shlq $0xb, %rax
leaq (%rdi,%rax), %r13
addq $0x1980, %r13           # imm = 0x1980
movl %r14d, %eax
shlq $0x7, %r14
addq %rdi, %rcx
addq $0x4c, %rcx
movzbl 0x22(%rax,%rcx), %ebx
leaq 0x70f2(%rip), %rdi      # 0xcf80
callq 0x44f0
movl (%rax), %eax
imulq $0x32, %rax, %rcx
addq %r15, %rcx
addq $0x4c, %rcx
movzbl (%rbx,%rcx), %ebx
shll $0x7, %ebx
shlq $0xb, %rax
leaq (%r15,%rax), %r12
addq $0x1980, %r12           # imm = 0x1980
movq 0x28(%r14,%r13), %rax
notq %rax
movq 0x8(%rsp), %rdx
andq %rdx, %rax
addq 0x38(%r14,%r13), %rbp
movb 0x30(%r14,%r13), %cl
shrq %cl, %rdx
addq %rax, %rbp
movq 0x40(%r14,%r13), %r15
leaq (%r15,%rdx), %rax
movq %rax, 0x28(%rsp)
movq %rdx, %r14
movq %rdx, 0x8(%rsp)
movq 0x8(%rbx,%r12), %rax
movq %rax, 0x18(%rsp)
callq 0x41e0
movq %rax, %r13
callq 0x4250
movsbl (%r15,%r14), %r10d
movl 0x14(%rbx,%r12), %r11d
movl 0x18(%rbx,%r12), %r14d
subq $0x8, %rsp
leaq 0x445c(%rip), %rdx      # 0xa37c
leaq 0x3663(%rip), %r8       # 0x958a
movl $0x1000, %esi           # imm = 0x1000
movq %r13, %rdi
movq %rax, 0x18(%rsp)
movq %rax, %rcx
movl $0x416, %r9d            # imm = 0x416
xorl %eax, %eax
movq %rbp, 0x28(%rsp)
pushq %rbp
movq 0x38(%rsp), %rbp
pushq 0x20(%rbx,%r12)
pushq %r11
pushq %r14
movq 0x58(%rsp), %r14
pushq %r10
pushq %rbp
pushq %r14
callq 0x4490
addq $0x40, %rsp
callq 0x41e0
movq %rax, %r13
callq 0x41e0
movq %rax, %rdi
callq 0x4120
movl $0x2, %edi
movq %r13, %rsi
movq %rax, %rdx
callq 0x40f0
movq 0x8(%rsp), %rax
cmpb $0x1, (%r15,%rax)
jne 0x5fd9
addq %rbx, %r12
movb $0x0, (%rbp)
movq 0x20(%r12), %rsi
cmpq $0x10000, %rsi          # imm = 0x10000
movq 0x20(%rsp), %rbx
jb 0x5fbe
movq %rbx, %rdi
movl $0x4, %edx
callq 0x4360
movq 0x18(%rsp), %rdi
movq %rbx, %rsi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x42f0
callq 0x41e0
leaq 0x4411(%rip), %rdx      # 0xa3f6
leaq 0x359e(%rip), %r8       # 0x958a
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
movq 0x10(%rsp), %rcx
movl $0x419, %r9d            # imm = 0x419
xorl %eax, %eax
pushq %rbp
pushq %r14
callq 0x4490
addq $0x10, %rsp
callq 0x41e0
movq %rax, %rbx
callq 0x41e0
movq %rax, %rdi
callq 0x4120
movl $0x2, %edi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x40f0
callq 0x4540
movl $0x1, %edi
callq 0x4370
nop