// File: attractivechaos[P]udb2/verstable/./verstable.h
// Function: intmap_t_rehash
static inline bool VT_CAT( NAME, _rehash )( NAME *table, size_t bucket_count )
{
  // The attempt to resize the bucket array and rehash the keys must occur inside a loop that incrementally doubles the
  // target bucket count because a failure could theoretically occur at any load factor due to the displacement limit.
  while( true )
  {
    NAME new_table = {
      0,
      bucket_count,
      (uint16_t *)MALLOC_FN( ( bucket_count + 4 ) * sizeof( uint16_t ) ),
      (VT_CAT( NAME, _bucket ) *)MALLOC_FN( bucket_count * sizeof( VT_CAT( NAME, _bucket ) ) )
    };

    if( !new_table.metadata || !new_table.buckets )
    {
      FREE_FN( new_table.metadata );
      FREE_FN( new_table.buckets );
      return false;
    }

    memset( new_table.metadata, 0x00, bucket_count * sizeof( uint16_t ) );

    // Like the placeholder metadata array, any allocated metadata array requires excess elements to ensure that
    // iteration functions never read beyond the end of it.
    // The first excess metadatum, at least, must be non-zero in order to ensure that our iteration functions stop at
    // the end of the actual metadata (producing an end iterator).
    memset( new_table.metadata + bucket_count, 0xFF, 4 * sizeof( uint16_t ) );

    for( size_t bucket = 0; bucket < table->bucket_count; ++bucket )
      if( table->metadata[ bucket ] != VT_EMPTY )
      {
        VT_CAT( NAME, _itr ) itr = VT_CAT( NAME, _insert_raw )(
          &new_table,
          table->buckets[ bucket ].key,
          #ifdef VAL_TY
          table->buckets[ bucket ].val,
          #endif
          true,
          false
        );

        if( VT_CAT( NAME, _is_end )( itr ) )
        {
          FREE_FN( new_table.metadata );
          FREE_FN( new_table.buckets );
          bucket_count *= 2;
          continue;
        }
      }

    if( table->bucket_count )
    {
      FREE_FN( table->metadata );
      FREE_FN( table->buckets );
    }

    *table = new_table;
    return true;
  }
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x78(%rsp)
movq %rsi, 0x70(%rsp)
movq $0x0, 0x50(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x70(%rsp), %rdi
addq $0x4, %rdi
shlq %rdi
callq 0x1070
movq %rax, 0x60(%rsp)
movq 0x70(%rsp), %rdi
shlq $0x3, %rdi
callq 0x1070
movq %rax, 0x68(%rsp)
cmpq $0x0, 0x60(%rsp)
je 0x1fed
cmpq $0x0, 0x68(%rsp)
jne 0x200e
movq 0x60(%rsp), %rdi
callq 0x1030
movq 0x68(%rsp), %rdi
callq 0x1030
movb $0x0, 0x87(%rsp)
jmp 0x2178
movq 0x60(%rsp), %rdi
movq 0x70(%rsp), %rdx
shlq %rdx
xorl %esi, %esi
callq 0x1050
movq 0x60(%rsp), %rdi
movq 0x70(%rsp), %rax
shlq %rax
addq %rax, %rdi
movl $0xff, %esi
movl $0x8, %edx
callq 0x1050
movq $0x0, 0x48(%rsp)
movq 0x48(%rsp), %rax
movq 0x78(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x2120
movq 0x78(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x48(%rsp), %rcx
movzwl (%rax,%rcx,2), %eax
cmpl $0x0, %eax
je 0x210b
movq 0x78(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x48(%rsp), %rcx
movl (%rax,%rcx,8), %edx
movq 0x78(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x48(%rsp), %rcx
movl 0x4(%rax,%rcx,8), %ecx
leaq 0x28(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movl $0x1, %r8d
xorl %r9d, %r9d
callq 0x1970
leaq 0x28(%rsp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rcx
movq %rcx, 0x10(%rsp)
movq 0x18(%rax), %rax
movq %rax, 0x18(%rsp)
callq 0x1f70
testb $0x1, %al
jne 0x20e6
jmp 0x2109
movq 0x60(%rsp), %rdi
callq 0x1030
movq 0x68(%rsp), %rdi
callq 0x1030
movq 0x70(%rsp), %rax
shlq %rax
movq %rax, 0x70(%rsp)
jmp 0x210d
jmp 0x210b
jmp 0x210d
movq 0x48(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x48(%rsp)
jmp 0x204a
movq 0x78(%rsp), %rax
cmpq $0x0, 0x8(%rax)
je 0x2148
movq 0x78(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x1030
movq 0x78(%rsp), %rax
movq 0x18(%rax), %rdi
callq 0x1030
movq 0x78(%rsp), %rax
movq 0x50(%rsp), %rcx
movq %rcx, (%rax)
movq 0x58(%rsp), %rcx
movq %rcx, 0x8(%rax)
movq 0x60(%rsp), %rcx
movq %rcx, 0x10(%rax)
movq 0x68(%rsp), %rcx
movq %rcx, 0x18(%rax)
movb $0x1, 0x87(%rsp)
movb 0x87(%rsp), %al
andb $0x1, %al
addq $0x88, %rsp
retq
nopl (%rax)