// File: /workspace/github_cpp_makefile_star2_O2/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 $0x28, %rsp
movq %rsi, %rbx
leaq 0x20(%rsp), %rbp
leaq 0x8(%rsp), %r13
movq %rbp, %rdx
movq %r13, %rcx
xorl %r8d, %r8d
callq 0x4610
movq %rax, %r14
movq (%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x4200
movq %rax, %r15
callq 0x4280
movsbl (%r14), %r10d
movq (%rbp), %r11
movl 0x14(%r11), %ebp
movl 0x18(%r11), %r12d
subq $0x8, %rsp
leaq 0x45f7(%rip), %rdx      # 0xa36c
leaq 0x37fe(%rip), %r8       # 0x957a
movl $0x1000, %esi           # imm = 0x1000
movq %r15, %rdi
movq %rax, 0x18(%rsp)
movq %rax, %rcx
movl $0x416, %r9d            # imm = 0x416
xorl %eax, %eax
pushq (%r13)
pushq 0x20(%r11)
pushq %rbp
pushq %r12
pushq %r10
pushq %r14
pushq %rbx
callq 0x4560
addq $0x40, %rsp
callq 0x4200
movq %rax, %r15
callq 0x4200
movq %rax, %rdi
callq 0x4130
pushq $0x2
popq %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x4100
cmpb $0x1, (%r14)
jne 0x5e17
movb $0x0, (%r14)
movq 0x20(%rsp), %rax
movq 0x20(%rax), %rsi
cmpq $0x10000, %rsi          # imm = 0x10000
jb 0x5df9
movq 0x8(%rsp), %rdi
pushq $0x4
popq %rdx
callq 0x43d0
movq 0x8(%rsp), %rsi
movq 0x18(%rsp), %rdi
callq 0x4340
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x4200
leaq 0x45c3(%rip), %rdx      # 0xa3e6
leaq 0x3750(%rip), %r8       # 0x957a
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
movq 0x10(%rsp), %rcx
movl $0x419, %r9d            # imm = 0x419
xorl %eax, %eax
pushq %r14
pushq %rbx
callq 0x4560
popq %rcx
popq %rdx
callq 0x4200
movq %rax, %rbx
callq 0x4200
movq %rax, %rdi
callq 0x4130
pushq $0x2
popq %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x4100
callq 0x4630
pushq $0x1
popq %rdi
callq 0x43e0
nop