// File: chahk0129[P]hash_bench/./index/extendible_hash.h
// Function: ExtendibleHash<char [32]>::Get(char (&) [32])
char* ExtendibleHash<Key_t>::Get(Key_t& key) {
    size_t f_hash;
    if constexpr(sizeof(Key_t) > 8)
	f_hash = hash_funcs[0](key, sizeof(Key_t), f_seed);
    else
	f_hash = hash_funcs[0](&key, sizeof(Key_t), f_seed);
    auto f_idx = (f_hash & kMask) * kNumPairPerCacheLine;

RETRY:
    while(dir->sema < 0){
	asm("nop");
    }

    auto x = (f_hash >> (8*sizeof(f_hash) - dir->depth)); 
    auto target = dir->_[x];

    if(!target){
	std::this_thread::yield();
	goto RETRY;
    }

    /* acquire segment shared lock */
    if(!target->mutex.try_lock_shared()){
	std::this_thread::yield();
	goto RETRY;
    }

    auto target_check = (f_hash >> (8*sizeof(f_hash) - dir->depth));
    if(target != dir->_[target_check]){
	target->mutex.unlock();
	std::this_thread::yield();
	goto RETRY;
    }

    for (unsigned i = 0; i < kNumPairPerCacheLine * kNumCacheLine; ++i) {
	auto loc = (f_idx+i) % Segment<Key_t>::kNumSlot;
	if constexpr(sizeof(Key_t)>8){
	    if(memcmp(target->_[loc].key, key, sizeof(Key_t)) == 0){
		Value_t v = target->_[loc].value;
		target->mutex.unlock();
		return (char*)v;
	    }
	}
	else{
	    if(memcmp(&target->_[loc].key, &key, sizeof(Key_t)) == 0){
		Value_t v = target->_[loc].value;
		target->mutex.unlock();
		return (char*)v;
	    }
	}
    }

#ifdef S_HASH
    size_t s_hash;
    if constexpr(sizeof(Key_t) > 8)
	s_hash = hash_funcs[2](key, sizeof(Key_t), s_seed);
    else
	s_hash = hash_funcs[2](&key, sizeof(Key_t), s_seed);
    auto s_idx = (s_hash & kMask) * kNumPairPerCacheLine;

    for(unsigned i=0; i<kNumPairPerCacheLine * kNumCacheLine; ++i){
	auto loc = (s_idx+i) % Segment<Key_t>::kNumSlot;
	if constexpr(sizeof(Key_t)>8){
	    if(memcmp(target->_[loc].key, key, sizeof(Key_t)) == 0){
		Value_t v = target->_[loc].value;
		target->mutex.unlock();
		return (char*)v;
	    }
	}
	else{
	    if(memcmp(&target->_[loc].key, &key, sizeof(Key_t)) == 0){
		Value_t v = target->_[loc].value;
		target->mutex.unlock();
		return (char*)v;
	    }
	}

    }
#endif

    target->mutex.unlock();
    return (char*)NONE;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq 0x3dd91(%rip), %rax     # 0x5a480
movq -0x18(%rbp), %rdi
movl $0x20, %esi
movl $0xc70697, %edx         # imm = 0xC70697
callq *%rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
andq $0xff, %rax
shlq $0x2, %rax
movq %rax, -0x28(%rbp)
jmp 0x1c717
movq -0x60(%rbp), %rax
movq 0x8(%rax), %rax
cmpq $0x0, 0x8(%rax)
jge 0x1c729
nop
jmp 0x1c717
movq -0x60(%rbp), %rax
movq -0x20(%rbp), %rdx
movq 0x8(%rax), %rsi
movl $0x40, %ecx
subq 0x18(%rsi), %rcx
shrq %cl, %rdx
movq %rdx, %rcx
movq %rcx, -0x30(%rbp)
movq 0x8(%rax), %rax
movq (%rax), %rax
movq -0x30(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x1c769
callq 0x1cbf0
jmp 0x1c715
movq -0x38(%rbp), %rdi
addq $0xa008, %rdi           # imm = 0xA008
callq 0x1d3d0
testb $0x1, %al
jne 0x1c784
callq 0x1cbf0
jmp 0x1c715
movq -0x60(%rbp), %rcx
movq -0x20(%rbp), %rax
movq 0x8(%rcx), %rdx
movl $0x40, %ecx
subq 0x18(%rdx), %rcx
shrq %cl, %rax
movq -0x60(%rbp), %rcx
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
movq 0x8(%rcx), %rcx
movq (%rcx), %rcx
movq -0x40(%rbp), %rdx
cmpq (%rcx,%rdx,8), %rax
je 0x1c7d3
movq -0x38(%rbp), %rdi
addq $0xa008, %rdi           # imm = 0xA008
callq 0x1cc30
callq 0x1cbf0
jmp 0x1c715
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpq $0x400, %rax            # imm = 0x400
jae 0x1c853
movq -0x28(%rbp), %rax
movl -0x44(%rbp), %ecx
addq %rcx, %rax
andq $0x3ff, %rax            # imm = 0x3FF
movq %rax, -0x50(%rbp)
movq -0x38(%rbp), %rdi
imulq $0x28, -0x50(%rbp), %rax
addq %rax, %rdi
movq -0x18(%rbp), %rsi
movl $0x20, %edx
callq 0x6190
cmpl $0x0, %eax
jne 0x1c846
movq -0x38(%rbp), %rax
imulq $0x28, -0x50(%rbp), %rcx
addq %rcx, %rax
movq 0x20(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x38(%rbp), %rdi
addq $0xa008, %rdi           # imm = 0xA008
callq 0x1cc30
movq -0x58(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x1c86b
jmp 0x1c848
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x1c7da
movq -0x38(%rbp), %rdi
addq $0xa008, %rdi           # imm = 0xA008
callq 0x1cc30
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop