// File: bhhbazinga[P]LockFreeHashTable/./lockfree_hashtable.h
// Function: LockFreeHashTable<int, int, std::hash<int>>::InitializeBucket(unsigned long)
typename LockFreeHashTable<K, V, Hash>::DummyNode*
LockFreeHashTable<K, V, Hash>::InitializeBucket(BucketIndex bucket_index) {
  BucketIndex parent_index = GetBucketParent(bucket_index);
  DummyNode* parent_head = GetBucketHeadByIndex(parent_index);
  if (nullptr == parent_head) {
    parent_head = InitializeBucket(parent_index);
  }

  int level = 1;
  Segment* segments = segments_;  // Point to current segment.
  while (level++ <= kMaxLevel - 2) {
    Segment& cur_segment =
        segments[(bucket_index / static_cast<SegmentIndex>(pow(
                                     kSegmentSize, kMaxLevel - level + 1))) %
                 kSegmentSize];
    Segment* sub_segments = cur_segment.get_sub_segments();
    if (nullptr == sub_segments) {
      // Try allocate segments.
      sub_segments = NewSegments(level);
      void* expected = nullptr;
      if (!cur_segment.data.compare_exchange_strong(
              expected, sub_segments, std::memory_order_release)) {
        delete[] sub_segments;
        sub_segments = static_cast<Segment*>(expected);
      }
    }
    segments = sub_segments;
  }

  Segment& cur_segment = segments[(bucket_index / kSegmentSize) % kSegmentSize];
  Bucket* buckets = cur_segment.get_sub_buckets();
  if (nullptr == buckets) {
    // Try allocate buckets.
    void* expected = nullptr;
    buckets = NewBuckets();
    if (!cur_segment.data.compare_exchange_strong(expected, buckets,
                                                  std::memory_order_release)) {
      delete[] buckets;
      buckets = static_cast<Bucket*>(expected);
    }
  }

  Bucket& bucket = buckets[bucket_index % kSegmentSize];
  DummyNode* head = bucket.load(std::memory_order_consume);
  if (nullptr == head) {
    // Try allocate dummy head.
    head = new DummyNode(bucket_index);
    DummyNode* real_head;  // If insert failed, real_head is the head of bucket.
    if (InsertDummyNode(parent_head, head, &real_head)) {
      // Dummy head must be inserted into the list before storing into bucket.
      bucket.store(head, std::memory_order_release);
    } else {
      delete head;
      head = real_head;
    }
  }
  return head;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x90(%rbp)
movq -0x10(%rbp), %rsi
callq 0xa850
movq -0x90(%rbp), %rdi
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rsi
callq 0xa2b0
movq %rax, -0x20(%rbp)
xorl %eax, %eax
cmpq -0x20(%rbp), %rax
jne 0xa43b
movq -0x90(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xa3e0
movq %rax, -0x20(%rbp)
movq -0x90(%rbp), %rax
movl $0x1, -0x24(%rbp)
addq $0x18, %rax
movq %rax, -0x30(%rbp)
movl -0x24(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0x24(%rbp)
cmpl $0x2, %eax
jg 0xa5e5
movq -0x30(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xa0(%rbp)
movl -0x24(%rbp), %ecx
movl $0x5, %eax
subl %ecx, %eax
cvtsi2sd %eax, %xmm1
movsd 0x6be7(%rip), %xmm0     # 0x11078
callq 0x2210
movq -0xa0(%rbp), %rax
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rcx
movq %rcx, %rsi
sarq $0x3f, %rsi
movsd 0x6bd4(%rip), %xmm1     # 0x11088
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rdx
andq %rsi, %rdx
orq %rdx, %rcx
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq -0x98(%rbp), %rax
andq $0x3f, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0xa770
movq %rax, -0x40(%rbp)
xorl %eax, %eax
cmpq -0x40(%rbp), %rax
jne 0xa5d8
movq -0x90(%rbp), %rdi
movl -0x24(%rbp), %esi
callq 0x8dd0
movq %rax, -0x40(%rbp)
movq $0x0, -0x48(%rbp)
movq -0x38(%rbp), %rdi
addq $0x8, %rdi
movq -0x40(%rbp), %rdx
leaq -0x48(%rbp), %rsi
movl $0x3, %ecx
callq 0xa890
testb $0x1, %al
jne 0xa5d6
movq -0x40(%rbp), %rax
movq %rax, -0xa8(%rbp)
cmpq $0x0, %rax
je 0xa5ce
movq -0xa8(%rbp), %rcx
movq %rcx, %rax
addq $-0x8, %rax
movq %rax, -0xc0(%rbp)
movq -0x8(%rcx), %rdx
movq %rdx, -0xb8(%rbp)
shlq $0x4, %rdx
movq %rcx, %rax
addq %rdx, %rax
cmpq %rax, %rcx
movq %rax, -0xb0(%rbp)
je 0xa5b3
movq -0xb0(%rbp), %rdi
addq $-0x10, %rdi
movq %rdi, -0xc8(%rbp)
callq 0x8cf0
movq -0xa8(%rbp), %rcx
movq -0xc8(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0xb0(%rbp)
jne 0xa582
movq -0xc0(%rbp), %rdi
movq -0xb8(%rbp), %rsi
shlq $0x4, %rsi
addq $0x8, %rsi
callq 0x2240
movq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0xa5d8
movq -0x40(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0xa451
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
shrq $0x6, %rcx
andq $0x3f, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
callq 0xa7a0
movq %rax, -0x58(%rbp)
xorl %eax, %eax
cmpq -0x58(%rbp), %rax
jne 0xa672
movq -0x90(%rbp), %rdi
movq $0x0, -0x60(%rbp)
callq 0x8ef0
movq %rax, -0x58(%rbp)
movq -0x50(%rbp), %rdi
addq $0x8, %rdi
movq -0x58(%rbp), %rdx
leaq -0x60(%rbp), %rsi
movl $0x3, %ecx
callq 0xa890
testb $0x1, %al
jne 0xa670
movq -0x58(%rbp), %rax
movq %rax, -0xd0(%rbp)
cmpq $0x0, %rax
je 0xa668
movq -0xd0(%rbp), %rdi
callq 0x2160
movq -0x60(%rbp), %rax
movq %rax, -0x58(%rbp)
jmp 0xa672
movq -0x58(%rbp), %rax
movq -0x10(%rbp), %rcx
andq $0x3f, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
movl $0x1, %esi
callq 0xa7d0
movq %rax, -0x70(%rbp)
xorl %eax, %eax
cmpq -0x70(%rbp), %rax
jne 0xa753
movl $0x20, %edi
callq 0x2140
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xd8(%rbp)
movq -0x10(%rbp), %rsi
callq 0x8f50
jmp 0xa6c9
movq -0x90(%rbp), %rdi
movq -0xd8(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x20(%rbp), %rsi
movq -0x70(%rbp), %rdx
leaq -0x88(%rbp), %rcx
callq 0xae40
testb $0x1, %al
jne 0xa6f5
jmp 0xa728
movq -0x68(%rbp), %rdi
movq -0x70(%rbp), %rsi
movl $0x3, %edx
callq 0x8f90
jmp 0xa751
movq -0xd8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
movl $0x20, %esi
callq 0x2150
jmp 0xa760
movq -0x70(%rbp), %rax
movq %rax, -0xe0(%rbp)
cmpq $0x0, %rax
je 0xa746
movq -0xe0(%rbp), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
movq -0x88(%rbp), %rax
movq %rax, -0x70(%rbp)
jmp 0xa753
movq -0x70(%rbp), %rax
addq $0xe0, %rsp
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x2230
nopl (%rax)