// File: /workspace/github_cpp_makefile_star2_O2/UTSASRG[P]Guarder/./bibopheap.hh
// Function: BibopHeap::initialize()
void * initialize() {
		unsigned threadNum, bagNum;
		size_t lastUsableBagSize;

		BibopHeap::_cacheSize = BIBOP_CACHE_SIZE;
		BibopHeap::_overProvObjBufSize = OVER_PROV_OBJ_BUF_SZ;

		#ifdef BIBOP_BAG_SIZE
		#pragma message "BIBOP_BAG_SIZE in use: overrides randomized bag size"
		_bibopBagSize = BIBOP_BAG_SIZE;
		#else		// randomized bag size
		unsigned randPower = getRandomNumber() % (LOG2(MAX_RANDOM_BAG_SIZE / MIN_RANDOM_BAG_SIZE) + 1);
		_bibopBagSize = MIN_RANDOM_BAG_SIZE << randPower;
		#endif

		if(_bibopBagSize > LARGE_OBJECT_THRESHOLD) {
				lastUsableBagSize = LARGE_OBJECT_THRESHOLD;
		} else {
				lastUsableBagSize = _bibopBagSize;
		}
		_numUsableBags = LOG2(lastUsableBagSize) - LOG2(BIBOP_MIN_BLOCK_SIZE) + 1;
		if(_numUsableBags > BIBOP_NUM_BAGS) {
				_numUsableBags = BIBOP_NUM_BAGS;
		}
		_lastUsableBag = _numUsableBags - 1;

		assert(BIBOP_HEAP_SIZE > 0);

		BibopHeap::_bagShiftBits = LOG2(_bibopBagSize);
		_threadShiftBits = LOG2((_bibopBagSize * BIBOP_NUM_BAGS));
		BibopHeap::_bagMask = _bibopBagSize - 1;

		PRINF("_bibopBagSize=0x%lx, _bagShiftBits=%ld, sizeof(PerThreadBag)=%zu",
			_bibopBagSize, BibopHeap::_bagShiftBits, sizeof(PerThreadBag));
		PRINF("BIBOP_NUM_BAGS=%u, _numUsableBags=%u", BIBOP_NUM_BAGS, _numUsableBags);
		PRINF("sizeof(PerThreadBag)=%zu, sizeof(BibopObjCache)=%zu, sizeof(BibopFreeCache)=%zu",
				sizeof(PerThreadBag), sizeof(BibopObjCache), sizeof(BibopFreeCache));

		// Bag size cannot be smaller than the large object threshold.
		assert(_bibopBagSize >= LARGE_OBJECT_THRESHOLD);

		// Allocate the heap all at once.
		allocHeap(BIBOP_HEAP_SIZE);

    unsigned long numBagObjects;
    unsigned long numCumObjects = 0;
    size_t unusableHeapSpace = (BIBOP_NUM_BAGS - _numUsableBags) * _bibopBagSize;

    // Initialize each thread bag's free list, and other information
    for(threadNum = 0; threadNum < MAX_ALIVE_THREADS; threadNum++) {
      size_t classSize = BIBOP_MIN_BLOCK_SIZE;

      for(bagNum = 0; bagNum < _numUsableBags; bagNum++) {
        numBagObjects = _bibopBagSize / classSize;

        #ifdef ENABLE_GUARDPAGE
            // We must perform this >1 test or else we will underflow this value
            // for bags which have 0 objects in them. Also, the last usable bag
            // will only contain a single object, but it will not be reduced to
            // make room for a guard page, but rather the next bag (which is
            // unusable) will be converted entirely into a guard page. 
            if(numBagObjects > 1) {
                if(classSize < PageSize) {
                    numBagObjects -= (PageSize / classSize);
                } else {
                    numBagObjects--;
                }
            }
        #endif

        // Update the following values; 
        numCumObjects += numBagObjects;
        classSize <<= 1;
      }
    }

		_shadowObjectInfoSizeShiftBits = LOG2(sizeof(shadowObjectInfo));
    _numBagsPerSubHeapMask = BIBOP_NUM_BAGS - 1;
    size_t numObjectsInHeap = numCumObjects;

		//unsigned freeCacheDivisor = 1;		// no reduction to deallocation buffer size
		unsigned freeCacheDivisor = 16;
		unsigned long numFreeAreaObjects = numObjectsInHeap / freeCacheDivisor;

		allocShadowMem(numObjectsInHeap);
		allocFreeArea(numFreeAreaObjects);
		allocGlobalFreeCache(numObjectsInHeap);

		// Allocate memory for use by each bag's object cache
		size_t objectCacheSize = OVER_PROV_OBJ_BUF_SZ + BIBOP_CACHE_SIZE;
		size_t objectCacheAreaSize = sizeof(uintptr_t) * objectCacheSize * BIBOP_NUM_BAGS * MAX_ALIVE_THREADS;
		uintptr_t * objectCacheStart = (uintptr_t *)MM::mmapAllocatePrivate(objectCacheAreaSize);
		uintptr_t * currentObjectCachePos = objectCacheStart;

		uintptr_t _uHeapStart = (uintptr_t)_heapBegin;
		uintptr_t _uShadowMemStart = (uintptr_t)_shadowMemBegin;
		uintptr_t _uFreeAreaBegin = (uintptr_t)_freeAreaBegin;
		unsigned long offsetShadowMem = 0;
		unsigned long offsetFreeArea = 0;
    unsigned long offsetBag = 0;

		// Initialize each thread bag's free list, and other information
		for(threadNum = 0; threadNum < MAX_ALIVE_THREADS; threadNum++) {
			PerThreadMap& curMap = _threadMap[threadNum];
			curMap.initialize(_bagShiftBits);

			for(bagNum = 0; bagNum < _numUsableBags; bagNum++) {
				unsigned shiftBits = curMap.getClassSize(bagNum);
				size_t classSize = (1U << shiftBits);
				if(threadNum == 0)
						PRDBG("bag %d classSize = %zu, shiftBits = %u", bagNum, classSize, shiftBits);
				PerThreadBag * curBag = &_threadBag[threadNum][bagNum];
				
				curBag->cache = &_bagCache[threadNum][bagNum];
				curBag->freeCache = &_freeCache[threadNum][bagNum];
				curBag->classSize = classSize;
				curBag->classMask = classSize - 1;
				curBag->shiftBits = shiftBits;
				curBag->bagNum = bagNum;
				curBag->threadIndex = threadNum; 

				numBagObjects = _bibopBagSize / classSize;
				uintptr_t bagStart = _uHeapStart + offsetBag;
				uintptr_t bagEnd = bagStart + _bibopBagSize;
				uintptr_t bagShadowMemStart = _uShadowMemStart + offsetShadowMem;
				uintptr_t bagFreeAreaStart = _uFreeAreaBegin + offsetFreeArea;

				//PRDBG("thread %d bag %d: heap start @ 0x%lx, shadow mem @ 0x%lx, free cache @ 0x%lx, Cache=%p, FreeCache=%p",
				//				threadNum, bagNum, bagStart, bagShadowMemStart, bagFreeAreaStart, curBag->cache, curBag->freeCache);

				#ifdef ENABLE_GUARDPAGE
						size_t guardsize = classSize > PAGESIZE ? classSize : PAGESIZE;
						size_t guardoffset = guardsize;
						if(bagNum == _lastUsableBag) {
								// If this bag can only fit one object,
								// forego the use of a guard object at the end of the bag.
								if(_bibopBagSize == lastUsableBagSize) {
										guardoffset = 0;
										guardsize = 0;
								}
								// Add to the guard size the amount of unusable space left on the heap.
								guardsize += (BIBOP_NUM_BAGS - LOG2(lastUsableBagSize) + LOG2(BIBOP_MIN_BLOCK_SIZE) - 1) * _bibopBagSize;

								//PRDBG("last usable bag: lastUsableBagSize=%zu, _bibopBagSize=%zu, guardsize=%zu, guardoffset=%zu",
								//		lastUsableBagSize, _bibopBagSize, guardsize, guardoffset);
						}
						curBag->guardsize = guardsize;
						curBag->guardoffset = guardoffset;
				#else
						size_t guardoffset = 0;
				#endif

				#ifdef ENABLE_GUARDPAGE
						// We must perform this >1 test or else we will underflow this value
						// for bags which have 0 objects in them. Also, the last usable bag
						// will only contain a single object, but it will not be reduced to
						// make room for a guard page, but rather the next bag (which is
						// unusable) will be converted entirely into a guard page. 
						if(numBagObjects > 1) {
								if(classSize < PageSize) {
										numBagObjects -= (PageSize / classSize);
								} else {
										numBagObjects--;
								}
						}
				#endif

				unsigned long bagFreeCacheCapacity = numBagObjects / freeCacheDivisor;

				curBag->startShadowMem = bagShadowMemStart;
				curBag->cache->initialize(bagStart, bagEnd, currentObjectCachePos, curBag->freeCache, shiftBits);
				// In order to prevent false sharing, do not utilize a global
				// free buffer for size classes smaller than the cache line size
				if(classSize >= CACHE_LINE_SIZE) {
						curBag->freeCache->initialize(bagFreeAreaStart, bagFreeCacheCapacity, NULL);
				} else {
						curBag->freeCache->initialize(bagFreeAreaStart, bagFreeCacheCapacity, &_globalFreeCache[shiftBits]);
				}

				currentObjectCachePos += objectCacheSize;

				curBag->startOffset = offsetBag;
				curBag->lastObjectIndex = numBagObjects - 1;

				// Update loop variables
				offsetBag += _bibopBagSize;
				offsetShadowMem += numBagObjects;
				offsetFreeArea += bagFreeCacheCapacity * sizeof(uintptr_t);
				}
			offsetBag += unusableHeapSpace;
		}

		#ifndef NDEBUG
		// DEBUG
		uintptr_t _uFreeAreaEnd = _uFreeAreaBegin + (numFreeAreaObjects * sizeof(uintptr_t));
		assert((_uFreeAreaBegin + offsetFreeArea) <= _uFreeAreaEnd);
		#endif

		_numBagsPerSubHeapMask = BIBOP_NUM_BAGS - 1;

		PRINF("_heapBegin=%p, _heapEnd=%p", _heapBegin, _heapEnd);
		PRINF("_shadowMemBegin=%p, _shadowMemEnd=%p, _freeAreaBegin=%p, _freeAreaEnd=%p",
						_shadowMemBegin, _shadowMemEnd, _freeAreaBegin, _freeAreaEnd);

		return _heapBegin;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdi, %r13
movq 0x8a9f(%rip), %rax      # 0xdf20
movl 0x8(%rax), %eax
movq 0x8ae5(%rip), %rcx      # 0xdf70
movl %eax, (%rcx)
shrl %eax
movq 0x8b02(%rip), %rcx      # 0xdf98
movl %eax, (%rcx)
callq 0x40b0
movabsq $0x1ffffffff, %rax      # imm = 0x1FFFFFFFF
leaq 0x1(%rax), %rcx
movq 0x8af6(%rip), %r14      # 0xdfa8
movq %rcx, (%r14)
movabsq $0xf00000010, %rcx      # imm = 0xF00000010
movq %rcx, 0x30(%r13)
movq 0x8a9e(%rip), %rbp      # 0xdf68
movq $0x21, (%rbp)
movl $0x25, 0x38(%r13)
movq 0x8b07(%rip), %rcx      # 0xdfe8
movq %rax, (%rcx)
callq 0x4200
movq %rax, %r15
callq 0x4280
movq %rax, %rbx
subq $0x8, %rsp
movl $0x80, %r10d
leaq 0x4161(%rip), %rdx      # 0x9666
leaq 0x406e(%rip), %r8       # 0x957a
xorl %r12d, %r12d
movl $0x1000, %esi           # imm = 0x1000
movq %r15, %rdi
movq %rax, %rcx
movl $0x2f6, %r9d            # imm = 0x2F6
xorl %eax, %eax
pushq %r10
pushq (%rbp)
pushq (%r14)
callq 0x4560
addq $0x20, %rsp
callq 0x4200
movq %rax, %r15
callq 0x4200
movq %rax, %rdi
callq 0x4130
pushq $0x2
popq %rbp
movl %ebp, %edi
movq %r15, %rsi
movq %rax, %rdx
callq 0x4100
callq 0x4200
movl 0x30(%r13), %r10d
leaq 0x4160(%rip), %rdx      # 0x96c8
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
movq %rbx, %rcx
leaq 0x4000(%rip), %r8       # 0x957a
movl $0x2f7, %r9d            # imm = 0x2F7
xorl %eax, %eax
pushq %r10
pushq $0x10
callq 0x4560
popq %rcx
popq %rdx
callq 0x4200
movq %rax, %r15
callq 0x4200
movq %rax, %rdi
callq 0x4130
movl %ebp, %edi
movq %r15, %rsi
movq %rax, %rdx
callq 0x4100
callq 0x4200
subq $0x8, %rsp
leaq 0x414f(%rip), %rdx      # 0x970e
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
movq %rbx, 0x20(%rsp)
movq %rbx, %rcx
movq %r14, %rbx
leaq 0x3fa1(%rip), %r8       # 0x957a
movl $0x2f9, %r9d            # imm = 0x2F9
xorl %eax, %eax
pushq $0x40
movl $0x80, %r10d
pushq %r10
pushq %r10
callq 0x4560
addq $0x20, %rsp
callq 0x4200
movq %rax, %r14
callq 0x4200
movq %rax, %rdi
callq 0x4130
movl %ebp, %edi
movq %r14, %rsi
movq %rax, %rdx
callq 0x4100
movq (%rbx), %rsi
cmpq $0x7ffff, %rsi          # imm = 0x7FFFF
jbe 0x5ac4
shlq $0xb, %rsi
movq %r13, %rdi
callq 0x4640
movl 0x30(%r13), %esi
pushq $0x10
popq %rcx
subl %esi, %ecx
movq (%rbx), %rbx
pushq $0x10
popq %rdi
xorl %r14d, %r14d
cmpl $0x80, %r12d
je 0x5670
movl %esi, %r8d
movq %rdi, %r9
subl $0x1, %r8d
jb 0x566b
movq %rbx, %rax
xorl %edx, %edx
divq %r9
addq %rax, %r14
addq %r9, %r9
jmp 0x5655
incl %r12d
jmp 0x5646
movl %ecx, %eax
andl $0x0, 0x48(%r13)
imulq %rax, %rbx
movq $0xf, 0x40(%r13)
movq %r14, %r15
shrq $0x4, %r15
movq %r13, %rdi
movq %r14, %rsi
callq 0x4160
movq %r13, %rdi
movq %r15, 0x48(%rsp)
movq %r15, %rsi
callq 0x4370
movq %r13, %rdi
movl %r14d, %esi
callq 0x4550
movq 0x8869(%rip), %rax      # 0xdf20
movl 0x8(%rax), %eax
movl %eax, %r14d
shrl %r14d
addl %eax, %r14d
movq %r14, %rdi
shlq $0xe, %rdi
pushq $-0x1
popq %rdx
xorl %esi, %esi
callq 0x4400
movq %rax, %r10
movq (%r13), %rax
movq %rax, 0x80(%rsp)
movq 0x10(%r13), %rax
movq %rax, 0x78(%rsp)
movq 0x20(%r13), %rax
movq %rax, 0x20(%rsp)
leaq 0x4c(%r13), %rax
movq %rax, 0x50(%rsp)
leaq 0x41980(%r13), %rbp
leaq 0x81980(%r13), %r15
leaq 0xa1980(%r13), %rax
movq %rax, 0x70(%rsp)
leaq 0x6e(%r13), %rax
movq %rax, 0x28(%rsp)
shlq $0x3, %r14
movq %r14, 0x88(%rsp)
xorl %eax, %eax
xorl %esi, %esi
xorl %edi, %edi
xorl %r9d, %r9d
movq 0x886b(%rip), %r12      # 0xdfa8
movq %r13, 0x90(%rsp)
movq %rbx, 0x58(%rsp)
cmpq $0x80, %rax
je 0x59c1
movq %rdi, 0x8(%rsp)
movq %rax, 0x10(%rsp)
imulq $0x32, %rax, %rdi
addq 0x50(%rsp), %rdi
movq 0x87f8(%rip), %rax      # 0xdf68
movq %rsi, (%rsp)
movl (%rax), %esi
movq %r10, %rbx
movq %r9, %r14
callq 0x43c0
movq %r14, %r9
movq (%rsp), %rsi
movq 0x8(%rsp), %rdi
movq %rbx, %r10
movq %rbp, 0x68(%rsp)
movq %r15, 0x60(%rsp)
movq %r15, %r8
xorl %r15d, %r15d
movl 0x30(%r13), %eax
cmpq %rax, %r15
jae 0x598e
movq 0x28(%rsp), %rax
movzbl (%rax,%r15), %r14d
pushq $0x1
popq %r13
movl %r14d, %ecx
shlq %cl, %r13
movq 0x10(%rsp), %rax
testq %rax, %rax
movq %r10, 0x40(%rsp)
movq %rdi, 0x8(%rsp)
movq %rsi, (%rsp)
movq %r9, 0x38(%rsp)
movq %r8, 0x30(%rsp)
jne 0x585e
callq 0x4200
subq $0x8, %rsp
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
leaq 0x3fac(%rip), %rdx      # 0x97a7
movq 0x20(%rsp), %rcx
leaq 0x3d73(%rip), %r8       # 0x957a
movl $0x343, %r9d            # imm = 0x343
xorl %eax, %eax
pushq %r14
pushq %r13
pushq %r15
callq 0x4560
addq $0x20, %rsp
callq 0x4200
movq %rax, %rbx
callq 0x4200
movq %rax, %rdi
callq 0x4130
pushq $0x2
popq %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x4100
movq 0x30(%rsp), %r8
movq 0x38(%rsp), %r9
movq (%rsp), %rsi
movq 0x10(%rsp), %rax
movq 0x8(%rsp), %rdi
movq 0x40(%rsp), %r10
movq %rbp, -0x40000(%rbp)
movq %r8, -0x3fff8(%rbp)
movq %r13, -0x3ffe0(%rbp)
decq %r13
movq %r13, -0x3ffd8(%rbp)
movl %r14d, -0x3ffd0(%rbp)
movl %r15d, -0x3ffec(%rbp)
movl %eax, -0x3ffe8(%rbp)
movq (%r12), %rdx
movq %rdx, %rbx
movl %r14d, %ecx
shrq %cl, %rbx
movq 0x80(%rsp), %rax
addq %rax, %rsi
addq %rsi, %rdx
movq 0x78(%rsp), %rax
addq %r9, %rax
movq 0x20(%rsp), %rcx
leaq (%rdi,%rcx), %r12
movq %rax, -0x3ffc0(%rbp)
movq %rbx, %r13
shrq $0x4, %r13
movq %rbp, %rdi
movq %r10, %rcx
movl %r14d, %r9d
callq 0x4580
movq -0x3fff8(%rbp), %rax
leaq (%r12,%r13,8), %rcx
cmpb $0x6, %r14b
jb 0x590b
movq %r12, 0x8(%rax)
movq %rcx, 0x10(%rax)
movq %r12, 0x18(%rax)
movq %r12, 0x20(%rax)
movq %r13, 0x28(%rax)
shlq $0x3, %r13
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rax)
jmp 0x5935
shll $0x7, %r14d
addq 0x70(%rsp), %r14
movq %r12, 0x8(%rax)
movq %rcx, 0x10(%rax)
movq %r12, 0x18(%rax)
movq %r12, 0x20(%rax)
movq %r13, 0x28(%rax)
shlq $0x3, %r13
andq $0x0, 0x38(%rax)
movq %r14, 0x30(%rax)
movq (%rsp), %rsi
movq %rsi, -0x3ffc8(%rbp)
leal -0x1(%rbx), %eax
movl %eax, -0x3fff0(%rbp)
movq 0x8658(%rip), %r12      # 0xdfa8
addq (%r12), %rsi
movq 0x38(%rsp), %r9
addq %rbx, %r9
movq 0x8(%rsp), %rdi
addq %r13, %rdi
incq %r15
movq 0x30(%rsp), %r8
addq $0x40, %r8
subq $-0x80, %rbp
movq 0x40(%rsp), %r10
addq 0x88(%rsp), %r10
movq 0x90(%rsp), %r13
jmp 0x57a0
movq 0x58(%rsp), %rbx
addq %rbx, %rsi
movq 0x10(%rsp), %rax
incq %rax
addq $0x32, 0x28(%rsp)
movq 0x60(%rsp), %r15
addq $0x400, %r15            # imm = 0x400
movq 0x68(%rsp), %rbp
addq $0x800, %rbp            # imm = 0x800
jmp 0x574a
movq 0x48(%rsp), %rax
movq 0x20(%rsp), %rcx
leaq (%rcx,%rax,8), %rax
addq %rcx, %rdi
cmpq %rax, %rdi
ja 0x5ae3
movq $0xf, 0x40(%r13)
callq 0x4200
movaps (%r13), %xmm0
subq $0x10, %rsp
movups %xmm0, (%rsp)
leaq 0x3e26(%rip), %rdx      # 0x9822
leaq 0x3b77(%rip), %r14      # 0x957a
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
movq 0x28(%rsp), %r15
movq %r15, %rcx
movq %r14, %r8
movl $0x39d, %r9d            # imm = 0x39D
xorl %eax, %eax
callq 0x4560
popq %rcx
popq %rdx
callq 0x4200
movq %rax, %rbx
callq 0x4200
movq %rax, %rdi
callq 0x4130
pushq $0x2
popq %rbp
movl %ebp, %edi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x4100
callq 0x4200
movaps 0x10(%r13), %xmm0
movaps 0x20(%r13), %xmm1
subq $0x20, %rsp
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
leaq 0x3df1(%rip), %rdx      # 0x985e
movl $0x1000, %esi           # imm = 0x1000
movq %rax, %rdi
movq %r15, %rcx
movq %r14, %r8
movl $0x39f, %r9d            # imm = 0x39F
xorl %eax, %eax
callq 0x4560
addq $0x20, %rsp
callq 0x4200
movq %rax, %rbx
callq 0x4200
movq %rax, %rdi
callq 0x4130
movl %ebp, %edi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x4100
movq (%r13), %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3cb4(%rip), %rdi      # 0x977f
leaq 0x3aa8(%rip), %rsi      # 0x957a
leaq 0x3b6f(%rip), %rcx      # 0x9648
movl $0x2fc, %edx            # imm = 0x2FC
callq 0x4220
leaq 0x3d04(%rip), %rdi      # 0x97ee
leaq 0x3a89(%rip), %rsi      # 0x957a
leaq 0x3b50(%rip), %rcx      # 0x9648
movl $0x398, %edx            # imm = 0x398
callq 0x4220