// File: tewalds[P]morat/hex/../lib/compacttree.h
// Function: Morat::CompactTree<Morat::Hex::AgentMCTS::Node>::compact(float, float)
void compact(float arenasize = 0, float generationsize = 0){
		assert(arenasize >= 0 && arenasize <= 1);
		assert(generationsize >= 0 && generationsize <= 1);

		memused = 0;

		if(head->used == 0)
			return;

		//clear the freelist
		freelist.clear();

		Chunk      * schunk = head; //source chunk
		unsigned int soff   = 0;    //source offset
		Chunk      * dchunk = schunk; //destination chunk
		unsigned int doff   = soff;   //destination offset

		unsigned int generationid = (unsigned int)(generationsize * current->id);
		bool compactthischunk = (generationid == 0);

		//iterate over each chunk, moving data blocks to the left to fill empty space
		while(schunk != NULL){
			//iterate over each Data block
			Data * s = (Data *)(schunk->mem + soff);
			assert(s->capacity > 0 && s->capacity < MAX_NUM);

			int ssize = s->mem_size(); //how much to move the source pointer

			//move from -> to, update parent pointer
			if(s->empty()){
				if(!compactthischunk){
					if(s->old()){//this empty segment is an unpopular size, lets compact this chunk to clean up this segment
						compactthischunk = true;
						dchunk = schunk;
						doff = soff;
					}else{ //freed recently, add to the free list
						freelist.push_nolock(s);
						s->header++; //empty, but a generation old
					}
				}//else this position will be overwritten by the next full chunk
			}else{
				if(!compactthischunk){
					memused += ssize;
				}else{
					assert(s->used > 0 && s->used <= s->capacity);
					int dsize = s->memused(); //how much to move the dest pointer
					Data * d = NULL;

					//where to move
					while(1){
						if((d = freelist.pop_nolock(s->used))){ //allocate off the freelist if possible
							break;
						}else if(doff + dsize <= dchunk->capacity){ //if space, allocate from this chunk
							assert(schunk->id > dchunk->id || (schunk == dchunk && soff >= doff)); //make sure I'm moving left
							d = (Data *)(dchunk->mem + doff);
							doff += dsize;
							break;
						}else{ //otherwise finish this chunk and prepare the next
							dchunk->used = doff;
							dchunk->clear_unused();

							dchunk = dchunk->next;
							doff = 0;
						}
					}

					//move!
					s->capacity = s->used;
					if(s != d){
						memmove(reinterpret_cast<void*>(d), reinterpret_cast<void*>(s), dsize);
						d->move(s);
					}
					memused += dsize;
				}
			}

			//update source
			soff += ssize;
			while(schunk && schunk->used <= soff){ //move forward, skip empty chunks
				//if the last chunk was being compacted out of order, finish it off
				if(schunk->id < generationid && compactthischunk){
					dchunk->used = doff;
					dchunk->clear_unused();
				}
				//go to the next source chunk
				schunk = schunk->next;
				soff = 0;
				//if we're done the static generation, initialize the destination chunk
				if(schunk){
					if(schunk->id == generationid){
						dchunk = schunk;
						doff = soff;
					}
					compactthischunk = (schunk->id >= generationid);
				}
			}
		}

		//finish the last used chunk
		dchunk->used = doff;
		dchunk->clear_unused();

		//free unused chunks
		Chunk * del = dchunk;
		while(del->next && del->id < arenasize*current->id){
			del = del->next;
			del->used = 0;
		}

		if(del->next != NULL){
			del->next->dealloc(true);
			delete del->next;
			del->next = NULL;
			numchunks = del->id + 1;
		}

		//set current to head in case some chunks aren't filled completely due to generations
		current = head;
		last = dchunk;
	}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x70(%rsp)
vmovss %xmm0, 0x6c(%rsp)
vmovss %xmm1, 0x68(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x10(%rsp)
vmovss 0x6c(%rsp), %xmm0
xorl %eax, %eax
vpxor %xmm1, %xmm1, %xmm1
vucomiss %xmm1, %xmm0
movb %al, 0x1f(%rsp)
jb 0x1bc2a
vmovss 0x315f3(%rip), %xmm0    # 0x4d210
vucomiss 0x6c(%rsp), %xmm0
setae %al
movb %al, 0x1f(%rsp)
movb 0x1f(%rsp), %al
testb $0x1, %al
jne 0x1bc34
jmp 0x1bc36
jmp 0x1bc55
leaq 0x31e4e(%rip), %rdi     # 0x4da8b
leaq 0x31a24(%rip), %rsi     # 0x4d668
movl $0x17a, %edx            # imm = 0x17A
leaq 0x31e5c(%rip), %rcx     # 0x4daac
callq 0x52a0
vmovss 0x68(%rsp), %xmm0
xorl %eax, %eax
vpxor %xmm1, %xmm1, %xmm1
vucomiss %xmm1, %xmm0
movb %al, 0xf(%rsp)
jb 0x1bc80
vmovss 0x3159d(%rip), %xmm0    # 0x4d210
vucomiss 0x68(%rsp), %xmm0
setae %al
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %al
testb $0x1, %al
jne 0x1bc8a
jmp 0x1bc8c
jmp 0x1bcab
leaq 0x31e8a(%rip), %rdi     # 0x4db1d
leaq 0x319ce(%rip), %rsi     # 0x4d668
movl $0x17b, %edx            # imm = 0x17B
leaq 0x31e06(%rip), %rcx     # 0x4daac
callq 0x52a0
movq 0x10(%rsp), %rax
movq $0x0, 0x13b8(%rax)
movq (%rax), %rax
cmpl $0x0, 0x10(%rax)
jne 0x1bcc9
jmp 0x1c1bf
movq 0x10(%rsp), %rdi
addq $0x20, %rdi
callq 0x205f0
movq 0x10(%rsp), %rax
movq (%rax), %rcx
movq %rcx, 0x60(%rsp)
movl $0x0, 0x5c(%rsp)
movq 0x60(%rsp), %rcx
movq %rcx, 0x50(%rsp)
movl 0x5c(%rsp), %ecx
movl %ecx, 0x4c(%rsp)
vmovss 0x68(%rsp), %xmm0
movq 0x8(%rax), %rax
vcvtusi2ssl 0x8(%rax), %xmm1, %xmm1
vmulss %xmm1, %xmm0, %xmm0
vcvttss2usi %xmm0, %eax
movl %eax, 0x48(%rsp)
cmpl $0x0, 0x48(%rsp)
sete %al
andb $0x1, %al
movb %al, 0x47(%rsp)
cmpq $0x0, 0x60(%rsp)
je 0x1c0c3
movq 0x60(%rsp), %rax
movq 0x18(%rax), %rax
movl 0x5c(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
movzwl 0x4(%rax), %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, 0xe(%rsp)
jle 0x1bd75
movq 0x38(%rsp), %rax
movzwl 0x4(%rax), %eax
cmpl $0x272, %eax            # imm = 0x272
setb %al
movb %al, 0xe(%rsp)
movb 0xe(%rsp), %al
testb $0x1, %al
jne 0x1bd7f
jmp 0x1bd81
jmp 0x1bda0
leaq 0x31dc0(%rip), %rdi     # 0x4db48
leaq 0x318d9(%rip), %rsi     # 0x4d668
movl $0x191, %edx            # imm = 0x191
leaq 0x31d11(%rip), %rcx     # 0x4daac
callq 0x52a0
movq 0x38(%rsp), %rdi
callq 0x1e620
movl %eax, 0x34(%rsp)
movq 0x38(%rsp), %rdi
callq 0x1e600
testb $0x1, %al
jne 0x1bdbe
jmp 0x1be14
testb $0x1, 0x47(%rsp)
jne 0x1be0f
movq 0x38(%rsp), %rdi
callq 0x20630
testb $0x1, %al
jne 0x1bdd5
jmp 0x1bdee
movb $0x1, 0x47(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x50(%rsp)
movl 0x5c(%rsp), %eax
movl %eax, 0x4c(%rsp)
jmp 0x1be0d
movq 0x10(%rsp), %rdi
addq $0x20, %rdi
movq 0x38(%rsp), %rsi
callq 0x1e7e0
movq 0x38(%rsp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0x1be0f
jmp 0x1c002
testb $0x1, 0x47(%rsp)
jne 0x1be38
movq 0x10(%rsp), %rax
movslq 0x34(%rsp), %rcx
addq 0x13b8(%rax), %rcx
movq %rcx, 0x13b8(%rax)
jmp 0x1c000
movq 0x38(%rsp), %rax
movzwl 0x6(%rax), %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, 0xd(%rsp)
jle 0x1be67
movq 0x38(%rsp), %rax
movzwl 0x6(%rax), %eax
movq 0x38(%rsp), %rcx
movzwl 0x4(%rcx), %ecx
cmpl %ecx, %eax
setle %al
movb %al, 0xd(%rsp)
movb 0xd(%rsp), %al
testb $0x1, %al
jne 0x1be71
jmp 0x1be73
jmp 0x1be92
leaq 0x31cf7(%rip), %rdi     # 0x4db71
leaq 0x317e7(%rip), %rsi     # 0x4d668
movl $0x1a5, %edx            # imm = 0x1A5
leaq 0x31c1f(%rip), %rcx     # 0x4daac
callq 0x52a0
movq 0x38(%rsp), %rdi
callq 0x20650
movl %eax, 0x30(%rsp)
movq $0x0, 0x28(%rsp)
movq 0x10(%rsp), %rdi
addq $0x20, %rdi
movq 0x38(%rsp), %rax
movzwl 0x6(%rax), %esi
callq 0x204b0
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
je 0x1bed0
jmp 0x1bfa7
movl 0x4c(%rsp), %eax
addl 0x30(%rsp), %eax
movq 0x50(%rsp), %rcx
cmpl 0xc(%rcx), %eax
ja 0x1bf75
movq 0x60(%rsp), %rax
movl 0x8(%rax), %ecx
movq 0x50(%rsp), %rdx
movb $0x1, %al
cmpl 0x8(%rdx), %ecx
movb %al, 0xc(%rsp)
ja 0x1bf27
movq 0x60(%rsp), %rcx
xorl %eax, %eax
cmpq 0x50(%rsp), %rcx
movb %al, 0xb(%rsp)
jne 0x1bf1f
movl 0x5c(%rsp), %eax
cmpl 0x4c(%rsp), %eax
setae %al
movb %al, 0xb(%rsp)
movb 0xb(%rsp), %al
movb %al, 0xc(%rsp)
movb 0xc(%rsp), %al
testb $0x1, %al
jne 0x1bf31
jmp 0x1bf33
jmp 0x1bf52
leaq 0x31c5d(%rip), %rdi     # 0x4db97
leaq 0x31727(%rip), %rsi     # 0x4d668
movl $0x1ae, %edx            # imm = 0x1AE
leaq 0x31b5f(%rip), %rcx     # 0x4daac
callq 0x52a0
movq 0x50(%rsp), %rax
movq 0x18(%rax), %rax
movl 0x4c(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movl 0x30(%rsp), %eax
addl 0x4c(%rsp), %eax
movl %eax, 0x4c(%rsp)
jmp 0x1bfa7
movl 0x4c(%rsp), %ecx
movq 0x50(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x50(%rsp), %rdi
callq 0x20670
movq 0x50(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x50(%rsp)
movl $0x0, 0x4c(%rsp)
jmp 0x1bfa2
jmp 0x1bea9
movq 0x38(%rsp), %rax
movw 0x6(%rax), %cx
movq 0x38(%rsp), %rax
movw %cx, 0x4(%rax)
movq 0x38(%rsp), %rax
cmpq 0x28(%rsp), %rax
je 0x1bfe8
movq 0x28(%rsp), %rdi
movq 0x38(%rsp), %rsi
movslq 0x30(%rsp), %rdx
callq 0x56e0
movq 0x28(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0x206c0
movq 0x10(%rsp), %rax
movslq 0x30(%rsp), %rcx
addq 0x13b8(%rax), %rcx
movq %rcx, 0x13b8(%rax)
jmp 0x1c002
movl 0x34(%rsp), %eax
addl 0x5c(%rsp), %eax
movl %eax, 0x5c(%rsp)
xorl %eax, %eax
cmpq $0x0, 0x60(%rsp)
movb %al, 0xa(%rsp)
je 0x1c02f
movq 0x60(%rsp), %rax
movl 0x10(%rax), %eax
cmpl 0x5c(%rsp), %eax
setbe %al
movb %al, 0xa(%rsp)
movb 0xa(%rsp), %al
testb $0x1, %al
jne 0x1c03c
jmp 0x1c0be
movq 0x60(%rsp), %rax
movl 0x8(%rax), %eax
cmpl 0x48(%rsp), %eax
jae 0x1c067
testb $0x1, 0x47(%rsp)
je 0x1c067
movl 0x4c(%rsp), %ecx
movq 0x50(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x50(%rsp), %rdi
callq 0x20670
movq 0x60(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x60(%rsp)
movl $0x0, 0x5c(%rsp)
cmpq $0x0, 0x60(%rsp)
je 0x1c0b9
movq 0x60(%rsp), %rax
movl 0x8(%rax), %eax
cmpl 0x48(%rsp), %eax
jne 0x1c0a4
movq 0x60(%rsp), %rax
movq %rax, 0x50(%rsp)
movl 0x5c(%rsp), %eax
movl %eax, 0x4c(%rsp)
movq 0x60(%rsp), %rax
movl 0x8(%rax), %eax
cmpl 0x48(%rsp), %eax
setae %al
andb $0x1, %al
movb %al, 0x47(%rsp)
jmp 0x1c00e
jmp 0x1bd2b
movl 0x4c(%rsp), %ecx
movq 0x50(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x50(%rsp), %rdi
callq 0x20670
movq 0x50(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rcx
xorl %eax, %eax
cmpq $0x0, (%rcx)
movb %al, 0x9(%rsp)
je 0x1c125
movq 0x10(%rsp), %rax
movq 0x20(%rsp), %rcx
vcvtusi2ssl 0x8(%rcx), %xmm0, %xmm1
vmovss 0x6c(%rsp), %xmm0
movq 0x8(%rax), %rax
vcvtusi2ssl 0x8(%rax), %xmm2, %xmm2
vmulss %xmm2, %xmm0, %xmm0
vucomiss %xmm1, %xmm0
seta %al
movb %al, 0x9(%rsp)
movb 0x9(%rsp), %al
testb $0x1, %al
jne 0x1c12f
jmp 0x1c14a
movq 0x20(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
movl $0x0, 0x10(%rax)
jmp 0x1c0e3
movq 0x20(%rsp), %rax
cmpq $0x0, (%rax)
je 0x1c1aa
movq 0x20(%rsp), %rax
movq (%rax), %rdi
movl $0x1, %esi
callq 0x20810
movq 0x20(%rsp), %rax
movq (%rax), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x1c18b
movq (%rsp), %rdi
callq 0x20940
movq (%rsp), %rdi
callq 0x53a0
movq 0x10(%rsp), %rax
movq 0x20(%rsp), %rcx
movq $0x0, (%rcx)
movq 0x20(%rsp), %rcx
movl 0x8(%rcx), %ecx
addl $0x1, %ecx
movl %ecx, 0x18(%rax)
movq 0x10(%rsp), %rax
movq (%rax), %rcx
movq %rcx, 0x8(%rax)
movq 0x50(%rsp), %rcx
movq %rcx, 0x10(%rax)
addq $0x78, %rsp
retq
nopw %cs:(%rax,%rax)
nop