// File: UTSASRG[P]Guarder/./bibopheap.hh
// Function: BibopHeap::getShadowObjectInfo(void*, BibopHeap::PerThreadBag**, void**, BibopHeap::PerThreadBag**)
inline shadowObjectInfo * getShadowObjectInfo(void * addr, PerThreadBag ** bag = NULL,
					void ** objectStart = NULL, PerThreadBag ** ownerBag = NULL) {
		unsigned long offset = (char *)addr - _heapBegin;
    unsigned long localBagOffset = offset & _bagMask;
		unsigned long globalBagNum = offset >> _bagShiftBits;
		unsigned long origOwnerTindex = offset >> _threadShiftBits;
		unsigned long origBagNum = globalBagNum & _numBagsPerSubHeapMask;

		PerThreadBag * origBag = &_threadBag[origOwnerTindex][origBagNum];

		if(bag) {
				unsigned objectSize = _threadMap[origOwnerTindex].getClassSize(origBagNum);
				unsigned currentThread = getThreadIndex(&currentThread);
				unsigned bagNum = _threadMap[currentThread].getBagNum(objectSize);
				*bag = &_threadBag[currentThread][bagNum];
		}

		if(ownerBag) {
				*ownerBag = origBag;
		}

		if(objectStart) {
				unsigned long objectStartOffset = localBagOffset & ~origBag->classMask;
				*objectStart = (void *)(_heapBegin + origBag->startOffset + objectStartOffset);
		}

		shadowObjectInfo * shadowinfo = (shadowObjectInfo *)(origBag->startShadowMem);

		shadowObjectInfo * retval = &shadowinfo[localBagOffset >> origBag->shiftBits];
		//PRDBG("getShadowObjectInfo(%p) == smAddr %p, local bag offset = 0x%lx, shift bits = %zu",
		//				addr, retval, localBagOffset, origBag->shiftBits);
		return retval;
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x10(%rbp), %rcx
movq (%rax), %rdx
subq %rdx, %rcx
movq %rcx, -0x30(%rbp)
movq -0x30(%rbp), %rcx
movq 0x6505(%rip), %rdx      # 0x10fe8
andq (%rdx), %rcx
movq %rcx, -0x38(%rbp)
movq -0x30(%rbp), %rdx
movq 0x6473(%rip), %rcx      # 0x10f68
movq (%rcx), %rcx
shrq %cl, %rdx
movq %rdx, %rcx
movq %rcx, -0x40(%rbp)
movq -0x30(%rbp), %rdx
movl 0x38(%rax), %ecx
shrq %cl, %rdx
movq %rdx, %rcx
movq %rcx, -0x48(%rbp)
movq -0x40(%rbp), %rcx
andq 0x40(%rax), %rcx
movq %rcx, -0x50(%rbp)
addq $0x1980, %rax           # imm = 0x1980
movq -0x48(%rbp), %rcx
shlq $0xb, %rcx
addq %rcx, %rax
movq -0x50(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0xabbc
movq -0x88(%rbp), %rdi
addq $0x4c, %rdi
imulq $0x32, -0x48(%rbp), %rax
addq %rax, %rdi
movq -0x50(%rbp), %rax
movl %eax, %esi
callq 0x5410
movl %eax, -0x5c(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x53d0
movq -0x88(%rbp), %rdi
movl %eax, -0x60(%rbp)
addq $0x4c, %rdi
movl -0x60(%rbp), %eax
imulq $0x32, %rax, %rax
addq %rax, %rdi
movl -0x5c(%rbp), %esi
callq 0x5100
movq -0x88(%rbp), %rcx
movl %eax, -0x64(%rbp)
addq $0x1980, %rcx           # imm = 0x1980
movl -0x60(%rbp), %eax
shlq $0xb, %rax
addq %rax, %rcx
movl -0x64(%rbp), %eax
shlq $0x7, %rax
addq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
cmpq $0x0, -0x28(%rbp)
je 0xabce
movq -0x58(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
cmpq $0x0, -0x20(%rbp)
je 0xac09
movq -0x88(%rbp), %rax
movq -0x38(%rbp), %rcx
movq -0x58(%rbp), %rdx
movq 0x28(%rdx), %rdx
xorq $-0x1, %rdx
andq %rdx, %rcx
movq %rcx, -0x70(%rbp)
movq (%rax), %rcx
movq -0x58(%rbp), %rax
addq 0x38(%rax), %rcx
addq -0x70(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x58(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq -0x38(%rbp), %rdx
movq -0x58(%rbp), %rcx
movl 0x30(%rcx), %ecx
shrq %cl, %rdx
movq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
nop